package com.jld.vod.view.widget

import android.content.Context
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.jld.vod.config.Config
import com.jld.vod.model.bean.AllModularRotateImgBean
import com.jld.vod.utils.DensityUtil
import com.jld.vod.utils.LogUtils

/**
 * Created by ${符柱成} on 2016/10/24.
 */
class UpCircleMenuLayout(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {
    private var mRadius = 0

    /**
     * 菜单的中心child的默认尺寸
     */
    private val RADIO_DEFAULT_CENTERITEM_DIMENSION = 1 / 3f

    /**
     * 当每秒移动角度达到该值时，认为是快速移动
     */
    private var mFlingableValue = FLINGABLE_VALUE

    /**
     * 该容器的内边距,无视padding属性，如需边距请用该变量
     */
    private var mPadding = 0f

    /**
     * 布局时的开始角度
     */
    private var mStartAngle = 36.0

    /**
     * 菜单项的图标
     */
    private var mItemImgs: List<AllModularRotateImgBean>? = null

    /**
     * 菜单项的文本
     */
    private val mItemTexts: Array<String>? = null


    /**
     * 菜单的个数
     */
    private var mMenuItemCount = 0

    /**
     * 检测按下到抬起时旋转的角度
     */

    private var mTmpAngle = 0f
    /**
     * 检测按下到抬起时使用的时间
     */
    private var mDownTime: Long = 0

    /**
     * 判断是否正在自动滚动
     */
    private var isTouchUp = true

    private var isFirstLoadding = false

    /**
     * 当前中间顶部的那个
     */
    private var mCurrentPosition = 0
    val MIN_CLICK_DELAY_TIME = 500
    private var lastClickTime: Long = 0

    /**
     * 设置布局的宽高，并策略menu item宽高
     */
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var resWidth = 0
        var resHeight = 0
        var startAngle = mStartAngle
        val angle = 360 / 10.toDouble()

        /**
         * 根据传入的参数，分别获取测量模式和测量值
         */
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        /**
         * 如果宽或者高的测量模式非精确值
         */
        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            // 主要设置为背景图的高度
            resWidth = defaultWidth
            resHeight = (resWidth * DEFAULT_BANNER_HEIGTH / DEFAULT_BANNER_WIDTH).toInt()
        } else {
            // 如果都设置为精确值，则直接取小值；
            resHeight = Math.min(width, height)
            resWidth = resHeight
        }
        setMeasuredDimension(resWidth, resHeight)

        // 获得直径
        mRadius = Math.max(measuredWidth, measuredHeight)

        // menu item数量
        val count = childCount
        // menu item尺寸
        var childSize: Int

        // menu item测量模式
        val childMode = MeasureSpec.EXACTLY

        // 迭代测量：根据孩子的数量进行遍历，为每一个孩子测量大小，设置监听回调。
        for (i in 0 until count) {
            val child = getChildAt(i)

            //LogUtils.logD("startAngle="+startAngle+"isTouchUp=="+isTouchUp+"isFirstLoadding=="+isFirstLoadding)
            if (startAngle > 359 && startAngle < 361 && isTouchUp && isFirstLoadding) {
              //  val currentTime = Calendar.getInstance().timeInMillis
               // if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
                 //   lastClickTime = currentTime
                    mOnMenuItemClickListener!!.itemClick(i) //设置监听回调。
              //  }
                mCurrentPosition = i //本次使用mCurrentPosition，只是把他作为一个temp变量。可以有更多的使用，比如动态设置每个孩子相隔的角度
                childSize = DensityUtil.dip2px(context, RADIO_TOP_CHILD_DIMENSION) //设置大小

            } else {
                childSize = DensityUtil.dip2px(context, RADIO_DEFAULT_CHILD_DIMENSION)
            }
            if (child.visibility == View.GONE) {
                continue
            }
            startAngle = startAngle % 360
            // 计算menu item的尺寸；以及和设置好的模式，去对item进行测量
            var makeMeasureSpec = -1
            makeMeasureSpec = MeasureSpec.makeMeasureSpec(childSize, childMode)
            child.measure(makeMeasureSpec, makeMeasureSpec)
            startAngle += angle
        }
        isFirstLoadding = false
        //item容器内边距
        mPadding = DensityUtil.dip2px(context, RADIO_MARGIN_LAYOUT.toFloat()).toFloat()
    }

    /**
     * MenuItem的点击事件接口
     *
     * @author zhy
     */
    interface OnMenuItemClickListener {
        fun itemClick(pos: Int)
        fun itemCenterClick(view: View?)
    }

    /**
     * MenuItem的点击事件接口
     */
    private var mOnMenuItemClickListener: OnMenuItemClickListener? =
        null

    /**
     * 设置MenuItem的点击事件接口
     *
     * @param mOnMenuItemClickListener
     */
    fun setOnMenuItemClickListener(mOnMenuItemClickListener: OnMenuItemClickListener?) {
        this.mOnMenuItemClickListener = mOnMenuItemClickListener
    }

    /**
     * 设置menu item的位置
     */
    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        //布置圆的半径
        val layoutRadius = mRadius
        // Laying out the child views
        val childCount = childCount
        var left: Int
        var top: Int
        // menu item 的尺寸
        var cWidth: Int

        // 根据menu item的个数，计算角度
        val angleDelay = 360 /  10.toFloat()
        // 遍历去设置menuitem的位置
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            //根据孩子遍历，设置中间顶部那个的大小以及其他图片大小。
            if (mStartAngle > 359 && mStartAngle < 361 && isTouchUp) {
                cWidth = DensityUtil.dip2px(context, RADIO_TOP_CHILD_DIMENSION)
                child.isSelected = true
            } else {
                cWidth = DensityUtil.dip2px(context, RADIO_DEFAULT_CHILD_DIMENSION)
                child.isSelected = false
            }
            if (child.visibility == View.GONE) {
                continue
            }
            //大于360就取余归于小于360度
            mStartAngle = mStartAngle % 360
            var tmp = 0f
            //计算图片布置的中心点的圆半径。就是tmp
            tmp = layoutRadius / 2f - cWidth / 2 - mPadding
            // tmp cosa 即menu item中心点的横坐标。计算的是item的位置，是计算位置！！！
            left = (layoutRadius / 2) + Math.round(tmp
                        * Math.cos(Math.toRadians(mStartAngle)) - 1 / 2f
                        * cWidth).toInt() + DensityUtil
                .dip2px(context, 1f)
            // tmp sina 即menu item的纵坐标
            top = (layoutRadius
                    / 2) + Math.round(tmp
                        * Math.sin(Math.toRadians(mStartAngle)) - 1 / 2f * cWidth
            ).toInt() + DensityUtil
                .dip2px(context, 8f)
            //接着当然是布置孩子的位置啦，就是根据小圆的来布置的
            child.layout(left, top, left + cWidth, top + cWidth)

            // 叠加尺寸
            mStartAngle += angleDelay.toDouble()
        }
    }

    private fun backOrPre() {     //缓冲的角度。即我们将要固定几个位置，而不是任意位置。我们要设计一个可能的角度去自动帮他选择。
        isTouchUp = true
        val angleDelay = 360 / 10.toFloat() //这个是每个图形相隔的角度
        if ((mStartAngle - 36) % angleDelay == 0.0) {
            return
        }
        val angle =
            ((mStartAngle - 36) % 36).toFloat() //angle就是那个不是18度开始布局，然后是36度的整数的多出来的部分角度
        if (angleDelay / 2 > angle) {
            mStartAngle -= angle.toDouble()
        } else if (angleDelay / 2 < angle) {
            mStartAngle =
                mStartAngle - angle + angleDelay //mStartAngle就是当前角度啦，取余36度就是多出来的角度，拿这个多出来的角度去数据处理。
        }
        requestLayout()
    }

    /**
     * 记录上一次的x，y坐标
     */
    private var mLastX = 0f
    private var mLastY = 0f

    //dispatchTouchEvent是处理触摸事件分发,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行super.dispatchTouchEvent(ev)，事件向下分发。
    //onTouchEvent是View中提供的方法，ViewGroup也有这个方法，view中不提供onInterceptTouchEvent。view中默认返回true，表示消费了这个事件。
    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y

        //LogUtils.logD("event.action"+x+"y="+y)
        isFirstLoadding = true

        parent.requestDisallowInterceptTouchEvent(true)
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                mLastX = x
                mLastY = y
                mDownTime = System.currentTimeMillis()
                mTmpAngle = 0f
                // 如果当前已经在快速滚动
            }
            MotionEvent.ACTION_MOVE -> {
                isTouchUp = false //注意isTouchUp 这个标记量！！！
                /**
                 * 获得开始的角度
                 */
                val start = getAngle(mLastX, mLastY)

                /**
                 * 获得当前的角度
                 */
                val end = getAngle(x, y)
                // 如果是一、四象限，则直接end-start，角度值都是正值
                if (getQuadrant(x, y) == 1 || getQuadrant(x, y) == 4) {
                    mStartAngle += end - start.toDouble()
                    mTmpAngle += end - start
                } else  // 二、三象限，色角度值是付值
                {
                    mStartAngle += start - end.toDouble()
                    mTmpAngle += start - end
                }
                // 重新布局
                if (mTmpAngle != 0f) {
                    requestLayout()
                }
                mLastX = x
                mLastY = y
            }
            MotionEvent.ACTION_UP -> backOrPre()
        }
        return super.dispatchTouchEvent(event)
    }

    /**
     * 主要为了action_down时，返回true
     */
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        return true
    }
    /**
     * 根据触摸的位置，计算角度
     *
     * @param xTouch
     * @param yTouch
     * @return
     */
    private fun getAngle(xTouch: Float, yTouch: Float): Float {
        val x = xTouch - mRadius / 2.0
        val y = yTouch - mRadius / 2.0
        return (Math.asin(
            y / Math.hypot(
                x,
                y
            )
        ) * 180 / Math.PI).toFloat()
    }

    /**
     * 根据当前位置计算象限
     *
     * @param x
     * @param y
     * @return
     */
    private fun getQuadrant(x: Float, y: Float): Int {
        val tmpX = (x - mRadius / 2).toInt()
        val tmpY = (y - mRadius / 2).toInt()
        return if (tmpX >= 0) {
            if (tmpY >= 0) 4 else 1
        } else {
            if (tmpY >= 0) 3 else 2
        }
    }

    fun setAngle(position: Int) {
        val angleDelay = 360 / 10.toFloat()
        if (position > mCurrentPosition) {
            mStartAngle += (mCurrentPosition - position) * angleDelay.toDouble()
        } else {
            mStartAngle -= (position - mCurrentPosition) * angleDelay.toDouble()
        }
        requestLayout()
    }

    /**
     * 设置菜单条目的图标和文本
     *
     * @param resIds
     */
    fun setMenuItemIconsAndTexts(resIds: List<AllModularRotateImgBean>?) {
        LogUtils.logD("resIds"+resIds)
        mItemImgs = resIds

        // 参数检查
        requireNotNull(resIds) { "菜单项文本和图片至少设置其一" }
        //

        // 初始化mMenuCount
        mMenuItemCount = resIds?.size ?: 0
        addMenuItems()
    }

    /**
     * 添加菜单项
     */
    private fun addMenuItems() {
        /**
         * 根据用户设置的参数，初始化view
         */
        for (i in 0 until mMenuItemCount) {
            val j = i
            val iv = ImageView(context)
            if (iv != null) {
                iv.visibility = View.VISIBLE
                try {
                    Glide.with(context).load(
                        Config.ApiBaseUrl+"/synchronization/previewImg?imgUrl="
                                +mItemImgs!![i].icon).into(iv)
                }catch (e:Exception)
                {
                    e.printStackTrace()
                }

              //  iv.setImageResource(mItemImgs!![i])
                iv.setOnClickListener {
                   //                         isTouchUp = true;
                }
            }

            // 添加view到容器中
            addView(iv)
        }
    }

    /**
     * 如果每秒旋转角度到达该值，则认为是自动滚动
     *
     * @param mFlingableValue
     */
    fun setFlingableValue(mFlingableValue: Int) {
        this.mFlingableValue = mFlingableValue
    }

    /**
     * 设置内边距的比例
     *
     * @param mPadding
     */
    fun setPadding(mPadding: Float) {
        this.mPadding = mPadding
    }

    /**
     * 获得默认该layout的尺寸
     *
     * @return
     */
    private val defaultWidth: Int
        private get() {
            val wm = context.getSystemService(
                Context.WINDOW_SERVICE
            ) as WindowManager
            val outMetrics = DisplayMetrics()
            wm.defaultDisplay.getMetrics(outMetrics)
            return Math.min(outMetrics.widthPixels, outMetrics.heightPixels)
        }

    companion object {
        const val DEFAULT_BANNER_WIDTH = 750.0f //中间显示的图标大小
        const val DEFAULT_BANNER_HEIGTH = 420.0f //其余图标大小

        /**
         * 该容器内图标child item的默认尺寸
         */
        private const val RADIO_DEFAULT_CHILD_DIMENSION = 90.0f
        private const val RADIO_TOP_CHILD_DIMENSION = 110.0f

        /**
         * 该容器的内边距,无视padding属性，如需边距请用该变量
         */
        private const val RADIO_PADDING_LAYOUT = 20f
        private const val RADIO_MARGIN_LAYOUT = 40

        /**
         * 当每秒移动角度达到该值时，认为是快速移动
         */
        private const val FLINGABLE_VALUE = 180

        /**
         * 如果移动角度达到该值，则屏蔽点击
         */
        private const val NOCLICK_VALUE = 3
    }

    init {
        // 无视padding
        setPadding(0, 0, 0, 0)
    }
}