package com.mayi.fastdevelop.view;

import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.FloatEvaluator;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.mayi.fastdevelop.R;
import com.mayi.fastdevelop.util.DisplayUtil;


public class IOSSwitchView extends View {
    private Context mContext;
    private int mHeight, mWidth;
    private Path mPath;
    private Paint mStrokePaint;         //边框画笔
    private Paint mSolidPaint;         //填充色画笔
    private Paint mCirclePaint;        //小圆球画笔
    private float mMarginLeft;                  //小圆球到左边距离
    private boolean mIsCheck;          //是否被选中
    private int CIRCLEPADDING;
    private int mCircleWidth;
    private int mDefaultSolidColor, mTargetSolidColor;
    private int mDefaultStrokeColor, mTargetStrokeColor;
    private int mDefaultCircleColor, mTargetCircleColor;
    private int mSolidColor_;
    private int mCircleColor_;
    private int mStrokeColor_;
    private ObjectAnimator mTranslateAnim, mSolidColorAnim, mCircleColorAnim, mStrokeColorAnim;
    private int mStrokeWidth;
    private int mRealWidth;
    private int mRealHeight;

    public interface OnCheckedChange {
        void onCheckChange(boolean isChecked);
    }

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

    public IOSSwitchView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IOSSwitchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        CIRCLEPADDING = DisplayUtil.dip2px(mContext, 1);
        TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.IOSSwitchView);
        mDefaultStrokeColor = a.getColor(R.styleable.IOSSwitchView_default_stroke_color, Color.parseColor("#707070"));
        mTargetStrokeColor = a.getColor(R.styleable.IOSSwitchView_target_stroke_color, Color.parseColor("#E83C3C"));
        mTargetCircleColor = a.getColor(R.styleable.IOSSwitchView_target_circle_color, Color.parseColor("#E83C3C"));
        mDefaultCircleColor = a.getColor(R.styleable.IOSSwitchView_default_circle_color, Color.parseColor("#707070"));
        mDefaultSolidColor = a.getColor(R.styleable.IOSSwitchView_default_solid_color, Color.WHITE);
        mTargetSolidColor = a.getColor(R.styleable.IOSSwitchView_target_solid_color, Color.WHITE);
        mIsCheck = a.getBoolean(R.styleable.IOSSwitchView_checked, false);
        mSolidColor_ = mIsCheck ? mTargetSolidColor : mDefaultSolidColor;
        mCircleColor_ = mIsCheck ? mTargetCircleColor : mDefaultCircleColor;
        mStrokeColor_ = mIsCheck ? mTargetStrokeColor : mDefaultStrokeColor;
        mTranslateAnim = initAnim("mMarginLeft", new FloatEvaluator());
        mSolidColorAnim = initAnim("mSolidColor_", new ArgbEvaluator());
        mCircleColorAnim = initAnim("mCircleColor_", new ArgbEvaluator());
        mStrokeColorAnim = initAnim("mStrokeColor_", new ArgbEvaluator());

        mStrokeWidth = DisplayUtil.dip2px(mContext, 2f);
        mMarginLeft = 0;
        mPath = new Path();
        mCirclePaint = new Paint();
        mStrokePaint = new Paint();
        mSolidPaint = new Paint();
        initPaint(mCirclePaint, mSolidPaint, mStrokePaint);
        mStrokePaint.setStyle(Paint.Style.STROKE);
        mTranslateAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mMarginLeft = (float) (animation.getAnimatedValue());
                postInvalidate();
            }
        });
        mCircleColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCircleColor_ = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        mSolidColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mSolidColor_ = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        mStrokeColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mStrokeColor_ = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });
    }

    private ObjectAnimator initAnim(String propertyName, TypeEvaluator evaluator) {
        ObjectAnimator anim = new ObjectAnimator();
        anim.setTarget(this);       //这里千万记住别写错，楼主因为写成了setObjectValue被坑了好几个小时
        anim.setPropertyName(propertyName);
        anim.setEvaluator(evaluator);
        return anim;
    }

    public void initPaint(Paint... paints) {
        for (int i = 0; i < paints.length; i++) {
            paints[i].setAntiAlias(true);
            paints[i].setStrokeWidth(mStrokeWidth);
        }
    }

    public void startAnim(boolean isCheck) {
        if (isCheck) {
            mCircleColorAnim.setIntValues(mDefaultCircleColor, mTargetCircleColor);
            mTranslateAnim.setFloatValues(0, mWidth - mHeight);
            mSolidColorAnim.setIntValues(mDefaultSolidColor, mTargetSolidColor);
            mStrokeColorAnim.setIntValues(mDefaultStrokeColor, mTargetStrokeColor);
        } else {
            mCircleColorAnim.setIntValues(mTargetCircleColor, mDefaultCircleColor);
            mTranslateAnim.setFloatValues(mWidth - mHeight, 0);
            mSolidColorAnim.setIntValues(mTargetSolidColor, mDefaultSolidColor);
            mStrokeColorAnim.setIntValues(mTargetStrokeColor, mDefaultStrokeColor);
        }
        AnimatorSet set = new AnimatorSet();
        set.setDuration(200);
        set.setInterpolator(new AccelerateDecelerateInterpolator());
        set.playTogether(mTranslateAnim, mCircleColorAnim, mSolidColorAnim, mStrokeColorAnim);
        set.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mWidth == 0) {
            mWidth = getWidth();
            mHeight = getHeight();
            mRealWidth = mWidth - mStrokeWidth * 2;
            mRealHeight = mHeight - mStrokeWidth * 2;
            mMarginLeft = mIsCheck ? mWidth - mHeight : 0;
            mCircleWidth = mHeight - CIRCLEPADDING * 2 - mStrokeWidth * 2;
        }
        if (mWidth <= 0 || mHeight <= 0) return;
        mPath.reset();
        mSolidPaint.setColor(mSolidColor_);
        mStrokePaint.setColor(mStrokeColor_);
        mCirclePaint.setColor(mCircleColor_);
        mPath.addRoundRect(mStrokeWidth, mStrokeWidth, mRealWidth + mStrokeWidth, mRealHeight + mStrokeWidth, mRealHeight / 2, mRealHeight / 2, Path.Direction.CW);
        canvas.drawPath(mPath, mStrokePaint);
        canvas.drawPath(mPath, mSolidPaint);
        canvas.drawCircle(mHeight / 2.0f + mMarginLeft, mHeight / 2f, mCircleWidth / 2, mCirclePaint);
    }

    public void setCheck(boolean checked) {
        this.setCheck(checked, true);
    }

    private void setCheck(boolean checked, boolean fromOut) {
        boolean flag = mIsCheck == checked;
        mIsCheck = checked;
        if (mListener != null && !flag) {
            mListener.onCheckChange(mIsCheck);
        }
        if (!fromOut) {
            startAnim(mIsCheck);
        } else {
            mSolidColor_ = mIsCheck ? mTargetSolidColor : mDefaultSolidColor;
            mCircleColor_ = mIsCheck ? mTargetCircleColor : mDefaultCircleColor;
            mStrokeColor_ = mIsCheck ? mTargetStrokeColor : mDefaultStrokeColor;
            mMarginLeft = mIsCheck ? mWidth - mHeight : 0;
            postInvalidate();
        }
    }

    public float getMarginLeft() {
        return mMarginLeft;
    }

    private OnCheckedChange mListener;

    public void setOnCheckedChangeListener(OnCheckedChange listener) {
        mListener = listener;
    }

    public void setMarginLeft(float marginLeft) {
        mMarginLeft = marginLeft;
    }

    public int getSolidColor_() {
        return mSolidColor_;
    }

    public void setSolidColor_(int solidColor_) {
        mSolidColor_ = solidColor_;
    }

    public int getCircleColor_() {
        return mCircleColor_;
    }

    public void setCircleColor_(int circleColor_) {
        mCircleColor_ = circleColor_;
    }

    public int getStrokeColor_() {
        return mStrokeColor_;
    }

    public void setStrokeColor_(int strokeColor_) {
        mStrokeColor_ = strokeColor_;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (mTranslateAnim.isRunning()) {
                    return false;
                }
                return true;
            case MotionEvent.ACTION_CANCEL:
                return false;
            case MotionEvent.ACTION_UP:
                setCheck(!mIsCheck, false);
                return true;
        }
        return true;
    }

    public boolean isCheck() {
        return mIsCheck;
    }
}