/* ----------------------------------------
 * Origin  : Inetum
 * Project : CDPP Propagation Tool 
 * ----------------------------------------
 * History 
 * Version : 30/11/2022 : LBE : V2.6
 * DM-ID : Redmine #l0481 : 30/11/2022 : Creation
 * ----------------------------------------
 */
package fr.tlse.irap.pt.client.controller.tools.carrington;

import java.util.List;

import fr.tlse.irap.pt.client.controller.common.Position2D;
import fr.tlse.irap.fieldLine.Footpoint;
import fr.tlse.irap.map.HCSLine;
import java.util.ArrayList;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CarringtonHCS {

    protected static final Logger log = LoggerFactory.getLogger(CarringtonHCS.class);
    private Path hcs;
    private Group nodes = new Group();
    private BooleanProperty hasChanged = new SimpleBooleanProperty();
    private BooleanProperty visibilityChanged = new SimpleBooleanProperty(true);

    private boolean isValid = true;
    private HCSLine hcsLine;

    public CarringtonHCS() {
        hcs = createHcs();
        nodes.getChildren().add(hcs);

        // Listen for HCS property changed 
//        hasChanged.addListener(
//                new ChangeListener<Boolean>() {
//            @Override
//            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
//                log.debug("HCSLine has Changed " + isValid + " " + newValue);
//                if (newValue) {
//                    if (isValid) {
//                        drawHcs();
//                    } else {
//                        clearHcs();
//                    }
//                }
//            }
//
//        });
        // Listen for property visibility changed => swap visibility 
        visibilityChanged.addListener(
                new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observedBoolean, Boolean oldValue, Boolean newValue) {
                if (newValue) {
                    drawHcs();
                } else {
                    clearHcs();
                }
            }
        });

    }

    public void setColor(Color c) {
        ((Path) nodes.getChildren().get(0)).setFill(c);
        ((Path) nodes.getChildren().get(0)).setStroke(c);
    }

    public List<Position2D> getPositions(List<Footpoint> pFp) {
        List<Position2D> positions = new ArrayList<Position2D>();
        double x, y;

        if (pFp.size() > 0) {
            for (Footpoint fp : pFp) {
                x = CarringtonHelper.longToX((double) fp.getLon());
                y = CarringtonHelper.latToY((double) fp.getLat());
                positions.add(new Position2D(x, y));
            }
        }
        return positions;
    }

    protected void drawHcs() {
        //log.debug("***Drawing HCS");
        updateHcs(hcs, getPositions(hcsLine.getPoints()));
        hcs.setVisible(true);
    }

    protected void clearHcs() {
        hcs.getElements().clear();
        hcs.setVisible(false);
    }

    public void show() {
        hcs.setVisible(true);
    }

    public void hide() {
        hcs.setVisible(false);
    }

    public boolean isVisible() {
        return hcs.isVisible();
    }

    /**
     * Update current line and trigger hasChanged
     *
     * @param pLine
     */
    public void setLine(HCSLine pLine) {
        hcsLine = pLine;
        if (pLine != null && pLine.getPoints() != null) {
            drawHcs();
        } else {
            clearHcs();
        }
    }

    public void showHide() {
        visibilityChanged.set(!visibilityChanged.get());
    }

    public Group getNodes() {
        return nodes;
    }

    /**
     * Create the HCS
     */
    public static Path createHcs() {

        final Path lPath = new Path();
        //lPath.setFill(Color.RED);
        lPath.setStroke(Color.RED);
        lPath.setStrokeWidth(2);
        lPath.setStrokeLineCap(StrokeLineCap.ROUND);
        lPath.getStrokeDashArray().addAll(4d);
        lPath.setId("HCS");
        lPath.setVisible(false);
        return lPath;
    }

    /**
     * Update the HCS with a list of position
     */
    public static void updateHcs(Path pHcs, List<Position2D> positions) {
        MoveTo moveTo;
        LineTo lineTo;
        Position2D lastPos = null;

        pHcs.getElements().clear();

        for (Position2D pos : positions) {
            //if(pHcs.getElements().size()>1) {
            //if first position or gap between new point, jump without line
            if (lastPos == null
                    || Math.abs(lastPos.getX() - pos.getX()) > 10
                    || Math.abs(lastPos.getY() - pos.getY()) > 10) {
                moveTo = new MoveTo(pos.getX(), pos.getY());
                pHcs.getElements().add(moveTo);
            } else {
                //log.debug("Setting line to " + pos.getX() + " " + pos.getY());
                //moveTo = new MoveTo(pos.getX(), pos.getY());
                lineTo = new LineTo(pos.getX(), pos.getY());
                //moveTo = new MoveTo(pos.getX(), pos.getY());
                //
                pHcs.getElements().add(lineTo);
            }
            //pHcs.getElements().add(moveTo);
            //}
            lastPos = pos;
        }
    }
}
