/*
 * 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.grid;

import static com.android.ide.common.layout.GridLayoutRule.GRID_SIZE;
import static com.android.ide.common.layout.GridLayoutRule.MARGIN_SIZE;
import static com.android.ide.common.layout.grid.GridModel.UNDEFINED;

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.IDragElement;
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.Rect;
import com.android.ide.common.api.SegmentType;
import com.android.ide.common.layout.GridLayoutRule;
import com.android.utils.Pair;

/**
 * Painter which paints feedback during drag, drop and resizing operations, as well as
 * static selection feedback
 */
public class GridLayoutPainter {

    /**
     * Creates a painter for drop feedback
     *
     * @param rule the corresponding {@link GridLayoutRule}
     * @param elements the dragged elements
     * @return a {@link IFeedbackPainter} which can paint the drop feedback
     */
    public static IFeedbackPainter createDropFeedbackPainter(GridLayoutRule rule,
            IDragElement[] elements) {
        return new DropFeedbackPainter(rule, elements);
    }

    /**
     * Paints the structure (the grid model) of the given GridLayout.
     *
     * @param style the drawing style to use to paint the structure lines
     * @param layout the grid layout node
     * @param gc the graphics context to paint into
     * @param grid the grid model to be visualized
     */
    public static void paintStructure(DrawingStyle style, INode layout, IGraphics gc,
            GridModel grid) {
        Rect b = layout.getBounds();

        gc.useStyle(style);
        for (int row = 0; row < grid.actualRowCount; row++) {
            int y = grid.getRowY(row);
            gc.drawLine(b.x, y, b.x2(), y);
        }
        for (int column = 0; column < grid.actualColumnCount; column++) {
            int x = grid.getColumnX(column);
            gc.drawLine(x, b.y, x, b.y2());
        }
    }

    /**
     * Paints a regular grid according to the {@link GridLayoutRule#GRID_SIZE} and
     * {@link GridLayoutRule#MARGIN_SIZE} dimensions. These are the same lines that
     * snap-to-grid will align with.
     *
     * @param layout the GridLayout node
     * @param gc the graphics context to paint the grid into
     */
    public static void paintGrid(INode layout, IGraphics gc) {
        Rect b = layout.getBounds();

        int oldAlpha = gc.getAlpha();
        gc.useStyle(DrawingStyle.GUIDELINE);
        gc.setAlpha(128);

        int y1 = b.y + MARGIN_SIZE;
        int y2 = b.y2() - MARGIN_SIZE;
        for (int y = y1; y < y2; y += GRID_SIZE) {
            int x1 = b.x + MARGIN_SIZE;
            int x2 = b.x2() - MARGIN_SIZE;
            for (int x = x1; x < x2; x += GRID_SIZE) {
                gc.drawPoint(x, y);
            }
        }
        gc.setAlpha(oldAlpha);
    }

    /**
     * Paint resizing feedback (which currently paints the grid model faintly.)
     *
     * @param gc the graphics context
     * @param layout the GridLayout
     * @param grid the grid model
     */
    public static void paintResizeFeedback(IGraphics gc, INode layout, GridModel grid) {
        paintStructure(DrawingStyle.GRID, layout, gc, grid);
    }

    /**
     * A painter which can paint the drop feedback for elements being dragged into or
     * within a GridLayout.
     */
    private static class DropFeedbackPainter implements IFeedbackPainter {
        private final GridLayoutRule mRule;
        private final IDragElement[] mElements;

        /** Constructs a new {@link GridLayoutPainter} bound to the given {@link GridLayoutRule}
         * @param rule the corresponding rule
         * @param elements the elements to draw */
        public DropFeedbackPainter(GridLayoutRule rule, IDragElement[] elements) {
            mRule = rule;
            mElements = elements;
        }

        // Implements IFeedbackPainter
        @Override
        public void paint(@NonNull IGraphics gc, @NonNull INode node,
                @NonNull DropFeedback feedback) {
            Rect b = node.getBounds();
            if (!b.isValid()) {
                return;
            }

            // Highlight the receiver
            gc.useStyle(DrawingStyle.DROP_RECIPIENT);
            gc.drawRect(b);
            GridDropHandler data = (GridDropHandler) feedback.userData;

            if (!GridLayoutRule.sGridMode) {
                paintFreeFormDropFeedback(gc, node, feedback, b, data);
            } else {
                paintGridModeDropFeedback(gc, b, data);
            }
        }

        /**
         * Paints the drag feedback for a free-form mode drag
         */
        private void paintFreeFormDropFeedback(IGraphics gc, INode node, DropFeedback feedback,
                Rect b, GridDropHandler data) {
            GridModel grid = data.getGrid();
            if (GridLayoutRule.sSnapToGrid) {
                GridLayoutPainter.paintGrid(node, gc);
            }
            GridLayoutPainter.paintStructure(DrawingStyle.GRID, node, gc, grid);

            GridMatch rowMatch = data.getRowMatch();
            GridMatch columnMatch = data.getColumnMatch();

            if (rowMatch == null || columnMatch == null) {
                return;
            }

            IDragElement first = mElements[0];
            Rect dragBounds = first.getBounds();
            int offsetX = 0;
            int offsetY = 0;
            if (rowMatch.type == SegmentType.BOTTOM) {
                offsetY -= dragBounds.h;
            } else if (rowMatch.type == SegmentType.BASELINE) {
                offsetY -= feedback.dragBaseline;
            }
            if (columnMatch.type == SegmentType.RIGHT) {
                offsetX -= dragBounds.w;
            } else if (columnMatch.type == SegmentType.CENTER_HORIZONTAL) {
                offsetX -= dragBounds.w / 2;
            }

            // Draw guidelines for matches
            int y = rowMatch.matchedLine;
            int x = columnMatch.matchedLine;
            Rect bounds = first.getBounds();

            // Draw margin
            if (rowMatch.margin != UNDEFINED && rowMatch.margin > 0) {
                gc.useStyle(DrawingStyle.DISTANCE);
                int centerX = bounds.w / 2 + offsetX + x;
                int y1;
                int y2;
                if (rowMatch.type == SegmentType.TOP) {
                    y1 = offsetY + y - 1;
                    y2 = rowMatch.matchedLine - rowMatch.margin;
                } else {
                    assert rowMatch.type == SegmentType.BOTTOM;
                    y1 = bounds.h + offsetY + y - 1;
                    y2 = rowMatch.matchedLine + rowMatch.margin;
                }
                gc.drawLine(b.x, y1, b.x2(), y1);
                gc.drawLine(b.x, y2, b.x2(), y2);
                gc.drawString(Integer.toString(rowMatch.margin),
                        centerX - 3, y1 + (y2 - y1 - 16) / 2);
            } else {
                gc.useStyle(rowMatch.margin == 0 ? DrawingStyle.DISTANCE
                        : rowMatch.createCell ? DrawingStyle.GUIDELINE_DASHED
                                : DrawingStyle.GUIDELINE);
                gc.drawLine(b.x, y, b.x2(), y );
            }

            if (columnMatch.margin != UNDEFINED && columnMatch.margin > 0) {
                gc.useStyle(DrawingStyle.DISTANCE);
                int centerY = bounds.h / 2 + offsetY + y;
                int x1;
                int x2;
                if (columnMatch.type == SegmentType.LEFT) {
                    x1 = offsetX + x - 1;
                    x2 = columnMatch.matchedLine - columnMatch.margin;
                } else {
                    assert columnMatch.type == SegmentType.RIGHT;
                    x1 = bounds.w + offsetX + x - 1;
                    x2 = columnMatch.matchedLine + columnMatch.margin;
                }
                gc.drawLine(x1, b.y, x1, b.y2());
                gc.drawLine(x2, b.y, x2, b.y2());
                gc.drawString(Integer.toString(columnMatch.margin),
                        x1 + (x2 - x1 - 16) / 2, centerY - 3);
            } else {
                gc.useStyle(columnMatch.margin == 0 ? DrawingStyle.DISTANCE
                        : columnMatch.createCell ? DrawingStyle.GUIDELINE_DASHED
                                : DrawingStyle.GUIDELINE);
                gc.drawLine(x, b.y, x, b.y2());
            }

            // Draw preview rectangles for all the dragged elements
            gc.useStyle(DrawingStyle.DROP_PREVIEW);
            offsetX += x - bounds.x;
            offsetY += y - bounds.y;

            for (IDragElement element : mElements) {
                if (element == first) {
                    mRule.drawElement(gc, first, offsetX, offsetY);
                    // Preview baseline as well
                    if (feedback.dragBaseline != -1) {
                        int x1 = dragBounds.x + offsetX;
                        int y1 = dragBounds.y + offsetY + feedback.dragBaseline;
                        gc.drawLine(x1, y1, x1 + dragBounds.w, y1);
                    }
                } else {
                    b = element.getBounds();
                    if (b.isValid()) {
                        gc.drawRect(b.x + offsetX, b.y + offsetY,
                                b.x + offsetX + b.w, b.y + offsetY + b.h);
                    }
                }
            }
        }

        /**
         * Paints the drag feedback for a grid-mode drag
         */
        private void paintGridModeDropFeedback(IGraphics gc, Rect b, GridDropHandler data) {
            int radius = mRule.getNewCellSize();
            GridModel grid = data.getGrid();

            gc.useStyle(DrawingStyle.GUIDELINE);
            // Paint grid
            for (int row = 1; row < grid.actualRowCount; row++) {
                int y = grid.getRowY(row);
                gc.drawLine(b.x, y - radius, b.x2(), y - radius);
                gc.drawLine(b.x, y + radius, b.x2(), y + radius);

            }
            for (int column = 1; column < grid.actualColumnCount; column++) {
                int x = grid.getColumnX(column);
                gc.drawLine(x - radius, b.y, x - radius, b.y2());
                gc.drawLine(x + radius, b.y, x + radius, b.y2());
            }
            gc.drawRect(b.x, b.y, b.x2(), b.y2());
            gc.drawRect(b.x + 2 * radius, b.y + 2 * radius,
                    b.x2() - 2 * radius, b.y2() - 2 * radius);

            GridMatch columnMatch = data.getColumnMatch();
            GridMatch rowMatch = data.getRowMatch();
            int column = columnMatch.cellIndex;
            int row = rowMatch.cellIndex;
            boolean createColumn = columnMatch.createCell;
            boolean createRow = rowMatch.createCell;

            Rect cellBounds = grid.getCellBounds(row, column, 1, 1);

            IDragElement first = mElements[0];
            Rect dragBounds = first.getBounds();
            int offsetX = cellBounds.x - dragBounds.x;
            int offsetY = cellBounds.y - dragBounds.y;

            gc.useStyle(DrawingStyle.DROP_ZONE_ACTIVE);
            if (createColumn) {
                gc.fillRect(new Rect(cellBounds.x - radius,
                        cellBounds.y + (createRow ? -radius : radius),
                        2 * radius + 1, cellBounds.h - (createRow ? 0 : 2 * radius)));
                offsetX -= radius + dragBounds.w / 2;
            }
            if (createRow) {
                gc.fillRect(new Rect(cellBounds.x + radius, cellBounds.y - radius,
                        cellBounds.w - 2 * radius, 2 * radius + 1));
                offsetY -= radius + dragBounds.h / 2;
            } else if (!createColumn) {
                // Choose this cell
                gc.fillRect(new Rect(cellBounds.x + radius, cellBounds.y + radius,
                        cellBounds.w - 2 * radius, cellBounds.h - 2 * radius));
            }

            gc.useStyle(DrawingStyle.DROP_PREVIEW);

            Rect bounds = first.getBounds();
            int x = offsetX;
            int y = offsetY;
            if (columnMatch.type == SegmentType.RIGHT) {
                x += cellBounds.w - bounds.w;
            } else if (columnMatch.type == SegmentType.CENTER_HORIZONTAL) {
                x += cellBounds.w / 2 - bounds.w / 2;
            }
            if (rowMatch.type == SegmentType.BOTTOM) {
                y += cellBounds.h - bounds.h;
            } else if (rowMatch.type == SegmentType.CENTER_VERTICAL) {
                y += cellBounds.h / 2 - bounds.h / 2;
            }

            mRule.drawElement(gc, first, x, y);
        }
    }

    /**
     * Paints the structure (the row and column boundaries) of the given
     * GridLayout
     *
     * @param view the instance of the GridLayout whose structure should be
     *            painted
     * @param style the drawing style to use for the cell boundaries
     * @param layout the layout element
     * @param gc the graphics context
     * @return true if the structure was successfully inferred from the view and
     *         painted
     */
    public static boolean paintStructure(Object view, DrawingStyle style, INode layout,
            IGraphics gc) {
        Pair<int[],int[]> cellBounds = GridModel.getAxisBounds(view);
        if (cellBounds != null) {
            int[] xs = cellBounds.getFirst();
            int[] ys = cellBounds.getSecond();
            Rect b = layout.getBounds();
            gc.useStyle(style);
            for (int row = 0; row < ys.length; row++) {
                int y = ys[row] + b.y;
                gc.drawLine(b.x, y, b.x2(), y);
            }
            for (int column = 0; column < xs.length; column++) {
                int x = xs[column] + b.x;
                gc.drawLine(x, b.y, x, b.y2());
            }

            return true;
        } else {
            return false;
        }
    }
}
