/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ResourceValues.h"

#include <algorithm>
#include <limits>
#include <set>

#include "androidfw/ResourceTypes.h"

#include "Resource.h"
#include "ResourceUtils.h"
#include "ValueVisitor.h"
#include "util/Util.h"

namespace aapt {

template <typename Derived>
void BaseValue<Derived>::Accept(RawValueVisitor* visitor) {
  visitor->Visit(static_cast<Derived*>(this));
}

template <typename Derived>
void BaseItem<Derived>::Accept(RawValueVisitor* visitor) {
  visitor->Visit(static_cast<Derived*>(this));
}

RawString::RawString(const StringPool::Ref& ref) : value(ref) {}

bool RawString::Equals(const Value* value) const {
  const RawString* other = ValueCast<RawString>(value);
  if (!other) {
    return false;
  }
  return *this->value == *other->value;
}

RawString* RawString::Clone(StringPool* new_pool) const {
  RawString* rs = new RawString(new_pool->MakeRef(*value));
  rs->comment_ = comment_;
  rs->source_ = source_;
  return rs;
}

bool RawString::Flatten(android::Res_value* out_value) const {
  out_value->dataType = android::Res_value::TYPE_STRING;
  out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
  return true;
}

void RawString::Print(std::ostream* out) const {
  *out << "(raw string) " << *value;
}

Reference::Reference() : reference_type(Type::kResource) {}

Reference::Reference(const ResourceNameRef& n, Type t)
    : name(n.ToResourceName()), reference_type(t) {}

Reference::Reference(const ResourceId& i, Type type)
    : id(i), reference_type(type) {}

Reference::Reference(const ResourceNameRef& n, const ResourceId& i)
    : name(n.ToResourceName()), id(i), reference_type(Type::kResource) {}

bool Reference::Equals(const Value* value) const {
  const Reference* other = ValueCast<Reference>(value);
  if (!other) {
    return false;
  }
  return reference_type == other->reference_type &&
         private_reference == other->private_reference && id == other->id &&
         name == other->name;
}

bool Reference::Flatten(android::Res_value* out_value) const {
  const ResourceId resid = id.value_or_default(ResourceId(0));
  const bool dynamic =
      (resid.package_id() != kFrameworkPackageId && resid.package_id() != kAppPackageId);

  if (reference_type == Reference::Type::kResource) {
    if (dynamic) {
      out_value->dataType = android::Res_value::TYPE_DYNAMIC_REFERENCE;
    } else {
      out_value->dataType = android::Res_value::TYPE_REFERENCE;
    }
  } else {
    if (dynamic) {
      out_value->dataType = android::Res_value::TYPE_DYNAMIC_ATTRIBUTE;
    } else {
      out_value->dataType = android::Res_value::TYPE_ATTRIBUTE;
    }
  }
  out_value->data = util::HostToDevice32(resid.id);
  return true;
}

Reference* Reference::Clone(StringPool* /*new_pool*/) const {
  return new Reference(*this);
}

void Reference::Print(std::ostream* out) const {
  *out << "(reference) ";
  if (reference_type == Reference::Type::kResource) {
    *out << "@";
    if (private_reference) {
      *out << "*";
    }
  } else {
    *out << "?";
  }

  if (name) {
    *out << name.value();
  }

  if (id && !Res_INTERNALID(id.value().id)) {
    *out << " " << id.value();
  }
}

bool Id::Equals(const Value* value) const {
  return ValueCast<Id>(value) != nullptr;
}

bool Id::Flatten(android::Res_value* out) const {
  out->dataType = android::Res_value::TYPE_INT_BOOLEAN;
  out->data = util::HostToDevice32(0);
  return true;
}

Id* Id::Clone(StringPool* /*new_pool*/) const { return new Id(*this); }

void Id::Print(std::ostream* out) const { *out << "(id)"; }

String::String(const StringPool::Ref& ref) : value(ref) {}

bool String::Equals(const Value* value) const {
  const String* other = ValueCast<String>(value);
  if (!other) {
    return false;
  }

  if (this->value != other->value) {
    return false;
  }

  if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
    return false;
  }

  auto other_iter = other->untranslatable_sections.begin();
  for (const UntranslatableSection& this_section : untranslatable_sections) {
    if (this_section != *other_iter) {
      return false;
    }
    ++other_iter;
  }
  return true;
}

bool String::Flatten(android::Res_value* out_value) const {
  // Verify that our StringPool index is within encode-able limits.
  if (value.index() > std::numeric_limits<uint32_t>::max()) {
    return false;
  }

  out_value->dataType = android::Res_value::TYPE_STRING;
  out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
  return true;
}

String* String::Clone(StringPool* new_pool) const {
  String* str = new String(new_pool->MakeRef(*value));
  str->comment_ = comment_;
  str->source_ = source_;
  str->untranslatable_sections = untranslatable_sections;
  return str;
}

void String::Print(std::ostream* out) const {
  *out << "(string) \"" << *value << "\"";
}

StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {}

bool StyledString::Equals(const Value* value) const {
  const StyledString* other = ValueCast<StyledString>(value);
  if (!other) {
    return false;
  }

  if (this->value != other->value) {
    return false;
  }

  if (untranslatable_sections.size() != other->untranslatable_sections.size()) {
    return false;
  }

  auto other_iter = other->untranslatable_sections.begin();
  for (const UntranslatableSection& this_section : untranslatable_sections) {
    if (this_section != *other_iter) {
      return false;
    }
    ++other_iter;
  }
  return true;
}

bool StyledString::Flatten(android::Res_value* out_value) const {
  if (value.index() > std::numeric_limits<uint32_t>::max()) {
    return false;
  }

  out_value->dataType = android::Res_value::TYPE_STRING;
  out_value->data = util::HostToDevice32(static_cast<uint32_t>(value.index()));
  return true;
}

StyledString* StyledString::Clone(StringPool* new_pool) const {
  StyledString* str = new StyledString(new_pool->MakeRef(value));
  str->comment_ = comment_;
  str->source_ = source_;
  str->untranslatable_sections = untranslatable_sections;
  return str;
}

void StyledString::Print(std::ostream* out) const {
  *out << "(styled string) \"" << *value->str << "\"";
  for (const StringPool::Span& span : value->spans) {
    *out << " " << *span.name << ":" << span.first_char << ","
         << span.last_char;
  }
}

FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {}

bool FileReference::Equals(const Value* value) const {
  const FileReference* other = ValueCast<FileReference>(value);
  if (!other) {
    return false;
  }
  return path == other->path;
}

bool FileReference::Flatten(android::Res_value* out_value) const {
  if (path.index() > std::numeric_limits<uint32_t>::max()) {
    return false;
  }

  out_value->dataType = android::Res_value::TYPE_STRING;
  out_value->data = util::HostToDevice32(static_cast<uint32_t>(path.index()));
  return true;
}

FileReference* FileReference::Clone(StringPool* new_pool) const {
  FileReference* fr = new FileReference(new_pool->MakeRef(*path));
  fr->file = file;
  fr->comment_ = comment_;
  fr->source_ = source_;
  return fr;
}

void FileReference::Print(std::ostream* out) const {
  *out << "(file) " << *path;
}

BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {}

BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
  value.dataType = dataType;
  value.data = data;
}

bool BinaryPrimitive::Equals(const Value* value) const {
  const BinaryPrimitive* other = ValueCast<BinaryPrimitive>(value);
  if (!other) {
    return false;
  }
  return this->value.dataType == other->value.dataType &&
         this->value.data == other->value.data;
}

bool BinaryPrimitive::Flatten(android::Res_value* out_value) const {
  out_value->dataType = value.dataType;
  out_value->data = util::HostToDevice32(value.data);
  return true;
}

BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const {
  return new BinaryPrimitive(*this);
}

void BinaryPrimitive::Print(std::ostream* out) const {
  switch (value.dataType) {
    case android::Res_value::TYPE_NULL:
      *out << "(null)";
      break;
    case android::Res_value::TYPE_INT_DEC:
      *out << "(integer) " << static_cast<int32_t>(value.data);
      break;
    case android::Res_value::TYPE_INT_HEX:
      *out << "(integer) 0x" << std::hex << value.data << std::dec;
      break;
    case android::Res_value::TYPE_INT_BOOLEAN:
      *out << "(boolean) " << (value.data != 0 ? "true" : "false");
      break;
    case android::Res_value::TYPE_INT_COLOR_ARGB8:
    case android::Res_value::TYPE_INT_COLOR_RGB8:
    case android::Res_value::TYPE_INT_COLOR_ARGB4:
    case android::Res_value::TYPE_INT_COLOR_RGB4:
      *out << "(color) #" << std::hex << value.data << std::dec;
      break;
    default:
      *out << "(unknown 0x" << std::hex << (int)value.dataType << ") 0x"
           << std::hex << value.data << std::dec;
      break;
  }
}

Attribute::Attribute(bool w, uint32_t t)
    : type_mask(t),
      min_int(std::numeric_limits<int32_t>::min()),
      max_int(std::numeric_limits<int32_t>::max()) {
  weak_ = w;
}

template <typename T>
constexpr T* add_pointer(T& val) {
  return &val;
}

bool Attribute::Equals(const Value* value) const {
  const Attribute* other = ValueCast<Attribute>(value);
  if (!other) {
    return false;
  }

  if (symbols.size() != other->symbols.size()) {
    return false;
  }

  if (type_mask != other->type_mask || min_int != other->min_int ||
      max_int != other->max_int) {
    return false;
  }

  std::vector<const Symbol*> sorted_a;
  std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
                 add_pointer<const Symbol>);
  std::sort(sorted_a.begin(), sorted_a.end(),
            [](const Symbol* a, const Symbol* b) -> bool {
              return a->symbol.name < b->symbol.name;
            });

  std::vector<const Symbol*> sorted_b;
  std::transform(other->symbols.begin(), other->symbols.end(),
                 std::back_inserter(sorted_b), add_pointer<const Symbol>);
  std::sort(sorted_b.begin(), sorted_b.end(),
            [](const Symbol* a, const Symbol* b) -> bool {
              return a->symbol.name < b->symbol.name;
            });

  return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
                    [](const Symbol* a, const Symbol* b) -> bool {
                      return a->symbol.Equals(&b->symbol) &&
                             a->value == b->value;
                    });
}

Attribute* Attribute::Clone(StringPool* /*new_pool*/) const {
  return new Attribute(*this);
}

void Attribute::PrintMask(std::ostream* out) const {
  if (type_mask == android::ResTable_map::TYPE_ANY) {
    *out << "any";
    return;
  }

  bool set = false;
  if ((type_mask & android::ResTable_map::TYPE_REFERENCE) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "reference";
  }

  if ((type_mask & android::ResTable_map::TYPE_STRING) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "string";
  }

  if ((type_mask & android::ResTable_map::TYPE_INTEGER) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "integer";
  }

  if ((type_mask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "boolean";
  }

  if ((type_mask & android::ResTable_map::TYPE_COLOR) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "color";
  }

  if ((type_mask & android::ResTable_map::TYPE_FLOAT) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "float";
  }

  if ((type_mask & android::ResTable_map::TYPE_DIMENSION) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "dimension";
  }

  if ((type_mask & android::ResTable_map::TYPE_FRACTION) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "fraction";
  }

  if ((type_mask & android::ResTable_map::TYPE_ENUM) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "enum";
  }

  if ((type_mask & android::ResTable_map::TYPE_FLAGS) != 0) {
    if (!set) {
      set = true;
    } else {
      *out << "|";
    }
    *out << "flags";
  }
}

void Attribute::Print(std::ostream* out) const {
  *out << "(attr) ";
  PrintMask(out);

  if (!symbols.empty()) {
    *out << " [" << util::Joiner(symbols, ", ") << "]";
  }

  if (min_int != std::numeric_limits<int32_t>::min()) {
    *out << " min=" << min_int;
  }

  if (max_int != std::numeric_limits<int32_t>::max()) {
    *out << " max=" << max_int;
  }

  if (IsWeak()) {
    *out << " [weak]";
  }
}

static void BuildAttributeMismatchMessage(DiagMessage* msg,
                                          const Attribute* attr,
                                          const Item* value) {
  *msg << "expected";
  if (attr->type_mask & android::ResTable_map::TYPE_BOOLEAN) {
    *msg << " boolean";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_COLOR) {
    *msg << " color";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_DIMENSION) {
    *msg << " dimension";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_ENUM) {
    *msg << " enum";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_FLAGS) {
    *msg << " flags";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_FLOAT) {
    *msg << " float";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_FRACTION) {
    *msg << " fraction";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_INTEGER) {
    *msg << " integer";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_REFERENCE) {
    *msg << " reference";
  }

  if (attr->type_mask & android::ResTable_map::TYPE_STRING) {
    *msg << " string";
  }

  *msg << " but got " << *value;
}

bool Attribute::Matches(const Item* item, DiagMessage* out_msg) const {
  android::Res_value val = {};
  item->Flatten(&val);

  // Always allow references.
  const uint32_t mask = type_mask | android::ResTable_map::TYPE_REFERENCE;
  if (!(mask & ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType))) {
    if (out_msg) {
      BuildAttributeMismatchMessage(out_msg, this, item);
    }
    return false;

  } else if (ResourceUtils::AndroidTypeToAttributeTypeMask(val.dataType) &
             android::ResTable_map::TYPE_INTEGER) {
    if (static_cast<int32_t>(util::DeviceToHost32(val.data)) < min_int) {
      if (out_msg) {
        *out_msg << *item << " is less than minimum integer " << min_int;
      }
      return false;
    } else if (static_cast<int32_t>(util::DeviceToHost32(val.data)) > max_int) {
      if (out_msg) {
        *out_msg << *item << " is greater than maximum integer " << max_int;
      }
      return false;
    }
  }
  return true;
}

bool Style::Equals(const Value* value) const {
  const Style* other = ValueCast<Style>(value);
  if (!other) {
    return false;
  }
  if (bool(parent) != bool(other->parent) ||
      (parent && other->parent &&
       !parent.value().Equals(&other->parent.value()))) {
    return false;
  }

  if (entries.size() != other->entries.size()) {
    return false;
  }

  std::vector<const Entry*> sorted_a;
  std::transform(entries.begin(), entries.end(), std::back_inserter(sorted_a),
                 add_pointer<const Entry>);
  std::sort(sorted_a.begin(), sorted_a.end(),
            [](const Entry* a, const Entry* b) -> bool {
              return a->key.name < b->key.name;
            });

  std::vector<const Entry*> sorted_b;
  std::transform(other->entries.begin(), other->entries.end(),
                 std::back_inserter(sorted_b), add_pointer<const Entry>);
  std::sort(sorted_b.begin(), sorted_b.end(),
            [](const Entry* a, const Entry* b) -> bool {
              return a->key.name < b->key.name;
            });

  return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
                    [](const Entry* a, const Entry* b) -> bool {
                      return a->key.Equals(&b->key) &&
                             a->value->Equals(b->value.get());
                    });
}

Style* Style::Clone(StringPool* new_pool) const {
  Style* style = new Style();
  style->parent = parent;
  style->parent_inferred = parent_inferred;
  style->comment_ = comment_;
  style->source_ = source_;
  for (auto& entry : entries) {
    style->entries.push_back(
        Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
  }
  return style;
}

void Style::Print(std::ostream* out) const {
  *out << "(style) ";
  if (parent && parent.value().name) {
    if (parent.value().private_reference) {
      *out << "*";
    }
    *out << parent.value().name.value();
  }
  *out << " [" << util::Joiner(entries, ", ") << "]";
}

static ::std::ostream& operator<<(::std::ostream& out,
                                  const Style::Entry& value) {
  if (value.key.name) {
    out << value.key.name.value();
  } else if (value.key.id) {
    out << value.key.id.value();
  } else {
    out << "???";
  }
  out << " = ";
  value.value->Print(&out);
  return out;
}

bool Array::Equals(const Value* value) const {
  const Array* other = ValueCast<Array>(value);
  if (!other) {
    return false;
  }

  if (items.size() != other->items.size()) {
    return false;
  }

  return std::equal(items.begin(), items.end(), other->items.begin(),
                    [](const std::unique_ptr<Item>& a,
                       const std::unique_ptr<Item>& b) -> bool {
                      return a->Equals(b.get());
                    });
}

Array* Array::Clone(StringPool* new_pool) const {
  Array* array = new Array();
  array->comment_ = comment_;
  array->source_ = source_;
  for (auto& item : items) {
    array->items.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
  }
  return array;
}

void Array::Print(std::ostream* out) const {
  *out << "(array) [" << util::Joiner(items, ", ") << "]";
}

bool Plural::Equals(const Value* value) const {
  const Plural* other = ValueCast<Plural>(value);
  if (!other) {
    return false;
  }

  auto one_iter = values.begin();
  auto one_end_iter = values.end();
  auto two_iter = other->values.begin();
  for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
    const std::unique_ptr<Item>& a = *one_iter;
    const std::unique_ptr<Item>& b = *two_iter;
    if (a != nullptr && b != nullptr) {
      if (!a->Equals(b.get())) {
        return false;
      }
    } else if (a != b) {
      return false;
    }
  }
  return true;
}

Plural* Plural::Clone(StringPool* new_pool) const {
  Plural* p = new Plural();
  p->comment_ = comment_;
  p->source_ = source_;
  const size_t count = values.size();
  for (size_t i = 0; i < count; i++) {
    if (values[i]) {
      p->values[i] = std::unique_ptr<Item>(values[i]->Clone(new_pool));
    }
  }
  return p;
}

void Plural::Print(std::ostream* out) const {
  *out << "(plural)";
  if (values[Zero]) {
    *out << " zero=" << *values[Zero];
  }

  if (values[One]) {
    *out << " one=" << *values[One];
  }

  if (values[Two]) {
    *out << " two=" << *values[Two];
  }

  if (values[Few]) {
    *out << " few=" << *values[Few];
  }

  if (values[Many]) {
    *out << " many=" << *values[Many];
  }

  if (values[Other]) {
    *out << " other=" << *values[Other];
  }
}

static ::std::ostream& operator<<(::std::ostream& out,
                                  const std::unique_ptr<Item>& item) {
  return out << *item;
}

bool Styleable::Equals(const Value* value) const {
  const Styleable* other = ValueCast<Styleable>(value);
  if (!other) {
    return false;
  }

  if (entries.size() != other->entries.size()) {
    return false;
  }

  return std::equal(entries.begin(), entries.end(), other->entries.begin(),
                    [](const Reference& a, const Reference& b) -> bool {
                      return a.Equals(&b);
                    });
}

Styleable* Styleable::Clone(StringPool* /*new_pool*/) const {
  return new Styleable(*this);
}

void Styleable::Print(std::ostream* out) const {
  *out << "(styleable) "
       << " [" << util::Joiner(entries, ", ") << "]";
}

bool operator<(const Reference& a, const Reference& b) {
  int cmp = a.name.value_or_default({}).compare(b.name.value_or_default({}));
  if (cmp != 0) return cmp < 0;
  return a.id < b.id;
}

bool operator==(const Reference& a, const Reference& b) {
  return a.name == b.name && a.id == b.id;
}

bool operator!=(const Reference& a, const Reference& b) {
  return a.name != b.name || a.id != b.id;
}

struct NameOnlyComparator {
  bool operator()(const Reference& a, const Reference& b) const {
    return a.name < b.name;
  }
};

void Styleable::MergeWith(Styleable* other) {
  // Compare only names, because some References may already have their IDs
  // assigned
  // (framework IDs that don't change).
  std::set<Reference, NameOnlyComparator> references;
  references.insert(entries.begin(), entries.end());
  references.insert(other->entries.begin(), other->entries.end());
  entries.clear();
  entries.reserve(references.size());
  entries.insert(entries.end(), references.begin(), references.end());
}

}  // namespace aapt
