/**
 *
 */
package com.android.settings.applications;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import com.android.settings.Utils;

public class LinearColorBar extends LinearLayout {

    static final int RIGHT_COLOR = 0xffced7db;
    static final int GRAY_COLOR = 0xff555555;
    static final int WHITE_COLOR = 0xffffffff;

    private float mRedRatio;
    private float mYellowRatio;
    private float mGreenRatio;

    private int mLeftColor;
    private int mMiddleColor;
    private int mRightColor = RIGHT_COLOR;

    private boolean mShowIndicator = true;
    private boolean mShowingGreen;

    private OnRegionTappedListener mOnRegionTappedListener;
    private int mColoredRegions = REGION_RED | REGION_YELLOW | REGION_GREEN;

    final Rect mRect = new Rect();
    final Paint mPaint = new Paint();

    int mLastInterestingLeft, mLastInterestingRight;
    int mLineWidth;

    int mLastLeftDiv, mLastRightDiv;
    int mLastRegion;

    final Path mColorPath = new Path();
    final Path mEdgePath = new Path();
    final Paint mColorGradientPaint = new Paint();
    final Paint mEdgeGradientPaint = new Paint();

    public static final int REGION_RED = 1<<0;
    public static final int REGION_YELLOW = 1<<1;
    public static final int REGION_GREEN = 1<<2;
    public static final int REGION_ALL = REGION_RED | REGION_YELLOW | REGION_GREEN;

    public interface OnRegionTappedListener {
        public void onRegionTapped(int region);
    }

    public LinearColorBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        setWillNotDraw(false);
        mPaint.setStyle(Paint.Style.FILL);
        mColorGradientPaint.setStyle(Paint.Style.FILL);
        mColorGradientPaint.setAntiAlias(true);
        mEdgeGradientPaint.setStyle(Paint.Style.STROKE);
        mLineWidth = getResources().getDisplayMetrics().densityDpi >= DisplayMetrics.DENSITY_HIGH
                ? 2 : 1;
        mEdgeGradientPaint.setStrokeWidth(mLineWidth);
        mEdgeGradientPaint.setAntiAlias(true);
        mLeftColor = mMiddleColor = Utils.getColorAccent(context);
    }

    public void setOnRegionTappedListener(OnRegionTappedListener listener) {
        if (listener != mOnRegionTappedListener) {
            mOnRegionTappedListener = listener;
            setClickable(listener != null);
        }
    }

    public void setColoredRegions(int regions) {
        mColoredRegions = regions;
        invalidate();
    }

    public void setRatios(float red, float yellow, float green) {
        mRedRatio = red;
        mYellowRatio = yellow;
        mGreenRatio = green;
        invalidate();
    }

    public void setColors(int red, int yellow, int green) {
        mLeftColor = red;
        mMiddleColor = yellow;
        mRightColor = green;
        updateIndicator();
        invalidate();
    }

    public void setShowIndicator(boolean showIndicator) {
        mShowIndicator = showIndicator;
        updateIndicator();
        invalidate();
    }

    public void setShowingGreen(boolean showingGreen) {
        if (mShowingGreen != showingGreen) {
            mShowingGreen = showingGreen;
            updateIndicator();
            invalidate();
        }
    }

    private void updateIndicator() {
        int off = getPaddingTop() - getPaddingBottom();
        if (off < 0) off = 0;
        mRect.top = off;
        mRect.bottom = getHeight();
        if (!mShowIndicator) {
            return;
        }
        if (mShowingGreen) {
            mColorGradientPaint.setShader(new LinearGradient(
                    0, 0, 0, off-2, mRightColor &0xffffff, mRightColor, Shader.TileMode.CLAMP));
        } else {
            mColorGradientPaint.setShader(new LinearGradient(
                    0, 0, 0, off-2, mMiddleColor&0xffffff, mMiddleColor, Shader.TileMode.CLAMP));
        }
        mEdgeGradientPaint.setShader(new LinearGradient(
                0, 0, 0, off/2, 0x00a0a0a0, 0xffa0a0a0, Shader.TileMode.CLAMP));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        updateIndicator();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mOnRegionTappedListener != null) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    final int x = (int) event.getX();
                    if (x < mLastLeftDiv) {
                        mLastRegion = REGION_RED;
                    } else if (x < mLastRightDiv) {
                        mLastRegion = REGION_YELLOW;
                    } else {
                        mLastRegion = REGION_GREEN;
                    }
                    invalidate();
                } break;
            }
        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void dispatchSetPressed(boolean pressed) {
        invalidate();
    }

    @Override
    public boolean performClick() {
        if (mOnRegionTappedListener != null && mLastRegion != 0) {
            mOnRegionTappedListener.onRegionTapped(mLastRegion);
            mLastRegion = 0;
        }
        return super.performClick();
    }

    private int pickColor(int color, int region) {
        if (isPressed() && (mLastRegion&region) != 0) {
            return WHITE_COLOR;
        }
        if ((mColoredRegions&region) == 0) {
            return GRAY_COLOR;
        }
        return color;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();

        int left = 0;

        int right = left + (int)(width*mRedRatio);
        int right2 = right + (int)(width*mYellowRatio);
        int right3 = right2 + (int)(width*mGreenRatio);

        int indicatorLeft, indicatorRight;
        if (mShowingGreen) {
            indicatorLeft = right2;
            indicatorRight = right3;
        } else {
            indicatorLeft = right;
            indicatorRight = right2;
        }

        if (mLastInterestingLeft != indicatorLeft || mLastInterestingRight != indicatorRight) {
            mColorPath.reset();
            mEdgePath.reset();
            if (mShowIndicator && indicatorLeft < indicatorRight) {
                final int midTopY = mRect.top;
                final int midBottomY = 0;
                final int xoff = 2;
                mColorPath.moveTo(indicatorLeft, mRect.top);
                mColorPath.cubicTo(indicatorLeft, midBottomY,
                        -xoff, midTopY,
                        -xoff, 0);
                mColorPath.lineTo(width+xoff-1, 0);
                mColorPath.cubicTo(width+xoff-1, midTopY,
                        indicatorRight, midBottomY,
                        indicatorRight, mRect.top);
                mColorPath.close();
                final float lineOffset = mLineWidth+.5f;
                mEdgePath.moveTo(-xoff+lineOffset, 0);
                mEdgePath.cubicTo(-xoff+lineOffset, midTopY,
                        indicatorLeft+lineOffset, midBottomY,
                        indicatorLeft+lineOffset, mRect.top);
                mEdgePath.moveTo(width+xoff-1-lineOffset, 0);
                mEdgePath.cubicTo(width+xoff-1-lineOffset, midTopY,
                        indicatorRight-lineOffset, midBottomY,
                        indicatorRight-lineOffset, mRect.top);
            }
            mLastInterestingLeft = indicatorLeft;
            mLastInterestingRight = indicatorRight;
        }

        if (!mEdgePath.isEmpty()) {
            canvas.drawPath(mEdgePath, mEdgeGradientPaint);
            canvas.drawPath(mColorPath, mColorGradientPaint);
        }

        if (left < right) {
            mRect.left = left;
            mRect.right = right;
            mPaint.setColor(pickColor(mLeftColor, REGION_RED));
            canvas.drawRect(mRect, mPaint);
            width -= (right-left);
            left = right;
        }

        mLastLeftDiv = right;
        mLastRightDiv = right2;

        right = right2;

        if (left < right) {
            mRect.left = left;
            mRect.right = right;
            mPaint.setColor(pickColor(mMiddleColor, REGION_YELLOW));
            canvas.drawRect(mRect, mPaint);
            width -= (right-left);
            left = right;
        }


        right = left + width;
        if (left < right) {
            mRect.left = left;
            mRect.right = right;
            mPaint.setColor(pickColor(mRightColor, REGION_GREEN));
            canvas.drawRect(mRect, mPaint);
        }
    }
}