package com.aquarius.customview;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

import java.util.ArrayList;
import java.util.Random;

/**
 * Created by aquarius on 17-4-11.
 */
public class LotteryView extends View {

    private int mScreenWidth;   // 屏幕宽度
    private int mScreenHeight;  // 屏幕高度

    private int mSelfTotalWidth;    // 自身最大的宽度

    private static float DEFAULT_SIZE_FACTOR = 0.85f;   // 自身占用屏幕宽度的比例

    private int mOuterCircleWidth;  // 最外边圆环
    private Paint mOuterCirclePaint;
    private int mOuterCircleBackgroundColor;

    private Paint mInnerPaint;
    private int mInnerCircleBackgroundColor;

    private Paint mSmallCirclePaint;
    private int mSmallCircleBlueColor;
    private int mSmallCircleYellowColor;
    private int mInnerCardTextColor;
    private int mCenterCardBackgroundColor;
    private int mInnerCardDefaultColor;

    private int mSmallCircleRadius;  // 小圆圈半径
    private int mInnerCardWidth;    // 卡片宽度
    private int mInnerCardSpace;    // 卡片间隔


    private boolean mHadInitial = false;
    private ArrayList<Pair<Pair<Integer, Integer>,Pair<Integer, Integer>>> mCardPositionInfoList;
    private Context mContext;
    private AlertDialog mAlertDialog;

    private int[] mPicResId;
    private String[] mInfoResArray;
    private Rect mBounds = new Rect();
    private float mSmallInfoTextSize;
    private float mBigInfoTextSize;

    private boolean mNeedRandomTimes = false;
    private int mInvalidateCircleCount;
    private int mInvalidateInnerCardCount;
    private int mLotteryInvalidateTimes;
    private boolean mStartAnimation = false; // not real animation
    private boolean mLastEndSelected = false;

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

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

    public LotteryView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mContext = context;
        acquireCustomAttValues(context, attrs);

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        mScreenWidth = dm.widthPixels;
        mScreenHeight = dm.heightPixels;
        mSelfTotalWidth = mScreenWidth < mScreenHeight ?
                (int)(mScreenWidth * DEFAULT_SIZE_FACTOR) : (int)(mScreenHeight * DEFAULT_SIZE_FACTOR);

        mSmallInfoTextSize = context.getResources().getDimension(R.dimen.lotteryview_inner_card_text_size);
        mBigInfoTextSize = context.getResources().getDimension(R.dimen.lotteryview_inner_card_big_text_size);
        mOuterCircleWidth = (int) context.getResources().getDimension(R.dimen.lotteryview_outer_circle_width);
        mInnerCardSpace   = (int) context.getResources().getDimension(R.dimen.lotteryview_inner_card_blank);
        mInnerCardWidth   = (mSelfTotalWidth- getPaddingLeft() -getPaddingRight() - mOuterCircleWidth * 2 -  mInnerCardSpace * 4) / 3;
        mSmallCircleRadius = (int) context.getResources().getDimension(R.dimen.lotteryview_outer_small_circle_radius);

        mInnerCardTextColor = context.getResources().getColor(R.color.inner_card_text_color);
        mCenterCardBackgroundColor = context.getResources().getColor(R.color.center_card_bg_color);

        mOuterCircleBackgroundColor = context.getResources().getColor(R.color.outer_circle_bg_color);
        mOuterCirclePaint = new Paint();
        mOuterCirclePaint.setColor(mOuterCircleBackgroundColor);
        mOuterCirclePaint.setAntiAlias(true);
        mOuterCirclePaint.setStrokeWidth(mOuterCircleWidth);
        mOuterCirclePaint.setStyle(Paint.Style.FILL);

        mSmallCircleBlueColor = mSmallCircleBlueColor != 0 ? mSmallCircleBlueColor : context.getResources().getColor(R.color.small_circle_color_blue);
        mSmallCircleYellowColor = mSmallCircleYellowColor != 0 ? mSmallCircleYellowColor : context.getResources().getColor(R.color.small_circle_color_yellow);
        mSmallCirclePaint = new Paint();
        mSmallCirclePaint.setColor(mSmallCircleBlueColor);
        mSmallCirclePaint.setAntiAlias(true);
        mOuterCirclePaint.setStyle(Paint.Style.FILL);


        mInnerCircleBackgroundColor = context.getResources().getColor(R.color.inner_circle_bg_color);
        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setColor(mInnerCircleBackgroundColor);
        mInnerPaint.setStyle(Paint.Style.FILL);

        mCardPositionInfoList = new ArrayList<>();
        initResId();
    }

    private void acquireCustomAttValues(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LotteryView);
        mSmallCircleBlueColor   = ta.getColor(R.styleable.LotteryView_outer_small_circle_color_default, 0);
        mSmallCircleYellowColor = ta.getColor(R.styleable.LotteryView_outer_small_circle_color_active, 0);
        mLotteryInvalidateTimes = ta.getInt(R.styleable.LotteryView_lottery_invalidate_times, 0);
        DEFAULT_SIZE_FACTOR     = ta.getFloat(R.styleable.LotteryView_self_width_size_factor, DEFAULT_SIZE_FACTOR);
        mInnerCardDefaultColor  = ta.getColor(R.styleable.LotteryView_inner_round_card_color_default, Color.parseColor("#ffffff"));
        ta.recycle();
    }

    private void initResId() {
        mPicResId = new int[]{
                R.mipmap.icon_huawei_mobile, R.mipmap.icon_xiaomi_bracelet, R.mipmap.icon_qq_sport,
                R.mipmap.icon_gopro_camera, 0, R.mipmap.icon_misfit_flash,
                R.mipmap.icon_qq_sport, R.mipmap.icon_qq_gongzai, 0
        };

        mInfoResArray = mContext.getResources().getStringArray(R.array.jifeng_array_info);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(mSelfTotalWidth, mSelfTotalWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);
        drawOuterRoundCircle(canvas);
        drawOuterDecorateSmallCircle(canvas);
        drawInnerBackground(canvas);
        drawInnerCards(canvas);
        loopSmallCircleAnimation();
        loopInnerRoundCardAnimation();
    }

    /** 外层带圆角矩形圆环 */
    private void drawOuterRoundCircle(Canvas canvas) {
        canvas.save();
        canvas.clipRect(
                mOuterCircleWidth + getPaddingLeft(),
                mOuterCircleWidth + getPaddingTop(),
                mSelfTotalWidth - mOuterCircleWidth - getPaddingRight(),
                mSelfTotalWidth - mOuterCircleWidth - getPaddingBottom(),
                Region.Op.DIFFERENCE);

        canvas.drawRoundRect(
                getPaddingLeft(),
                getPaddingTop(),
                mSelfTotalWidth - getPaddingRight(),
                mSelfTotalWidth - getPaddingBottom(),
                18, 18, mOuterCirclePaint);
        canvas.restore();
    }


    private void drawOuterDecorateSmallCircle(Canvas canvas) {
        int result = mInvalidateCircleCount % 2;

        // top
        int x = 0, y = 0;
        int sideSize = mSelfTotalWidth - mOuterCircleWidth * 2 - getPaddingLeft() - getPaddingRight(); // 除去最外边圆环后的边长
        for (int i = 0; i < 10; i++) {
            mSmallCirclePaint.setColor(i % 2 == result ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mOuterCircleWidth + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingLeft();
            y = (mOuterCircleWidth - mSmallCircleRadius * 2) / 2 + mSmallCircleRadius + getPaddingTop();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }

        // bottom
        for (int i = 0; i < 10; i++) {
            mSmallCirclePaint.setColor(i % 2 == result ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mOuterCircleWidth + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingLeft();
            y = mSelfTotalWidth - mOuterCircleWidth + (mOuterCircleWidth - mSmallCircleRadius * 2) / 2 + mSmallCircleRadius - getPaddingBottom();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }

        // left
        for(int i = 0; i < 9; i++) {
            mSmallCirclePaint.setColor(i % 2 == (result == 0 ? 1 : 0) ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mOuterCircleWidth / 2 + getPaddingLeft();
            y =  mOuterCircleWidth*2 + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingTop();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }

        // right
        for(int i = 0; i < 9; i++) {
            mSmallCirclePaint.setColor(i % 2 == result ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mSelfTotalWidth - mOuterCircleWidth / 2 - getPaddingRight();
            y =  mOuterCircleWidth*2 + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingTop();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }
    }

    private void drawInnerBackground(Canvas canvas) {
        canvas.drawRect(mOuterCircleWidth + getPaddingLeft(), mOuterCircleWidth + getPaddingTop(),
                mSelfTotalWidth - mOuterCircleWidth - getPaddingRight(),
                mSelfTotalWidth - mOuterCircleWidth - getPaddingBottom(), mInnerPaint);
    }

    private void drawInnerCards(Canvas canvas) {
        int left = 0, top = 0, right = 0, bottom = 0;
        int spaceNum = 0;
        for(int i = 0 ; i < 9 ; i++) {
            spaceNum = i % 3 + 1;
            left = mOuterCircleWidth + mInnerCardWidth * (i%3) + mInnerCardSpace * spaceNum + getPaddingLeft();
            top = mOuterCircleWidth + mInnerCardWidth * (i/3) +mInnerCardSpace * (i/3 + 1) + getPaddingTop();
            right = left + mInnerCardWidth;
            bottom = top + mInnerCardWidth;
            if(!mHadInitial) {
                mCardPositionInfoList.add(new Pair(new Pair(left, right), new Pair(top, bottom)));
            }
            drawInnerRoundCard(canvas, left, top, right, bottom, i);
        }
        mHadInitial = true;
    }

    private void drawInnerRoundCard(Canvas canvas, int left, int top, int right, int bottom, int index) {

        boolean need = switchCardColorIfNeed(index);

        mInnerPaint.setColor(mInnerCardDefaultColor);

        if(mStartAnimation && need) {
            mInnerPaint.setColor(mOuterCircleBackgroundColor);
        }

        // 绘制内部小卡片
        if(index == 4) {
            mInnerPaint.setColor(Color.parseColor("#73D7F8"));
        }

        canvas.drawRoundRect(left, top, right, bottom, 12, 12, mInnerPaint);

        if(index ==4) {
            mInnerPaint.setColor(mCenterCardBackgroundColor);
            int space = mInnerCardWidth / 9;
            canvas.drawRoundRect(left + space, top + space, right - space, bottom - space, 12, 12, mInnerPaint);
        }
        // 绘制卡片中的图片
        int picHeight = 0;
        if (mPicResId != null && mPicResId[index] != 0) {
            Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),mPicResId[index]);
            picHeight = bitmap.getHeight();
            int picLeft = left + (mInnerCardWidth - bitmap.getWidth()) / 2;
            int picTop  = top + mInnerCardWidth / 7;
            canvas.drawBitmap(BitmapFactory.decodeResource(mContext.getResources(),mPicResId[index]), picLeft, picTop, mInnerPaint);
        }
        // 绘制卡片说明文字
        if (mInfoResArray != null && !TextUtils.isEmpty(mInfoResArray[index])) {
            if(index == 4 || index == 8) { // center text
                mInnerPaint.setColor(index == 4 ? Color.parseColor("#ffffff") : mInnerCardTextColor);
                mInnerPaint.setTextSize(mBigInfoTextSize);
                int textX = left + (mInnerCardWidth - getTextWidth(mInfoResArray[index].substring(0, 2), mInnerPaint))/2;
                int textY_1 = top + (mInnerCardWidth/4 + getTextHeight(mInfoResArray[index].substring(0, 2), mInnerPaint)) - 8;
                int textY_2 = top + (mInnerCardWidth/4 + getTextHeight(mInfoResArray[index].substring(0, 2), mInnerPaint)*2 + mInnerCardWidth/10) -8;
                canvas.drawText(mInfoResArray[index], 0, 2, textX, textY_1, mInnerPaint);
                canvas.drawText(mInfoResArray[index], 2, 4, textX, textY_2, mInnerPaint);
                return;
            }
            mInnerPaint.setColor(mInnerCardTextColor);
            mInnerPaint.setTextSize(mSmallInfoTextSize);
            int textX = left + (mInnerCardWidth - getTextWidth(mInfoResArray[index], mInnerPaint))/2;
            int textY = top + picHeight + mInnerCardWidth / 4 + getTextHeight(mInfoResArray[index], mInnerPaint) -10;
            canvas.drawText(mInfoResArray[index],textX, textY, mInnerPaint);
        }
    }


    private boolean switchCardColorIfNeed(int index) {
        int result = mInvalidateInnerCardCount % 9;
        if((result == 0 && index == 0) || (result == 1 && index == 1) || (result == 2 && index == 2)
                || (result == 6 && index == 6)) {
            return true;
        }
        if((result == 3 && index == 5) || (result == 4 && index == 8) || (result == 5 && index == 7)
                || (result == 7 && index == 3)) {
            return true;
        }
        return false;
    }

    private void loopSmallCircleAnimation() {
        // not real animation, just like it.
        if(mStartAnimation){
            if(mInvalidateInnerCardCount % 8 == 0) {
                mInvalidateCircleCount++;
                //postInvalidate();
            }
        }else {
            mInvalidateCircleCount++;
            postInvalidateDelayed(800);
        }
    }

    private void loopInnerRoundCardAnimation() {
        if(!mStartAnimation || mLastEndSelected) return;

        if(mInvalidateInnerCardCount == mLotteryInvalidateTimes){
            //mStartAnimation = false;
            mLastEndSelected = true;
            postInvalidate();
            postDelayed(new ResultTask(mLotteryInvalidateTimes), 300);
            return;
        }

        mInvalidateInnerCardCount++;
        postInvalidateDelayed(50);

    }

    private class ResultTask implements Runnable{
        int times;
        public ResultTask(int times) {
            this.times = times;
        }
        @Override
        public void run() {
            mInvalidateInnerCardCount = 0;
            mLastEndSelected = false;
            String info = "";
            int i = times % 9;
            info = mInfoResArray[i];
            if(i == 3) info = mInfoResArray[5];
            if(i == 4) info = mInfoResArray[8];
            if(i == 5) info = mInfoResArray[7];
            if(i == 7) info = mInfoResArray[3];
            showResultDialog(mContext, info);
        }
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
            break;

            case MotionEvent.ACTION_UP:
                int index = getTouchPositionInCardList(x, y);
                if(index == 5) {
                    if(mNeedRandomTimes || mLotteryInvalidateTimes == 0) {
                        mLotteryInvalidateTimes =  (new Random().nextInt(9) + 1) * 9 + new Random().nextInt(9);
                        mNeedRandomTimes = true;
                    }
                    showReminderDialog(mContext);
                }
                break;
        }

        return true;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mStartAnimation = false;
        mInvalidateCircleCount = 0;
        mInvalidateInnerCardCount = 0;
        mNeedRandomTimes = false;

    }

    private void showResultDialog(Context context, String result) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle(R.string.result_title)
                .setMessage(context.getString(R.string.result_message, result))
                .setCancelable(true)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
       builder.create().show();
    }

    private void showReminderDialog(Context context) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle(R.string.choujiang)
                .setMessage(R.string.choujiang_desc)
                .setCancelable(false)
                .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if(mAlertDialog != null) mAlertDialog.dismiss();
                    }
                })
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mStartAnimation = true;
                        invalidate();
                    }
                });
        mAlertDialog = builder.create();
        mAlertDialog.show();
    }

    private int getTouchPositionInCardList(int x, int y) {
        if(mCardPositionInfoList != null) {
            int index = 1;
            for (Pair<Pair<Integer, Integer>,Pair<Integer, Integer>> pair : mCardPositionInfoList) {
                if(x > pair.first.first && x < pair.first.second && y > pair.second.first && y < pair.second.second) {
                    return index;
                }
                index++;
            }
        }
        return 0;
    }


    private int getTextWidth(String str, Paint paint) {
        paint.getTextBounds(str, 0, str.length(), mBounds);
        return mBounds.width();
    }

    private int getTextHeight(String text,Paint paint){
        paint.getTextBounds(text,0,text.length(), mBounds);
        return mBounds.height();
    }
}