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

import be.iminds.ilabt.jfed.experimenter_gui.config.JFedGuiConfig;
import be.iminds.ilabt.jfed.experimenter_gui.editor.actions.EditorActionsFactory;
import be.iminds.ilabt.jfed.experimenter_gui.editor.views.EditorViewsFactory;
import be.iminds.ilabt.jfed.experimenter_gui.ui.ExperimentEditorTabHost;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;


import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * User: twalcari
 * Date: 12/8/2014
 * Time: 15:58
 */
@Singleton
public class ExperimentEditorTabFactory {

    private final ExperimentEditorTabHost experimentEditorTabHost;

    private final JFedGuiConfig config;
    private final TestbedInfoSource testbedInfoSource;
    private final EditorViewsFactory editorViewsFactory;
    private final EditorActionsFactory editorActionsFactory;


    @Inject
    public ExperimentEditorTabFactory(ExperimentEditorTabHost experimentEditorTabHost,
                                      TestbedInfoSource testbedInfoSource, EditorViewsFactory editorViewsFactory, EditorActionsFactory editorActionsFactory,
                                      JFedGuiConfig config) {
        this.testbedInfoSource = testbedInfoSource;
        this.editorViewsFactory = editorViewsFactory;
        this.editorActionsFactory = editorActionsFactory;
        this.experimentEditorTabHost = experimentEditorTabHost;
        this.config = config;
    }


    public ExperimentEditorTab createExperimentEditorTab() {
        EditableRspec editableRspec = new EditableRspec(getNextNewExperimentDefinitionName());

        return new ExperimentEditorTab(editableRspec, testbedInfoSource, config, editorViewsFactory, editorActionsFactory, config);
    }


    public ExperimentEditorTab createExperimentEditorTab(EditableRspec editableRspec) {
        return new ExperimentEditorTab(editableRspec, testbedInfoSource, config, editorViewsFactory, editorActionsFactory, config);
    }


    /**
     * @return A new unique experiment definition name
     */
    private String getNextNewExperimentDefinitionName() {
        String baseName = "Untitled";

        if (!experimentDefinitionNameExists(baseName))
            return baseName;

        int counter = 1;
        String name = baseName + counter;
        while (experimentDefinitionNameExists(name)) {
            counter++;
            name = baseName + counter;
        }
        return name;
    }


    /**
     * Tests whether a given experiment definition is already open in the GUI
     */
    private boolean experimentDefinitionNameExists(String name) {
        return experimentEditorTabHost.getExperimentEditorTabs()
                .stream()
                .map(ExperimentEditorTab::getExperimentEditor)
                .map(ExperimentEditor::getEditableRspec)
                .map(EditableRspec::getName)
                .anyMatch(name::equals);
    }

}
