// 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 Tests for TypeEncoder and TypeDecoder.
 */

var test = require('prova');

var stringify = require('./../../src/vdl/stringify.js');
var types = require('./../../src/vdl/types.js');
var kind = require('./../../src/vdl/kind.js');
var Promise = require('./../../src/lib/promise');

var TypeEncoder = require('./../../src/vom/type-encoder.js');
var TypeDecoder = require('./../../src/vom/type-decoder.js');

var ByteMessageWriter = require(
    './../../src/vom/byte-message-writer.js');
var RawVomReader = require('./../../src/vom/raw-vom-reader.js');

/**
 * Type message reader reads type messages from the provided data.
 * @param {Uint8Array} bytes The input data.
 * @constructor
 */
function TypeMessageReader(bytes) {
  var header = bytes[0];
  this.rawReader = new RawVomReader(bytes);
  // consume the header byte.
  this.rawReader._readRawBytes(1);
  if (header !== 0x80) {
    throw new Error('Improperly formatted bytes. Must start with 0x80');
  }
}

/**
 * Read the next type message.
 */
TypeMessageReader.prototype.nextMessage = function(typeDecoder) {
  var reader = this;
  return this.rawReader.readInt().then(function(typeId) {
    if (typeId >= 0) {
      throw new Error('Value messages not implemented.');
    }
    return reader.rawReader.readUint().then(function(len) {
      return reader.rawReader._readRawBytes(len);
    }).then(function(bytes) {
      return {
        typeId: -typeId,
        messageBytes: bytes,
      };
    });
  }, function(err) {
    return null;
  });
};

test('type encoding encode and decode (optional fields filled)', function(t) {
  var tests = require('../vdl/type-test-cases.js');
  var promises = [];
  for (var i = 0; i < tests.length; i++) {
    promises.push(encodeDecodeType(t, tests[i].type));
  }
  Promise.all(promises).then(function() {
    t.end();
  }, t.end);
});

test('type encoding encode and decode (optional fields omitted)',
  function(t) {
  var tests = [
    {
      test: {
        kind: kind.OPTIONAL,
        elem: types.UINT64
      },
      expected: {
        name: '',
        kind: kind.OPTIONAL,
        elem: types.UINT64
      },
    },
    {
      test: {
        kind: kind.LIST,
        elem: {
          kind: kind.UINT16,
          name: 'namedUint16'
        }
      },
      expected: {
        kind: kind.LIST,
        name: '',
        elem: {
          kind: kind.UINT16,
          name: 'namedUint16'
        }
      }
    },
    {
      test: {
        kind: kind.UNION,
        name: 'unionName',
        fields: [
          {
            name: 'A',
            type: types.INT16
          },
          {
            name: 'B',
            type: {
              kind: kind.SET,
              key: types.BOOL
            }
          }
        ]
      },
      expected: {
        kind: kind.UNION,
        name: 'unionName',
        fields: [
          {
            name: 'A',
            type: types.INT16
          },
          {
            name: 'B',
            type: {
              name: '',
              kind: kind.SET,
              key: types.BOOL
            }
          }
        ]
      },
    },
    {
      test: {
        kind: kind.MAP,
        key: {
          kind: kind.INT16,
          name: 'namedInt16'
        },
        elem: {
          kind: kind.INT32,
          name: 'namedInt32'
        }
      },
      expected: {
        kind: kind.MAP,
        name: '',
        key: {
          kind: kind.INT16,
          name: 'namedInt16'
        },
        elem: {
          kind: kind.INT32,
          name: 'namedInt32'
        }
      },
    }
  ];

  var promises = [];
  for (var i = 0; i < tests.length; i++) {
    promises.push(encodeDecodeType(t, tests[i].test, tests[i].expected));
  }
  Promise.all(promises).then(function() {
    t.end();
  }, t.end);
});

var UPPER_LOOP_LIMIT = 100;
function encodeDecodeType(t, test, expected) {
  // If the expected result is not given, use the test value instead.
  expected = expected || test;

  var writer = new ByteMessageWriter();
  var typeEncoder = new TypeEncoder(writer);
  var id = typeEncoder.encodeType(test);

  var typeDecoder = new TypeDecoder();
  var reader = new TypeMessageReader(writer.getBytes());
  var j = 1;
  return readMessage();
  function readMessage() {
    return reader.nextMessage().then(function(message) {
      if (message === null) {
        return typeDecoder.lookupType(id).then(function(resultType) {
          var resultStr = stringify(resultType);
          var expectedStr = stringify(expected);
          return t.equals(resultStr, expectedStr);
        });
      }
      if (j === UPPER_LOOP_LIMIT) {
        return t.fail('read too many messages');
      }
      j++;
      return typeDecoder.defineType(message.typeId, message.messageBytes).
        then(readMessage);
    });
  }
}

// This tests a subset of potential type encoding errors.
test('type encoding encode errors', function(t) {
  var badTypes = {
    'no type': undefined,
    'no kind': {},
    'invalid kind': {
      kind: 'non-integer'
    },
    'unknown kind': {
      kind: -1
    },
    'list w/ bad elem': {
      kind: kind.LIST,
      name: 'testList',
      elem: true
    },
    'array w/ bad len': {
      kind: kind.ARRAY,
      name: 'testArray',
      elem: types.UINT64,
      len: -1
    },
    'set w/ labels': {
      kind: kind.SET,
      key: types.ANY,
      labels: ['labels', 'are', 'for', 'enums', 'only']
    },
    'enum w/ non-string labels': {
      kind: kind.ENUM,
      labels: ['do not', 'put a number in', 'the enum labels', 3]
    },
    'union w/o fields': {
      kind: kind.UNION,
      fields: []
    }
  };

  for (var testName in badTypes) {
    if (badTypes.hasOwnProperty(testName)) {
      var test = badTypes[testName];

      var writer = new ByteMessageWriter();
      var typeEncoder = new TypeEncoder(writer);
      t.throws(
        typeEncoder.encodeType.bind(typeEncoder, test),
        testName
      );
    }
  }
  t.end();
});
