/*******************************************************************************
 * Copyright (c) 2017 THALES GLOBAL SERVICES.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.sirius.diagram.ui.business.internal.migration;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.util.LabelViewConstants;
import org.eclipse.gmf.runtime.draw2d.ui.figures.BaseSlidableAnchor;
import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg;
import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities;
import org.eclipse.gmf.runtime.notation.Anchor;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.IdentityAnchor;
import org.eclipse.gmf.runtime.notation.Location;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.RelativeBendpoints;
import org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint;
import org.eclipse.sirius.business.api.migration.AbstractRepresentationsFileMigrationParticipant;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DiagramPlugin;
import org.eclipse.sirius.diagram.ui.business.api.query.DDiagramGraphicalQuery;
import org.eclipse.sirius.diagram.ui.business.api.query.NodeQuery;
import org.eclipse.sirius.diagram.ui.business.api.query.ViewQuery;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DEdgeBeginNameEditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DEdgeEndNameEditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DEdgeNameEditPart;
import org.eclipse.sirius.diagram.ui.part.SiriusVisualIDRegistry;
import org.eclipse.sirius.diagram.ui.provider.Messages;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.viewpoint.DAnalysis;
import org.eclipse.sirius.viewpoint.DView;
import org.osgi.framework.Version;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

/**
 * A representation file migration to detect labels that are far from their edge
 * and reset them to their default location.
 * 
 * @author lredor
 */
@SuppressWarnings("restriction")
public class SnapBackDistantLabelsMigrationParticipant extends AbstractRepresentationsFileMigrationParticipant {

    /**
     * The Sirius version for which this migration is added.
     */
    public static final Version MIGRATION_VERSION = new Version("10.1.9.201706271200"); //$NON-NLS-1$


    /**
     * The absolute maximum x or y coordinate from which label is considered
     * distant.
     */
    private static final int LABEL_UPPER_LIMIT = 1000;

    /**
     * The absolute minimal x or y coordinate from which label is not considered
     * distant.
     */
    private static final int LABEL_LOWER_LIMIT = 250;

    /**
     * The absolute maximum x or y coordinates from which node is considered
     * with "very huge coordinates".
     */
    private static final int NODES_LIMIT = 1000000;

    /**
     * Nodes with "very huge coordinates" are relocated to location near from
     * it. This value is arbitrary. It allows to "easily" see elements with a
     * zoom of 10%.
     */
    private static final int NODES_LIMIT_MOVE = 5000;

    private static final String NEGATIVE_X_KEY = "-x"; //$NON-NLS-1$

    private static final String POSITIVE_X_KEY = "+x"; //$NON-NLS-1$

    private static final String NEGATIVE_Y_KEY = "-y"; //$NON-NLS-1$

    private static final String POSITIVE_Y_KEY = "+y"; //$NON-NLS-1$

    /**
     * Determines a setter based on an input value and a new value.
     * 
     * @author lredor
     *
     */
    public interface Setter<F, T> {
        /**
         * Set a value of type <code>F</code> with the new value <code>T</code>.
         * 
         * @param input
         *            The object to modify
         * @param newValue
         *            The new value to set one property of <code>input</code>
         */
        void set(F input, T newValue);
    }
    
    @Override
    public Version getMigrationVersion() {
        return MIGRATION_VERSION;
    }

    @Override
    protected void postLoad(DAnalysis dAnalysis, Version loadedVersion) {
        if (loadedVersion.compareTo(MIGRATION_VERSION) < 0) {
            initializeSnapBackPositionMap();

            boolean isModified = false;
            StringBuilder sb = new StringBuilder(Messages.SnapBackDistantLabelsMigrationParticipant_title);
            List<Node> distantEdgeLabels = new ArrayList<Node>();

            for (DView dView : dAnalysis.getOwnedViews()) {
                for (DDiagram dDiagram : Iterables.filter(dView.getOwnedRepresentations(), DDiagram.class)) {
                    // Search distant edge labels
                    List<Node> currentDistantEdgeLabels = getDistantEdgeLabels(dDiagram);
                    distantEdgeLabels.addAll(currentDistantEdgeLabels);

                    if (currentDistantEdgeLabels.size() > 0) {
                        isModified = true;
                        // Add information to be logged
                        if (currentDistantEdgeLabels.size() > 1) {
                            sb.append(MessageFormat.format(Messages.SnapBackDistantLabelsMigrationParticipant_severalLabelsSnapBacked, currentDistantEdgeLabels.size(), dDiagram.getName()));
                        } else {
                            sb.append(MessageFormat.format(Messages.SnapBackDistantLabelsMigrationParticipant_oneLabelSnapBacked, dDiagram.getName()));
                        }

                        // Search and fix nodes with huge coordinates.
                        boolean nodesMoved = false;
                        Map<String, Map<Node, Integer>> currentnodesWithExtremeLocation = getNodesWithExtremeLocation(dDiagram);
                        for (String key : currentnodesWithExtremeLocation.keySet()) {
                            if (NEGATIVE_X_KEY.equals(key)) {
                                nodesMoved = moveNodesX(currentnodesWithExtremeLocation.get(key), false);
                            } else if (POSITIVE_X_KEY.equals(key)) {
                                nodesMoved = moveNodesX(currentnodesWithExtremeLocation.get(key), true);
                            } else if (NEGATIVE_Y_KEY.equals(key)) {
                                nodesMoved = moveNodesY(currentnodesWithExtremeLocation.get(key), false);
                            } else {
                                nodesMoved = moveNodesY(currentnodesWithExtremeLocation.get(key), true);
                            }
                        }

                        if (nodesMoved) {
                            // Add information to be logged
                            sb.append(Messages.SnapBackDistantLabelsMigrationParticipant_nodesMoved);
                        }
                    }
                }
            }

            // Fix distant edge labels
            for (Node distantEdgeLabel : distantEdgeLabels) {
                Point offset = LabelEditPart.getSnapBackPosition(distantEdgeLabel.getType());
                if (offset != null) {
                    ViewUtil.setStructuralFeatureValue(distantEdgeLabel, NotationPackage.eINSTANCE.getLocation_X(), Integer.valueOf(offset.x));
                    ViewUtil.setStructuralFeatureValue(distantEdgeLabel, NotationPackage.eINSTANCE.getLocation_Y(), Integer.valueOf(offset.y));
                }
            }

            if (isModified) {
                DiagramPlugin.getDefault().logInfo(sb.toString());
            }
        }
    }

    /**
     * Move all nodes to a more readable location.
     * 
     * @param nodesWithExtremeLocation
     *            List of couple, node with extreme location and corresponding
     *            huge coordinate.
     * @param isPositive
     *            true if the above list of nodes concerns nodes with positive
     *            X, false if it concerns negative X
     * @return true if at least one node has been moved, false otherwise
     */
    protected boolean moveNodesX(Map<Node, Integer> nodesWithExtremeLocation, boolean isPositive) {
        return moveNodes(nodesWithExtremeLocation, isPositive, new Setter<Location, Integer>() {
            @Override
            public void set(Location input, Integer newValue) {
                input.setX(newValue);
            }
        });
    }

    /**
     * Move all nodes to a more readable location.
     * 
     * @param nodesWithExtremeLocation
     *            List of couple, node with extreme location and corresponding
     *            huge coordinate.
     * @param isPositive
     *            true if the above list of nodes concerns nodes with positive
     *            X, false if it concerns negative X
     * @return true if at least one node has been moved, false otherwise
     */
    protected boolean moveNodesY(Map<Node, Integer> nodesWithExtremeLocation, boolean isPositive) {
        return moveNodes(nodesWithExtremeLocation, isPositive, new Setter<Location, Integer>() {
            @Override
            public void set(Location input, Integer newValue) {
                input.setY(newValue);
            }
        });
    }

    /**
     * Move all nodes to a more readable location.
     * 
     * @param nodesWithExtremeLocation
     *            List of couple, node with extreme location and corresponding
     *            location.
     * @param isPositive
     *            true if the above list of nodes concerns nodes with positive X
     *            or Y, false if it concerns negative X or Y
     * @param setter
     *            A setter to set new X or Y coordinate
     * @return true if at least one node has been moved, false otherwise
     */
    protected boolean moveNodes(Map<Node, Integer> nodesWithExtremeLocation, boolean isPositive, Setter<Location, Integer> setter) {
        boolean nodesMoved = false;
        int min = -NODES_LIMIT;
        int max = Integer.MIN_VALUE;
        if (isPositive) {
            min = Integer.MAX_VALUE;
            max = NODES_LIMIT;
        }
        // Get min and max values
        for (Integer coordinate : nodesWithExtremeLocation.values()) {
            nodesMoved = true;
            if (coordinate < min) {
                min = coordinate;
            }
            if (coordinate > max) {
                max = coordinate;
            }
        }
        // Get delta between min and max
        int delta = max - min;
        if (delta < NODES_LIMIT) {
            // Moves all nodes with the same delta
            for (Entry<Node, Integer> entry : nodesWithExtremeLocation.entrySet()) {
                if (isPositive) {
                    setter.set((Location) entry.getKey().getLayoutConstraint(), entry.getValue() - max - NODES_LIMIT_MOVE);
                } else {
                    setter.set((Location) entry.getKey().getLayoutConstraint(), entry.getValue() - min + NODES_LIMIT_MOVE);
                }
            }
        } else {
            // Move all nodes to the same location (-NODES_LIMIT)
            for (Entry<Node, Integer> entry : nodesWithExtremeLocation.entrySet()) {
                if (isPositive) {
                    setter.set((Location) entry.getKey().getLayoutConstraint(), -NODES_LIMIT_MOVE);
                } else {
                    setter.set((Location) entry.getKey().getLayoutConstraint(), NODES_LIMIT_MOVE);
                }
            }
        }
        return nodesMoved;
    }

    /**
     * Create dummy edge name edit part to initialize the
     * registerSnapBackPosition() method of each kind of edit part. Without this
     * initialization, when using
     * {@link LabelEditPart#getSnapBackPosition(String)}, the returned value is
     * null.
     */
    private void initializeSnapBackPositionMap() {
        new DEdgeNameEditPart(null);
        new DEdgeBeginNameEditPart(null);
        new DEdgeEndNameEditPart(null);
    }

    private List<Node> getDistantEdgeLabels(DDiagram dDiagram) {
        List<Node> distantEdgeLabels = new ArrayList<Node>();
        for (Edge edge : getEdges(dDiagram)) {
            for (Object child : edge.getChildren()) {
                if (child instanceof Node && new ViewQuery((Node) child).isForEdgeNameEditPart()) {
                    if (isLabelDistant(edge, (Node) child)) {
                        distantEdgeLabels.add((Node) child);
                    }
                }
            }
        }
        return distantEdgeLabels;
    }

    /**
     * Get all nodes with huge coordinates for this <code>dDiagram</code>. The
     * nodes are grouped by nodes with negative X, positive X, negative Y and
     * positive Y (using key {@link #NEGATIVE_X_KEY}, {@link #POSITIVE_X_KEY},
     * {@link #NEGATIVE_Y_KEY}, {@link #POSITIVE_Y_KEY}).
     * 
     * @param dDiagram
     *            The diagram in which to search.
     * @return a list of nodes with the "huge coordinate" group by type.
     */
    private Map<String, Map<Node, Integer>> getNodesWithExtremeLocation(DDiagram dDiagram) {
        Map<Node, Integer> nodesWithExtremeNegativeXLocation = new HashMap<Node, Integer>();
        Map<Node, Integer> nodesWithExtremePositiveXLocation = new HashMap<Node, Integer>();
        Map<Node, Integer> nodesWithExtremeNegativeYLocation = new HashMap<Node, Integer>();
        Map<Node, Integer> nodesWithExtremePositiveYLocation = new HashMap<Node, Integer>();
        for (Node node : getNodes(dDiagram)) {
            if (node.getLayoutConstraint() instanceof Location) {
                Location location = (Location) node.getLayoutConstraint();
                Point point = new Point(location.getX(), location.getY());
                // Do not deal with label between -lowerLimit and lowerLimit.
                if (Math.abs(location.getX()) > NODES_LIMIT) {
                    if (location.getX() > 0) {
                        nodesWithExtremePositiveXLocation.put(node, point.x());
                    } else {
                        nodesWithExtremeNegativeXLocation.put(node, point.x());
                    }
                }
                if (Math.abs(location.getY()) > NODES_LIMIT) {
                    if (location.getY() > 0) {
                        nodesWithExtremePositiveYLocation.put(node, point.y());
                    } else {
                        nodesWithExtremeNegativeYLocation.put(node, point.y());
                    }
                }
            }
        }
        Map<String, Map<Node, Integer>> result = new HashMap<String, Map<Node, Integer>>();
        result.put(NEGATIVE_X_KEY, nodesWithExtremeNegativeXLocation);
        result.put(POSITIVE_X_KEY, nodesWithExtremePositiveXLocation);
        result.put(NEGATIVE_Y_KEY, nodesWithExtremeNegativeYLocation);
        result.put(POSITIVE_Y_KEY, nodesWithExtremePositiveYLocation);
        return result;
    }

    /**
     * Check is the label is considered as distant from its edge:
     * <UL>
     * <LI>If the label is less than 250 pixels away from the reference point on
     * its corresponding edge, the label is not considered as distant.</LI>
     * <LI>If the label is more than 1000 pixels away from the reference point
     * on its corresponding edge, the label is considered as distant.</LI>
     * <LI>Between these 2 limits, the label is considered as distant if the
     * distance between the center of label and edge is highest that
     * "4*the size of the nearest segment".</LI>
     * </UL>
     * 
     * @param edgeLabel
     *            The label to check
     * @return true if the label is considered as distant from its edge, false
     *         otherwise.
     */
    private boolean isLabelDistant(Edge edge, Node edgeLabel) {
        boolean isLabelDistant = false;
        if (edgeLabel.getLayoutConstraint() instanceof Location) {
            Location location = (Location) edgeLabel.getLayoutConstraint();
            // Do not deal with label between -lowerLimit and lowerLimit.
            if (!(Math.abs(location.getX()) <= LABEL_LOWER_LIMIT && Math.abs(location.getY()) <= LABEL_LOWER_LIMIT)) {
                isLabelDistant = Math.abs(location.getX()) > LABEL_UPPER_LIMIT || Math.abs(location.getY()) > LABEL_UPPER_LIMIT;
                if (!isLabelDistant) {
                    try {
                        // Try to be more precise that just using location of
                        // label: Check if the distance between center of label
                        // and edge is highest that "4*the size of the nearest
                        // segment".
                        List<Point> result = Lists.newArrayList();
                        PointList ptList = new PointList();
                        Anchor anchor = edge.getSourceAnchor();
                        // We only handle case with node as source and identity
                        // anchor.
                        if (anchor instanceof IdentityAnchor && edge.getSource() instanceof Node) {
                            PrecisionPoint relativeReference = BaseSlidableAnchor.parseTerminalString(((IdentityAnchor) anchor).getId());
                            Rectangle sourceBounds = new NodeQuery((Node) edge.getSource()).getHandleBounds();
                            PrecisionPoint srcAnchorLoc = new PrecisionPoint(relativeReference.preciseX() * sourceBounds.width() + sourceBounds.x(),
                                    relativeReference.preciseY() * sourceBounds.height() + sourceBounds.y());
                            RelativeBendpoints bp = (RelativeBendpoints) edge.getBendpoints();
                            for (int i = 0; i < bp.getPoints().size(); i++) {
                                RelativeBendpoint rbp = (RelativeBendpoint) bp.getPoints().get(i);
                                Point fromSrc = srcAnchorLoc.getTranslated(rbp.getSourceX(), rbp.getSourceY());
                                result.add(fromSrc);
                                ptList.addPoint(fromSrc);
                            }
                            Point refPoint = PointListUtilities.calculatePointRelativeToLine(ptList, 0, getLocationOfReference(edgeLabel), true);
                            Point labelCenter = org.eclipse.sirius.diagram.ui.internal.edit.parts.locator.EdgeLabelQuery.relativeCenterCoordinateFromOffset(ptList, refPoint,
                                    new Point(location.getX(), location.getY()));

                            @SuppressWarnings("rawtypes")
                            List segments = PointListUtilities.getLineSegments(ptList);
                            LineSeg nearestSegment = PointListUtilities.getNearestSegment(segments, labelCenter.x, labelCenter.y);
                            double distance = nearestSegment.distanceToPoint(labelCenter.x(), labelCenter.y());
                            isLabelDistant = distance > nearestSegment.length() * 4;
                        }
                        // CHECKSTYLE:OFF
                    } catch (Exception e) {
                        // Do nothing, just avoid some specific cases not
                        // handled above.
                    }
                    // CHECKSTYLE:ON
                }
            }
        }
        return isLabelDistant;
    }

    @SuppressWarnings("restriction")
    private int getLocationOfReference(Node edgeLabel) {
        int locationOfRef = LabelViewConstants.MIDDLE_LOCATION;
        int type = SiriusVisualIDRegistry.getVisualID(edgeLabel.getType());
        if (DEdgeBeginNameEditPart.VISUAL_ID == type) {
            locationOfRef = LabelViewConstants.SOURCE_LOCATION;
        } else if (DEdgeEndNameEditPart.VISUAL_ID == type) {
            locationOfRef = LabelViewConstants.TARGET_LOCATION;
        }
        return locationOfRef;
    }

    /**
     * Get the {@link Edge}s with labels contained in the given {@link DDiagram}
     * .
     * 
     * @param dDiagram
     *            the given {@link DDiagram}.
     * @return the {@link Edge}s with labels contained in the given
     *         {@link DDiagram}.
     */
    private Collection<Edge> getEdges(DDiagram dDiagram) {
        DDiagramGraphicalQuery query = new DDiagramGraphicalQuery(dDiagram);
        Option<Diagram> gmfDiagram = query.getAssociatedGMFDiagram();
        if (gmfDiagram.some()) {
            return Lists.newArrayList(Iterables.filter(gmfDiagram.get().getEdges(), Edge.class));
        }
        return new ArrayList<Edge>();
    }
    
    /**
     * Get the {@link Edge}s with labels contained in the given {@link DDiagram}
     * .
     * 
     * @param dDiagram
     *            the given {@link DDiagram}.
     * @return the {@link Edge}s with labels contained in the given
     *         {@link DDiagram}.
     */
    private Collection<Node> getNodes(DDiagram dDiagram) {
        DDiagramGraphicalQuery query = new DDiagramGraphicalQuery(dDiagram);
        Option<Diagram> gmfDiagram = query.getAssociatedGMFDiagram();
        if (gmfDiagram.some()) {
            return Lists.newArrayList(Iterables.filter(gmfDiagram.get().getChildren(), Node.class));
        }
        return new ArrayList<Node>();
    }
}
