import { AESCipherSIVNonce96 } from '../../base/cipher/aes';
import { AbstractSelfAccountKeyring } from '../../keyring/account_base';
import { PeerAccountKeyring } from '../../keyring/account_peer';
import { AbstractCryptoConfig } from '../base';
import { RegisterChallengeConfigDumpArgs, RegisterChallengeConfigLoadArgs } from './args';
import { makeInfoByteArray } from '../../utility';
import { HKDFKeyGeneratorV1 } from '../../base/key/kdf';
import { Curve25519SharedSecretGenerator } from '../../base/key/dh';

export class RegisterChallengeConfigV1 extends AbstractCryptoConfig<
  RegisterChallengeConfigLoadArgs,
  RegisterChallengeConfigDumpArgs
> {
  constructor(never_dump: boolean = false) {
    super(1, never_dump);
  }

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

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

  public derive_key(self_kr: AbstractSelfAccountKeyring, peer_kr: PeerAccountKeyring) {
    return HKDFKeyGeneratorV1.new_key(
      64,
      Curve25519SharedSecretGenerator.new_key(
        self_kr.get_secret_key(AbstractSelfAccountKeyring.CURVE25519),
        peer_kr.get_public_key(AbstractSelfAccountKeyring.CURVE25519)
      ),
      new Uint8Array([]),
      makeInfoByteArray(['register-challenge'])
    );
  }
}
