import { Enum } from "@polkadot/types";
import { map } from "rxjs/operators";
import { u64FromCurrency } from "@equilab/api/genshiro/util";
import BN from "bn.js";
const transformBalanceStorage = (query, arg, transform) => {
    // HACK as we cannot properly transform queryMulti result, define AccountData getters on standard Enum
    if (!Enum.hacked) {
        Enum.hacked = true;
        for (const prop of ["free", "reserved", "miscFrozen", "feeFrozen"]) {
            Object.defineProperty(Enum.prototype, prop, {
                get() {
                    const accData = transform(this);
                    return accData[prop];
                },
                set() {
                    // Do nothing
                },
            });
        }
    }
    // Transform result if we call the func normally
    const boundFunction = (account) => 
    //@ts-ignore
    query(account, { 0: u64FromCurrency(arg) }).pipe(map(transform));
    // Bind currency as second key for doubleMap for queryMulti
    const boundCreator = (account) => query.creator([account, { 0: u64FromCurrency(arg) }]);
    Object.assign(boundCreator, { ...query.creator });
    return Object.assign(boundFunction, {
        ...query,
        creator: boundCreator,
    });
};
const signedBalancePredicate = (raw) => ["asNegative", "asPositive", "isNegative", "isPositive"].some((key) => Object.prototype.hasOwnProperty.call(raw, key));
export const createCustomAccount = (cur) => (instanceId, api) => {
    const registry = api.registry;
    const transform = (balance) => {
        let free = registry.createType("Balance");
        const reserved = registry.createType("Balance");
        const miscFrozen = registry.createType("Balance");
        const feeFrozen = registry.createType("Balance");
        if (signedBalancePredicate(balance)) {
            if (balance.isPositive) {
                free = registry.createType("Balance", balance.asPositive);
            }
            else if (balance.isNegative) {
                free = registry.createType("Balance", balance.asNegative.mul(new BN(-1)));
            }
        }
        return registry.createType("AccountData", {
            feeFrozen,
            free,
            miscFrozen,
            reserved,
        });
    };
    return transformBalanceStorage(api.query.eqBalances.account, cur, transform);
};
