package com.cr.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import androidx.appcompat.widget.AppCompatImageView
import com.cr.cruav.R

/**
 * 操作系统：MAC系统
 * 创建者：王成
 * 创建日期：2023/6/20 11:03
 * 描述：图片编辑视图
 */
class CrImageEditor @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : AppCompatImageView(context, attrs) {
    // define: 2023/6/20 缩放
    private var mScaleGestureDetector: ScaleGestureDetector? = null

    // define: 2023/6/20 平移
    private var mGestureDetector: GestureDetector? = null

    // todo: 2023/6/20 缩放平移矩阵
    private var mCurrentMatrix = Matrix()

    // todo: 2023/6/20 最小缩放
    private var mCenterX: Float? = 0f
    private var mCenterY: Float? = 0f

    // todo: 2023/6/20 点击位置点集合
    private var drawPoints = mutableListOf<PointF>()

    // todo: 2023/6/21 绘制点集合
    private var downPoints = mutableListOf<PointF>()

    // todo: 2023/6/20 画笔
    private var drawPointPaint = Paint()
    private var drawLinePaint = Paint()

    /**
     * 缩放监听
     */
    private val mScaleListener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        // todo: 2023/6/20 缩放开始
        override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
            return true
        }

        // todo: 2023/6/20 缩放中
        override fun onScale(detector: ScaleGestureDetector?): Boolean {
            var scaleFactor = detector?.scaleFactor
            if (mCenterX == 0f) {
                // todo: 2023/6/20 最小X轴缩放
                mCenterX = width / 2f
            }
            if (mCenterY == 0f) {
                // todo: 2023/6/20 最小Y轴缩放
                mCenterY = height / 2f
            }
            // todo: 2023/6/21 缩放变换
            mCurrentMatrix.postScale(scaleFactor!!, scaleFactor!!, mCenterX!!, mCenterY!!)
            invalidate()
            return true
        }

        // todo: 2023/6/20 缩放结束
        override fun onScaleEnd(detector: ScaleGestureDetector?) {

        }
    }


    /**
     * 平移监听
     */
    private val mTranslationListener = object : GestureDetector.SimpleOnGestureListener() {
        // todo: 2023/6/20 单击确认
        override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
            // todo: 2023/6/20 单击绘制一个点 试试
            e?.let {
                var point = PointF(it.x, it.y)
                // todo: 2023/6/21 由于缩放后点击，点击位置已经经过矩阵变换，为统一在重绘时变换，需要逆向变换一次
                downPoints.add(calculateInversePointF(point, mCurrentMatrix))
                // todo: 2023/6/21 重绘
                invalidate()
            }
            return true
        }

        // todo: 2023/6/20 移动
        override fun onScroll(
            e1: MotionEvent?,
            e2: MotionEvent?,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            // todo: 2023/6/21 设置变化矩阵
            mCurrentMatrix.postTranslate(-distanceX, -distanceY)
            // todo: 2023/6/21 重绘
            invalidate()
            return true
        }
    }

    /**
     * 根据矩阵计算点位置
     * @param pointF PointF 变化前
     * @param matrix Matrix 矩阵
     * @return PointF 变化后
     */
    private fun calculatePointF(pointF: PointF, matrix: Matrix): PointF {
        // todo: 2023/6/21 返回点
        var resPointF = PointF()
        // todo: 2023/6/21 获取矩阵数据
        var matrixValue = FloatArray(9)
        matrix.getValues(matrixValue)
        // todo: 2023/6/21 计算
        resPointF.x = pointF.x * matrixValue[0] + matrixValue[2]
        resPointF.y = pointF.y * matrixValue[4] + matrixValue[5]
        // todo: 2023/6/21 返回
        return resPointF
    }

    /**
     * 根据矩阵反向计算点位置
     * @param pointF PointF 变化前
     * @param matrix Matrix 变换矩阵
     * @return PointF 变化后
     */
    private fun calculateInversePointF(pointF: PointF, matrix: Matrix): PointF {
        // todo: 2023/6/21 返回点
        var resPointF = PointF()
        // todo: 2023/6/21 反转矩阵
        var inverseMatrix = Matrix()
        matrix.invert(inverseMatrix)
        // todo: 2023/6/21 获取矩阵数据
        var matrixValue = FloatArray(9)
        inverseMatrix.getValues(matrixValue)
        // todo: 2023/6/21 计算
        resPointF.x = pointF.x * matrixValue[0] + matrixValue[2]
        resPointF.y = pointF.y * matrixValue[4] + matrixValue[5]
        // todo: 2023/6/21 返回
        return resPointF
    }


    /**
     * 初始化
     */
    init {
        // todo: 2023/6/20 初始化平移、缩放监听
        mScaleGestureDetector = ScaleGestureDetector(context, mScaleListener)
        mGestureDetector = GestureDetector(context, mTranslationListener)
        // todo: 2023/6/20 初始化点画笔
        drawPointPaint.color = Color.BLUE
        drawPointPaint.isAntiAlias = true
        drawPointPaint.strokeWidth = 20f
        // todo: 2023/6/20 初始化线画笔
        drawLinePaint.color = context!!.getColor(R.color.line_4)
        drawLinePaint.isAntiAlias = true
        drawLinePaint.strokeWidth = 3.0f
    }

    /**
     * 绘制
     * @param canvas Canvas
     */
    override fun onDraw(canvas: Canvas?) {
        var saveCount = canvas?.save()
        canvas?.concat(mCurrentMatrix)
        super.onDraw(canvas)
        canvas?.restoreToCount(saveCount!!)

        // todo: 2023/6/21 变换
        drawPoints.clear()
        for (point in downPoints) {
            drawPoints.add(calculatePointF(point, mCurrentMatrix))
        }

        // todo: 2023/6/20 绘制点
        for (point in drawPoints) {
            canvas?.drawPoint(point.x, point.y, drawPointPaint)
        }
        // todo: 2023/6/20 绘制线
        if (drawPoints.size > 1) {
            var points = mutableListOf<Float>()
            for (i in 0 until drawPoints.size - 1) {
                var point1 = drawPoints[i]
                var point2 = drawPoints[i + 1]
                points.add(point1.x)
                points.add(point1.y)
                points.add(point2.x)
                points.add(point2.y)
            }
            canvas?.drawLines(points.toFloatArray(), drawLinePaint)
        }
    }

    /**
     * 覆写Touch事件
     * @param event MotionEvent
     * @return Boolean
     */
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        // todo: 2023/6/20 这里将触摸事件转接给ScaleGestureDetector与GestureDetector
        mScaleGestureDetector?.onTouchEvent(event)
        if (mScaleGestureDetector?.isInProgress == false) {
            mGestureDetector?.onTouchEvent(event)
        }
        return true
    }

    /**
     * 设置线的宽度
     * @param width Float 线的宽度
     */
    fun crSetLineWidth(width:Float){
        drawLinePaint.strokeWidth = width
        // todo: 2023/6/26 重绘
        invalidate()
    }

    /**
     * 设置线的颜色
     * @param color Int 线的颜色
     */
    fun crSetLineColor(color:Int){
        drawLinePaint.color = color
        // todo: 2023/6/26 重绘
        invalidate()
    }
}