package net.pokeranalytics.android.ui.fragment.data

import android.os.Bundle
import android.view.View
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.model.realm.TransactionType
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.helpers.DateTimePickerManager
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionRow
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.round
import net.pokeranalytics.android.util.extensions.shortDate
import net.pokeranalytics.android.util.extensions.sorted
import java.util.*

/**
 * Custom EditableDataFragment to manage the Transaction data
 */
class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDataSource {

	// Return the item as a Transaction object
	private val transaction: Transaction
		get() {
			return this.item as Transaction
		}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		super.onViewCreated(view, savedInstanceState)
		shouldOpenKeyboard = false
	}

	override fun getDataSource(): RowRepresentableDataSource {
		return this
	}

	override fun adapterRows(): List<RowRepresentable>? {
		return transaction.adapterRows()
	}

	override fun stringForRow(row: RowRepresentable): String {
		return when (row) {
			TransactionRow.BANKROLL -> this.transaction.bankroll?.name ?: NULL_TEXT
			TransactionRow.TYPE -> this.transaction.type?.name ?: NULL_TEXT
			TransactionRow.AMOUNT -> if (this.transaction.amount != 0.0) this.transaction.amount.round() else NULL_TEXT
			TransactionRow.COMMENT -> if (this.transaction.comment.isNotEmpty()) this.transaction.comment else NULL_TEXT
			TransactionRow.DATE -> this.transaction.date.shortDate()
			else -> super.stringForRow(row)
		}
	}

	override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
		return when (row) {
			TransactionRow.BANKROLL -> row.editingDescriptors(
				mapOf(
					"defaultValue" to this.transaction.bankroll,
					"data" to getRealm().sorted<Bankroll>()
				)
			)
			TransactionRow.TYPE -> row.editingDescriptors(
				mapOf(
					"defaultValue" to this.transaction.type,
					"data" to getRealm().sorted<TransactionType>()
				)
			)
			TransactionRow.AMOUNT -> row.editingDescriptors(mapOf("defaultValue" to (if (this.transaction.amount != 0.0) this.transaction.amount.round() else "")))
			TransactionRow.COMMENT -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.comment))
			else -> super.editDescriptors(row)
		}
	}

	override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
		when (row) {
			TransactionRow.DATE -> DateTimePickerManager.create(
				requireContext(),
				row,
				this,
				this.transaction.date,
				onlyDate = true,
				isClearable = false
			)
			else -> super.onRowSelected(position, row, fromAction)
		}
	}

	override fun onRowValueChanged(value: Any?, row: RowRepresentable) {
		super.onRowValueChanged(value, row)
		rowRepresentableAdapter.refreshRow(row)

		if (primaryKey == null) { // automatically change the row for new data
			GlobalScope.launch(Dispatchers.Main) {
				delay(200)
				when (row) {
					TransactionRow.BANKROLL -> onRowSelected(0, TransactionRow.TYPE)
					TransactionRow.TYPE -> onRowSelected(0, TransactionRow.AMOUNT)
//				TransactionRow.AMOUNT -> onRowSelected(0, TransactionRow.DATE)
//				TransactionRow.DATE -> onRowSelected(0, TransactionRow.COMMENT)
				}
			}
		}
	}

	override fun willSaveData() {
		super.willSaveData()
		val additive = this.transaction.type?.additive ?: true
		if (!additive) {
			this.transaction.amount *= -1
		}
	}

}