/*
 * 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 "ResourceTable.h"

#include <algorithm>
#include <memory>
#include <optional>
#include <tuple>

#include "android-base/logging.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"

#include "NameMangler.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
#include "text/Unicode.h"
#include "trace/TraceBuffer.h"
#include "util/Util.h"

using ::aapt::text::IsValidResourceEntryName;
using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::base::StringPrintf;

namespace aapt {

const char* Overlayable::kActorScheme = "overlay";

namespace {
bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs,
                    const ResourceNamedTypeRef& rhs) {
  return lhs->named_type < rhs;
}

template <typename T>
bool less_than_struct_with_name(const std::unique_ptr<T>& lhs, StringPiece rhs) {
  return lhs->name < rhs;
}

template <typename T>
bool greater_than_struct_with_name(StringPiece lhs, const std::unique_ptr<T>& rhs) {
  return rhs->name > lhs;
}

template <typename T>
struct NameEqualRange {
  bool operator()(const std::unique_ptr<T>& lhs, StringPiece rhs) const {
    return less_than_struct_with_name(lhs, rhs);
  }
  bool operator()(StringPiece lhs, const std::unique_ptr<T>& rhs) const {
    return greater_than_struct_with_name(lhs, rhs);
  }
};

template <typename T, typename U>
bool less_than_struct_with_name_and_id(const T& lhs,
                                       const std::pair<std::string_view, std::optional<U>>& rhs) {
  if (lhs.id != rhs.second) {
    return lhs.id < rhs.second;
  }
  return lhs.name < rhs.first;
}

template <typename T, typename Func, typename Elements>
T* FindElementsRunAction(android::StringPiece name, Elements& entries, Func action) {
  const auto iter =
      std::lower_bound(entries.begin(), entries.end(), name, less_than_struct_with_name<T>);
  const bool found = iter != entries.end() && name == (*iter)->name;
  return action(found, iter);
}

struct ConfigKey {
  const ConfigDescription* config;
  StringPiece product;
};

struct lt_config_key_ref {
  template <typename T>
  bool operator()(const T& lhs, const ConfigKey& rhs) const noexcept {
    int cmp = lhs->config.compare(*rhs.config);
    if (cmp == 0) {
      cmp = lhs->product.compare(rhs.product);
    }
    return cmp < 0;
  }
};

struct ConfigFlagKey {
  const ConfigDescription* config;
  StringPiece product;
  const FeatureFlagAttribute& flag;
};

struct lt_config_flag_key_ref {
  template <typename T>
  bool operator()(const T& lhs, const ConfigFlagKey& rhs) const noexcept {
    return std::tie(lhs->config, lhs->product, lhs->value->GetFlag()->name,
                    lhs->value->GetFlag()->negated) <
           std::tie(*rhs.config, rhs.product, rhs.flag.name, rhs.flag.negated);
  }
};

}  // namespace

ResourceTable::ResourceTable(ResourceTable::Validation validation) : validation_(validation) {
}

ResourceTablePackage* ResourceTable::FindPackage(android::StringPiece name) const {
  return FindElementsRunAction<ResourceTablePackage>(
      name, packages, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
}

ResourceTablePackage* ResourceTable::FindOrCreatePackage(android::StringPiece name) {
  return FindElementsRunAction<ResourceTablePackage>(name, packages, [&](bool found, auto& iter) {
    return found ? iter->get() : packages.emplace(iter, new ResourceTablePackage(name))->get();
  });
}

template <typename Func, typename Elements>
static ResourceTableType* FindTypeRunAction(const ResourceNamedTypeRef& type, Elements& entries,
                                            Func action) {
  const auto iter = std::lower_bound(entries.begin(), entries.end(), type, less_than_type);
  const bool found = iter != entries.end() && type == (*iter)->named_type;
  return action(found, iter);
}

ResourceTableType* ResourceTablePackage::FindTypeWithDefaultName(const ResourceType type) const {
  auto named_type = ResourceNamedTypeWithDefaultName(type);
  return FindType(named_type);
}

ResourceTableType* ResourceTablePackage::FindType(const ResourceNamedTypeRef& type) const {
  return FindTypeRunAction(type, types,
                           [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
}

ResourceTableType* ResourceTablePackage::FindOrCreateType(const ResourceNamedTypeRef& type) {
  return FindTypeRunAction(type, types, [&](bool found, auto& iter) {
    return found ? iter->get() : types.emplace(iter, new ResourceTableType(type))->get();
  });
}

ResourceEntry* ResourceTableType::CreateEntry(android::StringPiece name) {
  return FindElementsRunAction<ResourceEntry>(name, entries, [&](bool found, auto& iter) {
    return entries.emplace(iter, new ResourceEntry(name))->get();
  });
}

ResourceEntry* ResourceTableType::FindEntry(android::StringPiece name) const {
  return FindElementsRunAction<ResourceEntry>(
      name, entries, [&](bool found, auto& iter) { return found ? iter->get() : nullptr; });
}

ResourceEntry* ResourceTableType::FindOrCreateEntry(android::StringPiece name) {
  return FindElementsRunAction<ResourceEntry>(name, entries, [&](bool found, auto& iter) {
    return found ? iter->get() : entries.emplace(iter, new ResourceEntry(name))->get();
  });
}

ResourceConfigValue* ResourceEntry::FindValue(const ConfigDescription& config,
                                              android::StringPiece product) {
  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
                               lt_config_key_ref());
  if (iter != values.end()) {
    ResourceConfigValue* value = iter->get();
    if (value->config == config && value->product == product) {
      return value;
    }
  }
  return nullptr;
}

const ResourceConfigValue* ResourceEntry::FindValue(const android::ConfigDescription& config,
                                                    android::StringPiece product) const {
  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
                               lt_config_key_ref());
  if (iter != values.end()) {
    ResourceConfigValue* value = iter->get();
    if (value->config == config && value->product == product) {
      return value;
    }
  }
  return nullptr;
}

ResourceConfigValue* ResourceEntry::FindOrCreateValue(const ConfigDescription& config,
                                                      StringPiece product) {
  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
                               lt_config_key_ref());
  if (iter != values.end()) {
    ResourceConfigValue* value = iter->get();
    if (value->config == config && value->product == product) {
      return value;
    }
  }
  ResourceConfigValue* newValue =
      values.insert(iter, util::make_unique<ResourceConfigValue>(config, product))->get();
  return newValue;
}

std::vector<ResourceConfigValue*> ResourceEntry::FindAllValues(const ConfigDescription& config) {
  std::vector<ResourceConfigValue*> results;
  auto iter =
      std::lower_bound(values.begin(), values.end(), ConfigKey{&config, ""}, lt_config_key_ref());
  for (; iter != values.end(); ++iter) {
    ResourceConfigValue* value = iter->get();
    if (value->config != config) {
      break;
    }
    results.push_back(value);
  }
  return results;
}

ResourceConfigValue* FindOrPossiblyCreateFlaggedValue(
    std::vector<std::unique_ptr<ResourceConfigValue>>& values, const FeatureFlagAttribute& flag,
    const android::ConfigDescription& config, android::StringPiece product, bool create) {
  auto iter = std::lower_bound(values.begin(), values.end(), ConfigFlagKey{&config, product, flag},
                               lt_config_flag_key_ref());
  if (iter != values.end()) {
    ResourceConfigValue* value = iter->get();
    const auto value_flag = value->value->GetFlag().value();
    if (value_flag.name == flag.name && value_flag.negated == flag.negated &&
        value->config == config && value->product == product) {
      return value;
    }
  }
  if (create) {
    return values.insert(iter, util::make_unique<ResourceConfigValue>(config, product))->get();
  } else {
    return nullptr;
  }
}

ResourceConfigValue* ResourceEntry::FindOrCreateFlagDisabledValue(
    const FeatureFlagAttribute& flag, const android::ConfigDescription& config,
    android::StringPiece product) {
  return FindOrPossiblyCreateFlaggedValue(flag_disabled_values, flag, config, product, true);
}

ResourceConfigValue* ResourceEntry::FindOrCreateReadWriteFlagValue(
    const FeatureFlagAttribute& flag, const android::ConfigDescription& config,
    android::StringPiece product) {
  auto* value =
      FindOrPossiblyCreateFlaggedValue(readwrite_flag_values, flag, config, product, true);
  value->uses_readwrite_feature_flags = true;
  return value;
}

ResourceConfigValue* ResourceEntry::FindFlagDisabledValue(const FeatureFlagAttribute& flag,
                                                          const android::ConfigDescription& config,
                                                          android::StringPiece product) {
  return FindOrPossiblyCreateFlaggedValue(flag_disabled_values, flag, config, product, false);
}

ResourceConfigValue* ResourceEntry::FindReadWriteFlagValue(const aapt::FeatureFlagAttribute& flag,
                                                           const android::ConfigDescription& config,
                                                           android::StringPiece product) {
  return FindOrPossiblyCreateFlaggedValue(readwrite_flag_values, flag, config, product, false);
}

bool ResourceEntry::HasDefaultValue() const {
  // The default config should be at the top of the list, since the list is sorted.
  return !values.empty() && values.front()->config == ConfigDescription::DefaultConfig();
}

ResourceTable::CollisionResult ResourceTable::ResolveFlagCollision(FlagStatus existing,
                                                                   FlagStatus incoming) {
  switch (existing) {
    case FlagStatus::NoFlag:
      switch (incoming) {
        case FlagStatus::NoFlag:
          return CollisionResult::kConflict;
        case FlagStatus::Disabled:
          return CollisionResult::kKeepOriginal;
        case FlagStatus::Enabled:
          return CollisionResult::kTakeNew;
        case FlagStatus::RWFlag:
          return CollisionResult::kKeepOriginal;
        default:
          return CollisionResult::kConflict;
      }
    case FlagStatus::Disabled:
      switch (incoming) {
        case FlagStatus::NoFlag:
          return CollisionResult::kTakeNew;
        case FlagStatus::Disabled:
          return CollisionResult::kConflict;
        case FlagStatus::Enabled:
          return CollisionResult::kTakeNew;
        case FlagStatus::RWFlag:
          return CollisionResult::kTakeNew;
        default:
          return CollisionResult::kConflict;
      }
    case FlagStatus::Enabled:
      switch (incoming) {
        case FlagStatus::NoFlag:
          return CollisionResult::kKeepOriginal;
        case FlagStatus::Disabled:
          return CollisionResult::kKeepOriginal;
        case FlagStatus::Enabled:
          return CollisionResult::kConflict;
        case FlagStatus::RWFlag:
          return CollisionResult::kKeepOriginal;
        default:
          return CollisionResult::kConflict;
      }
    case FlagStatus::RWFlag:
      switch (incoming) {
        case FlagStatus::NoFlag:
          return CollisionResult::kTakeNew;
        case FlagStatus::Disabled:
          return CollisionResult::kKeepOriginal;
        case FlagStatus::Enabled:
          return CollisionResult::kTakeNew;
        case FlagStatus::RWFlag:
          return CollisionResult::kKeepOriginal;
        default:
          return CollisionResult::kConflict;
      }

    default:
      return CollisionResult::kConflict;
  }
}

// The default handler for collisions.
//
// Typically, a weak value will be overridden by a strong value. An existing weak
// value will not be overridden by an incoming weak value.
//
// There are some exceptions:
//
// Attributes: There are two types of Attribute values: USE and DECL.
//
// USE is anywhere an Attribute is declared without a format, and in a place that would
// be legal to declare if the Attribute already existed. This is typically in a
// <declare-styleable> tag. Attributes defined in a <declare-styleable> are also weak.
//
// DECL is an absolute declaration of an Attribute and specifies an explicit format.
//
// A DECL will override a USE without error. Two DECLs must match in their format for there to be
// no error.
ResourceTable::CollisionResult ResourceTable::ResolveValueCollision(Value* existing,
                                                                    Value* incoming) {
  Attribute* existing_attr = ValueCast<Attribute>(existing);
  Attribute* incoming_attr = ValueCast<Attribute>(incoming);
  if (!incoming_attr) {
    if (incoming->IsWeak()) {
      // We're trying to add a weak resource but a resource
      // already exists. Keep the existing.
      return CollisionResult::kKeepOriginal;
    } else if (existing->IsWeak()) {
      // Override the weak resource with the new strong resource.
      return CollisionResult::kTakeNew;
    }
    // The existing and incoming values are strong, this is an error
    // if the values are not both attributes.
    return CollisionResult::kConflict;
  }

  if (!existing_attr) {
    if (existing->IsWeak()) {
      // The existing value is not an attribute and it is weak,
      // so take the incoming attribute value.
      return CollisionResult::kTakeNew;
    }
    // The existing value is not an attribute and it is strong,
    // so the incoming attribute value is an error.
    return CollisionResult::kConflict;
  }

  CHECK(incoming_attr != nullptr && existing_attr != nullptr);

  //
  // Attribute specific handling. At this point we know both
  // values are attributes. Since we can declare and define
  // attributes all-over, we do special handling to see
  // which definition sticks.
  //
  if (existing_attr->IsCompatibleWith(*incoming_attr)) {
    // The two attributes are both DECLs, but they are plain attributes with compatible formats.
    // Keep the strongest one.
    return existing_attr->IsWeak() ? CollisionResult::kTakeNew : CollisionResult::kKeepOriginal;
  }

  if (existing_attr->IsWeak() && existing_attr->type_mask == android::ResTable_map::TYPE_ANY) {
    // Any incoming attribute is better than this.
    return CollisionResult::kTakeNew;
  }

  if (incoming_attr->IsWeak() && incoming_attr->type_mask == android::ResTable_map::TYPE_ANY) {
    // The incoming attribute may be a USE instead of a DECL.
    // Keep the existing attribute.
    return CollisionResult::kKeepOriginal;
  }

  return CollisionResult::kConflict;
}

namespace {
template <typename T, typename Comparer>
struct SortedVectorInserter : public Comparer {
  std::pair<bool, typename std::vector<T>::iterator> LowerBound(std::vector<T>& el,
                                                                const T& value) {
    auto it = std::lower_bound(el.begin(), el.end(), value, [&](auto& lhs, auto& rhs) {
      return Comparer::operator()(lhs, rhs);
    });
    bool found =
        it != el.end() && !Comparer::operator()(*it, value) && !Comparer::operator()(value, *it);
    return std::make_pair(found, it);
  }

  T* Insert(std::vector<T>& el, T&& value) {
    auto [found, it] = LowerBound(el, value);
    if (found) {
      return &*it;
    }
    return &*el.insert(it, std::move(value));
  }
};

struct PackageViewComparer {
  bool operator()(const ResourceTablePackageView& lhs, const ResourceTablePackageView& rhs) {
    return less_than_struct_with_name_and_id<ResourceTablePackageView, uint8_t>(
        lhs, std::tie(rhs.name, rhs.id));
  }
};

struct TypeViewComparer {
  bool operator()(const ResourceTableTypeView& lhs, const ResourceTableTypeView& rhs) {
    return lhs.id != rhs.id ? lhs.id < rhs.id : lhs.named_type < rhs.named_type;
  }
};

struct EntryViewComparer {
  bool operator()(const ResourceTableEntryView& lhs, const ResourceTableEntryView& rhs) {
    return less_than_struct_with_name_and_id<ResourceTableEntryView, uint16_t>(
        lhs, std::tie(rhs.name, rhs.id));
  }
};

void InsertEntryIntoTableView(
    ResourceTableView& table, const ResourceTablePackage* package, const ResourceTableType* type,
    const std::string& entry_name, const std::optional<ResourceId>& id,
    const Visibility& visibility, const std::optional<AllowNew>& allow_new,
    const std::optional<OverlayableItem>& overlayable_item,
    const std::optional<StagedId>& staged_id,
    const std::vector<std::unique_ptr<ResourceConfigValue>>& values,
    const std::vector<std::unique_ptr<ResourceConfigValue>>& flag_disabled_values,
    const std::vector<std::unique_ptr<ResourceConfigValue>>& readwrite_flag_values) {
  SortedVectorInserter<ResourceTablePackageView, PackageViewComparer> package_inserter;
  SortedVectorInserter<ResourceTableTypeView, TypeViewComparer> type_inserter;
  SortedVectorInserter<ResourceTableEntryView, EntryViewComparer> entry_inserter;

  ResourceTablePackageView new_package{package->name,
                                       id ? id.value().package_id() : std::optional<uint8_t>{}};
  auto view_package = package_inserter.Insert(table.packages, std::move(new_package));

  ResourceTableTypeView new_type{type->named_type,
                                 id ? id.value().type_id() : std::optional<uint8_t>{}};
  auto view_type = type_inserter.Insert(view_package->types, std::move(new_type));

  if (visibility.level == Visibility::Level::kPublic) {
    // Only mark the type visibility level as public, it doesn't care about being private.
    view_type->visibility_level = Visibility::Level::kPublic;
  }

  ResourceTableEntryView new_entry{.name = entry_name,
                                   .id = id ? id.value().entry_id() : std::optional<uint16_t>{},
                                   .visibility = visibility,
                                   .allow_new = allow_new,
                                   .overlayable_item = overlayable_item,
                                   .staged_id = staged_id};
  for (auto& value : values) {
    new_entry.values.emplace_back(value.get());
  }
  for (auto& value : flag_disabled_values) {
    new_entry.flag_disabled_values.emplace_back(value.get());
  }
  for (auto& value : readwrite_flag_values) {
    new_entry.readwrite_flag_values.emplace_back(value.get());
  }

  entry_inserter.Insert(view_type->entries, std::move(new_entry));
}
}  // namespace

const ResourceConfigValue* ResourceTableEntryView::FindValue(const ConfigDescription& config,
                                                             android::StringPiece product) const {
  auto iter = std::lower_bound(values.begin(), values.end(), ConfigKey{&config, product},
                               lt_config_key_ref());
  if (iter != values.end()) {
    const ResourceConfigValue* value = *iter;
    if (value->config == config && value->product == product) {
      return value;
    }
  }
  return nullptr;
}

const ResourceConfigValue* ResourceTableEntryView::FindFlagDisabledValue(
    const FeatureFlagAttribute& flag, const ConfigDescription& config,
    android::StringPiece product) const {
  auto iter = std::lower_bound(flag_disabled_values.begin(), flag_disabled_values.end(),
                               ConfigFlagKey{&config, product, flag}, lt_config_flag_key_ref());
  if (iter != values.end()) {
    const ResourceConfigValue* value = *iter;
    if (value->value->GetFlag() == flag && value->config == config &&
        StringPiece(value->product) == product) {
      return value;
    }
  }
  return nullptr;
}

const ResourceConfigValue* ResourceTableEntryView::FindReadWriteFlagValue(
    const FeatureFlagAttribute& flag, const ConfigDescription& config,
    android::StringPiece product) const {
  auto iter = std::lower_bound(readwrite_flag_values.begin(), readwrite_flag_values.end(),
                               ConfigFlagKey{&config, product, flag}, lt_config_flag_key_ref());
  if (iter != values.end()) {
    const ResourceConfigValue* value = *iter;
    if (value->value->GetFlag() == flag && value->config == config &&
        StringPiece(value->product) == product) {
      return value;
    }
  }
  return nullptr;
}

ResourceTableView ResourceTable::GetPartitionedView(const ResourceTableViewOptions& options) const {
  ResourceTableView view;
  for (const auto& package : packages) {
    for (const auto& type : package->types) {
      for (const auto& entry : type->entries) {
        InsertEntryIntoTableView(view, package.get(), type.get(), entry->name, entry->id,
                                 entry->visibility, entry->allow_new, entry->overlayable_item,
                                 entry->staged_id, entry->values, entry->flag_disabled_values,
                                 entry->readwrite_flag_values);

        if (options.create_alias_entries && entry->staged_id) {
          auto alias_id = entry->staged_id.value().id;
          InsertEntryIntoTableView(view, package.get(), type.get(), entry->name, alias_id,
                                   entry->visibility, entry->allow_new, entry->overlayable_item, {},
                                   entry->values, entry->flag_disabled_values,
                                   entry->readwrite_flag_values);
        }
      }
    }
  }

  // The android runtime does not support querying resources when the there are multiple type ids
  // for the same resource type within the same package. For this reason, if there are types with
  // multiple type ids, each type needs to exist in its own package in order to be queried by name.
  std::vector<ResourceTablePackageView> new_packages;
  SortedVectorInserter<ResourceTablePackageView, PackageViewComparer> package_inserter;
  SortedVectorInserter<ResourceTableTypeView, TypeViewComparer> type_inserter;
  for (auto& package : view.packages) {
    // If a new package was already created for a different type within this package, then
    // we can reuse those packages for other types that need to be extracted from this package.
    // `start_index` is the index of the first newly created package that can be reused.
    const size_t start_index = new_packages.size();
    std::map<ResourceNamedType, size_t> type_new_package_index;
    for (auto type_it = package.types.begin(); type_it != package.types.end();) {
      auto& type = *type_it;
      auto type_index_iter = type_new_package_index.find(type.named_type);
      if (type_index_iter == type_new_package_index.end()) {
        // First occurrence of the resource type in this package. Keep it in this package.
        type_new_package_index.insert(type_index_iter,
                                      std::make_pair(type.named_type, start_index));
        ++type_it;
        continue;
      }

      // The resource type has already been seen for this package, so this type must be extracted to
      // a new separate package.
      const size_t index = type_index_iter->second;
      if (new_packages.size() == index) {
        new_packages.emplace_back(ResourceTablePackageView{package.name, package.id});
      }

      // Move the type into a new package
      auto& other_package = new_packages[index];
      type_new_package_index[type.named_type] = index + 1;
      type_inserter.Insert(other_package.types, std::move(type));
      type_it = package.types.erase(type_it);
    }
  }

  for (auto& new_package : new_packages) {
    // Insert newly created packages after their original packages
    auto [_, it] = package_inserter.LowerBound(view.packages, new_package);
    view.packages.insert(++it, std::move(new_package));
  }

  return view;
}

bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag) {
  CHECK(diag != nullptr) << "Diagnostic pointer is null";

  const bool validate = validation_ == Validation::kEnabled;
  const android::Source source = res.value ? res.value->GetSource() : android::Source{};
  if (validate && !res.allow_mangled && !IsValidResourceEntryName(res.name.entry)) {
    diag->Error(android::DiagMessage(source)
                << "resource '" << res.name << "' has invalid entry name '" << res.name.entry);
    return false;
  }

  if (res.id.has_value() && !res.id->first.is_valid()) {
    diag->Error(android::DiagMessage(source)
                << "trying to add resource '" << res.name << "' with ID " << res.id->first
                << " but that ID is invalid");
    return false;
  }

  auto package = FindOrCreatePackage(res.name.package);
  auto type = package->FindOrCreateType(res.name.type);
  auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), res.name.entry,
                                   NameEqualRange<ResourceEntry>{});
  const size_t entry_count = std::distance(entry_it.first, entry_it.second);

  ResourceEntry* entry;
  if (entry_count == 0) {
    // Adding a new resource
    entry = type->CreateEntry(res.name.entry);
  } else if (entry_count == 1) {
    // Assume that the existing resource is being modified
    entry = entry_it.first->get();
  } else {
    // Multiple resources with the same name exist in the resource table. The only way to
    // distinguish between them is using resource id since each resource should have a unique id.
    CHECK(res.id.has_value()) << "ambiguous modification of resource entry '" << res.name
                              << "' without specifying a resource id.";
    entry = entry_it.first->get();
    for (auto it = entry_it.first; it != entry_it.second; ++it) {
      CHECK((bool)(*it)->id) << "ambiguous modification of resource entry '" << res.name
                             << "' with multiple entries without resource ids";
      if ((*it)->id == res.id->first) {
        entry = it->get();
        break;
      }
    }
  }

  if (res.id.has_value()) {
    if (entry->id && entry->id.value() != res.id->first) {
      if (res.id->second != OnIdConflict::CREATE_ENTRY) {
        diag->Error(android::DiagMessage(source)
                    << "trying to add resource '" << res.name << "' with ID " << res.id->first
                    << " but resource already has ID " << entry->id.value());
        return false;
      }
      entry = type->CreateEntry(res.name.entry);
    }
    entry->id = res.id->first;
  }

  if (res.visibility.has_value()) {
    // Only mark the type visibility level as public, it doesn't care about being private.
    if (res.visibility->level == Visibility::Level::kPublic) {
      type->visibility_level = Visibility::Level::kPublic;
    }

    if (res.visibility->level > entry->visibility.level) {
      // This symbol definition takes precedence, replace.
      entry->visibility = res.visibility.value();
    }

    if (res.visibility->staged_api) {
      entry->visibility.staged_api = entry->visibility.staged_api;
    }
  }

  if (res.overlayable.has_value()) {
    if (entry->overlayable_item) {
      diag->Error(android::DiagMessage(res.overlayable->source)
                  << "duplicate overlayable declaration for resource '" << res.name << "'");
      diag->Error(android::DiagMessage(entry->overlayable_item.value().source)
                  << "previous declaration here");
      return false;
    }
    entry->overlayable_item = res.overlayable.value();
  }

  if (res.allow_new.has_value()) {
    entry->allow_new = res.allow_new.value();
  }

  if (res.staged_id.has_value()) {
    entry->staged_id = res.staged_id.value();
  }

  if (res.value != nullptr && res.value->GetFlagStatus() == FlagStatus::Disabled) {
    auto disabled_config_value =
        entry->FindOrCreateFlagDisabledValue(res.value->GetFlag().value(), res.config, res.product);
    if (!disabled_config_value->value) {
      // Resource does not exist, add it now.
      // Must clone the value since it might be in the values vector as well
      CloningValueTransformer cloner(&string_pool);
      disabled_config_value->value = res.value->Transform(cloner);
    } else {
      diag->Error(android::DiagMessage(source)
                  << "duplicate flag disabled value for resource '" << res.name << "' with config '"
                  << res.config << "' and flag '"
                  << (res.value->GetFlag().value().negated ? "!" : "")
                  << res.value->GetFlag().value().name << "'");
      diag->Error(android::DiagMessage(source) << "resource previously defined here");
      return false;
    }
  }

  if (res.value != nullptr && res.value->GetFlagStatus() == FlagStatus::RWFlag) {
    auto flagged_config_value = entry->FindOrCreateReadWriteFlagValue(res.value->GetFlag().value(),
                                                                      res.config, res.product);

    if (!flagged_config_value->value) {
      // Resource does not exist, add it now.
      // Must clone the value since it might be in the values vector as well
      CloningValueTransformer cloner(&string_pool);
      flagged_config_value->value = res.value->Transform(cloner);
    } else {
      diag->Error(android::DiagMessage(source)
                  << "duplicate r/w flag value for resource '" << res.name << "' with config '"
                  << res.config << "' and flag '"
                  << (res.value->GetFlag().value().negated ? "!" : "")
                  << res.value->GetFlag().value().name << "'");
      diag->Error(android::DiagMessage(source) << "resource previously defined here");
      return false;
    }
  }

  if (res.value != nullptr) {
    auto config_value = entry->FindOrCreateValue(res.config, res.product);
    if (!config_value->value) {
      // Resource does not exist, add it now.
      config_value->value = std::move(res.value);
      config_value->uses_readwrite_feature_flags = res.uses_readwrite_feature_flags;
    } else {
      // Always resolve flag collisions, even when validation is disabled, to ensure the correct
      // value is selected based on flag status.
      auto result =
          ResolveFlagCollision(config_value->value->GetFlagStatus(), res.value->GetFlagStatus());
      if (result == CollisionResult::kConflict) {
        // If there's still a conflict, resolve value collisions only when validation is enabled.
        result = validate ? ResolveValueCollision(config_value->value.get(), res.value.get())
                          : CollisionResult::kKeepBoth;
      }
      switch (result) {
        case CollisionResult::kKeepBoth: {
          // Insert the value ignoring for duplicate configurations
          auto it = entry->values.insert(
              std::lower_bound(entry->values.begin(), entry->values.end(),
                               ConfigKey{&res.config, res.product}, lt_config_key_ref()),
              util::make_unique<ResourceConfigValue>(res.config, res.product));
          (*it)->value = std::move(res.value);
          (*it)->uses_readwrite_feature_flags = res.uses_readwrite_feature_flags;
          break;
        }

        case CollisionResult::kTakeNew:
          // Take the incoming value.
          config_value->value = std::move(res.value);
          config_value->uses_readwrite_feature_flags = res.uses_readwrite_feature_flags;
          break;

        case CollisionResult::kConflict:
          diag->Error(android::DiagMessage(source)
                      << "duplicate value for resource '" << res.name << "' "
                      << "with config '" << res.config << "'");
          diag->Error(android::DiagMessage(source) << "resource previously defined here");
          return false;

        case CollisionResult::kKeepOriginal:
          break;
      }
    }
  }

  return true;
}

std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(
    const ResourceNameRef& name) const {
  ResourceTablePackage* package = FindPackage(name.package);
  if (package == nullptr) {
    return {};
  }

  ResourceTableType* type = package->FindType(name.type);
  if (type == nullptr) {
    return {};
  }

  ResourceEntry* entry = type->FindEntry(name.entry);
  if (entry == nullptr) {
    return {};
  }
  return SearchResult{package, type, entry};
}

std::optional<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNameRef& name,
                                                                       ResourceId id) const {
  ResourceTablePackage* package = FindPackage(name.package);
  if (package == nullptr) {
    return {};
  }

  ResourceTableType* type = package->FindType(name.type);
  if (type == nullptr) {
    return {};
  }

  auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), name.entry,
                                   NameEqualRange<ResourceEntry>{});
  for (auto it = entry_it.first; it != entry_it.second; ++it) {
    if ((*it)->id == id) {
      return SearchResult{package, type, it->get()};
    }
  }
  return {};
}

bool ResourceTable::RemoveResource(const ResourceNameRef& name, ResourceId id) const {
  ResourceTablePackage* package = FindPackage(name.package);
  if (package == nullptr) {
    return {};
  }

  ResourceTableType* type = package->FindType(name.type);
  if (type == nullptr) {
    return {};
  }

  auto entry_it = std::equal_range(type->entries.begin(), type->entries.end(), name.entry,
                                   NameEqualRange<ResourceEntry>{});
  for (auto it = entry_it.first; it != entry_it.second; ++it) {
    if ((*it)->id == id) {
      type->entries.erase(it);
      return true;
    }
  }
  return false;
}

std::unique_ptr<ResourceTable> ResourceTable::Clone() const {
  std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>();
  CloningValueTransformer cloner(&new_table->string_pool);
  for (const auto& pkg : packages) {
    ResourceTablePackage* new_pkg = new_table->FindOrCreatePackage(pkg->name);
    for (const auto& type : pkg->types) {
      ResourceTableType* new_type = new_pkg->FindOrCreateType(type->named_type);
      new_type->visibility_level = type->visibility_level;

      for (const auto& entry : type->entries) {
        ResourceEntry* new_entry = new_type->CreateEntry(entry->name);
        new_entry->id = entry->id;
        new_entry->visibility = entry->visibility;
        new_entry->allow_new = entry->allow_new;
        new_entry->overlayable_item = entry->overlayable_item;

        for (const auto& config_value : entry->values) {
          ResourceConfigValue* new_value =
              new_entry->FindOrCreateValue(config_value->config, config_value->product);
          new_value->value = config_value->value->Transform(cloner);
        }
      }
    }
  }
  return new_table;
}

NewResourceBuilder::NewResourceBuilder(const ResourceNameRef& name) {
  res_.name = name.ToResourceName();
}

NewResourceBuilder::NewResourceBuilder(const std::string& name) {
  ResourceNameRef ref;
  CHECK(ResourceUtils::ParseResourceName(name, &ref)) << "invalid resource name: " << name;
  res_.name = ref.ToResourceName();
}

NewResourceBuilder& NewResourceBuilder::SetValue(std::unique_ptr<Value> value,
                                                 android::ConfigDescription config,
                                                 std::string product) {
  res_.value = std::move(value);
  res_.config = std::move(config);
  res_.product = std::move(product);
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetId(ResourceId id, OnIdConflict on_conflict) {
  res_.id = std::make_pair(id, on_conflict);
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetVisibility(Visibility visibility) {
  res_.visibility = std::move(visibility);
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetOverlayable(OverlayableItem overlayable) {
  res_.overlayable = std::move(overlayable);
  return *this;
}
NewResourceBuilder& NewResourceBuilder::SetAllowNew(AllowNew allow_new) {
  res_.allow_new = std::move(allow_new);
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetStagedId(StagedId staged_alias) {
  res_.staged_id = std::move(staged_alias);
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetAllowMangled(bool allow_mangled) {
  res_.allow_mangled = allow_mangled;
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetUsesReadWriteFeatureFlags(
    bool uses_readwrite_feature_flags) {
  res_.uses_readwrite_feature_flags = uses_readwrite_feature_flags;
  return *this;
}

NewResource NewResourceBuilder::Build() {
  return std::move(res_);
}

}  // namespace aapt
