package com.gamedog.vididin.manager.helpers

import com.ama.core.architecture.util.DateUtil
import com.ama.core.architecture.util.SpUtil
import com.gamedog.vididin.R
import com.gamedog.vididin.VididinEvents
import com.gamedog.vididin.main.fragments.task.BoxTaskRoot
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_ZERO_BUY
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_SIGN
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_AD
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_VIDEO
import com.gamedog.vididin.manager.taskbeans.TaskStateBox
import com.gamedog.vididin.manager.taskbeans.TaskStateBoxRoot
import com.gamedog.vididin.manager.taskbeans.TaskStateBoxSub
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_FINISH
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_ONGOING
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_CLAIMED
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_EXPIRED


class BoxTaskHelper: BaseTaskHelper<TaskStateBoxRoot, BoxTaskRoot>() {

    override val mSpKey = SpUtil.KEY_TASK_BOX

    init {
        registerEvents( { eventData->
            when (eventData?.mEventType) {
                VididinEvents.Event_Finish_One_Ad -> {
                    handleEvents(BOX_SUB_TASK_TYPE_AD)
                }

                VididinEvents.Event_Finish_One_Video -> {
                    handleEvents(BOX_SUB_TASK_TYPE_VIDEO)
                }

                VididinEvents.Event_Finish_One_Sign -> {
                    handleEvents(BOX_SUB_TASK_TYPE_SIGN)
                }

                VididinEvents.Event_Finish_One_Zerobuy -> {
                    handleEvents(BOX_SUB_TASK_TYPE_ZERO_BUY)
                }
            }

        }, VididinEvents.Event_Finish_One_Ad, VididinEvents.Event_Finish_One_Video,
            VididinEvents.Event_Finish_One_Sign, VididinEvents.Event_Finish_One_Zerobuy)
    }

    override fun loadTaskFromSp() {
        val taskStateBeanInSp = SpUtil.instance().getObject<TaskStateBoxRoot>(mSpKey)
        if (taskStateBeanInSp == null || isBoxRootTaskExpired(taskStateBeanInSp)) {
            mStateBean = generateStateBeanFromConfig()
            saveState2Sp()
        } else {
            mStateBean = taskStateBeanInSp
        }
    }

    private fun generateStateBeanFromConfig(): TaskStateBoxRoot {
        val boxStateList = mutableListOf<TaskStateBox>()
        mTaskConfig.chests.forEachIndexed { index, task ->
            val boxSubTaskStateList = mutableListOf<TaskStateBoxSub>()
            task.tasks.forEachIndexed { index, task ->
                boxSubTaskStateList.add(TaskStateBoxSub(task.task_id,
                    task.task_name, task.required_count, task.task_type))
            }

            boxStateList.add(TaskStateBox(task.chest_id, task.chest_name, task.duration_days,
                task.reward_type, task.reward_value, task.is_one_time, task.status, boxSubTaskStateList))
        }

        return TaskStateBoxRoot(DateUtil.getTodayStartTimeMs(), boxStateList)
    }


    @Synchronized
    private fun handleEvents(taskType: Int) {
        val currentBoxIndex = getCurrentBoxIndex()
        if (!isBoxAllFinished(currentBoxIndex)) {
            getCurrentBoxState()?.tasks?.forEachIndexed { index, subTask->
                if (taskType == subTask.task_type
                            && !isBoxSubTaskFinished(currentBoxIndex, index)) {
                    subTask.finishedNum++
                    saveState2Sp()
                    // TODO - if need notify
                }
            }
        }
    }


    private fun isBoxRootTaskExpired(taskStateBoxRoot: TaskStateBoxRoot): Boolean {
        var totalDurationDays = 0
        taskStateBoxRoot.tasks.forEach {
            totalDurationDays += it.duration_days
        }
        return DateUtil.isPeriodExpired(taskStateBoxRoot.startMs, totalDurationDays)
    }

    private fun isBoxTaskExpired(boxIndex: Int): Boolean {
        if (boxIndex >= 0 && boxIndex < mStateBean.tasks.size) {
            val curBoxState = mStateBean.tasks[boxIndex]
            return DateUtil.isPeriodExpired(mStateBean.startMs, curBoxState.duration_days)
        }

        return false
    }

    private fun isBoxAllTasksFinish(boxIndex: Int) : Boolean {
        if (boxIndex >= 0 && boxIndex < mStateBean.tasks.size) {
            val curBoxState = mStateBean.tasks[boxIndex]

            curBoxState.tasks.forEach {
                if (it.required_count > it.finishedNum) {
                    return false
                }
            }
            return true
        }

        return false
    }

    fun getCurrentBoxIndex(): Int {
        val boxRootStartMs = mStateBean.startMs

        mStateBean.tasks.forEachIndexed { index, box ->
            if (!DateUtil.isPeriodExpired(boxRootStartMs, box.duration_days)) {
                return index
            }
        }
        return -1
    }

    fun getCurrentBoxState(): TaskStateBox? {
        val currentBoxIndex = getCurrentBoxIndex()

        if (currentBoxIndex >= 0 && currentBoxIndex < mStateBean.tasks.size) {
            return mStateBean.tasks[currentBoxIndex]
        }
        return null
    }

    fun isBoxAllFinished(boxIndex: Int) : Boolean {
        val stateEnum = getBoxStateEnum(boxIndex)
        return stateEnum == STATE_FINISH || stateEnum == STATE_CLAIMED
    }

    fun isBoxSubTaskFinished(boxIndex: Int, subTaskIndex: Int) : Boolean {
        val subTaskState = mStateBean.tasks[boxIndex].tasks[subTaskIndex]
        return subTaskState.finishedNum >= subTaskState.required_count
    }

    fun getBoxStateEnum(boxIndex: Int): Int {
        if (boxIndex >= 0 && boxIndex < mStateBean.tasks.size) {
            val curBoxState = mStateBean.tasks[boxIndex]

            if (curBoxState.hasClaimedReward) {
                return STATE_CLAIMED
            } else {
                if (isBoxAllTasksFinish(boxIndex)) {
                    return STATE_FINISH
                } else {
                    if (isBoxTaskExpired(boxIndex)) {
                        return STATE_EXPIRED
                    } else {
                        return STATE_ONGOING
                    }
                }
            }
        }
        return -1
    }

    fun getCouldClaimCashNum(): Float {
        var waitClaimCashNum = 0F
        mStateBean.tasks.forEachIndexed { index, box ->
            if (getBoxStateEnum(index) == STATE_FINISH) {
                waitClaimCashNum += box.reward_value
            }
        }
        return waitClaimCashNum
    }

    fun getSubTaskHintStrRes(boxIndex: Int, subTaskIndex: Int): Int {
        when (boxIndex) {
            0-> {
                when (subTaskIndex) {
                    0-> {
                        return R.string.box_subtask_hint_1_1
                    }

                    1-> {
                        return R.string.box_subtask_hint_1_2
                    }

                    2-> {
                        return R.string.box_subtask_hint_1_3
                    }
                }
            }

            1-> {
                when (subTaskIndex) {
                    0-> {
                        return R.string.box_subtask_hint_2_1
                    }

                    1-> {
                        return R.string.box_subtask_hint_2_2
                    }

                    2-> {
                        return R.string.box_subtask_hint_2_3
                    }
                }
            }

            2-> {
                when (subTaskIndex) {
                    0-> {
                        return R.string.box_subtask_hint_3_1
                    }

                    1-> {
                        return R.string.box_subtask_hint_3_2
                    }

                    2-> {
                        return R.string.box_subtask_hint_3_3
                    }
                }
            }
        }

        return 0
    }

    fun getCurrentBoxTotalProgress(): Int {
        val currentBoxIndex = getCurrentBoxIndex()
        val boxList = mStateBean.tasks
        if (currentBoxIndex >= 0 && currentBoxIndex < boxList.size) {
            var totalFinished = 0
            var totalRequired = 0
            val currentBox = boxList[currentBoxIndex]

            currentBox.tasks.forEach {
                totalFinished += it.finishedNum
                totalRequired += it.required_count
            }

            if (totalRequired > 0) {
                val totalProgress = (100 * totalFinished) / totalRequired
                return if (totalProgress > 100) 100 else totalProgress
            }
        }
        return 0
    }

}