// 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 Represents a VOM decoder.
 * @private
 */

module.exports = Decoder;

var canonicalize = require('../vdl/canonicalize.js');
var TypeDecoder = require('./type-decoder.js');
var kind = require('../vdl/kind.js');
var Registry = require('../vdl/registry.js');
var types = require('../vdl/types.js');
var util = require('../vdl/util.js');
var unwrap = require('../vdl/type-util').unwrap;
var wiretype = require('../gen-vdl/v.io/v23/vom');
var nativeTypeRegistry = require('../vdl/native-type-registry');
var Deferred = require('../lib/deferred');
var Promise = require('../lib/promise');
var TaskSequence = require('../lib/task-sequence');
var promiseFor = require('../lib/async-helper').promiseFor;
var promiseWhile = require('../lib/async-helper').promiseWhile;
var versions = require('./versions');

var endByte = unwrap(wiretype.WireCtrlEnd);
var nilByte = unwrap(wiretype.WireCtrlNil);

/**
 * Create a decoder to read objects from the provided message reader.
 * Decode has the option of returning a deeply-wrapped object, or an object only
 * wrapped at the top-level.
 * @param {module:vanadium.vom.ByteArrayMessageReader} reader The message
 * reader.
 * @param {boolean=} deepWrap Whether to deeply wrap. Defaults to false.
 * @param {module:vanadium.vom.TypeDecoder} typeDecoder The type decoder to
 * use.  This can be null.
 * @memberof module:vanadium.vom
 * @constructor
 */
function Decoder(messageReader, deepWrap, typeDecoder) {
  this._messageReader = messageReader;
  this._typeDecoder = typeDecoder || new TypeDecoder();
  this._deepWrap = false;
  this._tasks = new TaskSequence();
}

/*
 * TODO(bprosnitz) We will want to be able to decode when we get callbacks.
 * Revisit this API.
 */
/**
 * Decodes the next object off of the message reader.
 * @return {object} The next object or null if no more objects are available.
 */
Decoder.prototype.decode = function(cb) {
  var def = new Deferred(cb);
  var decoder = this;
  this._tasks.addTask(function() {
    return decoder._messageReader.nextMessageType(decoder._typeDecoder).
      then(function(type) {
      if (type === null) {
        return null;
      }
      var reader = decoder._messageReader.rawReader;
      return decoder._decodeValue(type, reader, true);
    }).then(function(v) {
      def.resolve(v);
    }, function(err) {
      def.reject(err);
    });
  });
  return def.promise;
};

Decoder.prototype._decodeValue = function(t, reader, shouldWrap) {
  return this._decodeUnwrappedValue(t, reader).then(function(value) {
    // Special: JSValue should be reduced and returned as a native value.
    if (types.JSVALUE.equals(t)) {
      return canonicalize.reduce(value, types.JSVALUE);
    }

    if (nativeTypeRegistry.hasNativeType(t)) {
      return canonicalize.reduce(value, t);
    }
    // If this value should be wrapped, apply the constructor.
    if (t.kind !== kind.TYPEOBJECT && shouldWrap) {
      var Ctor = Registry.lookupOrCreateConstructor(t);
      if (Ctor.prototype._wrappedType) {
        return new Ctor(value);
      }
      if (value !== null && value !== undefined) {
        Object.defineProperty(value, 'constructor', {
          value: Ctor,
        });
      }
    }
    return value;
  });
};

Decoder.prototype._decodeUnwrappedValue = function(t, reader) {
  switch (t.kind) {
    case kind.BOOL:
      return reader.readBool();
    case kind.BYTE:
      return reader.readByte();
    case kind.UINT16:
    case kind.UINT32:
      return reader.readUint();
    case kind.UINT64:
      return reader.readBigUint();
    case kind.INT8:
    case kind.INT16:
    case kind.INT32:
      return reader.readInt();
    case kind.INT64:
      return reader.readBigInt();
    case kind.FLOAT32:
    case kind.FLOAT64:
      return reader.readFloat();
    case kind.COMPLEX64:
    case kind.COMPLEX128:
      return reader.readFloat().then(function(real) {
         return reader.readFloat().then(function(imag) {
           return {
             real: real,
             imag: imag
           };
         });
      });
    case kind.STRING:
      return reader.readString();
    case kind.ENUM:
      return this._decodeEnum(t, reader);
    case kind.LIST:
      return this._decodeList(t, reader);
    case kind.ARRAY:
      return this._decodeArray(t, reader);
    case kind.SET:
      return this._decodeSet(t, reader);
    case kind.MAP:
      return this._decodeMap(t, reader);
    case kind.STRUCT:
      return this._decodeStruct(t, reader);
    case kind.UNION:
      return this._decodeUnion(t, reader);
    case kind.ANY:
      return this._decodeAny(reader);
    case kind.OPTIONAL:
      return this._decodeOptional(t, reader);
    case kind.TYPEOBJECT:
      var decoder = this;
      var typeId;
      return reader.readUint().then(function(tId) {
        var mr = decoder._messageReader;
        if (mr._version === versions.version80) {
          typeId = tId;
        } else {
          typeId = mr._typeIds[tId];
        }
        return decoder._typeDecoder.lookupType(typeId);
      }).then(function(type) {
        if (type === undefined) {
          throw new Error('Undefined type for TYPEOBJECT id ' + typeId);
        }
        return type;
      });

    default:
      return Promise.reject(new Error('Support for decoding kind ' + t.kind +
        ' not yet implemented'));
  }
};

Decoder.prototype._decodeEnum = function(t, reader) {
  return reader.readUint().then(function(index) {
    if (t.labels.length <= index) {
      throw new Error('Invalid enum index ' + index);
    }
    return t.labels[index];
  });
};

Decoder.prototype._decodeList = function(t, reader) {
  var decoder = this;
  return reader.readUint().then(function(len) {
    return decoder._readSequence(t, len, reader);
  });
};

Decoder.prototype._decodeArray = function(t, reader) {
  var decoder = this;
  // Consume the zero length at the beginning of the array.
  return reader.readUint().then(function(b) {
    if (b !== 0) {
      throw new Error('Unexpected length ' + b);
    }
    return decoder._readSequence(t, t.len, reader);
  });
};

Decoder.prototype._readSequence = function(t, len, reader) {
  if (t.elem.kind === kind.BYTE) {
    // Read byte sequences directly into Uint8Arrays.

    // The Uint8Array is created by calling subarray. In node, this means that
    // its buffer points to the whole binary_reader buffer. To fix this, we
    // recreate the Uint8Array here to avoid exposing it.
    return reader._readRawBytes(len).then(function(b) {
      return new Uint8Array(b);
    });
  }

  var arr = new Array(len);
  var i = 0;
  var decoder = this;
  return promiseFor(len, function() {
    return decoder._decodeValue(t.elem, reader, false).then(function(val) {
      arr[i] = val;
      i++;
    });
  }).then(function() {
    return arr;
  });
};

Decoder.prototype._decodeSet = function(t, reader) {
  var decoder = this;
  var s = new Set();
  return reader.readUint().then(function(len) {
    return promiseFor(len, function() {
      return decoder._decodeValue(t.key, reader, false).then(function(key) {
        s.add(key);
      });
    });
  }).then(function() {
    return s;
  });
};

Decoder.prototype._decodeMap = function(t, reader) {
  var decoder = this;
  return reader.readUint().then(function(len) {
    var m = new Map();
    var i = 0;
    if (len > 0) {
      return decoder._decodeValue(t.key, reader, false).then(handleKey);
    }
    return m;

    function handleKey(key) {
      return decoder._decodeValue(t.elem, reader, false).then(function(value) {
        m.set(key, value);
        i++;
        if (i < len) {
          return decoder._decodeValue(t.key, reader, false).then(handleKey);
        }
        return m;
      });
    }
  });
};

Decoder.prototype._decodeStruct = function(t, reader) {
  var decoder = this;
  var Ctor = Registry.lookupOrCreateConstructor(t);
  var obj = Object.create(Ctor.prototype);

  return promiseWhile(notEndByte, readField).then(function() {
    return obj;
  }).then(function(obj) {
    t.fields.forEach(function(field) {
      var name = util.uncapitalize(field.name);
      if (!obj.hasOwnProperty(name)) {
        obj[name] = unwrap(canonicalize.zero(field.type));
      }
    });
    return obj;
  });
  function notEndByte() {
    return reader.tryReadControlByte().then(function(ctrl) {
      if (ctrl === endByte) {
        return false;
      }

      if (ctrl) {
        throw new Error('Unexpected control byte ' + ctrl);
      }
      return true;
    });
  }
  function readField() {
    var name = '';
    return reader.readUint().then(function(nextIndex) {
      if (t.fields.length <= nextIndex) {
        throw new Error('Struct index ' + nextIndex + ' out of bounds');
      }
      var field = t.fields[nextIndex];
      name = util.uncapitalize(field.name);
      return decoder._decodeValue(field.type, reader, false);
    }).then(function(val) {
      obj[name] = val;
    });
  }
};

Decoder.prototype._decodeOptional = function(t, reader) {
  var decoder = this;
  return reader.peekByte().then(function(isNil) {
    if (isNil === nilByte) {
      // We don't have to wait for the read to finish.
      reader.tryReadControlByte();
      return null;
    }
    return decoder._decodeValue(t.elem, reader, false);
  });
};

Decoder.prototype._decodeAny = function(reader) {
  var decoder = this;
  return reader.tryReadControlByte().then(function(ctrl) {
    if (ctrl === nilByte) {
      return null;
    }

    if (ctrl) {
      throw new Error('Unexpected control byte ' + ctrl);
    }
    var typeId;
    return reader.readUint().then(function(tId) {
      var mr = decoder._messageReader;
      if (mr._version === versions.version80) {
        typeId = tId;
      } else {
        typeId = mr._typeIds[tId];
      }
      return decoder._typeDecoder.lookupType(typeId);
    }).then(function(type) {
      if (type === undefined) {
        throw new Error('Undefined typeid ' + typeId);
      }
      return decoder._decodeValue(type, reader, true);
    });
  });
};

Decoder.prototype._decodeUnion = function(t, reader) {
  var decoder = this;
  var field;
  // Find the Union field that was set and decode its value.
  return reader.readUint().then(function(fieldIndex) {
    if (t.fields.length <= fieldIndex) {
      throw new Error('Union index ' + fieldIndex + ' out of bounds');
    }
    field = t.fields[fieldIndex];
    return decoder._decodeValue(field.type, reader, false);
  }).then(function(val) {
    // Return the Union with a single field set to its decoded value.
    var Ctor = Registry.lookupOrCreateConstructor(t);
    var obj = Object.create(Ctor.prototype);
    obj[util.uncapitalize(field.name)] = val;
    return obj;
  });
};
