package be.iminds.ilabt.jfed.experimenter_gui.editor;

import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXModelRspec;
import be.iminds.ilabt.jfed.rspec.parser.RspecCompare;
import be.iminds.ilabt.jfed.rspec.parser.RspecParseException;
import be.iminds.ilabt.jfed.rspec.rspec_source.RequestRspecSource;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.xml.stream.XMLStreamException;
import java.io.File;

/**
 * User: twalcari
 * Date: 5/20/2015
 * Time: 09:20
 */
public class EditableRspec {
    private static final Logger LOG = LoggerFactory.getLogger(EditableRspec.class);

    /**
     * The file from which this Rspec has been loaded, or where it has been saved to the last time
     */
    @Nullable
    private File file = null;

    /**
     * The name of the experiment. Typically relates to the filename of the rspec
     */
    private final StringProperty name = new SimpleStringProperty();

    private final ReadOnlyObjectWrapper<RequestRspecSource> requestRspecSource = new ReadOnlyObjectWrapper<>();

    @Nullable
    private String lastSavedRequestRspec = null;

    public EditableRspec(RequestRspecSource requestRspecSource, String name, File inputFile) {
        setRequestRspecSource(requestRspecSource);
        this.name.set(name);

        setFile(inputFile); //this setter also sets lastSavedRequestSpec
    }

    /**
     * Creates an empty editable rspec
     */
    public EditableRspec(String name) {
        setRequestRspecSource(new RequestRspecSource(new FXModelRspec("request")));
        this.name.set(name);

        //by setting an empty rspec as "last saved", the isDirty()-function will return false if the user doesn't do
        //anything in the editor at all.
        lastSavedRequestRspec = requestRspecSource.get().getRspecXmlString();
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
        this.lastSavedRequestRspec = requestRspecSource.get().getRspecXmlString();
    }

    public String getName() {
        return name.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public StringProperty nameProperty() {
        return name;
    }

    public RequestRspecSource getRequestRspecSource() {
        return requestRspecSource.get();
    }

    public ReadOnlyObjectProperty<RequestRspecSource> requestRspecSourceProperty() {
        return requestRspecSource.getReadOnlyProperty();
    }

    public void setRequestRspecSource(RequestRspecSource requestRspecSource) {
        this.requestRspecSource.set(requestRspecSource);
    }

    public boolean isDirty() {
        if(lastSavedRequestRspec == null)
            return false;

        try {
            RspecCompare compare =
                    new RspecCompare(requestRspecSource.get().getRspecXmlString(), lastSavedRequestRspec);

            return !compare.isEqual();
        } catch (XMLStreamException | RspecParseException e) {
            LOG.warn("Could not properly parse Rspecs to compare for dirty detection", e);
            return true;
        }
    }
}
