// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sill.h"

#include "feat.h"
#include <cmath>
#include <unordered_set>

namespace ots {

bool OpenTypeSILL::Parse(const uint8_t* data, size_t length) {
  if (GetFont()->dropped_graphite) {
    return Drop("Skipping Graphite table");
  }
  Buffer table(data, length);

  if (!table.ReadU32(&this->version) || this->version >> 16 != 1) {
    return Drop("Failed to read valid version");
  }
  if (!table.ReadU16(&this->numLangs)) {
    return Drop("Failed to read numLangs");
  }

  // The following three fields are deprecated and ignored. We fix them up here
  // just for internal consistency, but the Graphite engine doesn't care.
  if (!table.ReadU16(&this->searchRange) ||
      !table.ReadU16(&this->entrySelector) ||
      !table.ReadU16(&this->rangeShift)) {
    return Drop("Failed to read searchRange..rangeShift");
  }
  if (this->numLangs == 0) {
    if (this->searchRange != 0 || this->entrySelector != 0 || this->rangeShift != 0) {
      this->searchRange = this->entrySelector = this->rangeShift = 0;
    }
  } else {
    unsigned floorLog2 = std::floor(log2(this->numLangs));
    if (this->searchRange != (unsigned)std::pow(2, floorLog2) ||
        this->entrySelector != floorLog2 ||
        this->rangeShift != this->numLangs - this->searchRange) {
      this->searchRange = (unsigned)std::pow(2, floorLog2);
      this->entrySelector = floorLog2;
      this->rangeShift = this->numLangs - this->searchRange;
    }
  }

  std::unordered_set<size_t> unverified;
  //this->entries.resize(static_cast<unsigned long>(this->numLangs) + 1, this);
  for (unsigned long i = 0; i <= this->numLangs; ++i) {
    this->entries.emplace_back(this);
    LanguageEntry& entry = this->entries[i];
    if (!entry.ParsePart(table)) {
      return Drop("Failed to read entries[%u]", i);
    }
    for (unsigned j = 0; j < entry.numSettings; ++j) {
      size_t offset = entry.offset + j * 8;
      if (offset < entry.offset || offset > length) {
        return DropGraphite("Invalid LangFeatureSetting offset %zu/%zu",
                            offset, length);
      }
      unverified.insert(offset);
        // need to verify that this LanguageEntry points to valid
        // LangFeatureSetting
    }
  }

  while (table.remaining()) {
    unverified.erase(table.offset());
    LangFeatureSetting setting(this);
    if (!setting.ParsePart(table)) {
      return Drop("Failed to read a LangFeatureSetting");
    }
    settings.push_back(setting);
  }

  if (!unverified.empty()) {
    return Drop("%zu incorrect offsets into settings", unverified.size());
  }
  if (table.remaining()) {
    return Warning("%zu bytes unparsed", table.remaining());
  }
  return true;
}

bool OpenTypeSILL::Serialize(OTSStream* out) {
  if (!out->WriteU32(this->version) ||
      !out->WriteU16(this->numLangs) ||
      !out->WriteU16(this->searchRange) ||
      !out->WriteU16(this->entrySelector) ||
      !out->WriteU16(this->rangeShift) ||
      !SerializeParts(this->entries, out) ||
      !SerializeParts(this->settings, out)) {
    return Error("Failed to write table");
  }
  return true;
}

bool OpenTypeSILL::LanguageEntry::ParsePart(Buffer& table) {
  if (!table.ReadU8(&this->langcode[0]) ||
      !table.ReadU8(&this->langcode[1]) ||
      !table.ReadU8(&this->langcode[2]) ||
      !table.ReadU8(&this->langcode[3])) {
    return parent->Error("LanguageEntry: Failed to read langcode");
  }
  if (!table.ReadU16(&this->numSettings)) {
    return parent->Error("LanguageEntry: Failed to read numSettings");
  }
  if (!table.ReadU16(&this->offset)) {
    return parent->Error("LanguageEntry: Failed to read offset");
  }
  return true;
}

bool OpenTypeSILL::LanguageEntry::SerializePart(OTSStream* out) const {
  if (!out->WriteU8(this->langcode[0]) ||
      !out->WriteU8(this->langcode[1]) ||
      !out->WriteU8(this->langcode[2]) ||
      !out->WriteU8(this->langcode[3]) ||
      !out->WriteU16(this->numSettings) ||
      !out->WriteU16(this->offset)) {
    return parent->Error("LanguageEntry: Failed to write");
  }
  return true;
}

bool OpenTypeSILL::LangFeatureSetting::ParsePart(Buffer& table) {
  OpenTypeFEAT* feat = static_cast<OpenTypeFEAT*>(
      parent->GetFont()->GetTypedTable(OTS_TAG_FEAT));
  if (!feat) {
    return parent->Error("FeatureDefn: Required Feat table is missing");
  }

  if (!table.ReadU32(&this->featureId) ||
      !feat->IsValidFeatureId(this->featureId)) {
    return parent->Error("LangFeatureSetting: Failed to read valid featureId");
  }
  if (!table.ReadS16(&this->value)) {
    return parent->Error("LangFeatureSetting: Failed to read value");
  }
  if (!table.ReadU16(&this->reserved)) {
    return parent->Error("LangFeatureSetting: Failed to read reserved");
  }
  if (this->reserved != 0) {
    parent->Warning("LangFeatureSetting: Nonzero reserved");
  }
  return true;
}

bool OpenTypeSILL::LangFeatureSetting::SerializePart(OTSStream* out) const {
  if (!out->WriteU32(this->featureId) ||
      !out->WriteS16(this->value) ||
      !out->WriteU16(this->reserved)) {
    return parent->Error("LangFeatureSetting: Failed to read reserved");
  }
  return true;
}

}  // namespace ots
