// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.plugins.visualization.corebasics.animator;

import graphtea.graph.graph.*;
import graphtea.platform.core.BlackBoard;
import graphtea.platform.core.exception.ExceptionHandler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author Rouzbeh Ebrahimi  Ebrahimi ruzbehus@yahoo.com
 */
public class GeneralAnimator implements Runnable {

    public HashMap<Vertex, GPoint> vertexDestinations = new HashMap<>();
    public HashMap<Edge, List<GPoint>> edgeBendPoints = new HashMap<>();
    public boolean supportBendedEdge;

    GraphModel g;
    AbstractGraphRenderer gv;
    public Thread animate;
    private final BlackBoard blackboard;

    public GeneralAnimator(HashMap<Vertex, GPoint> vertexDestinations, GraphModel g, BlackBoard blackboard) {
        this.vertexDestinations = vertexDestinations;
        this.g = g;
        this.blackboard = blackboard;
    }

    public GeneralAnimator(HashMap<Vertex, GPoint> vertexDestinations, HashMap<Edge, List<GPoint>> edgeBendPoints, GraphModel g, BlackBoard blackboard) {
        this.vertexDestinations = vertexDestinations;
        this.edgeBendPoints = edgeBendPoints;
        this.g = g;
        supportBendedEdge = true;
        this.blackboard = blackboard;
    }

    public void start() {
        if (animate == null) {
            if (supportBendedEdge)
                animate = new Thread(new GeneralAnimator(vertexDestinations, edgeBendPoints, g, blackboard));
            else
                animate = new Thread(new GeneralAnimator(vertexDestinations, g, blackboard));

            animate.start();
        }
    }

    public void run() {
        final Thread current = Thread.currentThread();
        final List<GPoint> movements = new ArrayList<>();
        final List<GPoint> initials = new ArrayList<>();
        for (Vertex vertex : vertexDestinations.keySet()) {
            double initalX = vertex.getLocation().getX();
            GPoint GPoint = vertexDestinations.get(vertex);
            double totalXMovement = (GPoint.getX() - initalX);
            double initialY = vertex.getLocation().getY();
            double totalYMovement = (GPoint.getY() - initialY);
            initials.add(new GPoint(initalX, initialY));
            movements.add(new GPoint(totalXMovement, totalYMovement));
        }

        final int k = 21;
        for (int j = 1; j != k; j++) {
            AbstractGraphRenderer ren = blackboard.getData(AbstractGraphRenderer.EVENT_KEY);
            final int j1 = j;
            ren.ignoreRepaints(() -> doAnimateStep(movements, initials, j1, k, current));
        }
        if (supportBendedEdge) {
            paintEdges();
        }
    }

    private void doAnimateStep(List<GPoint> movements, List<GPoint> initials, int j, int k, Thread current) {
        int idx = 0;
        for (Vertex vertex : vertexDestinations.keySet()) {
            GPoint movement = movements.get(idx);
            GPoint initial = initials.get(idx);
            idx++;
            //                vertex.setLabel(initial.getY()+"");
            vertex.setLocation(new GPoint(initial.getX() + j * movement.getX() / k, initial.getY() + j * movement.getY() / k));

        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            ExceptionHandler.catchException(e);
        }
        while (animate == current) {
            //todo
            //                g.view.repaint();
        }
    }

    public void paintEdges() {
        for (Edge e : g.getEdges()) {
//            e.view.ssetBendedEdge(true);
//            e.view.setBendPoints(edgeBendPoints.get(e));
        }
//todo        g.repaint();
    }
}
