/*
 * ********************************************************************************************************************
 *
 *               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.views

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import android.widget.RelativeLayout
import com.google.zxing.*
import com.google.zxing.common.HybridBinarizer
import com.sybotan.android.base.utils.SQrCodeUtil
import com.sybotan.views.R
import org.jetbrains.anko.dip
import com.google.zxing.PlanarYUVLuminanceSource

/**
 * 扫描二维码View
 *
 * @author  庞利祥(sybotan@126.com)
 */
open class SQrCodeView(context: Context, attrs: AttributeSet? = null) : RelativeLayout(context, attrs) {
    /** 摄像视图 */
    private val cameraView = SCameraView(context)
    /** 扫描View */
    private val finderView = FinderView(context)

    /** 蒙板颜色 */
    var maskColor: Int = 0xA0000000.toInt()
    /** 扫描框颜色 */
    var frameColor: Int = 0xFFFFFF

    /** 初始化 */
    init {
        // 处理自定义属性
        parserAttrs(attrs)

        // 设置UI
        setupUi()
    } // init

    fun decode(bitmap: Bitmap): String? {
        val width = bitmap.width
        val height = bitmap.height
        val pixels = ByteArray(width * height)

        val viewSize = Math.min(width, height)
        val frame = Rect(viewSize / 4, viewSize / 4, viewSize * 3 / 4, viewSize * 3 / 4)
        val luminanceSource = PlanarYUVLuminanceSource(pixels, width, height, frame.left, frame.top, frame.width(), frame.height(), false)
        val binaryBitmap = BinaryBitmap(HybridBinarizer(luminanceSource))
        return SQrCodeUtil.decodeQrCode(binaryBitmap)
    } // Function decode()

    /**
     * 设置UI
     */
    private fun setupUi() {
        this.addView(cameraView)
        this.addView(finderView)
        cameraView.openCamera()
        return
    } // Function setupUi()

    /**
     * 处理自定义属性
     *
     * @param   attrs       自定义属性列表
     */
    private fun parserAttrs(attrs: AttributeSet?) {
        try {
            val t = context.obtainStyledAttributes(attrs, R.styleable.SQrCodeView)
            maskColor = t.getColor(R.styleable.SQrCodeView_mask_color, 0xA0000000.toInt())
            frameColor = t.getColor(R.styleable.SQrCodeView_frame_color, 0xFFFFFF)
            t.recycle()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return
    } // Function parserAttrs()

    /**
     * 扫描View
     *
     * @author  庞利祥(sybotan@126.com)
     */
    inner class FinderView(context: Context, attrs: AttributeSet? = null) : View(context, attrs) {
        var scannerAlpha = 0
        var offsetY = 0f

        private var possibleResultPoints = ArrayList<ResultPoint>(5)
        private var lastPossibleResultPoints: List<ResultPoint>? = null

        /** 构造函数 */
        init {

        } // init

        /**
         * 重载控件的onDraw函数
         *
         * @param   canvas      画布
         */
        @SuppressLint("DrawAllocation")
        override fun onDraw(canvas: Canvas) {
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
            val viewSize = Math.min(width, height).toFloat()

            val frame = RectF(viewSize / 4f, viewSize / 4f, viewSize * 0.75f, viewSize * 0.75f)

            // 绘制蒙板
            drawMask(canvas, frame)

            // 绘制扫描边框
            drawFrame(canvas, frame)

            // 绘制扫描线
            paint.color = Color.GRAY
            paint.strokeWidth = dip(1).toFloat()
            offsetY = (offsetY + 10) % ((frame.height() - 4) * 2)
            val middle = frame.bottom - Math.abs(offsetY - frame.height())
            canvas.drawRect(frame.left + 2, middle+1, frame.right - 1, middle +  3, paint)

            postInvalidateDelayed(30, frame.left.toInt(), frame.top.toInt(), frame.right.toInt(), frame.bottom.toInt())
            return
        } // Function onDraw()

        /**
         * 绘制蒙板
         *
         * @param   canvas      画布
         * @param   frameRect   边框Rect
         */
        private fun drawMask(canvas: Canvas, frameRect: RectF) {
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
            // 绘制蒙板
            paint.color = maskColor
            paint.style = Paint.Style.FILL
            canvas.drawRect(0f, 0f, width.toFloat(), frameRect.top, paint)
            canvas.drawRect(0f, frameRect.top, frameRect.left, frameRect.bottom, paint)
            canvas.drawRect(frameRect.right, frameRect.top, width.toFloat(), frameRect.bottom, paint)
            canvas.drawRect(0f, frameRect.bottom, width.toFloat(), height.toFloat(), paint)

            return
        } // Function drawMask()
        /**
         * 绘制扫描边框
         *
         * @param   canvas      画布
         * @param   frameRect   边框Rect
         */
        private fun drawFrame(canvas: Canvas, frameRect: RectF) {
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)

            // 绘制边框
            paint.color = frameColor
            paint.style = Paint.Style.STROKE
            paint.strokeWidth = dip(1).toFloat()
            canvas.drawRect(frameRect, paint)

            paint.strokeWidth = dip(4).toFloat()
            val cornerOffset = paint.strokeWidth / 2
            val cornerList = Path()
            val cornerSize = frameRect.width() / 12
            // 左上角
            cornerList.moveTo(frameRect.left - cornerOffset, frameRect.top - cornerOffset + cornerSize)
            cornerList.rLineTo(0f, - cornerSize)
            cornerList.rLineTo(cornerSize, 0f)
            // 右上角
            cornerList.moveTo(frameRect.right + cornerOffset - cornerSize, frameRect.top - cornerOffset)
            cornerList.rLineTo(cornerSize, 0f)
            cornerList.rLineTo(0f, cornerSize)
            // 右下角
            cornerList.moveTo(frameRect.right + cornerOffset, frameRect.bottom + cornerOffset - cornerSize)
            cornerList.rLineTo(0f, cornerSize)
            cornerList.rLineTo(-cornerSize, 0f)
            // 左下角
            cornerList.moveTo(frameRect.left - cornerOffset + cornerSize, frameRect.bottom + cornerOffset)
            cornerList.rLineTo(-cornerSize, 0f)
            cornerList.rLineTo(0f, -cornerSize)
            canvas.drawPath(cornerList, paint)

            return
        } // Function drawFrame()

    } // Class FinderView()
} // Class SQrCodeView