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

import be.iminds.ilabt.jfed.util.IOUtils;
import be.iminds.ilabt.jfed.util.JSonHelper;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.stage.FileChooser;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * StringArgumentChooser
 */
public class MapArgumentChooser extends CommandArgumentChooser<Map> implements Initializable {
    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(MapArgumentChooser.class);

    @FXML
    private TextArea textField;
    @FXML
    private Label errorLabel;
    @FXML
    private Button loadFromFileButton;

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

    public MapArgumentChooser(Map defaultValue, boolean showLoadFromFileButton) {
        this(defaultValue == null ? null : JSonHelper.jsonObjectToString(defaultValue), showLoadFromFileButton);
    }
    public MapArgumentChooser(String defaultValue, boolean showLoadFromFileButton) {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MapArgumentChooser.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
            if (defaultValue != null && !defaultValue.trim().isEmpty())
                textField.setText(defaultValue);
            else
                textField.setText("{  \n  \n}");

            loadFromFileButton.setVisible(showLoadFromFileButton);

            textField.textProperty().addListener((observable, oldValue, newValue) -> update(newValue));
            textField.focusedProperty().addListener((observable, oldValue, newValue) -> update(textField.getText()));

            errorLabel.managedProperty().bind(errorLabel.visibleProperty());
            errorLabel.setVisible(false);
            errorLabel.setText("ERROR: not a valid JSON struct");
            errorLabel.setStyle("-fx-text-fill: red;");
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    public void update(String stringValue) {
        Object newO;
        try {
            newO = JSonHelper.jsonStringToXmlRpcLikeObject(stringValue);
        } catch (Exception e) {
            newO = null;
        }
        if (newO == null || !(newO instanceof Map)) {
            textField.setStyle("-fx-text-fill: red;");
            errorLabel.setVisible(true);

            valueProperty.setValue(null);
        } else {
            Map newHt = (Map) newO;
            textField.setStyle("-fx-text-fill: black;");
            errorLabel.setVisible(false);

            valueProperty.setValue(newHt);
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        value = valueProperty;

        update(textField.getText());
    }

    public void loadFile() {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Load JSON from file");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JSON Files", "*.json"));
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("All Files", "*.*"));
        File file = fileChooser.showOpenDialog(textField.getScene().getWindow());
        if (file != null) {
            final String content;
            try {
                content = IOUtils.fileToString(file);
                Platform.runLater(() -> textField.setText(content));
            } catch (IOException e) {
                LOG.error("Failed to open file: " + file.getPath(), e);
            }
        }
    }
}
