import { AESCipherSIVDeterministic } from "../../../base/cipher/aes";
import { AbstractSelfAccountKeyring } from "../../../keyring/account_base";
import { AbstractCryptoConfig } from "../../base";
import { AccountMasterDeriveKeyV1 } from "../../common";
import { AccountRootKeyConfigDumpArgs, AccountRootKeyConfigLoadArgs } from "./args";
import { makeInfoByteArray } from "../../../utility";

/**
 * Account key encryption: AES-SIV
        KEY: 32B from account keyring -> 64B HKDF by context
        NONCE: none

    Used to encrypt various keys of the account. (for public key crypto)
    NOTE: No LRU cache on derive_key(), root keys are only loaded once and they are unique so there's no benefit.
 */
export class AccountRootKeyConfigV1 extends AbstractCryptoConfig<AccountRootKeyConfigLoadArgs, AccountRootKeyConfigDumpArgs>{

    constructor(never_dump: boolean = false){
        super(1, never_dump);
    }

    public load(args: AccountRootKeyConfigLoadArgs): Promise<Uint8Array>{
        return this.derive_key(args.self_kr, args.key_version).then((derive_key)=>{
            return AESCipherSIVDeterministic.decrypt(
                args.cipher.slice(this.version.byteLength), derive_key
            );
        })
        
    }

    public dump(args: AccountRootKeyConfigDumpArgs): Promise<Uint8Array>{
        return this.derive_key(args.self_kr, args.key_version).then((derive_key)=>{
            return AESCipherSIVDeterministic.encrypt(
                args.self_kr.get_secret_key(args.key_version),
                derive_key,
                undefined,
                this.version
            )
        })
        
    }

    public derive_key(self_kr: AbstractSelfAccountKeyring, key_version: string){
        
        return AccountMasterDeriveKeyV1.derive_key(
            self_kr, makeInfoByteArray(["account-root-key-", this.version, "-", key_version]), false
        )
    }
}