'use strict';

// See documentation here: http://www.microsoft.com/typography/otspec/name.htm

var _ = require('lodash');
var ByteBuffer = require('microbuffer');
var Str = require('../../str');

var TTF_NAMES = {
  COPYRIGHT: 0,
  FONT_FAMILY: 1,
  ID: 3,
  DESCRIPTION: 10,
  URL_VENDOR: 11
};

function tableSize(names) {
  var result = 6; // table header

  _.forEach(names, function (name) {
    result += 12 + name.data.length; //name header and data
  });
  return result;
}

function getStrings(name, id) {
  var result = [];
  var str = new Str(name);

  result.push({ data: str.toUTF8Bytes(), id: id, platformID : 1, encodingID : 0, languageID : 0 }); //mac standard
  result.push({ data: str.toUCS2Bytes(), id: id, platformID : 3, encodingID : 1, languageID : 0x409 }); //windows standard
  return result;
}

// Collect font names
function getNames(font) {
  var result = [];

  if (font.copyright) {
    result.push.apply(result, getStrings(font.copyright, TTF_NAMES.COPYRIGHT));
  }
  if (font.familyName) {
    result.push.apply(result, getStrings(font.familyName, TTF_NAMES.FONT_FAMILY));
  }
  if (font.id) {
    result.push.apply(result, getStrings(font.id, TTF_NAMES.ID));
  }
  result.push.apply(result, getStrings(font.description, TTF_NAMES.DESCRIPTION));
  result.push.apply(result, getStrings(font.url, TTF_NAMES.URL_VENDOR));

  _.forEach(font.sfntNames, function (sfntName) {
    result.push.apply(result, getStrings(sfntName.value, sfntName.id));
  });

  result.sort(function (a, b) {
    var orderFields = [ 'platformID', 'encodingID', 'languageID', 'id' ];
    var i;

    for (i = 0; i < orderFields.length; i++) {
      if (a[orderFields[i]] !== b[orderFields[i]]) {
        return a[orderFields[i]] < b[orderFields[i]] ? -1 : 1;
      }
    }
    return 0;
  });

  return result;
}

function createNameTable(font) {

  var names = getNames(font);

  var buf = new ByteBuffer(tableSize(names));

  buf.writeUint16(0); // formatSelector
  buf.writeUint16(names.length); // nameRecordsCount
  var offsetPosition = buf.tell();

  buf.writeUint16(0); // offset, will be filled later
  var nameOffset = 0;

  _.forEach(names, function (name) {
    buf.writeUint16(name.platformID); // platformID
    buf.writeUint16(name.encodingID); // platEncID
    buf.writeUint16(name.languageID); // languageID, English (USA)
    buf.writeUint16(name.id); // nameID
    buf.writeUint16(name.data.length); // reclength
    buf.writeUint16(nameOffset); // offset
    nameOffset += name.data.length;
  });
  var actualStringDataOffset = buf.tell();

  //Array of bytes with actual string data
  _.forEach(names, function (name) {
    buf.writeBytes(name.data);
  });

  //write actual string data offset
  buf.seek(offsetPosition);
  buf.writeUint16(actualStringDataOffset); // offset

  return buf;
}

module.exports = createNameTable;
