import r from '@foliojs-fork/restructure';
import {getEncoding, LANGUAGES} from '../encodings';

let NameRecord = new r.Struct({
  platformID: r.uint16,
  encodingID: r.uint16,
  languageID: r.uint16,
  nameID:     r.uint16,
  length:     r.uint16,
  string:     new r.Pointer(r.uint16,
    new r.String('length', t => getEncoding(t.platformID, t.encodingID, t.languageID)),
    { type: 'parent', relativeTo: ctx => ctx.parent.stringOffset, allowNull: false }
  )
});

let LangTagRecord = new r.Struct({
  length:  r.uint16,
  tag:     new r.Pointer(r.uint16, new r.String('length', 'utf16be'), {type: 'parent', relativeTo: ctx => ctx.stringOffset})
});

var NameTable = new r.VersionedStruct(r.uint16, {
  0: {
    count:          r.uint16,
    stringOffset:   r.uint16,
    records:        new r.Array(NameRecord, 'count')
  },
  1: {
    count:          r.uint16,
    stringOffset:   r.uint16,
    records:        new r.Array(NameRecord, 'count'),
    langTagCount:   r.uint16,
    langTags:       new r.Array(LangTagRecord, 'langTagCount')
  }
});

export default NameTable;

const NAMES = [
  'copyright',
  'fontFamily',
  'fontSubfamily',
  'uniqueSubfamily',
  'fullName',
  'version',
  'postscriptName', // Note: A font may have only one PostScript name and that name must be ASCII.
  'trademark',
  'manufacturer',
  'designer',
  'description',
  'vendorURL',
  'designerURL',
  'license',
  'licenseURL',
  null, // reserved
  'preferredFamily',
  'preferredSubfamily',
  'compatibleFull',
  'sampleText',
  'postscriptCIDFontName',
  'wwsFamilyName',
  'wwsSubfamilyName'
];

NameTable.process = function(stream) {
  var records = {};
  for (let record of this.records) {
    // find out what language this is for
    let language = LANGUAGES[record.platformID][record.languageID];

    if (language == null && this.langTags != null && record.languageID >= 0x8000) {
      language = this.langTags[record.languageID - 0x8000].tag;
    }

    if (language == null) {
      language = record.platformID + '-' + record.languageID;
    }

    // if the nameID is >= 256, it is a font feature record (AAT)
    let key = record.nameID >= 256 ? 'fontFeatures' : (NAMES[record.nameID] || record.nameID);
    if (records[key] == null) {
      records[key] = {};
    }

    let obj = records[key];
    if (record.nameID >= 256) {
      obj = obj[record.nameID] || (obj[record.nameID] = {});
    }

    if (typeof record.string === 'string' || typeof obj[language] !== 'string') {
      obj[language] = record.string;
    }
  }

  this.records = records;
};

NameTable.preEncode = function() {
  if (Array.isArray(this.records)) return;
  this.version = 0;

  let records = [];
  for (let key in this.records) {
    let val = this.records[key];
    if (key === 'fontFeatures') continue;

    records.push({
      platformID: 3,
      encodingID: 1,
      languageID: 0x409,
      nameID: NAMES.indexOf(key),
      length: Buffer.byteLength(val.en, 'utf16le'),
      string: val.en
    });

    if (key === 'postscriptName') {
      records.push({
        platformID: 1,
        encodingID: 0,
        languageID: 0,
        nameID: NAMES.indexOf(key),
        length: val.en.length,
        string: val.en
      });
    }
  }

  this.records = records;
  this.count = records.length;
  this.stringOffset = NameTable.size(this, null, false);
};
