// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * @fileoverview Type decoder handles decoding types from a VOM stream by
 * looking up by id.
 *
 * Definitions:
 * Type / Defined Type - The standard VOM JavaScript type object representation.
 * Partial Type - The type representation off the wire, identical to defined
 * types but child types are described by type ids rather than actual complete
 * type objects.
 *
 * Overview:
 * Type decoders hold a cache of decoded types. Types are read off the wire in
 * defineType() and then lazily converted from partial to defined types when
 * they are needed in lookupType().
 * @private
 */

module.exports = TypeDecoder;

/**
 * Create a TypeDecoder.
 * This holds the set of cached types and assists in decoding.
 * @constructor
 * @private
 */
function TypeDecoder() {
  this._definedTypes = {};
  // Partial types are similar to definedTypes but have type ids for child types
  // rather than fully defined type structures.
  this._partialTypes = {};
}

var kind = require('../vdl/kind.js');
var Type = require('../vdl/type.js');
var BootstrapTypes = require('./bootstrap-types.js');
var RawVomReader = require('./raw-vom-reader.js');
var unwrap = require('../vdl/type-util').unwrap;
var wiretype = require('../gen-vdl/v.io/v23/vom');

var endByte = unwrap(wiretype.WireCtrlEnd);

/**
 * Looks up a type in the decoded types cache by id.
 * @param {number} typeId The type id.
 * @return {Type} The decoded type or undefined.
 */
TypeDecoder.prototype.lookupType = function(typeId) {
  return this._lookupTypeImpl(typeId, true);
};

/**
 * Looks up a type in the decoded types cache by id.
 * @param {number} typeId The type id.
 * @param {boolean} defineUndefined True if partial types that this method
 * resolves to should be built. False otherwise.
 * Partial types should only be built when this is called through lookupType so
 * that they are built lazily.
 * @return {Type} The decoded type or undefined.
 */
TypeDecoder.prototype._lookupTypeImpl = function(typeId, definePartialTypes) {
  if (typeId < 0) {
    throw new Error('invalid negative type id.');
  }

  var type = BootstrapTypes.idToType(typeId);
  if (type !== undefined) {
    return type;
  }

  if (definePartialTypes && this._partialTypes.hasOwnProperty(typeId)) {
    this._tryBuildPartialType(typeId, this._partialTypes[typeId]);
  }

  return this._definedTypes[typeId];
};

/**
 * Add a new type definition to the type cache.
 * @param {number} typeId The id of the type.
 * @param {Uint8Array} The raw bytes that describe the type structure.
 */
TypeDecoder.prototype.defineType = function(typeId, messageBytes) {
  if (typeId < 0) {
    throw new Error('invalid negative type id ' + typeId + '.');
  }
  if (this._definedTypes[typeId] !== undefined ||
    this._partialTypes[typeId] !== undefined) {
    throw new Error('Cannot redefine type with id ' + typeId);
  }

  // Read the type in and add it to the partial type set.
  this._partialTypes[typeId] = this._readPartialType(messageBytes);
};

/**
 * Flattens the type's dependencies into a typeId->(type, partial type) map.
 * @private
 * @throws {Error} If the type's dependencies are not available.
 */
TypeDecoder.prototype._flattenTypeDepGraph = function(typeId, typeDeps) {
  // Already in map?
  if (typeDeps[typeId] !== undefined) {
    return;
  }
  // Already defined?
  if (this._lookupTypeImpl(typeId, false) !== undefined) {
    return;
  }
  // Allocate a type for the partial type.
  if (!this._partialTypes.hasOwnProperty(typeId)) {
    throw new Error('Type definition with ID ' + typeId +
      ' not received.');
  }
  var partialType = this._partialTypes[typeId];
  typeDeps[typeId] = {
    partialType: partialType,
    type: new Type()
  };

  // Recurse.
  if (partialType.namedTypeId !== undefined) {
    this._flattenTypeDepGraph(partialType.namedTypeId, typeDeps);
  }
  if (partialType.keyTypeId !== undefined) {
    this._flattenTypeDepGraph(partialType.keyTypeId, typeDeps);
  }
  if (partialType.elemTypeId !== undefined) {
    this._flattenTypeDepGraph(partialType.elemTypeId, typeDeps);
  }
  var i;
  if (partialType.typeIds !== undefined) {
    for (i = 0; i < partialType.typeIds.length; i++) {
      this._flattenTypeDepGraph(partialType.typeIds[i], typeDeps);
    }
  }
  if (partialType.fields !== undefined) {
    for (i = 0; i < partialType.fields.length; i++) {
      this._flattenTypeDepGraph(partialType.fields[i].typeId, typeDeps);
    }
  }
};

/**
 * Tries to build a partial type into a type.
 * This has two steps:
 * 1. Allocate type objects for all dependencies
 * 2. Copy the type and replace the type id with the created types.
 * 3. Copy named types and change the name.
 */
TypeDecoder.prototype._tryBuildPartialType = function(typeId) {
  if (!this._partialTypes.hasOwnProperty(typeId)) {
    throw new Error('Type definition with ID ' + typeId +
      ' not received.');
  }
  var partialType = this._partialTypes[typeId];

  var flattenedTypes = {};
  this._flattenTypeDepGraph(typeId, flattenedTypes);

  var self = this;
  var getType = function(id) {
    var type = self._lookupTypeImpl(id, false);
    if (type !== undefined) {
      return type;
    }
    type = flattenedTypes[id].type;
    if (type !== undefined) {
      return type;
    }
    throw new Error('Type unexpectedly undefined.');
  };

  var id;
  var type;
  var i;
  // All dependencies are ready. Build the type.
  for (id in flattenedTypes) {
    if (!flattenedTypes.hasOwnProperty(id)) {
      continue;
    }
    partialType = flattenedTypes[id].partialType;
    type = flattenedTypes[id].type;

    if (partialType.namedTypeId !== undefined) {
      // Handle named types in a second pass because it involves copying.
      continue;
    }

    type.kind = partialType.kind;
    if (partialType.name !== undefined) {
      type.name = partialType.name;
    }
    if (partialType.labels !== undefined) {
      type.labels = partialType.labels;
    }
    if (partialType.len !== undefined) {
      type.len = partialType.len;
    }

    if (partialType.keyTypeId !== undefined) {
      type.key = getType(partialType.keyTypeId);
    }
    if (partialType.elemTypeId !== undefined) {
      type.elem = getType(partialType.elemTypeId);
    }
    if (partialType.typeIds !== undefined) {
      type.types = new Array(partialType.typeIds.length);
      for (i = 0; i < partialType.typeIds.length; i++) {
        type.types[i] = getType(partialType.typeIds[i]);
      }
    }
    if (partialType.fields !== undefined) {
      type.fields = new Array(partialType.fields.length);
      for (i = 0; i < partialType.fields.length; i++) {
        var partialField = partialType.fields[i];
        type.fields[i] = {
          name: partialField.name,
          type: getType(partialField.typeId)
        };
      }
    }
  }

  // Now handle named types.
  for (id in flattenedTypes) {
    if (flattenedTypes.hasOwnProperty(id)) {
      partialType = flattenedTypes[id].partialType;
      type = flattenedTypes[id].type;

      if (partialType.namedTypeId !== undefined) {
        // Special case for named types.
        var toCopy = getType(partialType.namedTypeId);
        for (var fieldName in toCopy) {
          if (toCopy.hasOwnProperty(fieldName)) {
            type[fieldName] = toCopy[fieldName];
          }
        }
        type.name = partialType.name;
      }
    }
  }

  // Now that the types are all prepared, make them immutable.
  for (id in flattenedTypes) {
    if (flattenedTypes.hasOwnProperty(id)) {
      type = flattenedTypes[id].type;

      // Make the type immutable, setting its _unique string too.
      type.freeze();

      // Define the type.
      this._definedTypes[id] = type;

      // Remove the type from the partial type set.
      delete this._partialTypes[id];
    }
  }
};

/**
 * Read the binary type description into a partial type description.
 * @param {Uint8Array} messageBytes The binary type message.
 * @return {PartialType} The type that was read.
 */
TypeDecoder.prototype._readPartialType = function(messageBytes) {
  var reader = new RawVomReader(messageBytes);
  var unionId = reader.readUint();
  var partialType = {};
  var nextIndex;
  var i;
  switch (unionId) {
    case BootstrapTypes.unionIds.NAMED_TYPE:
      endDef:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.namedTypeId = reader.readUint();
            break;
          default:
            throw new Error('Unexpected index for WireNamed: ' + nextIndex);
          }
      }
      break;
    case BootstrapTypes.unionIds.ENUM_TYPE:
      partialType.kind = kind.ENUM;
      endDef2:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef2;
        }

        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.labels = new Array(reader.readUint());
            for (i = 0; i < partialType.labels.length; i++) {
              partialType.labels[i] = reader.readString();
            }
            break;
          default:
            throw new Error('Unexpected index for WireEnum: ' + nextIndex);
          }
      }
      break;
    case BootstrapTypes.unionIds.ARRAY_TYPE:
      partialType.kind = kind.ARRAY;
      endDef3:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef3;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.elemTypeId = reader.readUint();
            break;
          case 2:
            partialType.len = reader.readUint();
            break;
          default:
            throw new Error('Unexpected index for WireArray: ' + nextIndex);
          }
      }
      break;
    case BootstrapTypes.unionIds.LIST_TYPE:
      partialType.kind = kind.LIST;
      endDef4:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef4;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.elemTypeId = reader.readUint();
            break;
          default:
            throw new Error('Unexpected index for WireList: ' + nextIndex);
          }
      }
      break;
    case BootstrapTypes.unionIds.SET_TYPE:
      partialType.kind = kind.SET;
      endDef5:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef5;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.keyTypeId = reader.readUint();
            break;
          default:
            throw new Error('Unexpected index for WireSet: ' + nextIndex);
          }
      }
      break;
    case BootstrapTypes.unionIds.MAP_TYPE:
      partialType.kind = kind.MAP;
      endDef6:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef6;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.keyTypeId = reader.readUint();
            break;
          case 2:
            partialType.elemTypeId = reader.readUint();
            break;
          default:
            throw new Error('Unexpected index for WireMap: ' + nextIndex);
          }
      }
      break;
    case BootstrapTypes.unionIds.STRUCT_TYPE:
    case BootstrapTypes.unionIds.UNION_TYPE:
      if (unionId === BootstrapTypes.unionIds.STRUCT_TYPE) {
        partialType.kind = kind.STRUCT;
      } else {
        partialType.kind = kind.UNION;
      }
      endDef7:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef7;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.fields = new Array(reader.readUint());
            for (i = 0; i < partialType.fields.length; i++) {
              partialType.fields[i] = {};
              sfEndDef:
              while(true) {
                if (reader.tryReadControlByte() === endByte) {
                  break sfEndDef;
                }
                var sfNextIndex = reader.readUint();
                switch(sfNextIndex) {
                  case 0:
                    var s = reader.readString();
                    partialType.fields[i].name = s;
                    break;
                  case 1:
                    partialType.fields[i].typeId = reader.readUint();
                    break;
                }
              }
            }
            break;
          default:
            throw new Error('Unexpected index for WireStruct: ' + nextIndex);
          }
      }
      // We allow struct{} definitions.
      if (partialType.kind === kind.STRUCT) {
        partialType.fields = partialType.fields || [];
      }
      break;
    case BootstrapTypes.unionIds.OPTIONAL_TYPE:
      partialType.kind = kind.OPTIONAL;
      endDef9:
      while (true) {
        if (reader.tryReadControlByte() === endByte) {
          break endDef9;
        }
        nextIndex = reader.readUint();
        switch(nextIndex) {
          case 0:
            partialType.name = reader.readString();
            break;
          case 1:
            partialType.elemTypeId = reader.readUint();
            break;
          default:
            throw new Error('Unexpected index for WireOptional: ' + nextIndex);
          }
      }
      break;
    default:
      throw new Error('Unknown wire type id ' + unionId);
  }
  partialType.name = partialType.name || '';
  return partialType;
};
