import { AbstractSelfAccountKeyring } from "../../../keyring/account_base";
import { AbstractCryptoConfig } from "../../base";
import { AccountRoomKeyConfigDumpArgs, AccountRoomKeyConfigLoadArgs } from "./args";
import { AESCipherSIVDeterministic } from "../../../base/cipher/aes";
import { AbstractRoomKeyring } from "../../../keyring/room_base";
import { AccountMasterDeriveKeyV1 } from "../../common";
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 AccountRoomKeyConfigV1 extends AbstractCryptoConfig<AccountRoomKeyConfigLoadArgs, AccountRoomKeyConfigDumpArgs>{

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

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

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

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

}