const window = self;

import { WorkerRunMessage, WorkerRunResponse, WorkerOperation } from './worker-common';

import {
  AESCipherCBCWorker,
  AESCipherGCMWorker,
  AESCipherSIVDeterministicWorker,
  AESCipherSIVNonce96Worker,
} from '../crypto/worker_base/cipher/aes';
import { Ed25519DSWorker } from '../crypto/worker_base/ds/ec';
/*
import { Curve25519SharedSecretGeneratorWorker } from "../crypto/worker_base/key/dh";
import { Curve25519KeyGeneratorWorker, Ed25519KeyGeneratorWorker } from "../crypto/worker_base/key/ec";
import { HKDFKeyGeneratorV1Worker, HKDFKeyGeneratorV2Worker } from "../crypto/worker_base/key/kdf";
import { RandomKeyGenerator128Worker, RandomKeyGenerator256Worker, RandomKeyGenerator512Worker } from "../crypto/worker_base/key/random";
*/

let op = {
  [WorkerOperation.LOG]: function (param: any[]) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('variables inorder', ...param);
      }, 2000);
    });
  },

  [WorkerOperation.AESCipherSIVNonce96Encrypt]: function (
    param: [
      plain: Uint8Array,
      key: Uint8Array,
      nonce: Uint8Array,
      assoc: Uint8Array,
      prefix: Uint8Array
    ]
  ) {
    return AESCipherSIVNonce96Worker.encrypt(...param);
  },
  [WorkerOperation.AESCipherSIVNonce96Decrypt]: function (
    param: [cipher: Uint8Array, key: Uint8Array, assoc: Uint8Array]
  ) {
    return AESCipherSIVNonce96Worker.decrypt(...param);
  },

  [WorkerOperation.AESCipherSIVDeterministicEncrypt]: function (
    param: [plain: Uint8Array, key: Uint8Array, assoc: Uint8Array, prefix: Uint8Array]
  ) {
    return AESCipherSIVDeterministicWorker.encrypt(...param);
  },
  [WorkerOperation.AESCipherSIVDeterministicDecrypt]: function (
    param: [cipher: Uint8Array, key: Uint8Array, assoc: Uint8Array]
  ) {
    return AESCipherSIVDeterministicWorker.decrypt(...param);
  },

  [WorkerOperation.AESCipherGCMEncrypt]: function (
    param: [
      plain: Uint8Array,
      key: Uint8Array,
      nonce: Uint8Array,
      assoc: Uint8Array,
      prefix: Uint8Array
    ]
  ) {
    return AESCipherGCMWorker.encrypt(...param);
  },
  [WorkerOperation.AESCipherGCMDecrypt]: function (
    param: [cipher: Uint8Array, key: Uint8Array, assoc: Uint8Array]
  ) {
    return AESCipherGCMWorker.decrypt(...param);
  },

  [WorkerOperation.AESCipherCBCEncrypt]: function (
    param: [plain: Uint8Array, key: Uint8Array, iv: Uint8Array, prefix: Uint8Array]
  ) {
    return AESCipherCBCWorker.encrypt(...param);
  },
  [WorkerOperation.AESCipherCBCDecrypt]: function (param: [cipher: Uint8Array, key: Uint8Array]) {
    return AESCipherCBCWorker.decrypt(...param);
  },

  [WorkerOperation.Ed25519DSSign]: function (param: [plain: Uint8Array, secret_key: Uint8Array]) {
    return Ed25519DSWorker.sign(...param);
  },
  [WorkerOperation.Ed25519DSVerify]: function (
    param: [signature: Uint8Array, public_key: Uint8Array, plain: Uint8Array]
  ) {
    return Ed25519DSWorker.verify(...param);
  },

  /*
  [WorkerOperation.Curve25519SharedSecretGeneratorNewKey]: function (
    param: [secret_key: Uint8Array, other_public_key: Uint8Array]
  ) {
    return new Promise((resolve, reject)=>{
      try{
        resolve(Curve25519SharedSecretGeneratorWorker.new_key(...param));
      }catch(e){
        reject(e);
      }
    })
  },

  [WorkerOperation.Ed25519KeyGeneratorNewKey]: function (
    param: []
  ) {
    return new Promise((resolve, reject)=>{
      try{
        resolve(Ed25519KeyGeneratorWorker.new_key(...param));
      }catch(e){
        reject(e);
      }
    })
  },

  [WorkerOperation.Curve25519KeyGeneratorNewKey]: function (
    param: []
  ) {
    return new Promise((resolve, reject)=>{
      try{
        resolve(Curve25519KeyGeneratorWorker.new_key(...param));
      }catch(e){
        reject(e);
      }
    })
  },

  [WorkerOperation.HKDFKeyGeneratorV1NewKey]: function (
    param: [length: number, key: Uint8Array, salt?: Uint8Array, info?: Uint8Array]
  ) {
    return HKDFKeyGeneratorV1Worker.new_key(...param);
  },

  [WorkerOperation.HKDFKeyGeneratorV2NewKey]: function (
    param: [length: number, key: Uint8Array, salt?: Uint8Array, info?: Uint8Array]
  ) {
    return HKDFKeyGeneratorV2Worker.new_key(...param);
  },

  [WorkerOperation.RandomKeyGenerator128NewKey]: function (
    param: []
  ) {
    return new Promise((resolve, reject)=>{
      try{
        resolve(RandomKeyGenerator128Worker.new_key(...param));
      }catch(e){
        reject(e);
      }
    })
  },

  [WorkerOperation.RandomKeyGenerator256NewKey]: function (
    param: []
  ) {
    return new Promise((resolve, reject)=>{
      try{
        resolve(RandomKeyGenerator256Worker.new_key(...param));
      }catch(e){
        reject(e);
      }
    })
  },

  [WorkerOperation.RandomKeyGenerator512NewKey]: function (
    param: []
  ) {
    return new Promise((resolve, reject)=>{
      try{
        resolve(RandomKeyGenerator512Worker.new_key(...param));
      }catch(e){
        reject(e);
      }
    })
  },
  */
};

addEventListener('message', function (event: MessageEvent<WorkerRunMessage>) {
  var result: WorkerRunResponse = {
    operationId: event.data.operationId,
    response: null,
    error: false,
  };
  if (event.data.operation in op) {
    op[event.data.operation](<any>event.data.variables)
      .then((resp) => {
        result.response = resp;
      })
      .catch((err) => {
        console.error('worker err', err);
        result.response = '' + err;
        result.error = true;
      })
      .finally(() => {
        this.postMessage(result, null);
      });
  } else {
    console.error('can not find operation', event.data.operation);
    result.error = true;
    result.response = 'can not find operation';
    this.postMessage(result, null);
  }
});
