package com.yidianling.fm.widget

/**
 * @author <a href="https://www.jianshu.com/u/c1e5310dd724">xujian</a>
 * @描述:  FM播放页面动画效果
 * @Copyright Copyright (c) 2019
 * @Company 壹点灵
 * @date 2019/05/08
 */
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import com.yidianling.common.tools.RxDeviceTool
import java.lang.Exception
import java.util.*

class FMSurfaceView(context: Context?, attrs: AttributeSet?) : SurfaceView(context, attrs), SurfaceHolder.Callback {

    private var mHolder: SurfaceHolder? = null

    private var paint: Paint? = null
    private var path: Path? = null
    private var canvas: Canvas? = null

    private var timer: Timer? = null
    private var timerTask: TimerTask? = null

    private var minRadius: Float = (RxDeviceTool.getScreenWidth(context) * 150 / 375 / 2).toFloat() // 初始化最小六边形所在圆半径
    private var ringRadius: Float = (RxDeviceTool.getScreenWidth(context) * 145 / 375 / 2).toFloat() // 初始化内部圆环半径
    private var ringWidth: Float = (RxDeviceTool.getScreenWidth(context) * 10 / 375 / 2).toFloat() // 初始化内部圆环宽度
    private var presentRadius: Float = minRadius // 初始化当前最小六边形所在圆半径
    private var presentRadiusChangeNumber: Float = 1f
    private var maxRadius: Float = (RxDeviceTool.getScreenWidth(context) * 198 / 375 / 2).toFloat() // 初始化六边形所在圆最大时的半径

    private var circleSpace: Float = maxRadius - minRadius // 初始化圆边之间的距离
    private var clockwise: Boolean = true  // 默认最小的六边形为顺时针旋转
    private var hintColor: String = "FFFFFF" // 默认不透明色
    private var percentColorNum: Float = 105f // 初始化初始颜色透明度 255f的时候最小的六边形为纯色没有透明度，颜色为hintColor
    private var cornerRadius: Float = (RxDeviceTool.getScreenWidth(context) * 150 / 375 / 2).toFloat() // paint初始拐角半径
    private var periodTime: Long = 30 // 定时任务间隔时间
    private var firstPlay: Boolean = false
    private var xfermode: PorterDuffXfermode? = null

    init {
        initPaint()
        initPath()

        mHolder = holder
        mHolder?.addCallback(this)

        //该行代码为设置透明
        setZOrderOnTop(true)
        mHolder?.setFormat(PixelFormat.TRANSLUCENT)

        xfermode = PorterDuffXfermode(PorterDuff.Mode.XOR)//绘制交集，显示非交集
    }

    private fun initPath() {
        path = Path()
    }

    private fun initPaint() {
        paint = Paint(Color.GRAY)
        paint?.color = Color.WHITE
        paint?.isAntiAlias = true //抗锯齿
        paint?.style = Paint.Style.FILL //设置画笔为填充模式
        paint?.strokeCap = Paint.Cap.ROUND //画笔拐角为圆弧
        paint?.pathEffect = CornerPathEffect(cornerRadius) //设置path拐角半径
    }

    fun playTimer() {
        if (null == timer) {
            timer = Timer()
            timerTask = timerTask ?: object : TimerTask() {
                override fun run() {
                    drawAnimate()
                }
            }
            timer?.let {
                timer!!.schedule(timerTask, 0, periodTime)
            }
        }
    }

    private fun drawAnimate() {
        synchronized(this) {
                mHolder?.let {
                    canvas = mHolder?.lockCanvas()
                    canvas?.let {
                        //清空画布，进行重绘
                        canvas?.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)

                        //重置最小六边形半径
                        resetPresentRadius()

                        paint?.style = Paint.Style.FILL //设置画笔为填充模式

                        //绘制四个变化的六边形
                        drawMinHexagon()
                        drawMiddleHexagon()
                        drawMaxHexagon()
                        drawMMaxHexagon()

                        //绘制图片外面包围的一层圆
                        canvas?.let {
                            paint?.strokeWidth = ringWidth + 0.5f
                            paint?.style = Paint.Style.STROKE //设置画笔为线模式
                            paint?.color = Color.parseColor("#D0FFFFFF")
                            paint?.setShadowLayer(ringWidth, 1F, 1F, Color.parseColor("#D0FFFFFF"))
                            canvas!!.drawCircle((canvas?.width!! / 2).toFloat(), (canvas?.height!! / 2).toFloat(), ringRadius + 0.5f, paint!!)
                            paint?.setShadowLayer(0F, 0F, 0F, Color.WHITE)
                        }

                        presentRadius += presentRadiusChangeNumber //每次循环presentRadius+presentRadiusChangeNumber
                    }
                    //这里有些机型上面会出现异常，暴力try一次，也可以用 mHolder?.surface?.isValid先进行一次判断后进行try
                    try {
                        mHolder?.unlockCanvasAndPost(canvas) // android 4.3 会有IllegalArgumentException
                    } catch (e: Exception) {
                    }
                }
        }
    }

    private fun drawPath(point: Point, pointRadius: Float) {
        path = Path()
        path?.moveTo(point.x + canvas?.width!! / 2, point.y + canvas?.height!! / 2)
        for (i in 1..5) {
            path?.lineTo((point.x * Math.cos(getRadian(60 * i)) - point.y * Math.sin(getRadian(60 * i))).toFloat() + canvas?.width!! / 2,
                    (point.x * Math.sin(getRadian(60 * i)) + point.y * Math.cos(getRadian(60 * i))).toFloat() + canvas?.height!! / 2)
        }
        path?.close()

        path?.addCircle((canvas?.width!! / 2).toFloat(), (canvas?.height!! / 2).toFloat(), minRadius, Path.Direction.CCW)
        path?.fillType = Path.FillType.EVEN_ODD

        /**
         * 这边是2，1，根号3的三角形, 这部分代码绘制了从圆到六边形的变化
         */
        val mRadius = (pointRadius * 1.7320508075689 / 2).toFloat()
        if (mRadius > minRadius) {
            //设置paint 拐角半径
            if (mRadius - minRadius < 50f)
                paint?.pathEffect = CornerPathEffect(cornerRadius - (mRadius - minRadius) * 2)
            else
                paint?.pathEffect = CornerPathEffect(cornerRadius - 100f)

            canvas?.drawPath(path!!, paint!!)
        }
    }

    private fun getRotatePoint(point: Point, angle: Int): Point {
        return Point(
                (point.x * Math.cos(getRadian(angle)) - point.y * Math.sin(getRadian(angle))).toFloat(),
                (point.x * Math.sin(getRadian(angle)) + point.y * Math.cos(getRadian(angle))).toFloat()
        )
    }

    /**
     * 绘制最小的六边形
     */
    private fun drawMinHexagon() {
        val radius: Float = presentRadius
        var percentOfColor: String = getColorPercent(radius)
        percentOfColor = if (percentOfColor.length == 2) percentOfColor else "0${percentOfColor[0]}"
        paint?.color = Color.parseColor("#$percentOfColor$hintColor")
        canvas?.let {
            if (clockwise) {
                drawPath(getRotatePoint(Point(0f, radius), (radius - minRadius).toInt()), radius)
            } else {
                drawPath(getRotatePoint(Point(0f, radius), -(radius - minRadius).toInt()), radius)
            }
        }
    }

    /**
     * 绘制中间的六边形
     */
    private fun drawMiddleHexagon() {
        val radius: Float = presentRadius + circleSpace
        var percentOfColor: String = getColorPercent(radius)
        percentOfColor = if (percentOfColor.length == 2) percentOfColor else "0${percentOfColor[0]}"
        paint?.color = Color.parseColor("#$percentOfColor$hintColor")
        canvas?.let {
            if (clockwise) {
                drawPath(getRotatePoint(Point(0f, radius), -(radius - minRadius).toInt()), radius)
            } else {
                drawPath(getRotatePoint(Point(0f, radius), (radius - minRadius).toInt()), radius)
            }
        }
    }

    /**
     * 绘制最大的六边形
     */
    private fun drawMaxHexagon() {
        val radius: Float = presentRadius + circleSpace * 2
        var percentOfColor: String = getColorPercent(radius)
        percentOfColor = if (percentOfColor.length == 2) percentOfColor else "0${percentOfColor[0]}"
        paint?.color = Color.parseColor("#$percentOfColor$hintColor")
        canvas?.let {
            if (clockwise) {
                drawPath(getRotatePoint(Point(0f, radius), (radius - minRadius).toInt()), radius)
            } else {
                drawPath(getRotatePoint(Point(0f, radius), -(radius - minRadius).toInt()), radius)
            }
        }
    }

    /**
     * 绘制最大的六边形之再来一个更大的
     */
    private fun drawMMaxHexagon() {
        val radius: Float = presentRadius + circleSpace * 3
        var percentOfColor: String = getColorPercent(radius)
        percentOfColor = if (percentOfColor.length == 2) percentOfColor else "0${percentOfColor[0]}"
        paint?.color = Color.parseColor("#$percentOfColor$hintColor")
        canvas?.let {
            if (clockwise) {
                drawPath(getRotatePoint(Point(0f, radius), -(radius - minRadius).toInt()), radius)
            } else {
                drawPath(getRotatePoint(Point(0f, radius), (radius - minRadius).toInt()), radius)
            }
        }
    }

    private fun getColorPercent(radius: Float): String {
        return Integer.toHexString(((1f - (radius - minRadius) / (maxRadius + circleSpace * 3 - minRadius)) * percentColorNum).toInt())
    }

    /**
     * 重置最小半径
     */
    private fun resetPresentRadius() {
        if (presentRadius >= maxRadius) {
            presentRadius = minRadius
            clockwise = !clockwise
            firstPlay = true
        }
    }

    fun stopTimer() {
        releaseResource()
    }

    /**
     * 清除定时任务，进行资源释放
     */
    private fun releaseResource() {
        timer?.let {
            timer?.cancel()
            timerTask?.cancel()
            timerTask = null
            timer = null
        }
    }

    /**
     * 根据角度获取弧度值
     */
    private fun getRadian(angle: Int): Double {
        return angle * (Math.PI / 180)
    }

    override fun surfaceDestroyed(holder: SurfaceHolder?) {
        //mHolder?.removeCallback(this)
        releaseResource()
        this.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
    }

    override fun surfaceCreated(holder: SurfaceHolder?) {
        this.setLayerType(View.LAYER_TYPE_SOFTWARE, paint)
        drawAnimate()
    }

    override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
    }

    class Point(val x: Float, val y: Float)

}