package com.tencent.liteav.demo.superplayer.ui.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.ColorInt;

import com.tencent.liteav.demo.superplayer.R;

/**
 * 视频播放时的进度指示条
 */
public class PointProgressBar extends View {
    @ColorInt
    private static final int DEFAULT_BACKGROUND_COLOR = Color.parseColor("#FFFFFF");

    @ColorInt
    private static final int DEFAULT_PROGRESS_COLOR = Color.parseColor("#FF1234");

    public interface OnProgressBarChangeListener {

        void onProgressChanged(PointProgressBar progressBar, int progress, boolean fromUser);

        void onStartTrackingTouch(PointProgressBar progressBar);

        void onStopTrackingTouch(PointProgressBar progressBar);
    }

    @ColorInt
    private int backgroundColor;

    @ColorInt
    private int progressColor;

    private float progressHeight;

    private Drawable trackDrawable;
    private float trackWidth;
    private float trackHeight;

    private final int minValue = 0;
    private int maxValue;
    private int progress;

    private Paint backgroundPaint;
    private Paint progressPaint;

    private RectF backgroundRect;
    private RectF progressRect;

    private OnProgressBarChangeListener mListener;
    private boolean mIsOnDrag;
    private float mLastX;

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

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

    public PointProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

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

    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        setWillNotDraw(false);
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(
                    attrs, R.styleable.PointProgressBar, defStyleAttr, defStyleRes);

            backgroundColor = a.getColor(R.styleable.PointProgressBar_backgroundColor, DEFAULT_BACKGROUND_COLOR);
            progressColor = a.getColor(R.styleable.PointProgressBar_progressColor, DEFAULT_PROGRESS_COLOR);
            progressHeight = a.getDimension(R.styleable.PointProgressBar_progressHeight, 0f);

            trackDrawable = a.getDrawable(R.styleable.PointProgressBar_trackDrawable);
            trackWidth = a.getDimension(R.styleable.PointProgressBar_trackWidth, progressHeight);
            trackHeight = a.getDimension(R.styleable.PointProgressBar_trackHeight, progressHeight);
            trackDrawable.setBounds(0, 0, (int) trackWidth, (int) trackHeight);

            maxValue = a.getInt(R.styleable.PointProgressBar_maxValue, 100);
            progress = a.getInt(R.styleable.PointProgressBar_progress, 0);

            a.recycle();

            backgroundPaint = new Paint();
            backgroundPaint.setColor(backgroundColor);

            progressPaint = new Paint();
            progressPaint.setColor(progressColor);

            backgroundRect = new RectF();
            progressRect = new RectF();
        }
    }

    public int getMax() {
        return maxValue;
    }

    /* 设置进度条最大值 */
    public void setMax(int max) {
        if (max > 0) {
            maxValue = max;
        }

        internalResetValue();
    }

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        if (mIsOnDrag) return;
        this.progress = progress;
        internalResetValue();
    }

    public void setListener(OnProgressBarChangeListener listener) {
        this.mListener = listener;
    }

    /* 调整进度条的当前值使其满足仍然处于[minValue,maxValue] */
    private void internalResetValue() {
        if (progress > maxValue) {
            progress = maxValue;
        }

        if (progress < minValue) {
            progress = minValue;
        }

        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) return false;

        boolean isHandle = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isHandle = handleDownEvent(event);
                break;
            case MotionEvent.ACTION_MOVE:
                isHandle = handleMoveEvent(event);
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                isHandle = handleUpEvent(event);
                break;

        }
        return isHandle;
    }

    private boolean handleDownEvent(MotionEvent event) {
        float x = event.getX();

        float min = (x - 100f) / getWidth();
        float max = (x + 100f) / getWidth();
        float current = (progress + 0f) / maxValue;

        if (current >= min && current <= max) {
            if (mListener != null)
                mListener.onStartTrackingTouch(this);
            mIsOnDrag = true;
            mLastX = x;
            return true;
        }
        return false;
    }

    private boolean handleMoveEvent(MotionEvent event) {
        float x = event.getX();
        if (x < 0) x = 0;
        if (x > getWidth()) x = getWidth();

        Log.d("PointProgressBar", "handleMoveEvent x:" + progress);

        if (mIsOnDrag) {
            progress = (int) ((x / getWidth()) * maxValue);
            Log.d("PointProgressBar", "handleMoveEvent p:" + progress);
            invalidate();
            callbackProgress();
            mLastX = x;
            return true;
        }
        return false;
    }

    private boolean handleUpEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        if (mIsOnDrag) {
            mIsOnDrag = false;
            if (mListener != null) {
                mListener.onStopTrackingTouch(this);
            }
            return true;
        }
        return false;
    }

    private void callbackProgress() {
        if (mListener != null) {
            mListener.onProgressChanged(this, progress, true);
        }
    }

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

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

        backgroundRect.set(0, 0, w, h);
        progressRect.set(0, 0, 0, h);
    }


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

        float p = (progress + 0f) / (maxValue);
        progressRect.right = getWidth() * p;
        canvas.drawRoundRect(backgroundRect, progressHeight / 2, progressHeight / 2, backgroundPaint);
        canvas.drawRoundRect(progressRect, progressHeight / 2, progressHeight / 2, progressPaint);

        if (trackDrawable != null) {
            canvas.save();
            canvas.translate(-trackWidth / 2, -(trackHeight - progressHeight) / 2);
            canvas.translate(progressRect.right, 0);
            trackDrawable.draw(canvas);
            canvas.restore();
        }
    }


}
