/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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 com.android.ide.eclipse.adt.internal.editors.layout.gle2;

import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.RulesEngine;

import org.eclipse.swt.graphics.GC;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The {@link SelectionOverlay} paints the current selection as an overlay.
 */
public class SelectionOverlay extends Overlay {
    private final LayoutCanvas mCanvas;
    private boolean mHidden;

    /**
     * Constructs a new {@link SelectionOverlay} tied to the given canvas.
     *
     * @param canvas the associated canvas
     */
    public SelectionOverlay(LayoutCanvas canvas) {
        mCanvas = canvas;
    }

    /**
     * Set whether the selection overlay should be hidden. This is done during some
     * gestures like resize where the new bounds could be confused with the current
     * selection bounds.
     *
     * @param hidden when true, hide the selection bounds, when false, unhide.
     */
    public void setHidden(boolean hidden) {
        mHidden = hidden;
    }

    /**
     * Paints the selection.
     *
     * @param selectionManager The {@link SelectionManager} holding the
     *            selection.
     * @param gcWrapper The graphics context wrapper for the layout rules to use.
     * @param gc The SWT graphics object
     * @param rulesEngine The {@link RulesEngine} holding the rules.
     */
    public void paint(SelectionManager selectionManager, GCWrapper gcWrapper,
            GC gc, RulesEngine rulesEngine) {
        if (mHidden) {
            return;
        }

        List<SelectionItem> selections = selectionManager.getSelections();
        int n = selections.size();
        if (n > 0) {
            List<NodeProxy> selectedNodes = new ArrayList<NodeProxy>();
            boolean isMultipleSelection = n > 1;
            for (SelectionItem s : selections) {
                if (s.isRoot()) {
                    // The root selection is never painted
                    continue;
                }

                NodeProxy node = s.getNode();
                if (node != null) {
                    paintSelection(gcWrapper, gc, s, isMultipleSelection);
                    selectedNodes.add(node);
                }
            }

            if (selectedNodes.size() > 0) {
                paintSelectionFeedback(gcWrapper, selectedNodes, rulesEngine);
            } else {
                CanvasViewInfo root = mCanvas.getViewHierarchy().getRoot();
                if (root != null) {
                    NodeProxy parent = mCanvas.getNodeFactory().create(root);
                    rulesEngine.callPaintSelectionFeedback(gcWrapper,
                            parent, Collections.<INode>emptyList(), root.getViewObject());
                }
            }

            if (n == 1) {
                NodeProxy node = selections.get(0).getNode();
                if (node != null) {
                    paintHints(gcWrapper, node, rulesEngine);
                }
            }
        } else {
            CanvasViewInfo root = mCanvas.getViewHierarchy().getRoot();
            if (root != null) {
                NodeProxy parent = mCanvas.getNodeFactory().create(root);
                rulesEngine.callPaintSelectionFeedback(gcWrapper,
                        parent, Collections.<INode>emptyList(), root.getViewObject());
            }
        }
    }

    /** Paint hint for current selection */
    private void paintHints(GCWrapper gcWrapper, NodeProxy node, RulesEngine rulesEngine) {
        INode parent = node.getParent();
        if (parent instanceof NodeProxy) {
            NodeProxy parentNode = (NodeProxy) parent;
            List<String> infos = rulesEngine.callGetSelectionHint(parentNode, node);
            if (infos != null && infos.size() > 0) {
                gcWrapper.useStyle(DrawingStyle.HELP);

                Rect b = mCanvas.getImageOverlay().getImageBounds();
                if (b == null) {
                    return;
                }

                // Compute the location to display the help. This is done in
                // layout coordinates, so we need to apply the scale in reverse
                // when making pixel margins
                // TODO: We could take the Canvas dimensions into account to see
                // where there is more room.
                // TODO: The scrollbars should take the presence of hint text
                // into account.
                double scale = mCanvas.getScale();
                int x, y;
                if (b.w > b.h) {
                    x = (int) (b.x + 3 / scale);
                    y = (int) (b.y + b.h + 6 / scale);
                } else {
                    x = (int) (b.x + b.w + 6 / scale);
                    y = (int) (b.y + 3 / scale);
                }
                gcWrapper.drawBoxedStrings(x, y, infos);
            }
        }
    }

    private void paintSelectionFeedback(GCWrapper gcWrapper, List<NodeProxy> nodes,
            RulesEngine rulesEngine) {
        // Add fastpath for n=1

        // Group nodes into parent/child groups
        Set<INode> parents = new HashSet<INode>();
        for (INode node : nodes) {
            INode parent = node.getParent();
            if (/*parent == null || */parent instanceof NodeProxy) {
                NodeProxy parentNode = (NodeProxy) parent;
                parents.add(parentNode);
            }
        }
        ViewHierarchy viewHierarchy = mCanvas.getViewHierarchy();
        for (INode parent : parents) {
            List<INode> children = new ArrayList<INode>();
            for (INode node : nodes) {
                INode nodeParent = node.getParent();
                if (nodeParent == parent) {
                    children.add(node);
                }
            }
            CanvasViewInfo viewInfo = viewHierarchy.findViewInfoFor((NodeProxy) parent);
            Object view = viewInfo != null ? viewInfo.getViewObject() : null;

            rulesEngine.callPaintSelectionFeedback(gcWrapper,
                    (NodeProxy) parent, children, view);
        }
    }

    /** Called by the canvas when a view is being selected. */
    private void paintSelection(IGraphics gc, GC swtGc, SelectionItem item,
            boolean isMultipleSelection) {
        CanvasViewInfo view = item.getViewInfo();
        if (view.isHidden()) {
            return;
        }

        NodeProxy selectedNode = item.getNode();
        Rect r = selectedNode.getBounds();
        if (!r.isValid()) {
            return;
        }

        gc.useStyle(DrawingStyle.SELECTION);

        Margins insets = mCanvas.getInsets(selectedNode.getFqcn());
        int x1 = r.x;
        int y1 = r.y;
        int x2 = r.x2() + 1;
        int y2 = r.y2() + 1;

        if (insets != null) {
            x1 += insets.left;
            x2 -= insets.right;
            y1 += insets.top;
            y2 -= insets.bottom;
        }

        gc.drawRect(x1, y1, x2, y2);

        // Paint sibling rectangles, if applicable
        List<CanvasViewInfo> siblings = view.getNodeSiblings();
        if (siblings != null) {
            for (CanvasViewInfo sibling : siblings) {
                if (sibling != view) {
                    r = SwtUtils.toRect(sibling.getSelectionRect());
                    gc.fillRect(r);
                    gc.drawRect(r);
                }
            }
        }

        // Paint selection handles. These are painted in control coordinates on the
        // real SWT GC object rather than in layout coordinates on the GCWrapper,
        // since we want them to have a fixed size that is independent of the
        // screen zoom.
        CanvasTransform horizontalTransform = mCanvas.getHorizontalTransform();
        CanvasTransform verticalTransform = mCanvas.getVerticalTransform();
        int radius = SelectionHandle.PIXEL_RADIUS;
        int doubleRadius = 2 * radius;
        for (SelectionHandle handle : item.getSelectionHandles()) {
            int cx = horizontalTransform.translate(handle.centerX);
            int cy = verticalTransform.translate(handle.centerY);

            SwtDrawingStyle style = SwtDrawingStyle.of(DrawingStyle.SELECTION);
            gc.setAlpha(style.getStrokeAlpha());
            swtGc.fillRectangle(cx - radius, cy - radius, doubleRadius, doubleRadius);
        }
    }
}
