/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
/* jshint node:true, jasmine:true */
'use strict';

var codec = require('../lib/index.js');
var forge = require('node-forge');

var BigInteger = forge.jsbn.BigInteger;

describe('The codec ...', function() {
  var testString = 'scytl';
  var testStringBytes = new Uint8Array([115, 99, 121, 116, 108]);
  var testStringNonAscii = '你好';
  var testStringNonAsciiBytes = new Uint8Array([228, 189, 160, 229, 165, 189]);
  var testStringBase64 = 'c2N5dGw=';
  var testNumberString = '1234';
  var testNumberOneBase64 = 'AQ==';
  var testNumberBase64 = 'BNI=';
  var testStringHex = '736379746c';
  var testNumberOneHex = '01';
  var testNumberHex = '04d2';
  var testNumberBytes = new Uint8Array([4, 210]);

  describe('should be able to ..', function() {
    it('UTF-8 encode a string', function() {
      expect(codec.utf8Encode(testString)).toEqual(testStringBytes);
      expect(codec.utf8Encode(testStringNonAscii))
          .toEqual(testStringNonAsciiBytes);
    });

    it('UTF-8 decode an encoded string', function() {
      expect(codec.utf8Decode(testStringBytes)).toEqual(testString);
      expect(codec.utf8Decode(testStringNonAsciiBytes))
          .toBe(testStringNonAscii);
    });

    it('Convert some bytes to a BigInteger object', function() {
      expect(codec.bytesToBigInteger(testNumberBytes))
          .toEqual(new BigInteger(testNumberString));
    });

    it('Convert a BigInteger object to bytes', function() {
      expect(codec.bigIntegerToBytes(new BigInteger(testNumberString)))
          .toEqual(testNumberBytes);
    });

    it('Base64 encode some bytes', function() {
      expect(codec.base64Encode(testStringBytes)).toEqual(testStringBase64);
    });

    it('Base64 encode a string', function() {
      expect(codec.base64Encode(testString)).toBe(testStringBase64);
    });

    it('Base64 encode a BigInteger object', function() {
      expect(codec.base64Encode(BigInteger.ONE)).toBe(testNumberOneBase64);
      expect(codec.base64Encode(new BigInteger(testNumberString)))
          .toBe(testNumberBase64);
    });

    it('Base64 encode some bytes, using a specified output line length',
       function() {
         var base64 = codec.base64Encode(testStringBytes, {lineLength: 2});
         expect(base64.indexOf('\n')).toBe(3);
       });

    it('Base64 encode a string, using a specified output line length',
       function() {
         var base64 = codec.base64Encode(testString, {lineLength: 2});
         expect(base64.indexOf('\n')).toBe(3);
       });

    it('Base64 encode a BigInteger object, using a specified output line length',
       function() {
         var base64 = codec.base64Encode(
             new BigInteger(testNumberString), {lineLength: 2});
         expect(base64.indexOf('\n')).toBe(3);
       });

    it('Base64 decode some encoded bytes', function() {
      expect(codec.base64Decode(testStringBase64)).toEqual(testStringBytes);
    });

    it('Base64 decode a string', function() {
      expect(codec.utf8Decode(codec.base64Decode(testStringBase64)))
          .toBe(testString);
    });

    it('Base64 decode an encoded BigInteger object', function() {
      expect(codec.bytesToBigInteger(codec.base64Decode(testNumberOneBase64)))
          .toEqual(BigInteger.ONE);
      expect(codec.bytesToBigInteger(codec.base64Decode(testNumberBase64)))
          .toEqual(new BigInteger(testNumberString));
    });

    it('Hexadecimally encode some bytes', function() {
      expect(codec.hexEncode(testStringBytes)).toBe(testStringHex);
    });

    it('Hexadecimally encode a string', function() {
      expect(codec.hexEncode(testString)).toBe(testStringHex);
    });

    it('Hexadecimally encode a BigInteger object', function() {
      expect(codec.hexEncode(BigInteger.ONE)).toBe(testNumberOneHex);
      expect(codec.hexEncode(new BigInteger(testNumberString)))
          .toBe(testNumberHex);
    });

    it('Hexadecimally decode some encoded bytes', function() {
      expect(codec.hexDecode(testStringHex)).toEqual(testStringBytes);
    });

    it('Hexadecimally decode an encoded string', function() {
      expect(codec.utf8Decode(codec.hexDecode(testStringHex))).toBe(testString);
    });

    it('Hexadecimally decode an encoded BigInteger object', function() {
      expect(codec.bytesToBigInteger(codec.hexDecode(testNumberOneHex)))
          .toEqual(BigInteger.ONE);
      expect(codec.bytesToBigInteger(codec.hexDecode(testNumberHex)))
          .toEqual(new BigInteger(testNumberString));
    });

    it('Binary encode some bytes', function() {
      expect(codec.binaryEncode(testStringBytes)).toBe(testString);
    });

    it('Binary decode some encoded bytes', function() {
      expect(codec.binaryDecode(testString)).toEqual(testStringBytes);
    });

    it('Base64 encode some binary decoded bytes', function() {
      expect(codec.base64Encode(codec.binaryDecode(testString)))
          .toBe(testStringBase64);
    });

    it('Base64 encode some binary decoded bytes, using a specified output line length',
       function() {
         var base64 = codec.base64Encode(
             codec.binaryDecode(testString), {lineLength: 2});
         expect(base64.indexOf('\n')).toBe(3);
       });

    it('Base64 decode some binary encoded bytes', function() {
      expect(codec.binaryEncode(codec.base64Decode(testStringBase64)))
          .toBe(testString);
    });

    it('Hexadecimally encode some binary decoded bytes', function() {
      expect(codec.hexEncode(codec.binaryDecode(testString)))
          .toBe(testStringHex);
    });

    it('Hexadecimally decode some binary decoded bytes', function() {
      expect(codec.binaryEncode(codec.hexDecode(testStringHex)))
          .toBe(testString);
    });
  });
});
