package net.pokeranalytics.android.model.realm

import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.kotlin.where
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.interfaces.Manageable
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.rowrepresentable.BankrollRow
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow
import net.pokeranalytics.android.util.NULL_TEXT
import java.util.*
import kotlin.collections.ArrayList

open class Bankroll(name: String = "") : RealmObject(), Manageable, StaticRowRepresentableDataSource, RowRepresentable {

    companion object {
        fun newInstance() : Bankroll {
            val bankroll = Bankroll()
            return bankroll
        }

        val rowRepresentation : List<RowRepresentable> by lazy {
            val rows = ArrayList<RowRepresentable>()
            rows.add(SimpleRow.NAME)
            rows.add(BankrollRow.LIVE)
            rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.currency))
	        rows.add(BankrollRow.CURRENCY)
            rows
        }
    }

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

    // the name of the bankroll
    var name: String = name

    // Indicates whether the bankroll is live or online
    var live: Boolean = true

    // The list of transactions of the bankroll
    var transactions: RealmList<Transaction> = RealmList()

    // The currency of the bankroll
    var currency: Currency? = null

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

    // Row Representable Datasource
    override fun adapterRows(): List<RowRepresentable>? {
        return Bankroll.rowRepresentation
    }

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

    override fun boolForRow(row: RowRepresentable): Boolean {
        when (row) {
            BankrollRow.LIVE -> return !this.live
            else -> return 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? ?: ""
            BankrollRow.LIVE -> {
                this.live = if (value is Boolean) !value else false
            }
	        BankrollRow.CURRENCY -> {
		        this.currency?.code = value as String?
	        }
	        BankrollRow.RATE -> {
		        this.currency?.rate = (value as String? ?: "0").toDouble()
	        }
        }
    }

	override fun isValidForSave(): Boolean {
		return this.name.isNotEmpty()
	}

	override fun getFailedSaveMessage(): Int {
		return R.string.empty_name_for_br_error
	}

	override fun isValidForDelete(): Boolean {
		return this.realm.where<Session>().equalTo("bankroll.id", id).findAll().isEmpty()
	}

	override fun getFailedDeleteMessage(): Int {
		return R.string.bankroll_relationship_error
	}

}