/*
 * 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.annotations.NonNull;
import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.IColor;
import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.Point;
import com.android.ide.common.api.Rect;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.RGB;

import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Wraps an SWT {@link GC} into an {@link IGraphics} interface so that {@link IViewRule} objects
 * can directly draw on the canvas.
 * <p/>
 * The actual wrapped GC object is only non-null during the context of a paint operation.
 */
public class GCWrapper implements IGraphics {

    /**
     * The actual SWT {@link GC} being wrapped. This can change during the lifetime of the
     * object. It is generally set to something during an onPaint method and then changed
     * to null when not in the context of a paint.
     */
    private GC mGc;

    /**
     * Current style being used for drawing.
     */
    private SwtDrawingStyle mCurrentStyle = SwtDrawingStyle.INVALID;

    /**
     * Implementation of IColor wrapping an SWT color.
     */
    private static class ColorWrapper implements IColor {
        private final Color mColor;

        public ColorWrapper(Color color) {
            mColor = color;
        }

        public Color getColor() {
            return mColor;
        }
    }

    /** A map of registered colors. All these colors must be disposed at the end. */
    private final HashMap<Integer, ColorWrapper> mColorMap = new HashMap<Integer, ColorWrapper>();

    /**
     * A map of the {@link SwtDrawingStyle} stroke colors that we have actually
     * used (to be disposed)
     */
    private final Map<DrawingStyle, Color> mStyleStrokeMap = new EnumMap<DrawingStyle, Color>(
            DrawingStyle.class);

    /**
     * A map of the {@link SwtDrawingStyle} fill colors that we have actually
     * used (to be disposed)
     */
    private final Map<DrawingStyle, Color> mStyleFillMap = new EnumMap<DrawingStyle, Color>(
            DrawingStyle.class);

    /** The cached pixel height of the default current font. */
    private int mFontHeight = 0;

    /** The scaling of the canvas in X. */
    private final CanvasTransform mHScale;
    /** The scaling of the canvas in Y. */
    private final CanvasTransform mVScale;

    public GCWrapper(CanvasTransform hScale, CanvasTransform vScale) {
        mHScale = hScale;
        mVScale = vScale;
        mGc = null;
    }

    void setGC(GC gc) {
        mGc = gc;
    }

    private GC getGc() {
        return mGc;
    }

    void checkGC() {
        if (mGc == null) {
            throw new RuntimeException("IGraphics used without a valid context.");
        }
    }

    void dispose() {
        for (ColorWrapper c : mColorMap.values()) {
            c.getColor().dispose();
        }
        mColorMap.clear();

        for (Color c : mStyleStrokeMap.values()) {
            c.dispose();
        }
        mStyleStrokeMap.clear();

        for (Color c : mStyleFillMap.values()) {
            c.dispose();
        }
        mStyleFillMap.clear();
    }

    //-------------

    @Override
    public @NonNull IColor registerColor(int rgb) {
        checkGC();

        Integer key = Integer.valueOf(rgb);
        ColorWrapper c = mColorMap.get(key);
        if (c == null) {
            c = new ColorWrapper(new Color(getGc().getDevice(),
                    (rgb >> 16) & 0xFF,
                    (rgb >>  8) & 0xFF,
                    (rgb >>  0) & 0xFF));
            mColorMap.put(key, c);
        }

        return c;
    }

    /** Returns the (cached) pixel height of the current font. */
    @Override
    public int getFontHeight() {
        if (mFontHeight < 1) {
            checkGC();
            FontMetrics fm = getGc().getFontMetrics();
            mFontHeight = fm.getHeight();
        }
        return mFontHeight;
    }

    @Override
    public @NonNull IColor getForeground() {
        Color c = getGc().getForeground();
        return new ColorWrapper(c);
    }

    @Override
    public @NonNull IColor getBackground() {
        Color c = getGc().getBackground();
        return new ColorWrapper(c);
    }

    @Override
    public int getAlpha() {
        return getGc().getAlpha();
    }

    @Override
    public void setForeground(@NonNull IColor color) {
        checkGC();
        getGc().setForeground(((ColorWrapper) color).getColor());
    }

    @Override
    public void setBackground(@NonNull IColor color) {
        checkGC();
        getGc().setBackground(((ColorWrapper) color).getColor());
    }

    @Override
    public void setAlpha(int alpha) {
        checkGC();
        try {
            getGc().setAlpha(alpha);
        } catch (SWTException e) {
            // This means that we cannot set the alpha on this platform; this is
            // an acceptable no-op.
        }
    }

    @Override
    public void setLineStyle(@NonNull LineStyle style) {
        int swtStyle = 0;
        switch (style) {
        case LINE_SOLID:
            swtStyle = SWT.LINE_SOLID;
            break;
        case LINE_DASH:
            swtStyle = SWT.LINE_DASH;
            break;
        case LINE_DOT:
            swtStyle = SWT.LINE_DOT;
            break;
        case LINE_DASHDOT:
            swtStyle = SWT.LINE_DASHDOT;
            break;
        case LINE_DASHDOTDOT:
            swtStyle = SWT.LINE_DASHDOTDOT;
            break;
        default:
            assert false : style;
            break;
        }

        if (swtStyle != 0) {
            checkGC();
            getGc().setLineStyle(swtStyle);
        }
    }

    @Override
    public void setLineWidth(int width) {
        checkGC();
        if (width > 0) {
            getGc().setLineWidth(width);
        }
    }

    // lines

    @Override
    public void drawLine(int x1, int y1, int x2, int y2) {
        checkGC();
        useStrokeAlpha();
        x1 = mHScale.translate(x1);
        y1 = mVScale.translate(y1);
        x2 = mHScale.translate(x2);
        y2 = mVScale.translate(y2);
        getGc().drawLine(x1, y1, x2, y2);
    }

    @Override
    public void drawLine(@NonNull Point p1, @NonNull Point p2) {
        drawLine(p1.x, p1.y, p2.x, p2.y);
    }

    // rectangles

    @Override
    public void drawRect(int x1, int y1, int x2, int y2) {
        checkGC();
        useStrokeAlpha();
        int x = mHScale.translate(x1);
        int y = mVScale.translate(y1);
        int w = mHScale.scale(x2 - x1);
        int h = mVScale.scale(y2 - y1);
        getGc().drawRectangle(x, y, w, h);
    }

    @Override
    public void drawRect(@NonNull Point p1, @NonNull Point p2) {
        drawRect(p1.x, p1.y, p2.x, p2.y);
    }

    @Override
    public void drawRect(@NonNull Rect r) {
        checkGC();
        useStrokeAlpha();
        int x = mHScale.translate(r.x);
        int y = mVScale.translate(r.y);
        int w = mHScale.scale(r.w);
        int h = mVScale.scale(r.h);
        getGc().drawRectangle(x, y, w, h);
    }

    @Override
    public void fillRect(int x1, int y1, int x2, int y2) {
        checkGC();
        useFillAlpha();
        int x = mHScale.translate(x1);
        int y = mVScale.translate(y1);
        int w = mHScale.scale(x2 - x1);
        int h = mVScale.scale(y2 - y1);
        getGc().fillRectangle(x, y, w, h);
    }

    @Override
    public void fillRect(@NonNull Point p1, @NonNull Point p2) {
        fillRect(p1.x, p1.y, p2.x, p2.y);
    }

    @Override
    public void fillRect(@NonNull Rect r) {
        checkGC();
        useFillAlpha();
        int x = mHScale.translate(r.x);
        int y = mVScale.translate(r.y);
        int w = mHScale.scale(r.w);
        int h = mVScale.scale(r.h);
        getGc().fillRectangle(x, y, w, h);
    }

    // circles (actually ovals)

    public void drawOval(int x1, int y1, int x2, int y2) {
        checkGC();
        useStrokeAlpha();
        int x = mHScale.translate(x1);
        int y = mVScale.translate(y1);
        int w = mHScale.scale(x2 - x1);
        int h = mVScale.scale(y2 - y1);
        getGc().drawOval(x, y, w, h);
    }

    public void drawOval(Point p1, Point p2) {
        drawOval(p1.x, p1.y, p2.x, p2.y);
    }

    public void drawOval(Rect r) {
        checkGC();
        useStrokeAlpha();
        int x = mHScale.translate(r.x);
        int y = mVScale.translate(r.y);
        int w = mHScale.scale(r.w);
        int h = mVScale.scale(r.h);
        getGc().drawOval(x, y, w, h);
    }

    public void fillOval(int x1, int y1, int x2, int y2) {
        checkGC();
        useFillAlpha();
        int x = mHScale.translate(x1);
        int y = mVScale.translate(y1);
        int w = mHScale.scale(x2 - x1);
        int h = mVScale.scale(y2 - y1);
        getGc().fillOval(x, y, w, h);
    }

    public void fillOval(Point p1, Point p2) {
        fillOval(p1.x, p1.y, p2.x, p2.y);
    }

    public void fillOval(Rect r) {
        checkGC();
        useFillAlpha();
        int x = mHScale.translate(r.x);
        int y = mVScale.translate(r.y);
        int w = mHScale.scale(r.w);
        int h = mVScale.scale(r.h);
        getGc().fillOval(x, y, w, h);
    }


    // strings

    @Override
    public void drawString(@NonNull String string, int x, int y) {
        checkGC();
        useStrokeAlpha();
        x = mHScale.translate(x);
        y = mVScale.translate(y);
        // Background fill of text is not useful because it does not
        // use the alpha; we instead supply a separate method (drawBoxedStrings) which
        // first paints a semi-transparent mask for the text to sit on
        // top of (this ensures that the text is readable regardless of
        // colors of the pixels below the text)
        getGc().drawString(string, x, y, true /*isTransparent*/);
    }

    @Override
    public void drawBoxedStrings(int x, int y, @NonNull List<?> strings) {
        checkGC();

        x = mHScale.translate(x);
        y = mVScale.translate(y);

        // Compute bounds of the box by adding up the sum of the text heights
        // and the max of the text widths
        int width = 0;
        int height = 0;
        int lineHeight = getGc().getFontMetrics().getHeight();
        for (Object s : strings) {
            org.eclipse.swt.graphics.Point extent = getGc().stringExtent(s.toString());
            height += extent.y;
            width = Math.max(width, extent.x);
        }

        // Paint a box below the text
        int padding = 2;
        useFillAlpha();
        getGc().fillRectangle(x - padding, y - padding, width + 2 * padding, height + 2 * padding);

        // Finally draw strings on top
        useStrokeAlpha();
        int lineY = y;
        for (Object s : strings) {
            getGc().drawString(s.toString(), x, lineY, true /* isTransparent */);
            lineY += lineHeight;
        }
    }

    @Override
    public void drawString(@NonNull String string, @NonNull Point topLeft) {
        drawString(string, topLeft.x, topLeft.y);
    }

    // Styles

    @Override
    public void useStyle(@NonNull DrawingStyle style) {
        checkGC();

        // Look up the specific SWT style which defines the actual
        // colors and attributes to be used for the logical drawing style.
        SwtDrawingStyle swtStyle = SwtDrawingStyle.of(style);
        RGB stroke = swtStyle.getStrokeColor();
        if (stroke != null) {
            Color color = getStrokeColor(style, stroke);
            mGc.setForeground(color);
        }
        RGB fill = swtStyle.getFillColor();
        if (fill != null) {
            Color color = getFillColor(style, fill);
            mGc.setBackground(color);
        }
        mGc.setLineWidth(swtStyle.getLineWidth());
        mGc.setLineStyle(swtStyle.getLineStyle());
        if (swtStyle.getLineStyle() == SWT.LINE_CUSTOM) {
            mGc.setLineDash(new int[] {
                    8, 4
            });
        }
        mCurrentStyle = swtStyle;
    }

    /** Uses the stroke alpha for subsequent drawing operations. */
    private void useStrokeAlpha() {
        mGc.setAlpha(mCurrentStyle.getStrokeAlpha());
    }

    /** Uses the fill alpha for subsequent drawing operations. */
    private void useFillAlpha() {
        mGc.setAlpha(mCurrentStyle.getFillAlpha());
    }

    /**
     * Get the SWT stroke color (foreground/border) to use for the given style,
     * using the provided color description if we haven't seen this color yet.
     * The color will also be placed in the {@link #mStyleStrokeMap} such that
     * it can be disposed of at cleanup time.
     *
     * @param style The drawing style for which we want a color
     * @param defaultColorDesc The RGB values to initialize the color to if we
     *            haven't seen this color before
     * @return The color object
     */
    private Color getStrokeColor(DrawingStyle style, RGB defaultColorDesc) {
        return getStyleColor(style, defaultColorDesc, mStyleStrokeMap);
    }

    /**
     * Get the SWT fill (background/interior) color to use for the given style,
     * using the provided color description if we haven't seen this color yet.
     * The color will also be placed in the {@link #mStyleStrokeMap} such that
     * it can be disposed of at cleanup time.
     *
     * @param style The drawing style for which we want a color
     * @param defaultColorDesc The RGB values to initialize the color to if we
     *            haven't seen this color before
     * @return The color object
     */
    private Color getFillColor(DrawingStyle style, RGB defaultColorDesc) {
        return getStyleColor(style, defaultColorDesc, mStyleFillMap);
    }

    /**
     * Get the SWT color to use for the given style, using the provided color
     * description if we haven't seen this color yet. The color will also be
     * placed in the map referenced by the map parameter such that it can be
     * disposed of at cleanup time.
     *
     * @param style The drawing style for which we want a color
     * @param defaultColorDesc The RGB values to initialize the color to if we
     *            haven't seen this color before
     * @param map The color map to use
     * @return The color object
     */
    private Color getStyleColor(DrawingStyle style, RGB defaultColorDesc,
            Map<DrawingStyle, Color> map) {
        Color color = map.get(style);
        if (color == null) {
            color = new Color(getGc().getDevice(), defaultColorDesc);
            map.put(style, color);
        }

        return color;
    }

    // dots

    @Override
    public void drawPoint(int x, int y) {
        checkGC();
        useStrokeAlpha();
        x = mHScale.translate(x);
        y = mVScale.translate(y);

        getGc().drawPoint(x, y);
    }

    // arrows

    private static final int MIN_LENGTH = 10;


    @Override
    public void drawArrow(int x1, int y1, int x2, int y2, int size) {
        int arrowWidth = size;
        int arrowHeight = size;

        checkGC();
        useStrokeAlpha();
        x1 = mHScale.translate(x1);
        y1 = mVScale.translate(y1);
        x2 = mHScale.translate(x2);
        y2 = mVScale.translate(y2);
        GC graphics = getGc();

        // Make size adjustments to ensure that the arrow has enough width to be visible
        if (x1 == x2 && Math.abs(y1 - y2) < MIN_LENGTH) {
            int delta = (MIN_LENGTH - Math.abs(y1 - y2)) / 2;
            if (y1 < y2) {
                y1 -= delta;
                y2 += delta;
            } else {
                y1 += delta;
                y2-= delta;
            }

        } else if (y1 == y2 && Math.abs(x1 - x2) < MIN_LENGTH) {
            int delta = (MIN_LENGTH - Math.abs(x1 - x2)) / 2;
            if (x1 < x2) {
                x1 -= delta;
                x2 += delta;
            } else {
                x1 += delta;
                x2-= delta;
            }
        }

        graphics.drawLine(x1, y1, x2, y2);

        // Arrowhead:

        if (x1 == x2) {
            // Vertical
            if (y2 > y1) {
                graphics.drawLine(x2 - arrowWidth, y2 - arrowHeight, x2, y2);
                graphics.drawLine(x2 + arrowWidth, y2 - arrowHeight, x2, y2);
            } else {
                graphics.drawLine(x2 - arrowWidth, y2 + arrowHeight, x2, y2);
                graphics.drawLine(x2 + arrowWidth, y2 + arrowHeight, x2, y2);
            }
        } else if (y1 == y2) {
            // Horizontal
            if (x2 > x1) {
                graphics.drawLine(x2 - arrowHeight, y2 - arrowWidth, x2, y2);
                graphics.drawLine(x2 - arrowHeight, y2 + arrowWidth, x2, y2);
            } else {
                graphics.drawLine(x2 + arrowHeight, y2 - arrowWidth, x2, y2);
                graphics.drawLine(x2 + arrowHeight, y2 + arrowWidth, x2, y2);
            }
        } else {
            // Compute angle:
            int dy = y2 - y1;
            int dx = x2 - x1;
            double angle = Math.atan2(dy, dx);
            double lineLength = Math.sqrt(dy * dy + dx * dx);

            // Imagine a line of the same length as the arrow, but with angle 0.
            // Its two arrow lines are at (-arrowWidth, -arrowHeight) relative
            // to the endpoint (x1 + lineLength, y1) stretching up to (x2,y2).
            // We compute the positions of (ax,ay) for the point above and
            // below this line and paint the lines to it:
            double ax = x1 + lineLength - arrowHeight;
            double ay = y1 - arrowWidth;
            int rx = (int) (Math.cos(angle) * (ax-x1) - Math.sin(angle) * (ay-y1) + x1);
            int ry = (int) (Math.sin(angle) * (ax-x1) + Math.cos(angle) * (ay-y1) + y1);
            graphics.drawLine(x2, y2, rx, ry);

            ay = y1 + arrowWidth;
            rx = (int) (Math.cos(angle) * (ax-x1) - Math.sin(angle) * (ay-y1) + x1);
            ry = (int) (Math.sin(angle) * (ax-x1) + Math.cos(angle) * (ay-y1) + y1);
            graphics.drawLine(x2, y2, rx, ry);
        }

        /* TODO: Experiment with filled arrow heads?
        if (x1 == x2) {
            // Vertical
            if (y2 > y1) {
                for (int i = 0; i < arrowWidth; i++) {
                    graphics.drawLine(x2 - arrowWidth + i, y2 - arrowWidth + i,
                            x2 + arrowWidth - i, y2 - arrowWidth + i);
                }
            } else {
                for (int i = 0; i < arrowWidth; i++) {
                    graphics.drawLine(x2 - arrowWidth + i, y2 + arrowWidth - i,
                            x2 + arrowWidth - i, y2 + arrowWidth - i);
                }
            }
        } else if (y1 == y2) {
            // Horizontal
            if (x2 > x1) {
                for (int i = 0; i < arrowHeight; i++) {
                    graphics.drawLine(x2 - arrowHeight + i, y2 - arrowHeight + i, x2
                            - arrowHeight + i, y2 + arrowHeight - i);
                }
            } else {
                for (int i = 0; i < arrowHeight; i++) {
                    graphics.drawLine(x2 + arrowHeight - i, y2 - arrowHeight + i, x2
                            + arrowHeight - i, y2 + arrowHeight - i);
                }
            }
        } else {
            // Arbitrary angle -- need to use trig
            // TODO: Implement this
        }
        */
    }
}
