/* ----------------------------------------
 * Origin  : GFI INFORMATIQUE 
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 01/05/2015 : SCA : V2.1
 * VERSION : V2.12
 * DM-ID : redmine#11799 : 15/04/2025 : KHK : PFSS mode – Br Factor
 * ----------------------------------------
 */
package fr.tlse.irap.pt.client.controller.tools;

import java.util.Date;

import fr.tlse.irap.pt.client.component.CustomComponent;
import fr.tlse.irap.pt.client.component.ICustomComponent;
import fr.tlse.irap.pt.client.controller.dialogbox.DialogBox;
import fr.tlse.irap.pt.client.controller.eclipticPlane.EclipticPlaneController;
import fr.tlse.irap.pt.client.controller.timestamp.TimestampController;
import fr.tlse.irap.pt.client.controller.tools.externalLinks.AmdaDialogBox;
import fr.tlse.irap.pt.client.controller.tools.externalLinks.ApisDialogBox;
import fr.tlse.irap.pt.client.controller.tools.externalLinks.MedocDialogBox;
import fr.tlse.irap.pt.client.controller.tools.samp.JSampController;
import fr.tlse.irap.pt.client.controller.tools.sep.SepDashboardController;
import fr.tlse.irap.pt.client.controller.tools.timetable.TimeTableSepController;
import fr.tlse.irap.spaceElement.SpaceElement;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SepController extends GridPane implements ICustomComponent, IToolController{

    
        protected static final Logger log = LoggerFactory.getLogger(SepController.class);

	private BooleanProperty hasChanged = new SimpleBooleanProperty();
	private ObjectProperty<JMapTool> jMapTool = new SimpleObjectProperty<JMapTool>();

	@FXML protected SepController rootSep;
    @FXML public SepDashboardController sepDashboardComponent;
    @FXML protected TimeTableSepController timeTableComponent;
    @FXML protected Tab timetableTab;
    @FXML protected Button amdaBtn;
    @FXML protected Button medocBtn;
    @FXML protected Button apisBtn;
    @FXML protected Button sampBtn;

    private boolean isInitialized;
    
	public SepController() {
		super();
		CustomComponent.initCustomComponent(this);
		
        // listen for Sep Start changed
		sepDashboardComponent.getHasChanged().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (newValue) {
					// refresh timetable
                	timeTableComponent.updateView(sepDashboardComponent.sep);
			    	if (timetableTab.isSelected()) {
			    		timeTableComponent.updateView();
			    	}
                	// notify change
                	getHasChanged().set(true);
                }
            }
        });
        
    	// listen for sep End change
		this.getHasChanged().addListener(new ChangeListener<Boolean>() {
			@Override
			public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
				if (newValue) {
                	// compute propagation
					computeSep();
				}
			}
		});

	}

	@Override
	public void initComponentWith(EclipticPlaneController eclipticPlaneComponent, TimestampController timestampComponent) {
		if (isInitialized) {
			// refresh ecliptic from sep model
			sepDashboardComponent.updateEcliptic();
		}
		else {
			// first init
			isInitialized = true;
	        // Init dynamic part of components
			sepDashboardComponent.initComponentWith(eclipticPlaneComponent, timestampComponent);
			// Listen for end source change
			sepDashboardComponent.sepStartEndController.getEndSource().addListener(new ChangeListener<SpaceElement>() {
				@Override
				public void changed(ObservableValue<? extends SpaceElement> observable, SpaceElement oldValue, SpaceElement newValue) {
					if (newValue == null || (oldValue != null && oldValue.getName().equals(newValue.getName()))) {
						return;
					}
					if (sepDashboardComponent.sepStartEndController.isEndVisible()) {
						sepDashboardComponent.sep.setEndElement(newValue);
					}
					else {
						sepDashboardComponent.sep.setEndElement(null);
					}
					// notify for computation
					getHasChanged().set(true);
				}
			});
		}
	}

	/**
	 * Thread dedicated to Compute Sep process
	 */
	private void computeSep() {
		final Task<Object> computeSepWorker = computeSepWorker();

		computeSepWorker.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) {
							sepDashboardComponent.endCursor();
							// update all components from sep model
							sepDashboardComponent.updateView();
							sepDashboardComponent.updateEcliptic();
							
                                                        
                                                    //11799  - calling several time : remove it
                                                    log.debug("Listen for SEP Propagation End change : check pfss mode.");
                                                    sepDashboardComponent.updatingWithBrFactor();
                                                        
		                	getHasChanged().set(false);
							
						} else if (newState == Worker.State.FAILED || newState == Worker.State.CANCELLED) {
							// thread is failed or cancelled
		                	getHasChanged().set(false);
		                	sepDashboardComponent.endCursor();
		                	String target = sepDashboardComponent.sepStartEndController.getEndSource().get().getName();
							sepDashboardComponent.sepStartEndController.resetEndSource();
							DialogBox.warn("Position of " + target + " at start time has not be found.\nDefault End has been reset");
							computeSepWorker.getException().printStackTrace();
						}
					}

				});

		new Thread(computeSepWorker).start();
		sepDashboardComponent.waitCursor();
	}

	private Task<Object> computeSepWorker() {
		return new Task<Object>() {
			@Override
			protected Object call() throws Exception {
				return sepDashboardComponent.computeSep();
			}
		};
	}

	/**
	 *  Buttons Action
	 */
	
    @FXML 
    void amdaBtnAction(ActionEvent event) {
    	Date tStart = sepDashboardComponent.sep.getStartTime().getTime();
    	Date tEnd = sepDashboardComponent.sepEnd.getEndTime().getTime();
		AmdaDialogBox.show(tStart, tEnd);
    }

    @FXML 
    void medocBtnAction(ActionEvent event) {
    	Date tStart = sepDashboardComponent.sep.getStartTime().getTime();
    	Date tEnd = sepDashboardComponent.sepEnd.getEndTime().getTime();
		MedocDialogBox.show(tStart, tEnd);
    }

    @FXML 
    void apisBtnAction(ActionEvent event) {
    	SpaceElement endSource = sepDashboardComponent.sepEnd.getEndSource();
    	Date tEnd = sepDashboardComponent.sepEnd.getEndTime().getTime();
		ApisDialogBox.show(endSource.getName(), tEnd);
    }

    @FXML 
    void sampBtnAction(ActionEvent event) {
    	JSampController.getJSampFrame().setVisible(true);
    }

    @FXML 
    void timetableTabChange(Event event) {
    	if (timetableTab.isSelected()) {
    		timeTableComponent.updateView();
    	}
    }

	public BooleanProperty getHasChanged() {
		return hasChanged;
	}

	public void setHasChanged(BooleanProperty hasChanged) {
		this.hasChanged = hasChanged;
	}

	@Override
	public ObjectProperty<JMapTool> getJMapTool() {
		return jMapTool;
	}

	@Override
	public void setJMapTool(JMapTool jMapTool) {
		this.jMapTool.set(jMapTool);
	}

}
