package net.pokeranalytics.android.ui.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import io.realm.RealmResults
import io.realm.Sort
import io.realm.kotlin.where
import kotlinx.android.synthetic.main.fragment_history.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.activity.SessionActivity
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment
import net.pokeranalytics.android.ui.view.HistorySessionDiffCallback
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.util.extensions.getMonthAndYear
import net.pokeranalytics.android.util.extensions.isSameDay
import net.pokeranalytics.android.util.extensions.isSameMonth
import net.pokeranalytics.android.util.extensions.longDate
import java.util.*

class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate {

	companion object {
		fun newInstance(): HistoryFragment {
			val fragment = HistoryFragment()
			val bundle = Bundle()
			fragment.arguments = bundle
			return fragment
		}
	}

	private lateinit var historyAdapter: RowRepresentableAdapter
	private lateinit var realmSessions: RealmResults<Session>
	private val sessions: ArrayList<Session> = ArrayList()
	private val rows: ArrayList<RowRepresentable> = ArrayList()
	private var newSessionCreated: Boolean = false

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		return inflater.inflate(R.layout.fragment_history, container, false)
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		super.onViewCreated(view, savedInstanceState)
		initUI()
		initData()
	}

	override fun onDestroyView() {
		super.onDestroyView()
		realmSessions.removeAllChangeListeners()
	}

	override fun onResume() {
		super.onResume()

		//rows.clear()
		//endedSessions.addAll(getRealm().copyFromRealm(realmSessions))
		createSessionsHeaders()
	}

	/**
	 * Init UI
	 */
	private fun initUI() {

		newCashGame.setOnClickListener {
			SessionActivity.newInstance(requireContext(), false)
			newSessionCreated = true
		}

		newTournament.setOnClickListener {
			SessionActivity.newInstance(requireContext(), true)
			newSessionCreated = true
		}

	}

	/**
	 * Init data
	 */
	private fun initData() {
		realmSessions = getRealm().where<Session>().findAll().sort("creationDate", Sort.DESCENDING)

		val viewManager = SmoothScrollLinearLayoutManager(requireContext())
		historyAdapter = RowRepresentableAdapter(this, this)

		recyclerView.apply {
			setHasFixedSize(true)
			layoutManager = viewManager
			adapter = historyAdapter
		}
	}

	/**
	 * Create the endedSessions headers
	 */
	private fun createSessionsHeaders() {

		val oldRows = ArrayList<RowRepresentable>()
		oldRows.addAll(rows)

		rows.clear()
		sessions.clear()
		sessions.addAll(getRealm().copyFromRealm(realmSessions))
		noSessionFound.isVisible = sessions.isEmpty()

		GlobalScope.launch {

			val groupedByDay = false
			val calendar = Calendar.getInstance()
			val currentCalendar = Calendar.getInstance()

			for ((index, session) in sessions.withIndex()) {
				currentCalendar.time = session.creationDate
				if (groupedByDay) {
					if (!calendar.isSameDay(currentCalendar) || index == 0) {
						calendar.time = currentCalendar.time
						val header = CustomizableRowRepresentable(
							customViewType = RowViewType.HEADER_TITLE,
							title = session.creationDate.longDate()
						)
						rows.add(header)
					}
				} else {
					if (!calendar.isSameMonth(currentCalendar) || index == 0) {
						calendar.time = currentCalendar.time
						val header = CustomizableRowRepresentable(
							customViewType = RowViewType.HEADER_TITLE,
							title = session.creationDate.getMonthAndYear()
						)
						rows.add(header)
					}
				}
				rows.add(session)
			}

			val diffResult = DiffUtil.calculateDiff(HistorySessionDiffCallback(rows, oldRows))
			historyAdapter.updateRows(diffResult)

			if (newSessionCreated) {
				newSessionCreated = false
				recyclerView.smoothScrollToPosition(0)
			}
		}
	}


	override fun rowRepresentableForPosition(position: Int): RowRepresentable? {
		return this.rows[position]
	}

	override fun numberOfRows(): Int {
		return this.rows.size
	}

	override fun viewTypeForPosition(position: Int): Int {
		return rows[position].viewType
	}

	override fun indexForRow(row: RowRepresentable): Int {
		return this.rows.indexOf(row)
	}

	override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
		SessionActivity.newInstance(requireContext(), sessionId = (row as Manageable).id)
	}
}