/*
 * Copyright (C) 2011 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.common.layout.relative;

import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_BOTTOM;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_LEFT;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_RIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_TOP;
import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX;
import static com.android.SdkConstants.ID_PREFIX;
import static com.android.SdkConstants.NEW_ID_PREFIX;

import com.android.annotations.NonNull;
import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.DropFeedback;
import com.android.ide.common.api.IFeedbackPainter;
import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.Point;
import com.android.ide.common.api.Rect;
import com.android.ide.common.api.SegmentType;
import com.android.ide.common.layout.relative.DependencyGraph.Constraint;

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

/**
 * The {@link GuidelinePainter} is responsible for painting guidelines during an operation
 * which uses a {@link GuidelineHandler} such as a resize operation.
 */
public final class GuidelinePainter implements IFeedbackPainter {
    // ---- Implements IFeedbackPainter ----
    @Override
    public void paint(@NonNull IGraphics gc, @NonNull INode node, @NonNull DropFeedback feedback) {
        GuidelineHandler state = (GuidelineHandler) feedback.userData;

        for (INode dragged : state.mDraggedNodes) {
            gc.useStyle(DrawingStyle.DRAGGED);
            Rect bounds = dragged.getBounds();
            if (bounds.isValid()) {
                gc.fillRect(bounds);
            }
        }

        Set<INode> horizontalDeps = state.mHorizontalDeps;
        Set<INode> verticalDeps = state.mVerticalDeps;
        Set<INode> deps = new HashSet<INode>(horizontalDeps.size() + verticalDeps.size());
        deps.addAll(horizontalDeps);
        deps.addAll(verticalDeps);
        if (deps.size() > 0) {
            gc.useStyle(DrawingStyle.DEPENDENCY);
            for (INode n : deps) {
                // Don't highlight the selected nodes themselves
                if (state.mDraggedNodes.contains(n)) {
                    continue;
                }
                Rect bounds = n.getBounds();
                gc.fillRect(bounds);
            }
        }

        if (state.mBounds != null) {
            if (state instanceof MoveHandler) {
                gc.useStyle(DrawingStyle.DROP_PREVIEW);
            } else {
                // Resizing
                if (state.haveSuggestions()) {
                    gc.useStyle(DrawingStyle.RESIZE_PREVIEW);
                } else {
                    gc.useStyle(DrawingStyle.RESIZE_FAIL);
                }
            }
            gc.drawRect(state.mBounds);

            // Draw baseline preview too
            if (feedback.dragBaseline != -1) {
                int y = state.mBounds.y + feedback.dragBaseline;
                gc.drawLine(state.mBounds.x, y, state.mBounds.x2(), y);
            }
        }

        List<String> strings = new ArrayList<String>();

        showMatch(gc, state.mCurrentLeftMatch, state, strings,
                state.mLeftMargin, ATTR_LAYOUT_MARGIN_LEFT);
        showMatch(gc, state.mCurrentRightMatch, state, strings,
                state.mRightMargin, ATTR_LAYOUT_MARGIN_RIGHT);
        showMatch(gc, state.mCurrentTopMatch, state, strings,
                state.mTopMargin, ATTR_LAYOUT_MARGIN_TOP);
        showMatch(gc, state.mCurrentBottomMatch, state, strings,
                state.mBottomMargin, ATTR_LAYOUT_MARGIN_BOTTOM);

        if (strings.size() > 0) {
            // Update the drag tooltip
            StringBuilder sb = new StringBuilder(200);
            for (String s : strings) {
                if (sb.length() > 0) {
                    sb.append('\n');
                }
                sb.append(s);
            }
            feedback.tooltip = sb.toString();

            // Set the tooltip orientation to ensure that it does not interfere with
            // the constraint arrows
            if (state.mCurrentLeftMatch != null) {
                feedback.tooltipX = SegmentType.RIGHT;
            } else if (state.mCurrentRightMatch != null) {
                feedback.tooltipX = SegmentType.LEFT;
            }
            if (state.mCurrentTopMatch != null) {
                feedback.tooltipY = SegmentType.BOTTOM;
            } else if (state.mCurrentBottomMatch != null) {
                feedback.tooltipY = SegmentType.TOP;
            }
        } else {
            feedback.tooltip = null;
        }

        if (state.mHorizontalCycle != null) {
            paintCycle(gc, state, state.mHorizontalCycle);
        }
        if (state.mVerticalCycle != null) {
            paintCycle(gc, state, state.mVerticalCycle);
        }
    }

    /** Paints a particular match constraint */
    private void showMatch(IGraphics gc, Match m, GuidelineHandler state, List<String> strings,
            int margin, String marginAttribute) {
        if (m == null) {
            return;
        }
        ConstraintPainter.paintConstraint(gc, state.mBounds, m);

        // Display the constraint. Remove the @id/ and @+id/ prefixes to make the text
        // shorter and easier to read. This doesn't use stripPrefix() because the id is
        // usually not a prefix of the value (for example, 'layout_alignBottom=@+id/foo').
        String constraint = m.getConstraint(false /* generateId */);
        String description = constraint.replace(NEW_ID_PREFIX, "").replace(ID_PREFIX, "");
        if (description.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)) {
            description = description.substring(ATTR_LAYOUT_RESOURCE_PREFIX.length());
        }
        if (margin > 0) {
            int dp = state.getRulesEngine().pxToDp(margin);
            description = String.format("%1$s, margin=%2$d dp", description, dp);
        }
        strings.add(description);
    }

    /** Paints a constraint cycle */
    void paintCycle(IGraphics gc, GuidelineHandler state, List<Constraint> cycle) {
        gc.useStyle(DrawingStyle.CYCLE);
        assert cycle.size() > 0;

        INode from = cycle.get(0).from.node;
        Rect fromBounds = from.getBounds();
        if (state.mDraggedNodes.contains(from)) {
            fromBounds = state.mBounds;
        }
        Point fromCenter = fromBounds.center();
        INode to = null;

        List<Point> points = new ArrayList<Point>();
        points.add(fromCenter);

        for (Constraint constraint : cycle) {
            assert constraint.from.node == from;
            to = constraint.to.node;
            assert from != null && to != null;

            Point toCenter = to.getBounds().center();
            points.add(toCenter);

            // Also go through the dragged node bounds
            boolean isDragged = state.mDraggedNodes.contains(to);
            if (isDragged) {
                toCenter = state.mBounds.center();
                points.add(toCenter);
            }

            from = to;
            fromCenter = toCenter;
        }

        points.add(fromCenter);
        points.add(points.get(0));

        for (int i = 1, n = points.size(); i < n; i++) {
            gc.drawLine(points.get(i-1), points.get(i));
        }
    }
}
