package com.khmer9.yuki.screen.result

import android.annotation.SuppressLint
import android.media.MediaPlayer
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
import com.gdtlib.lib.adapter.BaseListItem
import com.khmer9.yuki.R
import com.khmer9.yuki.app.App
import com.khmer9.yuki.app.ShareActivity
import com.khmer9.yuki.base.BaseFragment
import com.khmer9.yuki.extension.btnClick
import com.khmer9.yuki.remote.ResultLotto
import com.khmer9.yuki.remote.main.SocketClientResultDataModel
import com.khmer9.yuki.remote.main.SocketClientTimeDataModel
import com.khmer9.yuki.util.MiddleDividerItemDecoration
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import kotlinx.android.synthetic.main.fragment_result.*

/**
 * A simple [Fragment] subclass as the second destination in the navigation.
 */
class ResultFragment : BaseFragment(R.layout.fragment_result) {
    private lateinit var adapterTable0: Table0Adapter
    private lateinit var adapterTable1: Table1Adapter
    private lateinit var adapterTable2: Table2Adapter
    private lateinit var adapterTable3: Table3Adapter
    private lateinit var adapterTable4: Table4Adapter
    private val shareViewModel = App.injectShareViewModel()
    private lateinit var itemDecoration: MiddleDividerItemDecoration
    private lateinit var betTouch: MediaPlayer
    private lateinit var moshi: Moshi
    private var itemsTable4: MutableList<Table4ListItem> = mutableListOf()
    private var itemsTable3: MutableList<Table3ListItem> = mutableListOf()
    private var itemsTable2: MutableList<Table2ListItem> = mutableListOf()
    private val itemsTable1: MutableList<Table1ListItem> = mutableListOf()
    private val itemsTable0: MutableList<Table0ListItem> = mutableListOf()
    private var resultList : MutableList<ResultLotto> = mutableListOf()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        (requireActivity() as ShareActivity).apply {
            betTouch = MediaPlayer.create(this, R.raw.bettouch)
        }
        moshi = Moshi.Builder().build()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        (requireActivity() as? ShareActivity)?.apply {
            groupToolbarIcons.isVisible = false
            view.findViewById<ImageView>(R.id.btn_close).setOnClickListener {
                if (!sharePref.getIsMute()) betTouch.start()
                it.btnClick().subscribe {
                    onBackPressed()
                }
            }

            refreshImageView.setOnClickListener {
                shareViewModel.remoteResult()
            }

            shareViewModel.getClientTime.observe(viewLifecycleOwner, Observer {
                if (!it.isNullOrEmpty()) {
                    val adapter: JsonAdapter<SocketClientTimeDataModel> = moshi.adapter(
                        SocketClientTimeDataModel::class.java
                    )
                    val socketClientTimeResponse = adapter.fromJson(it)
                    if (socketClientTimeResponse != null) {
                        getMessage(socketClientTimeResponse)
                    }
                }
            })
        }

        itemDecoration = MiddleDividerItemDecoration(requireContext(), MiddleDividerItemDecoration.ALL)
        itemDecoration.setDividerColor(
            ContextCompat.getColor(
                requireContext(),
                R.color.color_gray_800
            )
        )
        shareViewModel.remoteResult()
        shareViewModel.getResultState.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
            getResult(it)
        })
        shareViewModel.getClientResult.observe(viewLifecycleOwner, Observer {
            shareViewModel.remoteResult()
        })
        adapterTable0 = Table0Adapter()
        for (n in 1..120) {
            itemsTable0?.add(Table0ListItem(n, 0))
        }
        rv_tb0.addItemDecoration(itemDecoration)
        rv_tb0.setHasFixedSize(true)
        rv_tb0.layoutManager = GridLayoutManager(requireContext(), 20)
        rv_tb0.adapter = adapterTable0
        adapterTable0.submitList(itemsTable0 as List<BaseListItem>?)

        adapterTable1 = Table1Adapter()
        for (n in 1..120) {
            itemsTable1?.add(Table1ListItem(n, 0))
        }
        rv_tb1.addItemDecoration(itemDecoration)
        rv_tb1.setHasFixedSize(true)
        rv_tb1.layoutManager = GridLayoutManager(requireContext(), 20)
        rv_tb1.adapter = adapterTable1
        adapterTable1.submitList(itemsTable1 as List<BaseListItem>?)

        adapterTable2 = Table2Adapter()
        for (n in 1..120) {
            itemsTable2?.add(Table2ListItem(n, 0))
        }
        rv_tb2.addItemDecoration(itemDecoration)
        rv_tb2.setHasFixedSize(true)
        rv_tb2.layoutManager = GridLayoutManager(requireContext(), 20)
        rv_tb2.adapter = adapterTable2
        adapterTable2.submitList(itemsTable2 as List<Table2ListItem>)

        adapterTable3 = Table3Adapter()
        for (n in 1..120) {
            itemsTable3?.add(Table3ListItem(n, 0))
        }
        rv_tb3.addItemDecoration(itemDecoration)
        rv_tb3.setHasFixedSize(true)
        rv_tb3.layoutManager = GridLayoutManager(requireContext(), 20)
        rv_tb3.adapter = adapterTable3
        adapterTable3.submitList(itemsTable3 as List<Table3ListItem>)

        adapterTable4 = Table4Adapter()
        for (n in 1..120) {
            itemsTable4?.add(Table4ListItem(n, 0))
        }
        rv_tb4.addItemDecoration(itemDecoration)
        rv_tb4.setHasFixedSize(true)
        rv_tb4.layoutManager = GridLayoutManager(requireContext(), 20)
        rv_tb4.adapter = adapterTable4
        adapterTable4.submitList(itemsTable4 as List<Table4ListItem>)
    }

    private fun getResult(state: ResultViewState) {
        if (state.isProgress) {
            progress_tb0.isVisible = true
            progress_tb1.isVisible = true
            progress_tb2.isVisible = true
            progress_tb3.isVisible = true
            progress_tb4.isVisible = true
        } else {
            progress_tb0.isVisible = false
            progress_tb1.isVisible = false
            progress_tb2.isVisible = false
            progress_tb3.isVisible = false
            progress_tb4.isVisible = false
        }
        if (!state.resultList.isNullOrEmpty()) {
            Log.d("resultList", ""+ state.resultList?.size)
            //1 row have 20 column
            resultList = state.resultList as MutableList<ResultLotto>
            var yearIndex = 0
            var nDuplicateYear = 0
            val listYear = arrayListOf<Table0ListItem>()
            for (n in 1..120) {
                listYear.add(Table0ListItem(n, 0))
            }

            var bigSmallIndex = 0
            var nDuplicateBigSmall = 0
            val listBigSmall = arrayListOf<Table1ListItem>()
            for (n in 1..120) {
                listBigSmall.add(Table1ListItem(n, 0))
            }

            val listRange = arrayListOf<Table2ListItem>()
            for (n in 1..120) {
                listRange.add(Table2ListItem(n, 0))
            }
            var rangeIndex = 0
            var nDuplicateRange = 0

            var oddEvenIndex = 0
            var nDuplicateOddEven = 0
            val listOddEven = arrayListOf<Table3ListItem>()
            for (n in 1..120) {
                listOddEven.add(Table3ListItem(n, 0))
            }

            var blueRedIndex = 0
            var nDuplicateBlueRed = 0
            val listBlueRed = arrayListOf<Table4ListItem>()
            for (n in 1..120) {
                listBlueRed.add(Table4ListItem(n, 0))
            }
            state.resultList?.forEachIndexed { index, result ->
                Log.d("resultList", ""+index + "::" + result.toString())
                if (index == 0) {
                    Log.d("resultList", ""+index + "::" + result.year.yearNumber)
                    listYear[index].yearNumber = result.year.yearNumber
                    listBigSmall[index].color = getLargeSmall(result.smallLarge.name)
                    listRange[index].rangeNumber = getRange(result.range.name)
                    listOddEven[index].oddEvenNumber = getOddEven(result.oddEven.name)
                    listBlueRed[index].blueRedNumber = getBlueRed(result.blueRed.name)
                } else {
                    if (result.year.yearNumber == state.resultList!![index - 1].year.yearNumber) {
                        val isYear = result.year.yearNumber
                        nDuplicateYear += 1
                        if(nDuplicateYear==6){
                            listYear[index - yearIndex].yearNumber = result.year.yearNumber
                            nDuplicateYear = 0
                        }else{
                            yearIndex += sameYear(index, listYear, yearIndex, isYear, nDuplicateYear)
                        }
                    } else {
                        listYear[index - yearIndex].yearNumber = result.year.yearNumber
                        nDuplicateYear = 0
                    }

                    if (result.smallLarge.name == state.resultList!![index - 1].smallLarge.name) {
                        val isBigSmall = getLargeSmall(result.smallLarge.name)
                        nDuplicateBigSmall += 1
                        if(nDuplicateBigSmall==6){
                            listBigSmall[index - bigSmallIndex].color = getLargeSmall(result.smallLarge.name)
                            nDuplicateBigSmall = 0
                        }else{
                            bigSmallIndex += sameBigSmall(index, listBigSmall, bigSmallIndex, isBigSmall, nDuplicateBigSmall)
                        }
                    } else {
                        listBigSmall[index - bigSmallIndex].color = getLargeSmall(result.smallLarge.name)
                        nDuplicateBigSmall = 0
                    }

                    if (result.range.name == state.resultList!![index - 1].range.name) {
                        val range = getRange(result.range.name)
                        nDuplicateRange += 1
                        if(nDuplicateRange == 6){
                            listRange[index - rangeIndex].rangeNumber = getRange(result.range.name)
                            nDuplicateRange = 0
                        }else{
                            rangeIndex += sameRange(index, listRange, rangeIndex, range, nDuplicateRange)
                        }
                    } else {
                        listRange[index - rangeIndex].rangeNumber = getRange(result.range.name)
                        nDuplicateRange = 0
                    }


                    if (result.oddEven.name == state.resultList!![index - 1].oddEven.name) {
                        val isOddEven = getOddEven(result.oddEven.name)
                        nDuplicateOddEven += 1
                        if(nDuplicateOddEven==6){
                            nDuplicateOddEven = 0
                            listOddEven[index - oddEvenIndex].oddEvenNumber = getOddEven(result.oddEven.name)
                        }else{
                            oddEvenIndex += sameOddEven(index, listOddEven, oddEvenIndex, isOddEven, nDuplicateOddEven)
                        }
                    } else {
                        listOddEven[index - oddEvenIndex].oddEvenNumber = getOddEven(result.oddEven.name)
                        nDuplicateOddEven = 0
                    }


                    if (result.blueRed.name == state.resultList!![index - 1].blueRed.name) {
                        val isBlueRed = getBlueRed(result.blueRed.name)
                        nDuplicateBlueRed += 1
                        if(nDuplicateBlueRed==6){
                            listBlueRed[index - blueRedIndex].blueRedNumber = getBlueRed(result.blueRed.name)
                            nDuplicateBlueRed = 0
                        }else{
                            blueRedIndex += sameBlueRed(index, listBlueRed, blueRedIndex, isBlueRed, nDuplicateBlueRed)
                        }
                    } else {
                        listBlueRed[index - blueRedIndex].blueRedNumber = getBlueRed(result.blueRed.name)
                        nDuplicateBlueRed = 0
                    }
                }
            }
            adapterTable0.submitList(listYear as List<BaseListItem>?)
            adapterTable1.submitList(listBigSmall as List<BaseListItem>?)
            adapterTable2.submitList(listRange as List<BaseListItem>?)
            adapterTable3.submitList(listOddEven as List<BaseListItem>?)
            adapterTable4.submitList(listBlueRed as List<BaseListItem>?)
        }
    }

    private fun sameYear(columnIndex: Int, arrayList: ArrayList<Table0ListItem>, yearIndex: Int, isYear: Int, nDuplicateYear: Int): Int {
        var betweenIndex = 0
        if (arrayList[columnIndex + 19].yearNumber == 0) {//free space
            if (nDuplicateYear in 2..5) {
                for (i in 2..nDuplicateYear) arrayList[(columnIndex - yearIndex) + (i * 20) - 1].yearNumber = isYear
            } else {
                arrayList[(columnIndex - yearIndex + 19)].yearNumber = isYear
            }
            betweenIndex++
            return betweenIndex
        }
        return 0
    }

    private fun sameBigSmall(columnIndex: Int, arrayList: ArrayList<Table1ListItem>, bigSmallIndex: Int, isBigSmall: Int, nDuplicateBigSmall: Int): Int {
        var betweenIndex = 0
        if (arrayList[columnIndex + 19].color == 0) {//free space
            if (nDuplicateBigSmall in 2..5) {
                for (i in 2..nDuplicateBigSmall) arrayList[(columnIndex - bigSmallIndex) + (i * 20) - 1].color = isBigSmall
            } else {
                arrayList[(columnIndex - bigSmallIndex + 19)].color = isBigSmall
            }
            betweenIndex++
            return betweenIndex
        }
        return 0
    }

    private fun sameRange(columnIndex: Int, arrayList: ArrayList<Table2ListItem>, rangeIndex: Int, range: Int, nDuplicateRange: Int): Int {
        var betweenIndex = 0
        if (arrayList[columnIndex + 19].rangeNumber == 0) {//free space
            if (nDuplicateRange > 1) {
                for (i in 2..nDuplicateRange) arrayList[(columnIndex - rangeIndex) + (i * 20) - 1].rangeNumber = range
            } else {
                arrayList[(columnIndex - rangeIndex + 19)].rangeNumber = range
            }
            betweenIndex++
            return betweenIndex
        }
        return 0
    }

    private fun sameOddEven(columnIndex: Int, arrayList: ArrayList<Table3ListItem>, oddEvenIndex: Int, isOddEven: Int, nDuplicateOddEven: Int): Int {
        var betweenIndex = 0
        if (arrayList[columnIndex + 19].oddEvenNumber == 0) {//free space
            if (nDuplicateOddEven in 2..5) {
                for (i in 2..nDuplicateOddEven) arrayList[(columnIndex - oddEvenIndex) + (i * 20) - 1].oddEvenNumber = isOddEven
            } else {
                arrayList[(columnIndex - oddEvenIndex + 19)].oddEvenNumber = isOddEven
            }
            betweenIndex++
            return betweenIndex
        }
        return 0
    }

    private fun sameBlueRed(columnIndex: Int, arrayList: ArrayList<Table4ListItem>, blueRedIndex: Int, isBlueRed: Int, nDuplicateBlueRed: Int): Int {
        var betweenIndex = 0
        if (arrayList[columnIndex + 19].blueRedNumber == 0) {//free space
            if (nDuplicateBlueRed in 2..5) {
                for (i in 2..nDuplicateBlueRed) arrayList[(columnIndex - blueRedIndex) + (i * 20) - 1].blueRedNumber = isBlueRed
            } else {
                arrayList[(columnIndex - blueRedIndex + 19)].blueRedNumber = isBlueRed
            }
            betweenIndex++
            return betweenIndex
        }
        return 0
    }

    private fun getLargeSmall(type: String): Int {
        when (type.toLowerCase()) {
            "ស្តើង" -> {
                return 1//blue
            }
            "ក្រាស់" -> {
                return 2//red
            }
        }
        return 0
    }

    private fun getRange(type: String): Int {
        when (type) {
            "1-2-3" -> {
                return 1
            }
            "4-5-6" -> {
                return 4
            }
            "7-8-9" -> {
                return 7
            }
            "10-11-12" -> {
                return 10
            }
        }
        return 0
    }
    private fun getOddEven(type: String): Int {
        when (type.toLowerCase()) {
            "សេស" -> {
                return 1//blue
            }
            "គូ" -> {
                return 2//red
            }
        }
        return 0
    }
    private fun getBlueRed(type: String): Int {
        when (type.toLowerCase()) {
            "ខៀវ" -> {
                return 1//blue
            }
            "ក្រហម" -> {
                return 2//red
            }
        }
        return 0
    }

    @SuppressLint("SetTextI18n")
    fun getMessage(lotto: SocketClientTimeDataModel) {
        if (lotto.isCountDowning() && lotto.time == 128) {
            (requireActivity() as? ShareActivity)?.apply {
                shareViewModel.remoteResult()
            }
        }
    }
}
