/*
 * Copyright (C) 2013 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.gallery3d.filtershow.colorpicker;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

import com.android.gallery3d.R;

import java.util.ArrayList;

public class ColorRectView extends View implements ColorListener {
    private float mDpToPix;
    private float mRadius = 80;
    private float mCtrY = 100;
    private Paint mWheelPaint1;
    private Paint mWheelPaint2;
    private Paint mWheelPaint3;
    private float mCtrX = 100;
    private Paint mDotPaint;
    private float mDotRadus;
    private float mBorder;
    private int mBgcolor = 0;
    private float mDotX = Float.NaN;
    private float mDotY;
    private int mSliderColor = 0xFF33B5E5;
    private float[] mHSVO = new float[4];
    private int[] mColors = new int[] {
            0xFFFF0000,// red
            0xFFFFFF00,// yellow
            0xFF00FF00,// green
            0xFF00FFFF,// cyan
            0xFF0000FF,// blue
            0xFFFF00FF,// magenta
            0xFFFF0000,// red
    };
    private int mWidth;
    private int mHeight;
    public final static float DOT_SIZE = 20;
    public final static float BORDER_SIZE = 10;

    public ColorRectView(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);

        DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
        mDpToPix = metrics.density;
        mDotRadus = DOT_SIZE * mDpToPix;
        mBorder = BORDER_SIZE * mDpToPix;

        mWheelPaint1 = new Paint();
        mWheelPaint2 = new Paint();
        mWheelPaint3 = new Paint();
        mDotPaint = new Paint();

        mDotPaint.setStyle(Paint.Style.FILL);
        mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color));
        mSliderColor = ctx.getResources().getColor(R.color.slider_line_color);
        mWheelPaint1.setStyle(Paint.Style.FILL);
        mWheelPaint2.setStyle(Paint.Style.FILL);
        mWheelPaint3.setStyle(Paint.Style.FILL);
    }

    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
                (int) (mDotY + mDotRadus));
        float x = event.getX();
        float y = event.getY();

        x = Math.max(Math.min(x, mWidth - mBorder), mBorder);
        y = Math.max(Math.min(y, mHeight - mBorder), mBorder);
        mDotX = x;
        mDotY = y;
        float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder);
        if (sat > 1) {
            sat = 1;
        }

        double hue = Math.PI * 2 * (mDotX - mBorder) / (mHeight - 2 * mBorder);
        mHSVO[0] = ((float) Math.toDegrees(hue) + 360) % 360;
        mHSVO[1] = sat;
        notifyColorListeners(mHSVO);
        updateDotPaint();
        invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus),
                (int) (mDotY + mDotRadus));

        return true;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mWidth = w;
        mHeight = h;
        mCtrY = h / 2f;
        mCtrX = w / 2f;
        mRadius = Math.min(mCtrY, mCtrX) - 2 * mBorder;
        setUpColorPanel();
    }

    private void setUpColorPanel() {
        float val = mHSVO[2];
        int v = 0xFF000000 | 0x10101 * (int) (val * 0xFF);
        int[] colors = new int[] {
                0x0000000, v };
        int[] colors2 = new int[] {
                0x0000000, 0xFF000000 };
        int[] wheelColor = new int[mColors.length];
        float[] hsv = new float[3];
        for (int i = 0; i < wheelColor.length; i++) {
            Color.colorToHSV(mColors[i], hsv);
            hsv[2] = mHSVO[2];
            wheelColor[i] = Color.HSVToColor(hsv);
        }
        updateDot();
        updateDotPaint();
        SweepGradient sg = new SweepGradient(mCtrX, mCtrY, wheelColor, null);
        LinearGradient lg = new LinearGradient(
                mBorder, 0, mWidth - mBorder, 0, wheelColor, null, Shader.TileMode.CLAMP);

        mWheelPaint1.setShader(lg);
        LinearGradient rg = new LinearGradient(
                0, mBorder, 0, mHeight - mBorder, colors, null, Shader.TileMode.CLAMP);
        mWheelPaint2.setShader(rg);
        LinearGradient rg2 = new LinearGradient(
                0, mBorder, 0, mHeight - mBorder, colors2, null, Shader.TileMode.CLAMP);
        mWheelPaint3.setShader(rg2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(mBgcolor);
        RectF rect = new RectF();
        rect.left = mBorder;
        rect.right = mWidth - mBorder;
        rect.top = mBorder;
        rect.bottom = mHeight - mBorder;

        canvas.drawRect(rect, mWheelPaint1);
        canvas.drawRect(rect, mWheelPaint3);
        canvas.drawRect(rect, mWheelPaint2);

        if (!Float.isNaN(mDotX)) {
            canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint);
        }
    }

    private void updateDot() {

        double hue = mHSVO[0];
        double sat = mHSVO[1];

        mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * Math.toRadians(hue) / (Math.PI * 2));
        mDotY = (float) ((1 - sat) * (mHeight - 2 * mBorder) + mBorder);

    }

    private void updateDotPaint() {
        int[] colors3 = new int[] {
                mSliderColor, mSliderColor, 0x66000000, 0 };
        RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[] {
                0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
        mDotPaint.setShader(g);

    }

    @Override
    public void setColor(float[] hsvo) {
        System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length);

        setUpColorPanel();
        invalidate();

        updateDot();
        updateDotPaint();

    }

    ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>();

    public void notifyColorListeners(float[] hsv) {
        for (ColorListener l : mColorListeners) {
            l.setColor(hsv);
        }
    }

    public void addColorListener(ColorListener l) {
        mColorListeners.add(l);
    }

    public void removeColorListener(ColorListener l) {
        mColorListeners.remove(l);
    }
}
