/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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 com.android.hierarchyviewerlib.ui;

import com.android.hierarchyviewerlib.models.PixelPerfectModel;
import com.android.hierarchyviewerlib.models.PixelPerfectModel.IImageChangeListener;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

public class PixelPerfectPixelPanel extends Canvas implements IImageChangeListener {
    private PixelPerfectModel mModel;

    private Image mImage;

    private Image mOverlayImage;

    private Point mCrosshairLocation;

    public static final int PREFERRED_WIDTH = 180;

    public static final int PREFERRED_HEIGHT = 52;

    public PixelPerfectPixelPanel(Composite parent) {
        super(parent, SWT.NONE);
        mModel = PixelPerfectModel.getModel();
        mModel.addImageChangeListener(this);

        addPaintListener(mPaintListener);
        addDisposeListener(mDisposeListener);

        imageLoaded();
    }

    @Override
    public Point computeSize(int wHint, int hHint, boolean changed) {
        int height = PREFERRED_HEIGHT;
        int width = (wHint == SWT.DEFAULT) ? PREFERRED_WIDTH : wHint;
        return new Point(width, height);
    }

    private DisposeListener mDisposeListener = new DisposeListener() {
        @Override
        public void widgetDisposed(DisposeEvent e) {
            mModel.removeImageChangeListener(PixelPerfectPixelPanel.this);
        }
    };

    private PaintListener mPaintListener = new PaintListener() {
        @Override
        public void paintControl(PaintEvent e) {
            synchronized (PixelPerfectPixelPanel.this) {
                e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
                e.gc.fillRectangle(0, 0, getBounds().width, getBounds().height);
                if (mImage != null) {
                    RGB pixel =
                            mImage.getImageData().palette.getRGB(mImage.getImageData().getPixel(
                                    mCrosshairLocation.x, mCrosshairLocation.y));
                    Color rgbColor = new Color(Display.getDefault(), pixel);
                    e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
                    e.gc.setBackground(rgbColor);
                    e.gc.drawRectangle(4, 4, 60, 30);
                    e.gc.fillRectangle(5, 5, 59, 29);
                    rgbColor.dispose();
                    e.gc.drawText("#"
                            + Integer
                                    .toHexString(
                                            (1 << 24) + (pixel.red << 16) + (pixel.green << 8)
                                                    + pixel.blue).substring(1), 4, 35, true);
                    e.gc.drawText("R:", 80, 4, true);
                    e.gc.drawText("G:", 80, 20, true);
                    e.gc.drawText("B:", 80, 35, true);
                    e.gc.drawText(Integer.toString(pixel.red), 97, 4, true);
                    e.gc.drawText(Integer.toString(pixel.green), 97, 20, true);
                    e.gc.drawText(Integer.toString(pixel.blue), 97, 35, true);
                    e.gc.drawText("X:", 132, 4, true);
                    e.gc.drawText("Y:", 132, 20, true);
                    e.gc.drawText(Integer.toString(mCrosshairLocation.x) + " px", 149, 4, true);
                    e.gc.drawText(Integer.toString(mCrosshairLocation.y) + " px", 149, 20, true);

                    if (mOverlayImage != null) {
                        int xInOverlay = mCrosshairLocation.x;
                        int yInOverlay =
                                mCrosshairLocation.y
                                        - (mImage.getBounds().height - mOverlayImage.getBounds().height);
                        if (xInOverlay >= 0 && yInOverlay >= 0
                                && xInOverlay < mOverlayImage.getBounds().width
                                && yInOverlay < mOverlayImage.getBounds().height) {
                            pixel =
                                    mOverlayImage.getImageData().palette.getRGB(mOverlayImage
                                            .getImageData().getPixel(xInOverlay, yInOverlay));
                            rgbColor = new Color(Display.getDefault(), pixel);
                            e.gc
                                    .setForeground(Display.getDefault().getSystemColor(
                                            SWT.COLOR_WHITE));
                            e.gc.setBackground(rgbColor);
                            e.gc.drawRectangle(204, 4, 60, 30);
                            e.gc.fillRectangle(205, 5, 59, 29);
                            rgbColor.dispose();
                            e.gc.drawText("#"
                                    + Integer.toHexString(
                                            (1 << 24) + (pixel.red << 16) + (pixel.green << 8)
                                                    + pixel.blue).substring(1), 204, 35, true);
                            e.gc.drawText("R:", 280, 4, true);
                            e.gc.drawText("G:", 280, 20, true);
                            e.gc.drawText("B:", 280, 35, true);
                            e.gc.drawText(Integer.toString(pixel.red), 297, 4, true);
                            e.gc.drawText(Integer.toString(pixel.green), 297, 20, true);
                            e.gc.drawText(Integer.toString(pixel.blue), 297, 35, true);
                        }
                    }
                }
            }
        }
    };

    private void doRedraw() {
        Display.getDefault().syncExec(new Runnable() {
            @Override
            public void run() {
                redraw();
            }
        });
    }

    @Override
    public void crosshairMoved() {
        synchronized (this) {
            mCrosshairLocation = mModel.getCrosshairLocation();
        }
        doRedraw();
    }

    @Override
    public void imageChanged() {
        synchronized (this) {
            mImage = mModel.getImage();
        }
        doRedraw();
    }

    @Override
    public void imageLoaded() {
        synchronized (this) {
            mImage = mModel.getImage();
            mCrosshairLocation = mModel.getCrosshairLocation();
            mOverlayImage = mModel.getOverlayImage();
        }
        doRedraw();
    }

    @Override
    public void overlayChanged() {
        synchronized (this) {
            mOverlayImage = mModel.getOverlayImage();
        }
        doRedraw();
    }

    @Override
    public void overlayTransparencyChanged() {
        // pass
    }

    @Override
    public void selectionChanged() {
        // pass
    }

    @Override
    public void treeChanged() {
        // pass
    }

    @Override
    public void zoomChanged() {
        // pass
    }
}
