package cash.z.ecc.android.sdk.type

import cash.z.ecc.android.sdk.model.Zatoshi

/**
 * Data structure to hold the total and available balance of the wallet. This is what is
 * received on the balance channel.
 *
 * @param total the total balance, ignoring funds that cannot be used.
 * @param available the amount of funds that are available for use. Typical reasons that funds
 * may be unavailable include fairly new transactions that do not have enough confirmations or
 * notes that are tied up because we are awaiting change from a transaction. When a note has
 * been spent, its change cannot be used until there are enough confirmations.
 */
data class WalletBalance(
    val total: Zatoshi,
    val available: Zatoshi
) {
    init {
        require(total.value >= available.value) { "Wallet total balance must be >= available balance" }
    }

    val pending = total - available

    operator fun plus(other: WalletBalance): WalletBalance =
        WalletBalance(
            total + other.total,
            available + other.available
        )
}

/**
 * Model object for holding a wallet birthday.
 *
 * @param height the height at the time the wallet was born.
 * @param hash the hash of the block at the height.
 * @param time the block time at the height. Represented as seconds since the Unix epoch.
 * @param tree the sapling tree corresponding to the height.
 */
data class WalletBirthday(
    val height: Int = -1,
    val hash: String = "",
    val time: Long = -1,
    // Note: this field does NOT match the name of the JSON, so will break with field-based JSON parsing
    val tree: String = ""
) {
    companion object
}

/**
 * A grouping of keys that correspond to a single wallet account but do not have spend authority.
 *
 * @param extfvk the extended full viewing key which provides the ability to see inbound and
 * outbound shielded transactions. It can also be used to derive a z-addr.
 * @param extpub the extended public key which provides the ability to see transparent
 * transactions. It can also be used to derive a t-addr.
 */
data class UnifiedViewingKey(
    val extfvk: String = "",
    val extpub: String = ""
)

data class UnifiedAddressAccount(
    val accountId: Int = -1,
    override val rawShieldedAddress: String = "",
    override val rawTransparentAddress: String = ""
) : UnifiedAddress

interface UnifiedAddress {
    val rawShieldedAddress: String
    val rawTransparentAddress: String
}

enum class ZcashNetwork(
    val id: Int,
    val networkName: String,
    val saplingActivationHeight: Int,
    val defaultHost: String,
    val defaultPort: Int
) {
    Testnet(0, "testnet", 995_000, "lite.hushpool.is", 9067),
    Mainnet(1, "mainnet", 995_000, "lite.hushpool.is", 9067);

    companion object {
        fun from(id: Int) = values().first { it.id == id }
    }
}
