package be.iminds.ilabt.jfed.ui.javafx.probe_gui.command_arguments;

import be.iminds.ilabt.jfed.highlevel.model.ParameterHistoryModel;
import be.iminds.ilabt.jfed.lowlevel.AnyCredential;
import be.iminds.ilabt.jfed.ui.javafx.probe_gui.dialog.CredentialEditDialog;
import be.iminds.ilabt.jfed.ui.javafx.probe_gui.dialog.CredentialViewDialog;
import be.iminds.ilabt.jfed.util.StringConverterListCell;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.util.StringConverter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * StringArgumentChooser
 */
public class MultiCredentialArgumentChooser extends CommandArgumentChooser<List<AnyCredential>> {
    @FXML
    private ListView<AnyCredential> listView;
    @FXML
    private Button addButton;
    @FXML
    private Button editButton;
    @FXML
    private Button viewButton;

    private final ObjectProperty<List<AnyCredential>> valueProperty = new SimpleObjectProperty<>();

    private final ParameterHistoryModel parameterHistoryModel;
    private final CredentialSubject credentialSubject;

    public MultiCredentialArgumentChooser(ParameterHistoryModel parameterHistoryModel, CredentialSubject credentialSubject) {
        this.parameterHistoryModel = parameterHistoryModel;

        this.credentialSubject = credentialSubject;

        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MultiCredentialArgumentChooser.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();

            assert listView != null;

            listView.setCellFactory(StringConverterListCell.getListViewCellFactory(new StringConverter<AnyCredential>() {
                @Override
                public String toString(AnyCredential credential) {
                    return credential.getName();
                }

                @Override
                public AnyCredential fromString(String string) {
                    throw new RuntimeException("not supported and not supposed to be used");
                }
            }));

            addButton.managedProperty().bind(addButton.visibleProperty());
            editButton.managedProperty().bind(editButton.visibleProperty());
            viewButton.managedProperty().bind(viewButton.visibleProperty());

            listView.getSelectionModel().selectedItemProperty().addListener((observableValue, oldSelected, newSelected) -> {
                if (newSelected != null) {
                    editButton.setVisible(true);
                    viewButton.setVisible(true);
                } else {
                    editButton.setVisible(false);
                    viewButton.setVisible(false);
                }
            });

            listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

            switch (credentialSubject) {
                case USER: {
                    listView.setItems(parameterHistoryModel.getUserCredentialsList());
                    break;
                }
                case SLICE: {
                    listView.setItems(parameterHistoryModel.getSliceCredentialsList());
                    break;
                }
                case ANY: {
                    listView.setItems(parameterHistoryModel.getAnyCredentialsList());
                    break;
                }
            }

            if (!listView.getItems().isEmpty()) {
                listView.getSelectionModel().selectLast();
            }

            final ObservableList<AnyCredential> selectedItems = listView.getSelectionModel().getSelectedItems();
            selectedItems.addListener((ListChangeListener<AnyCredential>) change -> valueProperty.set(new ArrayList<>(selectedItems)));
            //init
            valueProperty.set(new ArrayList<>(selectedItems));
            value = valueProperty;
            assert value != null;
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @FXML
    public void add() {
        ObservableList<AnyCredential> creds = null;
        switch (credentialSubject) {
            case USER: {
                creds = parameterHistoryModel.getUserCredentialsList();
                break;
            }
            case SLICE: {
                creds = parameterHistoryModel.getSliceCredentialsList();
                break;
            }
            case ANY: {
                creds = parameterHistoryModel.getUncategorizedCredentialsList();
                break;
            }
        }

        AnyCredential newCredentialInfo = CredentialEditDialog.showAddDialog();
        if (newCredentialInfo != null)
            creds.add(newCredentialInfo);
    }

    @FXML
    public void edit() {
        AnyCredential selected = listView.getSelectionModel().selectedItemProperty().get();

        if (selected == null)
            return;

        AnyCredential editedCredentialInfo = CredentialEditDialog.showDialog(false, selected);
        if (editedCredentialInfo != null) {
            ObservableList<AnyCredential> creds = null;
            switch (credentialSubject) {
                case USER: {
                    creds = parameterHistoryModel.getUserCredentialsList();
                    break;
                }
                case SLICE: {
                    creds = parameterHistoryModel.getSliceCredentialsList();
                    break;
                }
                case ANY: {
                    creds = parameterHistoryModel.getUncategorizedCredentialsList();
                    break;
                }
            }

            creds.remove(selected);
            creds.add(editedCredentialInfo);
        }
    }

    @FXML
    public void view() {
        AnyCredential selected = listView.getSelectionModel().selectedItemProperty().get();
        if (selected != null)
            CredentialViewDialog.showDialog(selected);
    }
}
