package be.iminds.ilabt.jfed.rspec.model.controller;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Cedric
 */
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(namespace="http://jfed.iminds.be/rspec/ext/jfed-command/1")
public class ExperimentBarrierSegment {
    private final static Logger LOG = LoggerFactory.getLogger(ExperimentBarrierSegment.class);

    private List<ExperimentCommand> commands;
    private final StringProperty tag;
    private int orderNumber;
    private final BooleanProperty started = new SimpleBooleanProperty(false);
    private final BooleanProperty completed = new SimpleBooleanProperty(false);

    private final ChangeListener<Boolean> finishedListener =
            (observableValue, oldFinishedVal, newFinishedVal) -> updateFinished();

    private void updateFinished() {
        for (ExperimentCommand command : commands) {
            if (!command.isFinished()) {
                completed.setValue(false);
                return;
            }
        }
        completed.setValue(true);
    }

    public ExperimentBarrierSegment(){
        tag = new SimpleStringProperty("");
        commands = new ArrayList<>();
    }
    
    public ExperimentBarrierSegment(String tag){
        this();
        this.tag.set(tag);
    }
    
    public ExperimentBarrierSegment(String tag, int id){
        this(tag);
        this.orderNumber = id;
    }
    
    public ExperimentBarrierSegment(String tag, int id, List<ExperimentCommand> commands){
        this(tag, id);
        this.commands = commands;
    }

    public void addCommand(final ExperimentCommand command){
        commands.add(command);
        command.setBarrierSegmentOrderNumber(orderNumber);

        command.getFinishedProperty().addListener(finishedListener);
        updateFinished();
    }
    
    public void deleteCommand(ExperimentCommand command){
        commands.remove(command);        
        command.getFinishedProperty().removeListener(finishedListener);
        updateFinished();
    }
    
    public List<ExperimentCommand> getCommands() {
        return commands;
    }

    @XmlTransient
    public void setCommands(List<ExperimentCommand> commands) {
        for(ExperimentCommand command : this.commands){
            command.getFinishedProperty().removeListener(finishedListener);
        }
        
        commands.clear();
        started.set(false);
        completed.set(false);
        
        for(ExperimentCommand c : commands){
            addCommand(c);
        }
    }

    public int getOrderNumber() {
        return orderNumber;
    }
    
    @XmlAttribute
    public void setOrderNumber(int orderNumber) {
        this.orderNumber = orderNumber;
    }

    public String getTag() {
        return tag.get();
    }

    @XmlAttribute
    public void setTag(String tag) {
        this.tag.set(tag);
    }

    public StringProperty tagProperty() {
        return tag;
    }

    public BooleanProperty completedProperty() {
        return completed;
    }

    @XmlTransient
    public boolean isCompleted() {
        return completed.get();
    }

    public void start(){
        started.set(true);
        
        //If this barrier segment is empty, it is automatically completed upon starting
//        if(commands.isEmpty())
//            completed.set(true);
        updateFinished();
    }
    
    public void rewind(){
        completed.set(false);
        started.set(false);
    }
    
    public void skip(){
        started.set(true);
        for(ExperimentCommand c : commands){
            c.setSkipped(true);
            c.setStarted(true);
            c.setFinished(true);
        }
        completed.set(true);
    }
    
    public BooleanProperty getStarted(){
        return started;
    }
    
}
