package com.gamedog.vididin.manager

import com.ama.core.architecture.util.DateUtil
import com.ama.core.architecture.util.FileUtil
import com.ama.core.architecture.util.SpUtil
import com.gamedog.vididin.main.fragments.task.Task
import com.gamedog.vididin.main.fragments.task.TaskBean
import com.google.gson.GsonBuilder
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.*

class TaskManager private constructor() {
    companion object {
        // 新手任务分类及其子类
        private const val TAG_CATEGORY_NEWBIE_TASK = "newbie_task"
        private const val TAG_TASK_NEWBIE_FIRST_WITHDRAW = "newbie_first_withdraw"
        private const val TAG_TASK_NEWBIE_PUSH_NOTIFY = "newbie_push_notify"
        private const val TAG_TASK_NEWBIE_JOIN_DISCORD = "newbie_join_discord"
        private const val TAG_TASK_NEWBIE_7DAY_CHECKIN = "newbie_7day_checkin"

        // 日常任务分类及其子类
        private const val TAG_CATEGORY_DAILY_TASK = "daily_task"
        private const val TAG_TASK_DAILY_CHECKIN = "daily_checkin"
        private const val TAG_TASK_DAILY_VIDEO = "daily_video_ladder"
        private const val TAG_TASK_DAILY_AD = "daily_ad_ladder"




        @Volatile
        private var instance: TaskManager? = null

        fun instance(): TaskManager {
            return instance ?: synchronized(this) {
                instance ?: TaskManager().also {
                    instance = it
                }
            }
        }
    }


    private var mCurDayIndexDailySign: Int = 0
    private val mutex = Mutex()

    @Volatile
    private var initialized = false
    private var mTaskConfig: TaskBean? = null
    private var mDailySignData: DailySignBean = DailySignBean()
    private val mGson = GsonBuilder().create()


    init {
        loadTaskConfigAsync()

        // TODO - remove test code
        if (true) {
            generateTestDailySignTestBean()
        }
    }


    suspend fun getTaskConfig(): TaskBean? = mutex.withLock {
        if (!initialized) {
            loadTaskConfigFromAsset()
        }
        return mTaskConfig
    }

    private fun loadTaskConfigAsync() {
        CoroutineScope(Dispatchers.IO).launch {
            mutex.withLock {
                if (!initialized) {
                    loadTaskConfigFromAsset()
                    loadTaskStatesFromSp()
                }
            }
        }
    }

    private suspend fun loadTaskConfigFromAsset() {
        return withContext(Dispatchers.IO) {
            val configStr = FileUtil.readAssetsFile("taskConfig.json")
            mTaskConfig = mGson.fromJson(configStr, TaskBean::class.java)
            initialized = true
        }
    }


    private suspend fun loadTaskStatesFromSp() {
        return withContext(Dispatchers.IO) {
            val taskStateBeanInSp = SpUtil.instance().getObject<DailySignBean>(SpUtil.KEY_TASK_BEAN)
            if (taskStateBeanInSp == null) {
                SpUtil.instance().putObject(SpUtil.KEY_TASK_BEAN, mDailySignData)
            } else {
                mDailySignData = taskStateBeanInSp
            }
        }
    }




    //-------------------------  Get tasks  -------------------------------
    // 日常任务
    fun getDailyCheckInTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_DAILY_TASK)?.getTaskById(TAG_TASK_DAILY_CHECKIN)
    }

    fun getDailyVideoTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_DAILY_TASK)?.getTaskById(TAG_TASK_DAILY_VIDEO)
    }

    fun getDailyAdTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_DAILY_TASK)?.getTaskById(TAG_TASK_DAILY_AD)
    }

    // 新手任务
    fun getNewbieFirstWithdrawTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_NEWBIE_TASK)?.getTaskById(TAG_TASK_NEWBIE_FIRST_WITHDRAW)
    }

    fun getNewbieEnableNotifyTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_NEWBIE_TASK)?.getTaskById(TAG_TASK_NEWBIE_PUSH_NOTIFY)
    }

    fun getNewbieJoinDiscordTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_NEWBIE_TASK)?.getTaskById(TAG_TASK_NEWBIE_JOIN_DISCORD)
    }

    fun getNewbieCheckInTask(): Task? {
        return mTaskConfig?.task_module_config?.getTaskCategoryById(TAG_CATEGORY_NEWBIE_TASK)?.getTaskById(TAG_TASK_NEWBIE_7DAY_CHECKIN)
    }




    //----------------------------- 每日签到 -----------------------------//

    fun getHomeWatchDurationRewardNum(): Int {
        return 28;  // TODO - mTaskConfigBean.xxxx
    }


    fun getCurDayIndexOfDailyCheckIn() : Int {
        var dayIndexOfPeriod = 0

        val periodStartMs = mDailySignData.startMs
        if (periodStartMs > 0) {
            dayIndexOfPeriod = DateUtil.getPassedDayNum(periodStartMs, DateUtil.getCurTimeMs())
            if (dayIndexOfPeriod > 6) {
                mDailySignData.startMs = DateUtil.getCurTimeMs()
                SpUtil.instance().putObject(SpUtil.KEY_TASK_BEAN, mDailySignData)
            }
        } else {
            mDailySignData.startMs = DateUtil.getCurTimeMs()
            SpUtil.instance().putObject(SpUtil.KEY_TASK_BEAN, mDailySignData)
        }

        mCurDayIndexDailySign = dayIndexOfPeriod
        return dayIndexOfPeriod
    }

    fun getDailySignStateBean(dayIndex: Int): DailySignDayInfoBean {
        return mDailySignData.signStateList[dayIndex]
    }

    fun executeDailySign(dayIndex: Int, rewardNum: Int) : Boolean {
        val daySignState = mDailySignData.signStateList[dayIndex]

        if (!daySignState.hasSigned) {
            daySignState.hasSigned = true
            daySignState.hasRewardedNum += rewardNum
            saveDailySignInfo()
            return true
        }
        return false
    }

    private fun saveDailySignInfo() {
        SpUtil.instance().putObject(SpUtil.KEY_DAILY_SIGN, mDailySignData)
    }

    private fun generateTestDailySignTestBean() {
        mDailySignData = DailySignBean().apply {
            startMs = DateUtil.getCurTimeMs() - 4 * DateUtil.MS_NUM_ONE_DAY
            signStateList.clear()
            signStateList.add(DailySignDayInfoBean(hasSigned = true, hasWatchedAd = true))
            signStateList.add(DailySignDayInfoBean(hasSigned = false, hasWatchedAd = false))
            signStateList.add(DailySignDayInfoBean(hasSigned = true, hasWatchedAd = false))
            signStateList.add(DailySignDayInfoBean(hasSigned = false, hasWatchedAd = false))
            signStateList.add(DailySignDayInfoBean(hasSigned = false, hasWatchedAd = false))
            signStateList.add(DailySignDayInfoBean(hasSigned = false, hasWatchedAd = false))
            signStateList.add(DailySignDayInfoBean(hasSigned = false, hasWatchedAd = false))
        }

        SpUtil.instance().putObject(SpUtil.KEY_TASK_BEAN, mDailySignData)
    }

    fun getForgotSignDays(): Int {
        var forgotSignDays = 0
        mDailySignData.signStateList.forEach { item->
            if (!item.hasSigned) {
                forgotSignDays++
            }
        }
        return forgotSignDays
    }

}


