import {AccountIndexes, AccountKeys, AddressKey} from "../../../models/wallet.entities";
import {BaseAccount} from "../interfaces/BaseAccountInterface";
import {
    AccountType, classifyTransaction,
    fetchTotalBalance,
    fetchTransactionsHistory,
    sumBalance,
    sumTokensBalance
} from "../../../utils/WalletUtils";
import {PrivateKey} from "libnexa-ts";
import {TransactionEntity} from "../../../models/transaction.entities";

export default class DAppAccount extends BaseAccount {

    private readonly _accountIndex: number;
    private readonly _accountKey: AddressKey;

    constructor(bip44Account: number, accountIndex: number, addressKey: AddressKey) {
        super(bip44Account)
        this._accountIndex = accountIndex;
        this._accountKey = addressKey
    }

    // this is used in AccountStore.ts to get the key to be used in the map for this account
    public getAccountStoreKey(): string {
        return String(this._bip44Account + '.' + this._accountIndex);
    }

    public getAccountType(): AccountType {
        return AccountType.DAPP_ACCOUNT;
    }

    public getNewAddress() {
        return this._accountKey.address;
    }

    public getNewChangeAddress(): string {
        return this._accountKey.address;
    }

    get accountIndexes(): AccountIndexes {
        return {
            rIndex: this._accountIndex,
            cIndex: 0
        };
    }

    get accountKeys(): AccountKeys {
        return {
            receiveKeys: [this._accountKey],
            changeKeys: [this._accountKey]
        };
    }

    async loadBalances(): Promise<void> {
        let balances = await fetchTotalBalance([this._accountKey]);
        let tokenBalances = [this._accountKey].map(k => k.tokensBalance);
        super.balance = sumBalance(balances)
        super.tokenBalances = sumTokensBalance(tokenBalances)
    }

    getKeyFromAddress(address: string): AddressKey {
        return this._accountKey;
    }

    async getTransactions(fromHeight?: number, address?: string): Promise<Map<string, TransactionEntity>> {
        let txPromises:TransactionEntity[] = []

        const transactions = await fetchTransactionsHistory([address ?? this._accountKey.address], fromHeight ?? 0)
        for (let tx of transactions.txs.values()) {
            let t = await classifyTransaction(tx, [address ?? this._accountKey.address])
            txPromises.push(t)
        }
        await Promise.all(txPromises)
        for (let txEntity of txPromises){
            this.transactions.set(txEntity.txId, txEntity)
        }
        return this.transactions
    }
}
