/* ----------------------------------------
 * Origin  : GFI INFORMATIQUE 
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 01/05/2015 : SCA : V2.1
 * Version : 25/11/2022 : LBE : V2.6
 * DM-ID : Redmine#7316 : new AMDA parameters
 * VERSION : 01/10/2024: KKH
 * DM-ID : redmine#10965 : 01/10/2024 : CDPP interface behavior : Check and update startDate
 * VERSION : V2.12
 * DM-ID : redmine#10953: 17/03/2025 : KHK : Reset values when calling CDPP webservice
 * ----------------------------------------
 */
package fr.tlse.irap.pt.client.controller.tools.externalLinks;

import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;

import eu.schudt.javafx.controls.calendar.DatePicker;
import fr.tlse.irap.pt.client.component.DialogComponent;
import fr.tlse.irap.pt.client.component.IDialogComponent;
import fr.tlse.irap.pt.client.controller.common.FilterKeyEvent;
import fr.tlse.irap.pt.client.controller.common.Formatter;
import fr.tlse.irap.pt.client.controller.common.Item;
import fr.tlse.irap.pt.client.controller.common.MapMenu;
import fr.tlse.irap.pt.client.controller.dialogbox.DialogBox;
import fr.tlse.irap.pt.client.controller.tools.externalLinks.AmdaModel.Observer;
import fr.tlse.irap.pt.client.controller.tools.externalLinks.AmdaModel.PlotParam;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.MenuButton;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AmdaComponent extends AnchorPane implements Initializable, IDialogComponent, IAmda {

    private static final Logger log = LoggerFactory.getLogger(AmdaComponent.class);
   
    private DialogComponent dialog;

    @FXML
    protected GridPane gridPane;
    @FXML
    protected GridPane startTimeGridPane;
    @FXML
    protected final DatePicker datePicker = new DatePicker("startTime");
    @FXML
    private TextField timeInterval;
    @FXML
    private ChoiceBox<String> unitTimeInt;
    @FXML
    private MenuButton chooseMenuBtn;
    @FXML
    private TextField observer;
    @FXML
    private TextField parameters;
    @FXML
    private Button okBtn;
    @FXML
    private Button startTimeBtn;
    @FXML
    private Button endTimeBtn;

    private MapMenu amdaMenu;
    private Date startDate;
    private Date endDate;
    private boolean plotIsFound;
    private String obsId;

    @Override
    public void initialize(URL location, ResourceBundle resources) {      
        // init date picker
        datePicker.selectedDateProperty().set(new Date());
        addDatePicker();
        
        // init combo boxes
        ExternalLinks.initUnitTime(unitTimeInt);

        timeInterval.addEventFilter(KeyEvent.ANY, new FilterKeyEvent(
                timeInterval, 4, 1, 9999, Formatter.getFormatter(), new SimpleBooleanProperty(), timeInterval.focusedProperty()));

        // init context menu
        amdaMenu = new MapMenu();
        List<Item> menus = new ArrayList<Item>();
        for (Observer obs : Observer.values()) {
            menus.add(AmdaItemBuilder.getObserverItem(obs, amdaMenu.getMap(), this));
        }
        amdaMenu.addAll(menus);

        // Init button state
        okBtn.setDisable(true);

        chooseMenuBtn.getItems().clear();
        chooseMenuBtn.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                event.consume();
                if (event.getButton() == MouseButton.PRIMARY) {
                    amdaMenu.show(chooseMenuBtn, event.getScreenX(), event.getScreenY());
                    event.consume();
                }
                if (event.getButton() == MouseButton.SECONDARY) {
                    amdaMenu.hide();
                    event.consume();
                }
            }
        });
        observer.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                event.consume();
                if (event.getButton() == MouseButton.PRIMARY) {
                    amdaMenu.show(chooseMenuBtn, event.getScreenX(), event.getScreenY());
                    event.consume();
                }
                if (event.getButton() == MouseButton.SECONDARY) {
                    amdaMenu.hide();
                    event.consume();
                }
            }
        });

        startTimeBtn.setOnMouseClicked(new EventHandler<Event>() {
            @Override
            public void handle(Event event) {
                datePicker.selectedDateProperty().set(startDate);
            }
        });
        endTimeBtn.setOnMouseClicked(new EventHandler<Event>() {
            @Override
            public void handle(Event event) {
                datePicker.selectedDateProperty().set(endDate);
            }
        });
    }

    @FXML
    public void onClickOK() {
        
        // 10965 - CDPP interface behavior 
        // Check and update startDate before send request to AMDA
        datePicker.checkAndUpdateDate(true);                
        callAmda();
    }

    public void initComponentWith(Date startDate, Date endDate) {       
        this.startDate = startDate;
        this.endDate = endDate;
        initComponent();
        dialog.show();
    }

    private void initComponent() {
        // set default values
        unitTimeInt.setValue(unitTimeInt.getItems().get(2));
        // init start date
        datePicker.selectedDateProperty().set(startDate);
        
        // 10953 - Reset values when calling CDPP webservice
        observer.setText("");
        parameters.setText("");
        okBtn.setDisable(true);  
    }

    @Override
    public void runChoose(Observer obs, PlotParam params) {
        this.obsId = obs.getId();

        if (PlotParam.PP_ST_EP.equals(params)) {
            this.obsId += "-EP";
        }
        if (PlotParam.PP_SO_MAG.equals(params)) {
            this.obsId += "_MAG";
        }
//                if(PlotParam.PP_JUNO_JUPITER_ORBIT.equals(params)) {
//                    this.obsId+="_JUPITER_ORBIT";
//                }
        observer.setText(obs.getName());
        parameters.setText(params.getShortList());
        okBtn.setDisable(false);
    }

    public void setDialog(DialogComponent dialog) {
        this.dialog = dialog;
    }

    public DialogComponent getDialog() {
        return dialog;
    }

    protected void addDatePicker() {
        ExternalLinks.setStyleDate(datePicker);
        startTimeGridPane.add(datePicker, 0, 0);
    }

    private void callAmda() {       
        final Task<Object> callAmdaWorker = callAmdaWorker();

        callAmdaWorker.stateProperty().addListener(
                new ChangeListener<Worker.State>() {
            @Override
            public void changed(
                    ObservableValue<? extends Worker.State> observableValue,
                    Worker.State oldState, Worker.State newState) {

                if (newState == Worker.State.SUCCEEDED) {
                    //System.out.println("Calling AMDA interface succesfully ended");
                    // thread is done with success
                    endCursor();
                    if (!plotIsFound) {
                        DialogBox.warn("No data found");
                    }

                } else if (newState == Worker.State.FAILED || newState == Worker.State.CANCELLED) {
                    // thread is failed or cancelled
                    endCursor();
                    if (callAmdaWorker.getException() != null) {
                        DialogBox.error(" Error while calling AMDA interface.\n" + callAmdaWorker.getException().getMessage());
                    } else {
                        DialogBox.error(" Error while calling AMDA interface.\n ");
                    }
                }
            }

        });
        plotIsFound = false;
        new Thread(callAmdaWorker).start();
        waitCursor();
    }

    private Task<Object> callAmdaWorker() {
        return new Task<Object>() {
            @Override
            protected Object call() throws Exception {
                String lObsId = obsId;
                if(lObsId.equals(Observer.JUNO.getId())) {
                    GregorianCalendar lDataSplitDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
                    lDataSplitDate.set(2016,5,30);
                    //System.out.println("**** "+lDataSplitDate.getTime()+" "+datePicker.selectedDateProperty().get());
                    if(datePicker.selectedDateProperty().get().before(lDataSplitDate.getTime())) {
                        lObsId+="_CRUISE";
                    }else {
                        lObsId+="_JUPITER_ORBIT";
                    }
                }
                plotIsFound = ExternalLinks.callAmda(datePicker.selectedDateProperty().get(), getInterval(), lObsId, parameters.getText());
                return true;
            }
        };
    }

    /**
     * get interval in seconds
     *
     * @return
     */
    private long getInterval() {
        long ti = Formatter.toDouble(timeInterval.getText()).longValue();
        return ExternalLinks.computeTimeInSeconds(ti, unitTimeInt.getValue());
    }

    private void waitCursor() {
        this.setDisable(true);
        this.getScene().setCursor(Cursor.WAIT);
    }

    private void endCursor() {
        this.setDisable(false);
        this.getScene().setCursor(null);
    }

}
