/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.java.graph;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Stroke;
import javax.swing.UIManager;
import org.netbeans.api.visual.anchor.AnchorShape;
import org.netbeans.api.visual.layout.LayoutFactory;
import org.netbeans.api.visual.widget.ConnectionWidget;
import org.netbeans.api.visual.widget.LabelWidget;
import org.netbeans.api.visual.widget.LevelOfDetailsWidget;
import org.netbeans.api.visual.widget.Widget;
import static org.netbeans.modules.java.graph.Bundle.TIP_Primary;
import static org.netbeans.modules.java.graph.Bundle.TIP_Secondary;
import static org.netbeans.modules.java.graph.Bundle.TIP_VersionConflict;
import static org.netbeans.modules.java.graph.Bundle.TIP_VersionWarning;
import static org.netbeans.modules.java.graph.DependencyGraphScene.VersionProvider.VERSION_CONFLICT;
import static org.netbeans.modules.java.graph.DependencyGraphScene.VersionProvider.VERSION_NO_CONFLICT;
import static org.netbeans.modules.java.graph.DependencyGraphScene.VersionProvider.VERSION_POTENTIAL_CONFLICT;
import org.openide.util.NbBundle.Messages;

/**
 *
 * @author mkleint
 */
class EdgeWidget<I extends GraphNodeImplementation> extends ConnectionWidget {
    public static final int DISABLED = 0;
    public static final int GRAYED = 1;
    public static final int REGULAR = 2;
    public static final int HIGHLIGHTED = 3;
    public static final int HIGHLIGHTED_PRIMARY = 4;

    private static float[] hsbVals = new float[3];

    private GraphEdge<I> edge;
    private int state = REGULAR;
    private boolean isConflict;
    private int edgeConflictType;

    private LabelWidget conflictVersion;
    private Widget versionW;
    private Stroke origStroke;

    EdgeWidget(DependencyGraphScene<I> scene, GraphEdge<I> edge) {
        super(scene);
        this.edge = edge;
        origStroke = getStroke();
        setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
        
        if(scene.supportsVersions()) {
            isConflict = scene.isConflict(edge.getTarget());
            edgeConflictType = getConflictType();

            updateVersionW(isConflict);
        }
    }
       
    private void updateVersionW (boolean isConflict) {
        DependencyGraphScene<I> scene = getDependencyGraphScene();
        assert scene.supportsVersions();
        
        GraphNode<I> targetNode = scene.getGraphNodeRepresentant(edge.getTarget());
        if (targetNode == null) {
            return;
        }
        
        int includedConflictType = targetNode.getConflictType(scene::isConflict, scene::compareVersions);

        if (versionW == null) {
            if (isConflict || includedConflictType != VERSION_NO_CONFLICT) {
                versionW = new LevelOfDetailsWidget(scene, 0.5, 0.7, Double.MAX_VALUE, Double.MAX_VALUE);
                conflictVersion = new LabelWidget(scene, scene.getVersion(edge.getTarget()));
                if (isConflict) {
                    Color c = getConflictColor(edgeConflictType);
                    if (c != null) {
                        conflictVersion.setForeground(c);
                    }
                }
                versionW.addChild(conflictVersion);
                addChild(versionW);
                setConstraint(versionW, LayoutFactory.ConnectionWidgetLayoutAlignment.CENTER_RIGHT, 0.5f);
            }
        } else {
            if (!isConflict && includedConflictType == VERSION_NO_CONFLICT) {
                if (versionW.getParentWidget() == this) {
                    removeChild(versionW);
                } // else already removed??
            }
        }
    }

    public void setState (int state) {        
        this.state = state;
        updateAppearance(((DependencyGraphScene)getScene()).isAnimated());
    }

    /**
     * readable widgets are calculated  based on scene zoom factor when zoom factor changes, the readable scope should too
     */
    public void updateReadableZoom() {
        if (state == HIGHLIGHTED || state == HIGHLIGHTED_PRIMARY) {
            updateAppearance(false);
        }
    }

    private DependencyGraphScene<I> getDependencyGraphScene() {
        return (DependencyGraphScene<I>)getScene();
    }
    
    public void modelChanged () {
        DependencyGraphScene scene = getDependencyGraphScene();
        if(scene.supportsVersions()) {
            edgeConflictType = getConflictType();
            isConflict = scene.isConflict(edge.getTarget());
            // correction if some graph editing(fixing) was done
            if (isConflict && edgeConflictType == VERSION_NO_CONFLICT) {
                isConflict = false;
            }

            updateVersionW(isConflict);
        }
        updateAppearance(((DependencyGraphScene)getScene()).isAnimated());
    }

    @Messages({
        "TIP_VersionConflict=Conflict with {0} version required by {1}",
        "TIP_VersionWarning=Warning, overridden by {0} version required by {1}",
        "TIP_Primary=Primary dependency path",
        "TIP_Secondary=Secondary dependency path"
    })
    @SuppressWarnings("fallthrough")
    @org.netbeans.api.annotations.common.SuppressWarnings(value = "SF_SWITCH_FALLTHROUGH")
    void updateAppearance (boolean animated) {
        Color inactiveC = UIManager.getColor("textInactiveText");
        if (inactiveC == null) {
            inactiveC = Color.LIGHT_GRAY;
        }
        Color activeC = UIManager.getColor("textText");
        if (activeC == null) {
                activeC = Color.BLACK;
            }
        Color conflictC = getConflictColor(edgeConflictType);
        if (conflictC == null) {
            conflictC = activeC;
        }

        Stroke s = getDependencyGraphScene().getStroke(edge);     
        Stroke stroke = s != null ? s : origStroke;
        
        Color c = activeC;
        switch (state) {
            case REGULAR:
                c = edge.isPrimary() ? middleColor(activeC, inactiveC) : isConflict ? conflictC : inactiveC;
                break;
            case GRAYED:
                c = isConflict ? deriveColor(conflictC, 0.7f) : inactiveC;
                break;
            case HIGHLIGHTED_PRIMARY:
                stroke = new BasicStroke(3);
                // without break!
            case HIGHLIGHTED:
                c = isConflict ? conflictC : activeC;
                break;
        }
        
        if (state != DISABLED) {
            StringBuilder sb = new StringBuilder("<html>");
            if (isConflict) {
                DependencyGraphScene grScene = getDependencyGraphScene();
                assert grScene.supportsVersions();
                GraphNodeImplementation included = grScene.getGraphNodeRepresentant(
                        edge.getTarget()).getImpl();
                if (included == null) {
                    return;
                }
                String version = grScene.getVersion(included);
                GraphNodeImplementation parent = included.getParent();
                String requester = parent != null ? parent.getName() : "???";
                String confText = edgeConflictType == VERSION_CONFLICT ? TIP_VersionConflict(version, requester) : TIP_VersionWarning(version, requester);
                conflictVersion.setToolTipText(confText);
                sb.append(confText);
                sb.append("<br>");
            }
            sb.append("<i>");
            if (edge.isPrimary()) {
                sb.append(TIP_Primary());
            } else {
                sb.append(TIP_Secondary());
            }
            sb.append("</i>");
            sb.append("</html>");
            setToolTipText(sb.toString());
        } else {
            setToolTipText(null);
        }

        if (conflictVersion != null) {
            conflictVersion.setForeground(c);
            Font origF = getScene().getDefaultFont();
            conflictVersion.setFont(state == HIGHLIGHTED || state == HIGHLIGHTED_PRIMARY
                    ? NodeWidget.getReadable(getScene(), origF) : origF);
        }

        setVisible(state != DISABLED && ((DependencyGraphScene)getScene()).isVisible(edge));

        setStroke(stroke);
        
        DependencyGraphScene grScene = (DependencyGraphScene)getScene();
        if (animated) {
            grScene.getSceneAnimator().animateForegroundColor(this, c);
        } else {
            setForeground(c);
        }
    }

    private int getConflictType () {
        GraphNode<I> included = ((DependencyGraphScene)getScene()).getGraphNodeRepresentant(edge.getTarget());
        if (included == null) {
            return VERSION_NO_CONFLICT;
        }
        DependencyGraphScene<I> scene = getDependencyGraphScene();
        int ret = scene.compareVersions(edge.getTarget(), included.getImpl());
                                return ret > 0 ? 
                                        VERSION_CONFLICT : 
                                        ret < 0 ?
                                            VERSION_POTENTIAL_CONFLICT : 
                                            VERSION_NO_CONFLICT;        
    }

    private static Color getConflictColor (int conflictType) {
        return conflictType == VERSION_CONFLICT ? NodeWidget.CONFLICT
                : conflictType == VERSION_POTENTIAL_CONFLICT
                ? NodeWidget.WARNING : null;
    }

    /** Derives color from specified with saturation multiplied by given ratio.
     */
    static Color deriveColor (Color c, float saturationR) {
        Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), hsbVals);
        hsbVals[1] = Math.min(1.0f, hsbVals[1] * saturationR);
        return Color.getHSBColor(hsbVals[0], hsbVals[1], hsbVals[2]);
    }

    private static Color middleColor (Color c1, Color c2) {
        return new Color(
                (c1.getRed() + c2.getRed()) / 2,
                (c1.getGreen() + c2.getGreen()) / 2,
                (c1.getBlue() + c2.getBlue()) / 2);
    }

}
