/*
 * Copyright (C) 2008 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.music;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

public class VerticalTextSpinner extends View {
    private static final int SELECTOR_ARROW_HEIGHT = 15;

    private static int TEXT_SPACING;
    private static int TEXT_MARGIN_RIGHT;
    private static int TEXT_SIZE;
    private static int TEXT1_Y;
    private static int TEXT2_Y;
    private static int TEXT3_Y;
    private static int TEXT4_Y;
    private static int TEXT5_Y;
    private static int SCROLL_DISTANCE;

    private static final int SCROLL_MODE_NONE = 0;
    private static final int SCROLL_MODE_UP = 1;
    private static final int SCROLL_MODE_DOWN = 2;

    private static final long DEFAULT_SCROLL_INTERVAL_MS = 400;
    private static final int MIN_ANIMATIONS = 4;

    private final Drawable mBackgroundFocused;
    private final Drawable mSelectorFocused;
    private final Drawable mSelectorNormal;
    private final int mSelectorDefaultY;
    private final int mSelectorMinY;
    private final int mSelectorMaxY;
    private final int mSelectorHeight;
    private final TextPaint mTextPaintDark;
    private final TextPaint mTextPaintLight;

    private int mSelectorY;
    private Drawable mSelector;
    private int mDownY;
    private boolean isDraggingSelector;
    private int mScrollMode;
    private long mScrollInterval;
    private boolean mIsAnimationRunning;
    private boolean mStopAnimation;
    private boolean mWrapAround = true;

    private int mTotalAnimatedDistance;
    private int mNumberOfAnimations;
    private long mDelayBetweenAnimations;
    private int mDistanceOfEachAnimation;

    private String[] mTextList;
    private int mCurrentSelectedPos;
    private OnChangedListener mListener;

    private String mText1;
    private String mText2;
    private String mText3;
    private String mText4;
    private String mText5;

    public interface OnChangedListener {
        void onChanged(VerticalTextSpinner spinner, int oldPos, int newPos, String[] items);
    }

    public VerticalTextSpinner(Context context) {
        this(context, null);
    }

    public VerticalTextSpinner(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VerticalTextSpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        float scale = getResources().getDisplayMetrics().density;
        TEXT_SPACING = (int) (18 * scale);
        TEXT_MARGIN_RIGHT = (int) (25 * scale);
        TEXT_SIZE = (int) (22 * scale);
        SCROLL_DISTANCE = TEXT_SIZE + TEXT_SPACING;
        TEXT1_Y = (TEXT_SIZE * (-2 + 2)) + (TEXT_SPACING * (-2 + 1));
        TEXT2_Y = (TEXT_SIZE * (-1 + 2)) + (TEXT_SPACING * (-1 + 1));
        TEXT3_Y = (TEXT_SIZE * (0 + 2)) + (TEXT_SPACING * (0 + 1));
        TEXT4_Y = (TEXT_SIZE * (1 + 2)) + (TEXT_SPACING * (1 + 1));
        TEXT5_Y = (TEXT_SIZE * (2 + 2)) + (TEXT_SPACING * (2 + 1));

        mBackgroundFocused = context.getResources().getDrawable(R.drawable.pickerbox_background);
        mSelectorFocused = context.getResources().getDrawable(R.drawable.pickerbox_selected);
        mSelectorNormal = context.getResources().getDrawable(R.drawable.pickerbox_unselected);

        mSelectorHeight = mSelectorFocused.getIntrinsicHeight();
        mSelectorDefaultY = (mBackgroundFocused.getIntrinsicHeight() - mSelectorHeight) / 2;
        mSelectorMinY = 0;
        mSelectorMaxY = mBackgroundFocused.getIntrinsicHeight() - mSelectorHeight;

        mSelector = mSelectorNormal;
        mSelectorY = mSelectorDefaultY;

        mTextPaintDark = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaintDark.setTextSize(TEXT_SIZE);
        mTextPaintDark.setColor(
                context.getResources().getColor(android.R.color.primary_text_light));

        mTextPaintLight = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaintLight.setTextSize(TEXT_SIZE);
        mTextPaintLight.setColor(
                context.getResources().getColor(android.R.color.secondary_text_dark));

        mScrollMode = SCROLL_MODE_NONE;
        mScrollInterval = DEFAULT_SCROLL_INTERVAL_MS;
        calculateAnimationValues();
    }

    public void setOnChangeListener(OnChangedListener listener) {
        mListener = listener;
    }

    public void setItems(String[] textList) {
        mTextList = textList;
        calculateTextPositions();
    }

    public void setSelectedPos(int selectedPos) {
        mCurrentSelectedPos = selectedPos;
        calculateTextPositions();
        postInvalidate();
    }

    public void setScrollInterval(long interval) {
        mScrollInterval = interval;
        calculateAnimationValues();
    }

    public void setWrapAround(boolean wrap) {
        mWrapAround = wrap;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        /* This is a bit confusing, when we get the key event
         * DPAD_DOWN we actually roll the spinner up. When the
         * key event is DPAD_UP we roll the spinner down.
         */
        if ((keyCode == KeyEvent.KEYCODE_DPAD_UP) && canScrollDown()) {
            mScrollMode = SCROLL_MODE_DOWN;
            scroll();
            mStopAnimation = true;
            return true;
        } else if ((keyCode == KeyEvent.KEYCODE_DPAD_DOWN) && canScrollUp()) {
            mScrollMode = SCROLL_MODE_UP;
            scroll();
            mStopAnimation = true;
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    private boolean canScrollDown() {
        return (mCurrentSelectedPos > 0) || mWrapAround;
    }

    private boolean canScrollUp() {
        return ((mCurrentSelectedPos < (mTextList.length - 1)) || mWrapAround);
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
        if (gainFocus) {
            setBackgroundDrawable(mBackgroundFocused);
            mSelector = mSelectorFocused;
        } else {
            setBackgroundDrawable(null);
            mSelector = mSelectorNormal;
            mSelectorY = mSelectorDefaultY;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final int y = (int) event.getY();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                requestFocus();
                mDownY = y;
                isDraggingSelector =
                        (y >= mSelectorY) && (y <= (mSelectorY + mSelector.getIntrinsicHeight()));
                break;

            case MotionEvent.ACTION_MOVE:
                if (isDraggingSelector) {
                    int top = mSelectorDefaultY + (y - mDownY);
                    if (top <= mSelectorMinY && canScrollDown()) {
                        mSelectorY = mSelectorMinY;
                        mStopAnimation = false;
                        if (mScrollMode != SCROLL_MODE_DOWN) {
                            mScrollMode = SCROLL_MODE_DOWN;
                            scroll();
                        }
                    } else if (top >= mSelectorMaxY && canScrollUp()) {
                        mSelectorY = mSelectorMaxY;
                        mStopAnimation = false;
                        if (mScrollMode != SCROLL_MODE_UP) {
                            mScrollMode = SCROLL_MODE_UP;
                            scroll();
                        }
                    } else {
                        mSelectorY = top;
                        mStopAnimation = true;
                    }
                }
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
            default:
                mSelectorY = mSelectorDefaultY;
                mStopAnimation = true;
                invalidate();
                break;
        }
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        /* The bounds of the selector */
        final int selectorLeft = 0;
        final int selectorTop = mSelectorY;
        final int selectorRight = getWidth();
        final int selectorBottom = mSelectorY + mSelectorHeight;

        /* Draw the selector */
        mSelector.setBounds(selectorLeft, selectorTop, selectorRight, selectorBottom);
        mSelector.draw(canvas);

        if (mTextList == null) {
            /* We're not setup with values so don't draw anything else */
            return;
        }

        final TextPaint textPaintDark = mTextPaintDark;
        if (hasFocus()) {
            /* The bounds of the top area where the text should be light */
            final int topLeft = 0;
            final int topTop = 0;
            final int topRight = selectorRight;
            final int topBottom = selectorTop + SELECTOR_ARROW_HEIGHT;

            /* Assign a bunch of local finals for performance */
            final String text1 = mText1;
            final String text2 = mText2;
            final String text3 = mText3;
            final String text4 = mText4;
            final String text5 = mText5;
            final TextPaint textPaintLight = mTextPaintLight;

            /*
             * Draw the 1st, 2nd and 3rd item in light only, clip it so it only
             * draws in the area above the selector
             */
            canvas.save();
            canvas.clipRect(topLeft, topTop, topRight, topBottom);
            drawText(canvas, text1, TEXT1_Y + mTotalAnimatedDistance, textPaintLight);
            drawText(canvas, text2, TEXT2_Y + mTotalAnimatedDistance, textPaintLight);
            drawText(canvas, text3, TEXT3_Y + mTotalAnimatedDistance, textPaintLight);
            canvas.restore();

            /*
             * Draw the 2nd, 3rd and 4th clipped to the selector bounds in dark
             * paint
             */
            canvas.save();
            canvas.clipRect(selectorLeft, selectorTop + SELECTOR_ARROW_HEIGHT, selectorRight,
                    selectorBottom - SELECTOR_ARROW_HEIGHT);
            drawText(canvas, text2, TEXT2_Y + mTotalAnimatedDistance, textPaintDark);
            drawText(canvas, text3, TEXT3_Y + mTotalAnimatedDistance, textPaintDark);
            drawText(canvas, text4, TEXT4_Y + mTotalAnimatedDistance, textPaintDark);
            canvas.restore();

            /* The bounds of the bottom area where the text should be light */
            final int bottomLeft = 0;
            final int bottomTop = selectorBottom - SELECTOR_ARROW_HEIGHT;
            final int bottomRight = selectorRight;
            final int bottomBottom = getMeasuredHeight();

            /*
             * Draw the 3rd, 4th and 5th in white text, clip it so it only draws
             * in the area below the selector.
             */
            canvas.save();
            canvas.clipRect(bottomLeft, bottomTop, bottomRight, bottomBottom);
            drawText(canvas, text3, TEXT3_Y + mTotalAnimatedDistance, textPaintLight);
            drawText(canvas, text4, TEXT4_Y + mTotalAnimatedDistance, textPaintLight);
            drawText(canvas, text5, TEXT5_Y + mTotalAnimatedDistance, textPaintLight);
            canvas.restore();

        } else {
            drawText(canvas, mText3, TEXT3_Y, textPaintDark);
        }
        if (mIsAnimationRunning) {
            if ((Math.abs(mTotalAnimatedDistance) + mDistanceOfEachAnimation) > SCROLL_DISTANCE) {
                mTotalAnimatedDistance = 0;
                if (mScrollMode == SCROLL_MODE_UP) {
                    int oldPos = mCurrentSelectedPos;
                    int newPos = getNewIndex(1);
                    if (newPos >= 0) {
                        mCurrentSelectedPos = newPos;
                        if (mListener != null) {
                            mListener.onChanged(this, oldPos, mCurrentSelectedPos, mTextList);
                        }
                    }
                    if (newPos < 0 || ((newPos >= mTextList.length - 1) && !mWrapAround)) {
                        mStopAnimation = true;
                    }
                    calculateTextPositions();
                } else if (mScrollMode == SCROLL_MODE_DOWN) {
                    int oldPos = mCurrentSelectedPos;
                    int newPos = getNewIndex(-1);
                    if (newPos >= 0) {
                        mCurrentSelectedPos = newPos;
                        if (mListener != null) {
                            mListener.onChanged(this, oldPos, mCurrentSelectedPos, mTextList);
                        }
                    }
                    if (newPos < 0 || (newPos == 0 && !mWrapAround)) {
                        mStopAnimation = true;
                    }
                    calculateTextPositions();
                }
                if (mStopAnimation) {
                    final int previousScrollMode = mScrollMode;

                    /* No longer scrolling, we wait till the current animation
                     * completes then we stop.
                     */
                    mIsAnimationRunning = false;
                    mStopAnimation = false;
                    mScrollMode = SCROLL_MODE_NONE;

                    /* If the current selected item is an empty string
                     * scroll past it.
                     */
                    if ("".equals(mTextList[mCurrentSelectedPos])) {
                        mScrollMode = previousScrollMode;
                        scroll();
                        mStopAnimation = true;
                    }
                }
            } else {
                if (mScrollMode == SCROLL_MODE_UP) {
                    mTotalAnimatedDistance -= mDistanceOfEachAnimation;
                } else if (mScrollMode == SCROLL_MODE_DOWN) {
                    mTotalAnimatedDistance += mDistanceOfEachAnimation;
                }
            }
            if (mDelayBetweenAnimations > 0) {
                postInvalidateDelayed(mDelayBetweenAnimations);
            } else {
                invalidate();
            }
        }
    }

    /**
     * Called every time the text items or current position
     * changes. We calculate store we don't have to calculate
     * onDraw.
     */
    private void calculateTextPositions() {
        mText1 = getTextToDraw(-2);
        mText2 = getTextToDraw(-1);
        mText3 = getTextToDraw(0);
        mText4 = getTextToDraw(1);
        mText5 = getTextToDraw(2);
    }

    private String getTextToDraw(int offset) {
        int index = getNewIndex(offset);
        if (index < 0) {
            return "";
        }
        return mTextList[index];
    }

    private int getNewIndex(int offset) {
        int index = mCurrentSelectedPos + offset;
        if (index < 0) {
            if (mWrapAround) {
                index += mTextList.length;
            } else {
                return -1;
            }
        } else if (index >= mTextList.length) {
            if (mWrapAround) {
                index -= mTextList.length;
            } else {
                return -1;
            }
        }
        return index;
    }

    private void scroll() {
        if (mIsAnimationRunning) {
            return;
        }
        mTotalAnimatedDistance = 0;
        mIsAnimationRunning = true;
        invalidate();
    }

    private void calculateAnimationValues() {
        mNumberOfAnimations = (int) mScrollInterval / SCROLL_DISTANCE;
        if (mNumberOfAnimations < MIN_ANIMATIONS) {
            mNumberOfAnimations = MIN_ANIMATIONS;
            mDistanceOfEachAnimation = SCROLL_DISTANCE / mNumberOfAnimations;
            mDelayBetweenAnimations = 0;
        } else {
            mDistanceOfEachAnimation = SCROLL_DISTANCE / mNumberOfAnimations;
            mDelayBetweenAnimations = mScrollInterval / mNumberOfAnimations;
        }
    }

    private void drawText(Canvas canvas, String text, int y, TextPaint paint) {
        int width = (int) paint.measureText(text);
        int x = getMeasuredWidth() - width - TEXT_MARGIN_RIGHT;
        canvas.drawText(text, x, y, paint);
    }

    public int getCurrentSelectedPos() {
        return mCurrentSelectedPos;
    }
}
