/*
 * ********************************************************************************************************************
 *
 *               iFHS7.
 *              ;BBMBMBMc                  rZMBMBR              BMB
 *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
 *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
 *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
 *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
 *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
 *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
 *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
 *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
 *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
 *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
 *         i0BM: SWKHKGO  MBDv
 *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2019.  斯伯坦机器人
 *              ,  XMW  ..
 *                  r                                                                     All rights reserved.
 *
 * ********************************************************************************************************************
 */

package com.sybotan.android.graphy.items

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.SizeF
import com.sybotan.android.graphy.SGraphyItem
import java.util.*
import kotlin.math.*

/**
 * SGraphy图形引擎时钟Item
 *
 * @author  庞利祥(sybotan@126.com)
 *
 * @param   size        时间大小
 * @param   parent      指向父节点
 */
class SGraphyClockItem(var size: SizeF, parent: SGraphyItem? = null) : SGraphyItem(parent) {
    /** 是否显示刻度 */
    var isShowScale = true
    /** 刻度颜色 */
    var scaleColor = Color.BLACK
    /** 刻度文本颜色 */
    var textColor = Color.BLACK
    /** 时针颜色 */
    var hourColor = Color.BLACK
    /** 分针颜色 */
    var minuteColor = Color.BLACK
    /** 秒针颜色 */
    var secondColor = Color.RED
    /** 是否显示秒针 */
    var isShowSecond = true
    /** 是否平滑移动秒针 */
    var isSmooth = true
    /** 边缘宽度 */
    var padding = 100f

    /** 画笔 */
    private val pen = Paint()

    /** 表半径 */
    private val radius: Float
        get() = min(size.width, size.height) / 2f - padding

    /** 绘制间隔时间 */
    private val interval: Long
        get() = if (isShowSecond && isSmooth) {     // 如果显示秒针，且要平滑移动秒针，间隔40毫秒
            40
        } else {                                    // 否则，间隔1秒
            1000
        }

    /** 分解时间的日历对象 */
    private val calendar = Calendar.getInstance()

    /**
     * Item对象边界区域
     *
     * @return  边界区域
     */
    override fun boundingRect(): RectF {
        return RectF(0f, 0f, size.width, size.height)
    } // Function boundingRect()

    /**
     * 绘制时钟
     *
     * @param   canvas      画布
     * @param   rect        更新区域
     */
    override fun onDraw(canvas: Canvas) {
        // 定位坐标原点为控件的中心
        canvas.translate(size.width / 2f, size.height / 2f)

        if (isShowScale) {          // 如果显示刻度
            drawScale(canvas)
            drawScaleText(canvas)
        }


        calendar.time = Date()
        val hour = calendar.get(Calendar.HOUR)
        val minute = calendar.get(Calendar.MINUTE)
        var second = calendar.get(Calendar.SECOND).toFloat()

        if (isSmooth) {         // 如果是平滑移动秒针
            second += calendar.get(Calendar.MILLISECOND) / 1000f
        }

        drawHour(canvas, hour, minute, second)
        drawMinute(canvas, minute, second)

        if (isShowSecond) {         // 如果显示秒针
            drawSecond(canvas, second)
        }

        postInvalidateDelayed(interval)

        return
    } // Function onDraw()

    /**
     * 绘制刻度
     *
     * @param   canvas      画布
     */
    private fun drawScale(canvas: Canvas) {
        // 刻度长度
        val scaleLength = max(radius / 10f, 2f)
        val scaleLength1 = scaleLength * 1.2f
        val strokeWidth = max(radius / 100f, 2f)
        val strokeWidth1 = strokeWidth * 2f

        canvas.save()
        pen.color = scaleColor

        for (i in 1..12) {          // 12小时刻度
            pen.strokeWidth = strokeWidth1
            canvas.drawLine(0f, - radius, 0f, - radius + scaleLength1, pen)

            if (radius >= 50) {     // 如果半度大于40显示分钟刻度
                canvas.rotate(6f)
                for (j in 1..4) {       // 分钟刻度
                    pen.strokeWidth = strokeWidth
                    canvas.drawLine(0f, -radius, 0f, -radius + scaleLength, pen)
                    canvas.rotate(6.0f)
                }
            } else {
                canvas.rotate(30f)
            }
        }

        canvas.restore()
        return
    } // Function drawScale()

    /**
     * 绘制刻度数字
     *
     * @param   canvas      画布
     */
    private fun drawScaleText(canvas: Canvas) {
        val fontSize = radius / 5f
        if (fontSize < 20) {         // 字体小于20，则不绘制刻度数字
            return
        }

        pen.color = textColor
        pen.textAlign = Paint.Align.CENTER
        pen.textSize = fontSize
        val offset = (pen.fontMetrics.bottom + pen.fontMetrics.top) / 2
        val r = radius - radius / 3.8f
        for (i in 1 .. 12) {    // 依次画12个时钟刻度
            val x1 = (r * cos(i * PI / 6f - PI / 2f)).toFloat()
            val y1 = (r * sin(i * PI / 6f - PI / 2f) - offset).toFloat()
            canvas.drawText("$i", x1, y1, pen)
        }

        return
    } // Function drawScaleText()

    /**
     * 绘制时针
     *
     * @param   canvas      画布
     * @param   hour        时
     * @param   minute      分
     * @param   second      秒
     */
    private fun drawHour(canvas: Canvas, hour: Int, minute: Int, second: Float) {
        canvas.save()
        pen.strokeCap = Paint.Cap.ROUND
        pen.strokeWidth = max(radius / 30f, 4f)
        pen.color = hourColor
        canvas.rotate(hour * 30f + minute * 30f / 60 + second * 30f / 60 / 60)
        canvas.drawLine(0f, radius / 10f, 0f, - radius / 2.5f, pen)
        canvas.drawCircle(0f, 0f, radius / 30f, pen)
        canvas.restore()

        return
    } // Function drawHour()

    /**
     * 绘制分针
     *
     * @param   canvas      画布
     * @param   minute      分
     * @param   second      秒
     */
    private fun drawMinute(canvas: Canvas, minute: Int, second: Float) {
        canvas.save()
        pen.strokeCap = Paint.Cap.ROUND
        pen.strokeWidth = max(radius / 40f, 4f)
        pen.color = minuteColor
        canvas.rotate(minute * 6f + second * 6f / 60f)
        canvas.drawLine(0f, radius / 10f, 0f, - radius * 3f / 5f, pen)
        pen.color = Color.YELLOW
        canvas.drawCircle(0f, 0f, radius / 100f, pen)
        canvas.restore()

        return
    } // Function drawMinute()

    /**
     * 绘制秒针
     *
     * @param   canvas      画布
     * @param   second      秒
     */
    private fun drawSecond(canvas: Canvas, second: Float) {
        canvas.save()
        pen.strokeCap = Paint.Cap.ROUND
        pen.strokeWidth = max(radius / 100f, 3f)
        pen.color = secondColor
        canvas.rotate(second * 6f)
        canvas.drawLine(0f, radius / 5f, 0f, - radius + radius / 10f, pen)
        canvas.drawCircle(0f, 0f, radius / 30f, pen)
        canvas.drawCircle(0f, - radius + radius / 5f, radius / 60f, pen)
        pen.color = Color.YELLOW
        canvas.drawCircle(0f, 0f, radius / 100f, pen)
        canvas.restore()

        return
    } // Function drawSecond()
} // Class SGraphyClockItem