package net.pokeranalytics.android.model.realm

import android.content.Context
import io.realm.Realm
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus
import net.pokeranalytics.android.model.interfaces.NameManageable
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.view.Localizable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.ui.view.rowrepresentable.TransactionTypeRow
import java.util.*
import kotlin.collections.ArrayList


open class TransactionType : RealmObject(), NameManageable, StaticRowRepresentableDataSource, RowRepresentable {

	enum class Value(val additive: Boolean) : Localizable {
		WITHDRAWAL(false),
		DEPOSIT(true),
		BONUS(true);

		override val resId: Int?
			get() {
				return when (this) {
					WITHDRAWAL -> R.string.withdrawal
					DEPOSIT -> R.string.deposit
					BONUS -> R.string.bonus
				}
			}
	}

	companion object {
		val rowRepresentation: List<RowRepresentable> by lazy {
			val rows = ArrayList<RowRepresentable>()
			rows.add(SimpleRow.NAME)
			rows.addAll(TransactionTypeRow.values())
			rows
		}

		fun getByValue(value: Value, realm: Realm): TransactionType {
			val type = realm.where(TransactionType::class.java).equalTo("kind", value.ordinal).findFirst()
			type?.let {
				return it
			}
			throw IllegalStateException("Transaction type ${value.name} should exist in database!")
		}

	}

	@PrimaryKey
	override var id = UUID.randomUUID().toString()

	/**
	 * The name of the transaction type
 	 */
	override var name: String = ""

	/**
	 * Whether or not the amount is added, or subtracted to the bankroll total
	 * The value can only be changed if no transaction is linked to this type
	 */
	var additive: Boolean = false

	// Whether or not the type can be deleted by the user
	var lock: Boolean = false

	// The predefined kind, if necessary, like: Withdrawal, deposit, or tips
	var kind: Int? = null

	override fun getDisplayName(context: Context): String {
		return this.name
	}

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

	override fun stringForRow(row: RowRepresentable): String {
		return when (row) {
			SimpleRow.NAME -> this.name
			else -> return super.stringForRow(row)
		}
	}

	override fun boolForRow(row: RowRepresentable): Boolean {
		return when (row) {
			TransactionTypeRow.TRANSACTION_ADDITIVE -> this.additive
			else -> super.boolForRow(row)
		}
	}

	override fun editDescriptors(row: RowRepresentable): ArrayList<RowRepresentableEditDescriptor>? {
		return row.editingDescriptors(mapOf("defaultValue" to this.name))
	}

	override fun updateValue(value: Any?, row: RowRepresentable) {
		when (row) {
			SimpleRow.NAME -> this.name = value as String? ?: ""
			TransactionTypeRow.TRANSACTION_ADDITIVE -> this.additive = value as Boolean? ?: false
		}
	}

	override fun isValidForDelete(realm: Realm): Boolean {
		return realm.where(Transaction::class.java)
			.equalTo("type.id", this.id).findAll().isEmpty()
	}

	override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int {
		return R.string.transaction_relationship_error
	}

}

