// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

goog.module('tink.KeysetHandle');

const Aead = goog.require('tink.Aead');
const InvalidArgumentsException = goog.require('tink.exception.InvalidArgumentsException');
const KeyManager = goog.require('tink.KeyManager');
const KeysetReader = goog.require('tink.KeysetReader');
const KeysetWriter = goog.require('tink.KeysetWriter');
const PbKeyMaterialType = goog.require('proto.google.crypto.tink.KeyData.KeyMaterialType');
const PbKeyStatusType = goog.require('proto.google.crypto.tink.KeyStatusType');
const PbKeyTemplate = goog.require('proto.google.crypto.tink.KeyTemplate');
const PbKeyset = goog.require('proto.google.crypto.tink.Keyset');
const PrimitiveSet = goog.require('tink.PrimitiveSet');
const Random = goog.require('tink.subtle.Random');
const Registry = goog.require('tink.Registry');
const SecurityException = goog.require('tink.exception.SecurityException');
const Util = goog.require('tink.Util');

/**
 * Keyset handle provide abstracted access to Keysets, to limit the exposure of
 * actual protocol buffers that hold sensitive key material.
 *
 * @final
 */
class KeysetHandle {
  /**
   * @param {!PbKeyset} keyset
   */
  constructor(keyset) {
    Util.validateKeyset(keyset);

    /** @const @private {!PbKeyset} */
    this.keyset_ = keyset;
  }

  /**
   * Creates a KeysetHandle from an encrypted keyset obtained via reader, using
   * masterKeyAead to decrypt the keyset.
   *
   * @param {!KeysetReader} reader
   * @param {!Aead} masterKeyAead
   *
   * @return {!Promise<!KeysetHandle>}
   */
  static async read(reader, masterKeyAead) {
    // TODO implement
    throw new SecurityException('KeysetHandle -- read: Not implemented yet.');
  }

  /**
   * Creates a KeysetHandle from a keyset, obtained via reader, which
   * must contain no secret key material.
   *
   * This can be used to load public keysets or envelope encryption keysets.
   * Users that need to load cleartext keysets can use CleartextKeysetHandle.
   *
   * @param {!KeysetReader} reader
   * @return {!KeysetHandle}
   */
  static readNoSecret(reader) {
    if (reader === null) {
      throw new SecurityException('Reader has to be non-null.');
    }
    const keyset = reader.read();
    const keyList = keyset.getKeyList();
    for (let key of keyList) {
      switch (key.getKeyData().getKeyMaterialType()) {
        case PbKeyMaterialType.ASYMMETRIC_PUBLIC:  // fall through
        case PbKeyMaterialType.REMOTE:
          continue;
      }
      throw new SecurityException('Keyset contains secret key material.');
    }
    return new KeysetHandle(keyset);
  }

  /**
   * Returns a new KeysetHandle that contains a single new key generated
   * according to keyTemplate.
   *
   * @param {!PbKeyTemplate} keyTemplate
   *
   * @return {!Promise<!KeysetHandle>}
   */
  static async generateNew(keyTemplate) {
    // TODO(thaidn): move this to a key manager.
    const keyset = await KeysetHandle.generateNewKeyset_(keyTemplate);
    return new KeysetHandle(keyset);
  }

  /**
   * Generates a new Keyset that contains a single new key generated
   * according to keyTemplate.
   *
   * @param {!PbKeyTemplate} keyTemplate
   * @private
   * @return {!Promise<!PbKeyset>}
   */
  static async generateNewKeyset_(keyTemplate) {
    const key = new PbKeyset.Key()
                    .setStatus(PbKeyStatusType.ENABLED)
                    .setOutputPrefixType(keyTemplate.getOutputPrefixType());
    const keyId = KeysetHandle.generateNewKeyId_();
    key.setKeyId(keyId);
    const keyData = await Registry.newKeyData(keyTemplate);
    key.setKeyData(keyData);
    const keyset = new PbKeyset();
    keyset.addKey(key);
    keyset.setPrimaryKeyId(keyId);
    return keyset;
  }

  /**
   * Generates a new random key ID.
   *
   * @private
   * @return {number} The key ID.
   */
  static generateNewKeyId_() {
    const bytes = Random.randBytes(4);
    let value = 0;
    for (let i = 0; i < bytes.length; i++) {
      value += (bytes[i] & 0xFF) << (i * 8);
    }
    // Make sure the key ID is a positive integer smaller than 2^32.
    return Math.abs(value) % 2 ** 32;
  };


  /**
   * Returns a primitive that uses key material from this keyset handle. If
   * opt_customKeyManager is defined then the provided key manager is used to
   * instantiate primitives. Otherwise key manager from Registry is used.
   *
   * @template P
   *
   * @param {!Object} primitiveType
   * @param {?KeyManager.KeyManager<P>=} opt_customKeyManager
   *
   * @return {!Promise<!P>}
   */
  async getPrimitive(primitiveType, opt_customKeyManager) {
    if (!primitiveType) {
      throw new InvalidArgumentsException('primitive type must be non-null');
    }
    const primitiveSet =
        await this.getPrimitiveSet_(primitiveType, opt_customKeyManager);
    return Registry.wrap(primitiveSet);
  }

  /**
   * Creates a set of primitives corresponding to the keys with status Enabled
   * in the given keysetHandle, assuming all the correspoding key managers are
   * present (keys with status different from Enabled are skipped). If provided
   * uses customKeyManager instead of registered key managers for keys supported
   * by the customKeyManager.
   *
   * @template P
   * @private
   *
   * @param {!Object} primitiveType
   * @param {?KeyManager.KeyManager<P>=} opt_customKeyManager
   *
   * @return {!Promise.<!PrimitiveSet.PrimitiveSet<P>>}
   */
  async getPrimitiveSet_(primitiveType, opt_customKeyManager) {
    const primitiveSet = new PrimitiveSet.PrimitiveSet(primitiveType);
    const keys = this.keyset_.getKeyList();
    const keysLength = keys.length;
    for (let i = 0; i < keysLength; i++) {
      const key = keys[i];
      if (key.getStatus() === PbKeyStatusType.ENABLED) {
        const keyData = key.getKeyData();
        if (!keyData) {
          throw new SecurityException('Key data has to be non null.');
        }
        let primitive;
        if (opt_customKeyManager &&
            opt_customKeyManager.getKeyType() === keyData.getTypeUrl()) {
          primitive =
              await opt_customKeyManager.getPrimitive(primitiveType, keyData);
        } else {
          primitive = await Registry.getPrimitive(primitiveType, keyData);
        }
        const entry = primitiveSet.addPrimitive(primitive, key);
        if (key.getKeyId() === this.keyset_.getPrimaryKeyId()) {
          primitiveSet.setPrimary(entry);
        }
      }
    }
    return primitiveSet;
  }


  /**
   * Encrypts the underlying keyset with the provided masterKeyAead wnd writes
   * the resulting encryptedKeyset to the given writer which must be non-null.
   *
   * @param {!KeysetWriter} writer
   * @param {!Aead} masterKeyAead
   *
   */
  async write(writer, masterKeyAead) {
    // TODO implement
    throw new SecurityException('KeysetHandle -- write: Not implemented yet.');
  }

  /**
   * Returns the keyset held by this KeysetHandle.
   *
   * @package
   * @return {!PbKeyset}
   */
  getKeyset() {
    return this.keyset_;
  }
}

exports = KeysetHandle;
