/* ----------------------------------------
 * Origin  : GFI INFORMATIQUE 
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 01/05/2015 : SCA : V2.1
 * Version : 24/03/2016 : SCA : V2.2 (PSWS-H2020)
 * Add comets
 * Version : 12/09/2023 : LBE : V2.8
 * DM-ID : Redmine#10500 : 12/09/2023 : new END points
 * Version : 05/08/2024 : LBE : V2.11
 * DM-ID : Redmine#l0763 : 05/08/2024 : PFSS grid lines
 * VERSION : V2.12
 * DM-ID : redmine#11799 : 08/04/2025 : KHK : PFSS mode – Br Factor
 * Version : V2.13
 * DM-ID : redmine#12279 : 10/09/2025 : LBE : Add field lines in 3d panel
 * ----------------------------------------
 */
package fr.tlse.irap.pt.client.controller.tools.corotation;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.tlse.irap.pt.client.component.CustomComponent;
import fr.tlse.irap.pt.client.component.ICustomComponent;
import fr.tlse.irap.pt.client.controller.common.Formatter;
import fr.tlse.irap.pt.client.controller.common.SpaceElementCollection;
import fr.tlse.irap.pt.client.controller.dialogbox.DialogBox;
import fr.tlse.irap.pt.client.controller.drawingPlane.DrawHelper.DrawingCmeType;
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.IToolController.JMapTool;
import fr.tlse.irap.pt.client.controller.tools.IToolController.Tool;
import fr.tlse.irap.pt.client.controller.tools.carrington.CarringtonDashboardController;
import fr.tlse.irap.pt.client.controller.tools.plot.FluxPlotComponent;
import fr.tlse.irap.pt.client.controller.tools.plot.SpectroPlotComponent;
import fr.tlse.irap.pt.client.controller.tools.plot.VPlotComponent;
import fr.tlse.irap.fieldLine.FieldLine;
import fr.tlse.irap.fieldLine.FieldLineWrapper;
import fr.tlse.irap.fieldLine.FieldPoint;
import fr.tlse.irap.pos.Position;
import fr.tlse.irap.pos.PositionWrapper;
import fr.tlse.irap.pt.client.services.ServiceFactory;
import fr.tlse.irap.spaceElement.Comet;
import fr.tlse.irap.spaceElement.Planet;
import fr.tlse.irap.spaceElement.Probe;
import fr.tlse.irap.spaceElement.SpaceElement;
import fr.tlse.irap.spaceElement.SpaceElementWrapper;
import fr.tlse.irap.spaceElement.Sun;
import fr.tlse.irap.tool.corotation.Corotation;
import fr.tlse.irap.tool.corotation.CorotationEnd;
import fr.tlse.irap.utils.CoordConverter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
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.fxml.FXML;
import javafx.scene.Cursor;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.GridPane;

public class CorotationDashboardController extends GridPane implements ICustomComponent {

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

    private BooleanProperty hasChanged = new SimpleBooleanProperty();
    private ObjectProperty<Date> startDate;

    public Corotation corotation = new Corotation();
    public CorotationEnd corotationEnd = new CorotationEnd();

    @FXML
    protected CorotationDashboardController rootCorotationDashboard;
    @FXML
    protected CarringtonDashboardController carringtonDashboard;
    @FXML
    protected VPlotComponent vPlotComponent;
    @FXML
    protected FluxPlotComponent fluxPlotComponent;
    @FXML
    protected SpectroPlotComponent spectroPlotComponent;
    @FXML
    public CorotationStartEndController corotationStartEndController;

    protected EclipticPlaneController eclipticPlaneController;
    protected TimestampController timestampController;

    private int NB_STEP = 100;
    /*Current date - cursor date */
    private Date resultDate = new Date();
    
    //11799  Get Br factor in PFSS mode (checkbox) and Start = SUN 
    //private double brFactor = Double.NaN;
    private double brFactor = 2; // 2 by default

    public CorotationDashboardController() {
        super();
        CustomComponent.initCustomComponent(this);

        // Change start field listener
        corotationStartEndController.getHasChanged().addListener(
                new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (newValue) {                   
                    // update Radial model with start fields model
                    corotationStartEndController.getStartModel().update(corotation);
                    // update carrington view
                    updateCarringtonFromCorotation();
                    // notify this change
                    notifyChanged();                    
                }
            }

        });

        // Change Carrington CME listener
        carringtonDashboard.getHasChanged().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    // update Carrington CME 
                    carringtonDashboard.updateCME();

                    if (carringtonDashboard.isValidCME()) {
                        // update Corotation Model
                        updateCorotationFromCarrington();
                        // update carrington view 
                        carringtonDashboard.updateView(corotation, corotationEnd);
                        // update start fields
                        updateStartView();

                    }
                }
            }
        });

        // Change Carrington Fieldlines listener
        carringtonDashboard.getHasFieldLinesChanged().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    log.debug("***CorotDashboardCtrl: CarringtonDashBoard Field lines changed");
                    eclipticPlaneController.updateFieldLinesWith(carringtonDashboard.getFieldLines(),
                            corotation.getSunAttitudeT());               
                    //11799
                    carringtonDashboard.setCorotationDashboardController(rootCorotationDashboard);              
                }
            }
        });
        
        // Change Carrington GridFieldlines listener
        carringtonDashboard.getHasGridFieldLinesChanged().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    log.debug("***CorotDashboardCtrl: CarringtonDashBoard Field lines changed");
                    eclipticPlaneController.updateGridFieldLinesWith(
                            carringtonDashboard.getGridFieldLines().getFieldLines(),
                            carringtonDashboard.getGridFieldLines().getFlTimes()
                    );
                }
            }
        });

        // Change VPlot listener
        vPlotComponent.getHasChanged().addListener(
                new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    if (vPlotComponent.getVPlotModel().isValid()) {
                        // update Corotation Model from Vplot
                        corotation.setSpeedSolarWind(vPlotComponent.getVPlotModel().getSpeed());
                        // update start date 
                        startDate.set(vPlotComponent.getVPlotModel().getDate());
                    } else {
                        if (corotation.isInSitu()) {
                            corotation.setSpeedSolarWind(Corotation.DEFAULT_SPEED);
                        }
                    }
                    //log.debug("Init Corotation Start");
                    initCorotationStart();
                }
            }
        });
        // Change SpectroPlot listener
        spectroPlotComponent.getHasChanged().addListener(
                new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    if (spectroPlotComponent.getSpectroPlotModel().isValid()) {
                        // update start date 
                        startDate.set(spectroPlotComponent.getSpectroPlotModel().getDate());
                    }
                    initCorotationStart();
                }
            }
        });
    }

    /**
     * Dynamic component initialization
     */
    public void initComponentWith(EclipticPlaneController pEclipticPlaneController, TimestampController pTimestampController) {

        if (this.startDate == null) {

            this.timestampController = pTimestampController;
            this.eclipticPlaneController = pEclipticPlaneController;

            // Init dynamic part of components
            pTimestampController.initTimeScrollBar(0, NB_STEP);
            carringtonDashboard.initComponent(DrawingCmeType.SPIRAL);
            carringtonDashboard.setEndTime(corotationEnd.getEndTime().getTime());

            // bind start date properties
            bindStartDate();
            // bind start/end properties
            bindStartEndSource();
            // bind time slider properties
            timestampController.getResultTScrollBar().valueProperty().addListener(new ChangeListener<Number>() {
                @Override
                public void changed(ObservableValue<? extends Number> arg0, Number oldValue, Number newValue) {
                    updateResultTime(newValue.intValue());
                    carringtonDashboard.setCurrentTime(resultDate);
                    eclipticPlaneController.setCurrentTime(resultDate);
//            carringtonDashboard.setTime(resultDate);
//            carringtonDashboard.setEndTime(corotationEnd.getEndTime().getTime());
                }
            });

//        timestampController.getResultTScrollBar().maxProperty().addListener(new ChangeListener<Number>() {
//            @Override
//            public void changed(ObservableValue<? extends Number> arg0, Number oldValue, Number newValue) {
//                //TODO: Listen to end changes ?
//             }
//        });
        }
        //update field line on ecliptic with current carrington config
        eclipticPlaneController.updateFieldLinesWith(carringtonDashboard.getFieldLines(),
                corotation.getSunAttitudeT());       
    }

    /**
     * Bind start date Listen to start date changes
     */
    private void bindStartDate() {
        // bind Radial start time to startDate
        corotationStartEndController.getStartModel().getStartTime().bind(timestampController.getStartTimeProperty());
        // bind Radial current date to timestamp selected date
        this.startDate = timestampController.selectedDateProperty();
        if (startDate.get() != null) {
            // Send startDate to controller which need it
            carringtonDashboard.setStartDate(startDate);
            vPlotComponent.setStartDate(startDate);
            fluxPlotComponent.setStartDate(startDate);
            spectroPlotComponent.setStartDate(startDate);          
        }
    }

    /**
     * Bind start/end source Listen to start source changes
     */
    private void bindStartEndSource() {
        // Set startSource to controller which need it
        vPlotComponent.setStartSource(corotationStartEndController.getStartModel().getStartSource());
        spectroPlotComponent.setStartSource(corotationStartEndController.getStartModel().getStartSource());
        // Set endSource to controller which need it
        carringtonDashboard.setEndSource(corotationStartEndController.getEndSource(), corotationStartEndController.getEndVisible());
        // init start/end source menu
        corotationStartEndController.loadMenu();
        // Listen for space elements list change
        SpaceElementCollection.getHasChanged().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (!newValue) {
                    // init start/end source menu
                    corotationStartEndController.loadMenu();
                    // notify change for refreshing timetable
                    notifyChanged();
                }
            }
        });
        // Listen for start source change
        corotationStartEndController.getStartModel().getStartSource().addListener(new ChangeListener<SpaceElement>() {
            @Override
            public void changed(ObservableValue<? extends SpaceElement> observable, SpaceElement oldValue, SpaceElement newValue) {
                corotation.setStartElement(newValue);
            }
        });
        // first init
        corotation.setStartElement(new Sun());
    }

    /**
     * Configure views according to JMap Tool
     *
     * @param jMapTool
     */
    public void setJMapTool(JMapTool jMapTool) {
        corotationStartEndController.setJMapTool(jMapTool);
        carringtonDashboard.setJMapTool(jMapTool);
    }

    /**
     * Initialize Corotation Start fields (set default values and compute HAE
     * central axis)
     */
    public void initCorotationStart() {
        final Task<Object> initCorotationStartWorker = initCorotationStartWorker();

        initCorotationStartWorker.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) {
                    // thread is done with success
                    endCursor();
                    // update carrington view
                    carringtonDashboard.updateView(corotation, corotationEnd);
                    // update start fields
                    updateStartView();
                    // Reset default In Situ mode 
                    corotation.setInSitu(true);

                } else if (newState == Worker.State.FAILED || newState == Worker.State.CANCELLED) {
                    // thread is failed or cancelled
                    endCursor();
                    String source = corotationStartEndController.getStartModel().getStartSource().get().getName();
                    corotationStartEndController.runStartPoint(new Sun());
                    DialogBox.warn("Position of " + source + " at start time has not be found.\nDefault start has been reset to SUN");
                    initCorotationStartWorker.getException().printStackTrace();
                }
            }

        });

        new Thread(initCorotationStartWorker).start();
        waitCursor();
    }

    private Task<Object> initCorotationStartWorker() {
        return new Task<Object>() {
            @Override
            protected Object call() throws Exception {
                if (corotation.isInSitu()) {
                    // compute Radial start
                    corotationStartEndController.getStartModel().compute(corotation, startDate.get());
                } else {
                    // compute Carrington source from tStart and longStart
                    corotationStartEndController.getStartModel().computeSource(corotation, startDate.get());
                }

                return true;
            }
        };
    }

    /**
     * Compute Corotation end fields + impact
     *
     * @return
     * @throws Exception
     */
    public boolean computeCorotation() throws Exception {

        corotationEnd = corotationStartEndController.compute(corotation);        
        log.debug("CorotationDashboardController.computeCorotation() corotationEnd:"
                + corotationEnd.getEndSource().getName());           
        return true;
    }

    /**
     * Update start view and notify the current change
     */
    public void updateStartView() {
        corotationStartEndController.getStartModel().setUpViewWith(corotation);
        notifyChanged();
    }

    /**
     * Update view from end model Corotation
     */
    public void updateView() {
        if (corotation.getEndElement() != null) {
            corotationStartEndController.setUpViewWith(corotationEnd);
        } else {
            corotationStartEndController.clearView();
        }

    }

    /**
     * Update Ecliptic view and result time
     */
    public void updateEcliptic() {
        // update Ecliptic only from the active tool
        if (eclipticPlaneController.getTool() == Tool.COROTATION) {
            // set Start/End source
            eclipticPlaneController.setStartSource(corotation.getStartElement());
            //eclipticPlaneComponent.setEndSource(corotation.getEndElement());
            eclipticPlaneController.setEndSource(corotationEnd.getEndSource());
            // update result time 
            int step = (int) this.timestampController.getResultTScrollBar().valueProperty().get();
            updateResultTime(step);
            // update result date => ask ecliptic to be refreshed
            timestampController.updateResultDate();
            // enable slider
            timestampController.getResultTScrollBar().setDisable(false);
            eclipticPlaneController.updateFieldLinesWith(carringtonDashboard.getFieldLines(),
                    corotation.getSunAttitudeT());
            carringtonDashboard.setEndTime(corotationEnd.getEndTime().getTime());

        }
    }

    /**
     * Update result time from a step and redraw spiral with its new footpoint
     * longitude
     *
     * @param step
     */
    private void updateResultTime(int step) {       
        if (eclipticPlaneController.getTool() == Tool.COROTATION) {

            //log.debug("******************* Setting time from corrotationEnd " + corotationEnd.getEndTime().getTime());
           
            // update result time
            setResultTime(step);
            // update ecliptic
            double lStart = corotation.getLongSourceT();
            double lEnd = corotationEnd.getLongEndSource();
            double footpointLong = lStart + ((CoordConverter.normalizeLongitude(lEnd - lStart) / NB_STEP) * step);
                       
//            log.debug("*******************  updateResultTime() footpointLong" + footpointLong);
//            log.debug("*******************  updateResultTime() corotation.getRotationPeriod(): " + corotation.getRotationPeriod());
//            log.debug("*******************  updateResultTime() corotation.getSpeedSolarWind(): " + corotation.getSpeedSolarWind());
//            log.debug("*******************  updateResultTime()  corotation.getSpreadCIR(): " + corotation.getSpreadCIR());
           
            eclipticPlaneController.drawSpiral(
                    footpointLong,
                    corotation.getRotationPeriod(),
                    corotation.getSpeedSolarWind(),
                    corotation.getSpreadCIR());
//            carringtonDashboard.setTime(resultDate);
//            carringtonDashboard.setEndTime(corotationEnd.getEndTime().getTime());
        }
    }

    /**
     *
     * @param step
     */
    private void setResultTime(int step) {
        resultDate.setTime(getResultTime(step));
        timestampController.setResultTime(resultDate);

    }

    /**
     * Get result time from step between start time and end time
     *
     * @param step
     * @return
     */
    private long getResultTime(int step) {
        long startTime = startDate.get().getTime();
        long endTime = corotationEnd.getEndTime().getTimeInMillis();
        //if end = Sun, end time before start, reverse time slider
        if (endTime < startTime) {
            step = NB_STEP - step;
        }
        long newTime = startTime + ((endTime - startTime) / NB_STEP) * step;
        return newTime;
    }

    /**
     * Update Corotation Model from Carrington CME
     */
    private void updateCorotationFromCarrington() {        
        Double longitude = carringtonDashboard.getLongSource();
        if (longitude != null) {
            corotation.setLongSource(longitude);
        }
        longitude = carringtonDashboard.getLongExtent();
        if (longitude != null) {
            //11799 brFactor                       
            // In PFSS mode 
            //      Extent = Spread * 2  / brFactor
            //      Spread = Extent * brFactor / 2
            // by default 
            //      Extent = Spread * 2
            //      Spread = Extent / 2
            
            corotation.setSpreadCIR(longitude /  brFactor);
            
            if (corotation.getSpreadCIR() > 0) {
                corotation.setSpeedError(0.0);
//				corotation.setTimeError(0.0);
            }
        }
        // compute HAE long start from Carrington source
        corotationStartEndController.getStartModel().computeFromSource(corotation);
    }

    /**
     * Update Carrington CME from Corotation Model
     */
    public void updateCarringtonFromCorotation() {       
        // compute Carrington source 
        corotationStartEndController.getStartModel().computeSource(corotation);    
        // update carrington view 
        carringtonDashboard.updateView(corotation, corotationEnd);
        log.debug("************************** end time:" + corotationEnd.getEndTime().getTime());
    }

    public BooleanProperty getHasChanged() {
        return hasChanged;
    }

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

    public void notifyChanged() {
        getHasChanged().set(true);
        getHasChanged().set(false);
    }

    public ObjectProperty<Date> getStartDate() {
        return startDate;
    }

    public void waitCursor() {
        corotationStartEndController.setDisable(true);
        carringtonDashboard.setDisable(true);
        vPlotComponent.setDisable(true);
        spectroPlotComponent.setDisable(true);
        rootCorotationDashboard.setCursor(Cursor.WAIT);
    }

    public void endCursor() {
        corotationStartEndController.setDisable(false);
        carringtonDashboard.setDisable(false);
        vPlotComponent.setDisable(false);
        spectroPlotComponent.setDisable(false);
        rootCorotationDashboard.setCursor(null);
    }
   


    
    //11799
    public void updatingWithBrFactor() {

        //11799 - Get Br factor in PFSS mode (checkbox) and Start = SUN 
        if ((corotationStartEndController.getStartModel().getStartSource().get().getId() == 10)) {

            if (carringtonDashboard.isPfssMode()) {
                log.debug("--- Corotation - PFSS mode ENABLE and Start = SUN ");
                brFactor = getBrFactor();
            } else {
                log.debug("--- Corotation - PFSS mode DISABLE and Start = SUN ");
                    brFactor = 2; 
            }
            //log.debug("---  Corotation -  brFactor:" + brFactor);

            carringtonDashboard.setBrFactorCorotation(brFactor);
            // Triggering on Spread field to  update spiral and Carrington  
            log.debug("Triggering on Spread field to update all application (finally calling CorotationController.computeCorotation()).");
            corotationStartEndController.getHasSpreadChanged().set(true);
            corotationStartEndController.getHasSpreadChanged().set(false);  

        }

    }
  
    
    public double getBrFactor() {

        double brFactorTmp = 0;
        ArrayList<PositionWrapper> lStartPts = new ArrayList<>();
        ArrayList<Date> lTimes = new ArrayList<>();
        // Rs : 696 340km
        double Rs = 696340;

        Date lDateRequest = startDate.get();
        log.debug("--- Corotation - BrFactor on date :" + lDateRequest);

        // By default END is set to Earth
        log.debug("--- START:" + corotationStartEndController.getStartModel().getStartSource().get().getName());
        // END : do not used corotationStartEndController.getEndSource(), his position is not set
        Position lEndPos = corotationEnd.getEndSource().getPosition();
        double lP[] = CoordConverter.toSpheric(lEndPos.getX(), lEndPos.getY(), lEndPos.getZ());
        log.debug("--- END :" + corotationEnd.getEndSource().getName() + " - Position=(" + lEndPos.getX() + "/" + lEndPos.getY() + "/" + lEndPos.getZ() );
        log.debug("--- Long=" + lP[0] + " Lat=" + lP[1] + " length=" + lEndPos.length()
                + "(" +lEndPos.length() / Rs + " Rs)");

        //get input points from selected objects
        SpaceElementWrapper lstStartPoints = new SpaceElementWrapper();
        if (corotationEnd.getEndSource() instanceof Probe) {
            lstStartPoints.getProbes().add((Probe) corotationEnd.getEndSource());
        } else if (corotationEnd.getEndSource() instanceof Planet) {
            lstStartPoints.getPlanets().add((Planet) corotationEnd.getEndSource());
        } else if (corotationEnd.getEndSource() instanceof Comet) {
            lstStartPoints.getComets().add((Comet) corotationEnd.getEndSource());
        } else {
            log.debug("--- Unkown element END:" + corotationEnd.getEndSource().getName());
        }

        // START : SUN
        SpaceElement lSunWithAtt = ServiceFactory.getPositionService().getPositionElement(
                corotationStartEndController.getStartModel().getStartSource().get(), startDate.get());
        FieldLineWrapper lFls = ServiceFactory.getFieldLineService().getPSPFSSFieldLine(
                lstStartPoints, startDate.get(), corotation.getSpeedSolarWind(), lSunWithAtt.getAttitude());

        List<FieldLine> fieldLines = lFls.getFieldLines();

        log.debug("Nb fieldLines returned:" + fieldLines.size());

        if (fieldLines.size() > 0) {

            // Data found
            // one date request, one line expected
            for (int i = 0; i < fieldLines.size(); i++) {
                FieldLine fieldLine = fieldLines.get(i);
                log.debug("Nb of points :" + fieldLine.getPoints().size());
//                for (int j = 0; j < fieldLine.getPoints().size(); j++) {
//                    FieldPoint fPoint = fieldLine.getPoints().get(j);
//
//                    System.out.println("---  point :" + j 
//                        + " - x,y,z :" + fPoint.getX()+ " , " + fPoint.getY()+ " , " + fPoint.getZ()+
//                        " - module (Km) :" + fPoint.length()+" - :" + fPoint.length()/Rs+" Rs");               
//                    System.out.println("---   point :" + j
//                            + " - Bx,By,Bz :" + fPoint.getBx() + " , " + fPoint.getBy() + " , " + fPoint.getBz() + " - Br :" + fPoint.Br());
//                }

                // get points at 1Rs and 2.5Rs                
                double Br1Rs, Br2_5Rs;

//                log.debug("--- Index PFSS = " + fieldLine.getPfssIdx());
//                log.debug("--- at Index PFSS Distance (Rs) = " + fieldLine.getPoints().get(fieldLine.getPfssIdx() + 1).length() / Rs);
//                log.debug("--- at surface Distance (Rs) = " + fieldLine.getPoints().get(fieldLine.getPoints().size() - 1).length() / Rs);
                // 2.5Rs : Index PFSS - Index in list of field points where parker points end and pfss starts.                
                if ((fieldLine.getPoints().get(fieldLine.getPfssIdx() + 1).length() / Rs)
                        < fieldLine.getPoints().get(fieldLine.getPoints().size() - 1).length() / Rs) {
                    // case 1 : Data is ordered from 1Rs to 2.5Rs
                    Br1Rs = fieldLine.getPoints().get(fieldLine.getPfssIdx() + 1).Br();
                    Br2_5Rs = fieldLine.getPoints().get(fieldLine.getPoints().size() - 1).Br();
                } else {
                    // case 2 : Data is ordered from 2.5Rs to 1Rs
                    Br1Rs = fieldLine.getPoints().get(fieldLine.getPoints().size() - 1).Br();
                    Br2_5Rs = fieldLine.getPoints().get(fieldLine.getPfssIdx() + 1).Br();
                }
                log.debug("--- Br1Rs = " + Br1Rs + " , Br2_5Rs = " + Br2_5Rs);

                // Br(r=1Rs) / (2.5*2.5 * Br(r=2.5Rs)))
                brFactorTmp = Br1Rs / (2.5 * 2.5 * Br2_5Rs);
                log.debug("--- BrFactor = Br1Rs / ((2.5 * 2.5) * Br2.5Rs) = " + brFactorTmp);

                // In Carrington dashboard, 
                // In PFSS mode 
                //      Extent = Spread * 2  / brFactor
                //      Spread = Extent * brFactor / 2
                // by default 
                //      Extent = Spread * 2
                //      Spread = Extent / 2
                brFactorTmp = 2 * (1 / brFactorTmp);
            }
        } else {
            // no cube found
            // Set Br factor to default value :2
            log.debug("--- No PFSS data found for this date:" + lDateRequest);
            log.debug("--- BrFactor = 2 ");
            DialogBox.warn("No PFSS data found for Corotation!");
            
            brFactorTmp = 2;
        }

        return brFactorTmp;
    }
    
    
//    public CheckBox getCbxPfssMode() {
//        return carringtonDashboard.getCbxPfssMode();
//    }
    
}
