package com.develop.food.base.widgets

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.LinearSnapHelper
import com.develop.base.R
import com.develop.base.databinding.TimePickerViewBinding
import com.develop.food.base.adapter.CookTimeAdapter


class TimePickerView : ConstraintLayout {

    private var binding: TimePickerViewBinding

    private var timeColor = Color.WHITE
    private val firstData = mutableListOf<String>()
    private val secondData = mutableListOf<String>()

    private lateinit var firstAdapter: CookTimeAdapter
    private lateinit var secondAdapter: CookTimeAdapter

    private var firstTimePos = 0
    private var secondTimePos = 0

    private var maxTime = 8 * 60 * 60
    private var minTime = 0

    var onTimePickerCallback: OnTimePickerCallback? = null
    private var firstManager :ScrollLinearManager
    private var secondManager :ScrollLinearManager
    constructor(context: Context) : super(context) {}
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        initAttrs(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        initAttrs(context, attrs)
    }

    init {
        val root = View.inflate(context, R.layout.time_picker_view, this)
        binding = TimePickerViewBinding.bind(root)
        repeat(92) { idx ->
            if (idx < 10) {
                firstData.add("0$idx")
            } else {
                firstData.add(idx.toString())
            }
        }
        repeat(60) { idx ->

            if (idx < 10) {
                secondData.add("0$idx")
            } else {
                secondData.add(idx.toString())
            }
        }
        firstManager = ScrollLinearManager(context)
        secondManager = ScrollLinearManager(context)
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        context.obtainStyledAttributes(attrs, R.styleable.TimePickerView).apply {
            timeColor = getColor(R.styleable.TimePickerView_time_color, Color.WHITE)
        }.recycle()
        binding.tvSetTimeFirst.layoutManager = firstManager
        binding.tvSetTimeSecond.layoutManager = secondManager
        firstAdapter = CookTimeAdapter(firstData, timeColor)
        secondAdapter = CookTimeAdapter(secondData, timeColor)
        binding.tvDotTime.setTextColor(timeColor)
        binding.tvFirstBottom.setTextColor(timeColor)
        binding.tvSecondBottom.setTextColor(timeColor)
        binding.tvSetTimeFirst.adapter = firstAdapter
        binding.tvSetTimeSecond.adapter = secondAdapter
        binding.tvSetTimeFirst.addOnScrollListener(LinearPositionObserver { pos ->

            if(!showHour &&  pos >= 91){
                showHour = true
                firstTimePos = (pos / 60)
                secondTimePos = (pos - 60)
                binding.tvSetTimeFirst.scrollToPosition(firstTimePos)
                binding.tvSetTimeSecond.scrollToPosition(secondTimePos)
            }else if (showHour && pos <= 0){
                showHour = false
                firstTimePos= secondTimePos
                secondTimePos= 0
                binding.tvSetTimeFirst.scrollToPosition(firstTimePos)
                binding.tvSetTimeSecond.scrollToPosition(secondTimePos)
            }else if(showHour && (firstTimePos == 1 && secondTimePos < 30)){
                showHour = false
                firstTimePos = (firstTimePos*60 + secondTimePos)
                secondTimePos = 0
                binding.tvSetTimeFirst.scrollToPosition(firstTimePos)
                binding.tvSetTimeSecond.scrollToPosition(secondTimePos)
            }else{
                firstTimePos = pos;
            }

            updateDisplayTime()
        })
        binding.tvSetTimeFirst.setOnTouchListener { view, motionEvent ->
            onTimePickerCallback?.onTimePickerTouchFirst()
            false
        }
        binding.tvSetTimeSecond.addOnScrollListener(LinearPositionObserver { pos ->
            secondTimePos = pos
            updateDisplayTime()
        })
        binding.tvSetTimeSecond.setOnTouchListener { view, motionEvent ->
            onTimePickerCallback?.onTimePickerTouchFirst()
            false
        }
        LinearSnapHelper().attachToRecyclerView(binding.tvSetTimeFirst)
        LinearSnapHelper().attachToRecyclerView(binding.tvSetTimeSecond)
    }

    private fun checkChangeTimeScale(firstPos: Int) {
        val firstUnit: String
        val secondUnit: String
        if (showHour) {
            firstUnit = "hour"
            secondUnit = "min"
        } else {
            firstUnit = "min"
            secondUnit = "sec"
        }
        if (firstUnit != binding.tvFirstBottom.text) {
            binding.tvFirstBottom.text = firstUnit
        }
        if (secondUnit != binding.tvSecondBottom.text) {
            binding.tvSecondBottom.text = secondUnit
        }
    }

    private fun updateDisplayTime() {
       if(!checkLimitTime(true)){
           return
       }
        if (showHour) {
            setTimeInternal(
                firstTimePos,
                secondTimePos,
                0,
                false,
                setByUser = true
            )
        } else {
            setTimeInternal(
                0,
                firstTimePos,
                secondTimePos,
                false,
                setByUser = true
            )
        }
    }

    var showHour = false;

    var totalTime = 0;

    @SuppressLint("SetTextI18n")
    fun setTimeInternal(
        hours: Int,
        minute: Int,
        second: Int,
        changeSetting: Boolean,
        setByUser: Boolean = false
    ) {



        val firstTime: Int
        val secondTime: Int
        val lastShowHour = showHour;
        showHour = ((hours * 60  + minute) >= 91)
        totalTime = (hours * 3600 + minute * 60 + second)

        if(!checkLimitTime(setByUser)){
              return;
        }

        if (showHour) {
            checkChangeTimeScale(91)
            firstTime = (hours + minute / 60)
            secondTime = (minute % 60)
        } else {
            checkChangeTimeScale(30)
            firstTime = (hours*60 + minute)
            secondTime = second
        }
        binding.let {
            if (changeSetting || showHour != lastShowHour) {
                firstTimePos = firstTime
                secondTimePos = secondTime
                it.tvSetTimeFirst.scrollToPosition(firstTimePos)
                it.tvSetTimeSecond.scrollToPosition(secondTimePos)
            }
            val firstStr = if (firstTime < 10) {
                "0$firstTime"
            } else {
                firstTime.toString()
            }
            val secondStr = if (secondTime < 10) {
                "0$secondTime"
            } else {
                secondTime.toString()
            }
            onTimePickerCallback?.onTimePicker(hours, minute, second, "${firstStr}:${secondStr}", setByUser)
        }
        Log.d("PickerView", "h:${hours}, m:${minute}, s:${second}, setByUser:${setByUser}")
    }

    /**
     * 设置最大最小时间
     * 单位秒
     */
    fun setTimeRange(minTime: Int, maxTime: Int) {
        this.minTime = minTime
        this.maxTime = maxTime
        checkLimitTime()
    }

    private fun checkLimitTime(setByUser: Boolean = false): Boolean {
        val minMinutes = (minTime / 60 % 60)
        val minHours = (minTime / 3600)
        val minSeconds = minTime % 60
        val maxMinutes = (maxTime / 60 % 60)
        val maxHours = (maxTime / 3600)
        val maxSeconds = maxTime % 60
        val currentSeconds: Int
        if (showHour) {
            currentSeconds = totalTime
        }else {
            currentSeconds = totalTime
        }
        if (currentSeconds < minTime) {
            setTimeInternal(
                minHours,
                minMinutes,
                minSeconds,
                changeSetting = true,
                setByUser = setByUser
            )
            return false;
        }else if (currentSeconds > maxTime) {
            setTimeInternal(
                maxHours,
                maxMinutes,
                maxSeconds,
                changeSetting = true,
                setByUser = setByUser
            )
            return false;
        }
        return true;
    }

    fun setTargetTime(time: String) {
        binding.tvTargetTime.visibility = View.VISIBLE
        binding.tvTargetTime.text = time
    }

    fun hideTargetTime() {
        binding.tvTargetTime.visibility = View.INVISIBLE
    }

    fun isTimeCanChange(isCanChange: Boolean) {
        firstManager.setCanScrollVertically(isCanChange)
        secondManager.setCanScrollVertically(isCanChange)
    }

    interface OnTimePickerCallback {
        fun onTimePicker(hours: Int, minute: Int, second: Int, time: String, setByUser: Boolean)
        fun onTimePickerTouchFirst()
    }
}