import { AbstractCryptoConfig } from "../base";
import { AccountConfigLoadArgs, AccountConfigDumpArgs } from '../account/args';
import { AbstractSelfAccountKeyring } from "../../keyring/account_base";
import { AESCipherSIVNonce96 } from "../../base/cipher/aes";
import { AccountMasterDeriveKeyV1 } from "../common";
import { makeInfoByteArray } from "../../utility";

/**
 * Account-private data encryption: AES-SIV
        KEY: 32B master key -> 64B HKDF by context
        NONCE: 12B random

    Key rotation is not necessary, no account will exhaust the safe usage limits of a key. If there would be
    some special account data that could potentially lead to exhaustion, then that shall be encrypted with a
    different context where time windowing is present.
    NOTE: Small LRU cache on derive_key(). This is used many times, but there's not many different values.
 */
export class AccountConfigV1 extends AbstractCryptoConfig<AccountConfigLoadArgs, AccountConfigDumpArgs>{

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

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

    public dump(args: AccountConfigDumpArgs): Promise<Uint8Array>{
        return this.derive_key(args.self_kr).then((derive_key)=>{
            return AESCipherSIVNonce96.encrypt(args.plain, derive_key, undefined, undefined, this.version)
        })        
    }

    public derive_key(self_kr: AbstractSelfAccountKeyring): Promise<Uint8Array>{
        
        return AccountMasterDeriveKeyV1.derive_key(self_kr,  makeInfoByteArray(["account-", this.version]))
    }
}