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

import be.iminds.ilabt.jfed.experimenter_gui.TriggeredMessageHandler;
import be.iminds.ilabt.jfed.experimenter_gui.config.AdvertisementFetchManager;
import be.iminds.ilabt.jfed.experimenter_gui.config.JFedGuiConfig;
import be.iminds.ilabt.jfed.experimenter_gui.editor.ModelRspecEditor;
import be.iminds.ilabt.jfed.experimenter_gui.editor.properties.map.MapDialogFactory;
import be.iminds.ilabt.jfed.experimenter_gui.util.ui.FXUtils;
import be.iminds.ilabt.jfed.fedmon.webapi.client.FedmonWebApiClient;
import be.iminds.ilabt.jfed.fedmon.webapi.service.json.ResourceClass;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.lowlevel.authority.AuthorityFinder;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecNode;
import be.iminds.ilabt.jfed.ui.javafx.util.StageUtils;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.util.List;

/**
 * User: twalcari
 * Date: 12/2/2014
 * Time: 14:45
 */
@Singleton
public class AdaptivePropertiesDialogFactory {
    private static final Logger LOG = LoggerFactory.getLogger(AdaptivePropertiesDialogFactory.class);

    private final JFedGuiConfig config;
    private final TestbedInfoSource testbedInfoSource;
    private final AdvertisementFetchManager advertisementFetchManager;
    private final AuthorityFinder authorityFinder;
    private final MapDialogFactory mapDialogFactory;
    private final FedmonWebApiClient fedmonWebApiClient;
    private final TriggeredMessageHandler triggeredMessageHandler;
    private final Provider<SelectDiskImageDialog> selectDiskImageDialogProvider;

    //Note: FedmonWebApiClient is bound to singleton FedmonWebApiCachedClient in HighLevelModule
    //Note: FedmonWebApiCachedClient caches ServerGlimpse for 10 minutes with default settings

    @Inject
    public AdaptivePropertiesDialogFactory(JFedGuiConfig config, TestbedInfoSource testbedInfoSource,
                                           AdvertisementFetchManager advertisementFetchManager, AuthorityFinder authorityFinder,
                                           MapDialogFactory mapDialogFactory,
                                           FedmonWebApiClient fedmonWebApiClient, TriggeredMessageHandler triggeredMessageHandler,
                                           Provider<SelectDiskImageDialog> selectDiskImageDialogProvider) {
        this.config = config;
        this.testbedInfoSource = testbedInfoSource;
        this.advertisementFetchManager = advertisementFetchManager;
        this.authorityFinder = authorityFinder;
        this.mapDialogFactory = mapDialogFactory;
        this.fedmonWebApiClient = fedmonWebApiClient;
        this.triggeredMessageHandler = triggeredMessageHandler;
        this.selectDiskImageDialogProvider = selectDiskImageDialogProvider;
    }

    public AdaptivePropertiesDialog createAdaptivePropertiesDialog(@Nonnull ModelRspecEditor modelRspecEditor, @Nonnull FXRspecNode node) {
        assert node != null;
        ResourceClass resourceClass =
                node.getResourceClassId() == null ?
                        null :
                        config.getResourceClass(node.getResourceClassId());

        List<ResourceClass> matchingResourceClasses = config.findAllPossibleResourceClasses(node);

        if (resourceClass != null && !matchingResourceClasses.contains(resourceClass)) {
            ResourceClass newResourceClass = config.findBestResourceClass(node);
//            assert newResourceClass != null;
            LOG.debug("ResourceClass know for node {} is \"{}\". " +
                    "But that class does not match the node -> changing it to: {}",
                    node.getClientId(),
                    resourceClass.getId(),
                    newResourceClass == null ? null : newResourceClass.getId());
            if (newResourceClass != null) {
                resourceClass = newResourceClass;
            } else {
                LOG.warn("config.findBestResourceClass(node) returned null");
            }
        }

        if (resourceClass == null) {
            resourceClass = config.findBestResourceClass(node);

            if (resourceClass == null) {
                //no resource or resourceClass known for this node
                //will have to fall back to generic

                resourceClass = config.getDefaultResourceClass();
            }

            assert resourceClass != null;
            LOG.debug("No resourceClass know for node " + node.getClientId() + ". Falling back to: " + resourceClass.getId());
        }

        assert resourceClass != null;

        return new AdaptivePropertiesDialog(modelRspecEditor, node,
                config, advertisementFetchManager, testbedInfoSource,
                authorityFinder, resourceClass, mapDialogFactory,
                fedmonWebApiClient, triggeredMessageHandler, selectDiskImageDialogProvider);
    }

    public void showAdaptivePropertiesDialog(Window parent,
                                             ModelRspecEditor modelRspecEditor, FXRspecNode node) {
        AdaptivePropertiesDialog adaptivePropertiesDialog = createAdaptivePropertiesDialog(modelRspecEditor, node);
        Scene scene = new Scene(adaptivePropertiesDialog);

        Stage dialogStage = new Stage();
        StageUtils.setJFedStageIcons(dialogStage);
        dialogStage.setScene(scene);

        String debug = "";
        int addDebug = 0;
        assert (addDebug++) == 0;
        if (addDebug > 0) debug = " (" + adaptivePropertiesDialog.getResourceClassId() + ")";

        dialogStage.setTitle("Properties of " + node.getClientId() + debug);
        dialogStage.setMinHeight(600);
        dialogStage.setMaxHeight(800);
        dialogStage.setMinWidth(500);
        FXUtils.centerToOwner(parent, dialogStage);

        dialogStage.showAndWait();
    }
}
