/*
 * Copyright (C) 2017 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 "configuration/ConfigurationParser.h"

#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <utility>

#include "ResourceUtils.h"
#include "android-base/file.h"
#include "android-base/logging.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/IDiagnostics.h"
#include "configuration/ConfigurationParser.internal.h"
#include "io/File.h"
#include "io/FileSystem.h"
#include "io/StringStream.h"
#include "util/Files.h"
#include "util/Util.h"
#include "xml/XmlActionExecutor.h"
#include "xml/XmlDom.h"
#include "xml/XmlUtil.h"

using ::android::ConfigDescription;

namespace aapt {

namespace {

using ::aapt::configuration::Abi;
using ::aapt::configuration::AndroidManifest;
using ::aapt::configuration::AndroidSdk;
using ::aapt::configuration::ConfiguredArtifact;
using ::aapt::configuration::DeviceFeature;
using ::aapt::configuration::Entry;
using ::aapt::configuration::ExtractConfiguration;
using ::aapt::configuration::GlTexture;
using ::aapt::configuration::Group;
using ::aapt::configuration::Locale;
using ::aapt::configuration::OrderedEntry;
using ::aapt::configuration::OutputArtifact;
using ::aapt::configuration::PostProcessingConfiguration;
using ::aapt::configuration::handler::AbiGroupTagHandler;
using ::aapt::configuration::handler::AndroidSdkTagHandler;
using ::aapt::configuration::handler::ArtifactFormatTagHandler;
using ::aapt::configuration::handler::ArtifactTagHandler;
using ::aapt::configuration::handler::DeviceFeatureGroupTagHandler;
using ::aapt::configuration::handler::GlTextureGroupTagHandler;
using ::aapt::configuration::handler::LocaleGroupTagHandler;
using ::aapt::configuration::handler::ScreenDensityGroupTagHandler;
using ::aapt::io::IFile;
using ::aapt::io::RegularFile;
using ::aapt::io::StringInputStream;
using ::aapt::util::TrimWhitespace;
using ::aapt::xml::Element;
using ::aapt::xml::NodeCast;
using ::aapt::xml::XmlActionExecutor;
using ::aapt::xml::XmlActionExecutorPolicy;
using ::aapt::xml::XmlNodeAction;
using ::android::StringPiece;
using ::android::base::ReadFileToString;

const std::unordered_map<StringPiece, Abi> kStringToAbiMap = {
    {"armeabi", Abi::kArmeV6}, {"armeabi-v7a", Abi::kArmV7a},  {"arm64-v8a", Abi::kArm64V8a},
    {"x86", Abi::kX86},        {"x86_64", Abi::kX86_64},       {"mips", Abi::kMips},
    {"mips64", Abi::kMips64},  {"universal", Abi::kUniversal},
};
const std::array<StringPiece, 8> kAbiToStringMap = {
    {"armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64", "mips", "mips64", "universal"}};

constexpr const char* kAaptXmlNs = "http://schemas.android.com/tools/aapt";

android::NoOpDiagnostics noop_;

/** Returns the value of the label attribute for a given element. */
std::string GetLabel(const Element* element, android::IDiagnostics* diag) {
  std::string label;
  for (const auto& attr : element->attributes) {
    if (attr.name == "label") {
      label = attr.value;
      break;
    }
  }

  if (label.empty()) {
    diag->Error(android::DiagMessage() << "No label found for element " << element->name);
  }
  return label;
}

/** Returns the value of the version-code-order attribute for a given element. */
std::optional<int32_t> GetVersionCodeOrder(const Element* element, android::IDiagnostics* diag) {
  const xml::Attribute* version = element->FindAttribute("", "version-code-order");
  if (version == nullptr) {
    std::string label = GetLabel(element, diag);
    diag->Error(android::DiagMessage() << "No version-code-order found for element '"
                                       << element->name << "' with label '" << label << "'");
    return {};
  }
  return std::stoi(version->value);
}

/** XML node visitor that removes all of the namespace URIs from the node and all children. */
class NamespaceVisitor : public xml::Visitor {
 public:
  void Visit(xml::Element* node) override {
    node->namespace_uri.clear();
    VisitChildren(node);
  }
};

/** Copies the values referenced in a configuration group to the target list. */
template <typename T>
bool CopyXmlReferences(const std::optional<std::string>& name, const Group<T>& groups,
                       std::vector<T>* target) {
  // If there was no item configured, there is nothing to do and no error.
  if (!name) {
    return true;
  }

  // If the group could not be found, then something is wrong.
  auto group = groups.find(name.value());
  if (group == groups.end()) {
    return false;
  }

  for (const T& item : group->second.entry) {
    target->push_back(item);
  }
  return true;
}

/**
 * Attempts to replace the placeholder in the name string with the provided value. Returns true on
 * success, or false if the either the placeholder is not found in the name, or the value is not
 * present and the placeholder was.
 */
bool ReplacePlaceholder(StringPiece placeholder, const std::optional<StringPiece>& value,
                        std::string* name, android::IDiagnostics* diag) {
  size_t offset = name->find(placeholder.data());
  bool found = (offset != std::string::npos);

  // Make sure the placeholder was present if the desired value is present.
  if (!found) {
    if (value) {
      diag->Error(android::DiagMessage() << "Missing placeholder for artifact: " << placeholder);
      return false;
    }
    return true;
  }

  DCHECK(found) << "Missing return path for placeholder not found";

  // Make sure the placeholder was not present if the desired value was not present.
  if (!value) {
    diag->Error(android::DiagMessage()
                << "Placeholder present but no value for artifact: " << placeholder);
    return false;
  }

  name->replace(offset, placeholder.length(), value.value().data());

  // Make sure there was only one instance of the placeholder.
  if (name->find(placeholder.data()) != std::string::npos) {
    diag->Error(android::DiagMessage() << "Placeholder present multiple times: " << placeholder);
    return false;
  }
  return true;
}

/**
 * An ActionHandler for processing XML elements in the XmlActionExecutor. Returns true if the
 * element was successfully processed, otherwise returns false.
 */
using ActionHandler = std::function<bool(configuration::PostProcessingConfiguration* config,
                                         xml::Element* element, android::IDiagnostics* diag)>;

/** Binds an ActionHandler to the current configuration being populated. */
xml::XmlNodeAction::ActionFuncWithDiag Bind(configuration::PostProcessingConfiguration* config,
                                            const ActionHandler& handler) {
  return [config, handler](xml::Element* root_element, android::SourcePathDiagnostics* diag) {
    return handler(config, root_element, diag);
  };
}

/** Converts a ConfiguredArtifact into an OutputArtifact. */
std::optional<OutputArtifact> ToOutputArtifact(const ConfiguredArtifact& artifact,
                                               const std::string& apk_name,
                                               const PostProcessingConfiguration& config,
                                               android::IDiagnostics* diag) {
  if (!artifact.name && !config.artifact_format) {
    diag->Error(android::DiagMessage()
                << "Artifact does not have a name and no global name template defined");
    return {};
  }

  std::optional<std::string> artifact_name =
      (artifact.name) ? artifact.Name(apk_name, diag)
                      : artifact.ToArtifactName(config.artifact_format.value(), apk_name, diag);

  if (!artifact_name) {
    diag->Error(android::DiagMessage() << "Could not determine split APK artifact name");
    return {};
  }

  OutputArtifact output_artifact;
  output_artifact.name = artifact_name.value();

  android::SourcePathDiagnostics src_diag{{output_artifact.name}, diag};
  bool has_errors = false;

  if (!CopyXmlReferences(artifact.abi_group, config.abi_groups, &output_artifact.abis)) {
    src_diag.Error(android::DiagMessage()
                   << "Could not lookup required ABIs: " << artifact.abi_group.value());
    has_errors = true;
  }

  if (!CopyXmlReferences(artifact.locale_group, config.locale_groups, &output_artifact.locales)) {
    src_diag.Error(android::DiagMessage()
                   << "Could not lookup required locales: " << artifact.locale_group.value());
    has_errors = true;
  }

  if (!CopyXmlReferences(artifact.screen_density_group, config.screen_density_groups,
                         &output_artifact.screen_densities)) {
    src_diag.Error(android::DiagMessage() << "Could not lookup required screen densities: "
                                          << artifact.screen_density_group.value());
    has_errors = true;
  }

  if (!CopyXmlReferences(artifact.device_feature_group, config.device_feature_groups,
                         &output_artifact.features)) {
    src_diag.Error(android::DiagMessage() << "Could not lookup required device features: "
                                          << artifact.device_feature_group.value());
    has_errors = true;
  }

  if (!CopyXmlReferences(artifact.gl_texture_group, config.gl_texture_groups,
                         &output_artifact.textures)) {
    src_diag.Error(android::DiagMessage() << "Could not lookup required OpenGL texture formats: "
                                          << artifact.gl_texture_group.value());
    has_errors = true;
  }

  if (artifact.android_sdk) {
    auto entry = config.android_sdks.find(artifact.android_sdk.value());
    if (entry == config.android_sdks.end()) {
      src_diag.Error(android::DiagMessage() << "Could not lookup required Android SDK version: "
                                            << artifact.android_sdk.value());
      has_errors = true;
    } else {
      output_artifact.android_sdk = {entry->second};
    }
  }

  if (has_errors) {
    return {};
  }
  return {output_artifact};
}

}  // namespace

namespace configuration {

/** Returns the binary reprasentation of the XML configuration. */
std::optional<PostProcessingConfiguration> ExtractConfiguration(const std::string& contents,
                                                                const std::string& config_path,
                                                                android::IDiagnostics* diag) {
  StringInputStream in(contents);
  std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, diag, android::Source(config_path));
  if (!doc) {
    return {};
  }

  // Strip any namespaces from the XML as the XmlActionExecutor ignores anything with a namespace.
  Element* root = doc->root.get();
  if (root == nullptr) {
    diag->Error(android::DiagMessage() << "Could not find the root element in the XML document");
    return {};
  }

  std::string& xml_ns = root->namespace_uri;
  if (!xml_ns.empty()) {
    if (xml_ns != kAaptXmlNs) {
      diag->Error(android::DiagMessage() << "Unknown namespace found on root element: " << xml_ns);
      return {};
    }

    xml_ns.clear();
    NamespaceVisitor visitor;
    root->Accept(&visitor);
  }

  XmlActionExecutor executor;
  XmlNodeAction& root_action = executor["post-process"];
  XmlNodeAction& artifacts_action = root_action["artifacts"];

  PostProcessingConfiguration config;

  // Parse the artifact elements.
  artifacts_action["artifact"].Action(Bind(&config, ArtifactTagHandler));
  artifacts_action["artifact-format"].Action(Bind(&config, ArtifactFormatTagHandler));

  // Parse the different configuration groups.
  root_action["abi-groups"]["abi-group"].Action(Bind(&config, AbiGroupTagHandler));
  root_action["screen-density-groups"]["screen-density-group"].Action(
      Bind(&config, ScreenDensityGroupTagHandler));
  root_action["locale-groups"]["locale-group"].Action(Bind(&config, LocaleGroupTagHandler));
  root_action["android-sdks"]["android-sdk"].Action(Bind(&config, AndroidSdkTagHandler));
  root_action["gl-texture-groups"]["gl-texture-group"].Action(
      Bind(&config, GlTextureGroupTagHandler));
  root_action["device-feature-groups"]["device-feature-group"].Action(
      Bind(&config, DeviceFeatureGroupTagHandler));

  if (!executor.Execute(XmlActionExecutorPolicy::kNone, diag, doc.get())) {
    diag->Error(android::DiagMessage() << "Could not process XML document");
    return {};
  }

  return {config};
}

StringPiece AbiToString(Abi abi) {
  return kAbiToStringMap.at(static_cast<size_t>(abi));
}

/**
 * Returns the common artifact base name from a template string.
 */
std::optional<std::string> ToBaseName(std::string result, StringPiece apk_name,
                                      android::IDiagnostics* diag) {
  const StringPiece ext = file::GetExtension(apk_name);
  size_t end_index = apk_name.rfind(ext);
  const std::string base_name =
      (end_index != std::string::npos) ? std::string{apk_name.begin(), end_index} : "";

  // Base name is optional.
  if (result.find("${basename}") != std::string::npos) {
    auto maybe_base_name = base_name.empty() ? std::nullopt
                                             : std::optional<StringPiece>{base_name};
    if (!ReplacePlaceholder("${basename}", maybe_base_name, &result, diag)) {
      return {};
    }
  }

  // Extension is optional.
  if (result.find("${ext}") != std::string::npos) {
    // Make sure we disregard the '.' in the extension when replacing the placeholder.
    if (!ReplacePlaceholder("${ext}", {ext.substr(1)}, &result, diag)) {
      return {};
    }
  } else {
    // If no extension is specified, and the name template does not end in the current extension,
    // add the existing extension.
    if (!util::EndsWith(result, ext)) {
      result.append(ext);
    }
  }

  return result;
}

std::optional<std::string> ConfiguredArtifact::ToArtifactName(StringPiece format,
                                                              StringPiece apk_name,
                                                              android::IDiagnostics* diag) const {
  std::optional<std::string> base = ToBaseName(std::string(format), apk_name, diag);
  if (!base) {
    return {};
  }
  std::string result = std::move(base.value());

  if (!ReplacePlaceholder("${abi}", abi_group, &result, diag)) {
    return {};
  }

  if (!ReplacePlaceholder("${density}", screen_density_group, &result, diag)) {
    return {};
  }

  if (!ReplacePlaceholder("${locale}", locale_group, &result, diag)) {
    return {};
  }

  if (!ReplacePlaceholder("${sdk}", android_sdk, &result, diag)) {
    return {};
  }

  if (!ReplacePlaceholder("${feature}", device_feature_group, &result, diag)) {
    return {};
  }

  if (!ReplacePlaceholder("${gl}", gl_texture_group, &result, diag)) {
    return {};
  }

  return result;
}

std::optional<std::string> ConfiguredArtifact::Name(StringPiece apk_name,
                                                    android::IDiagnostics* diag) const {
  if (!name) {
    return {};
  }

  return ToBaseName(name.value(), apk_name, diag);
}

}  // namespace configuration

/** Returns a ConfigurationParser for the file located at the provided path. */
std::optional<ConfigurationParser> ConfigurationParser::ForPath(const std::string& path) {
  std::string contents;
  if (!ReadFileToString(path, &contents, true)) {
    return {};
  }
  return ConfigurationParser(contents, path);
}

ConfigurationParser::ConfigurationParser(std::string contents, const std::string& config_path)
    : contents_(std::move(contents)), config_path_(config_path), diag_(&noop_) {
}

std::optional<std::vector<OutputArtifact>> ConfigurationParser::Parse(
    android::StringPiece apk_path) {
  std::optional<PostProcessingConfiguration> maybe_config =
      ExtractConfiguration(contents_, config_path_, diag_);
  if (!maybe_config) {
    return {};
  }

  // Convert from a parsed configuration to a list of artifacts for processing.
  const std::string apk_name(file::GetFilename(apk_path));
  std::vector<OutputArtifact> output_artifacts;

  PostProcessingConfiguration& config = maybe_config.value();

  bool valid = true;
  int version = 1;

  for (const ConfiguredArtifact& artifact : config.artifacts) {
    std::optional<OutputArtifact> output_artifact =
        ToOutputArtifact(artifact, apk_name, config, diag_);
    if (!output_artifact) {
      // Defer return an error condition so that all errors are reported.
      valid = false;
    } else {
      output_artifact.value().version = version++;
      output_artifacts.push_back(std::move(output_artifact.value()));
    }
  }

  if (!config.ValidateVersionCodeOrdering(diag_)) {
    diag_->Error(android::DiagMessage() << "could not validate post processing configuration");
    valid = false;
  }

  if (valid) {
    // Sorting artifacts requires that all references are valid as it uses them to determine order.
    config.SortArtifacts();
  }

  if (!valid) {
    return {};
  }

  return {output_artifacts};
}

namespace configuration {
namespace handler {

bool ArtifactTagHandler(PostProcessingConfiguration* config, Element* root_element,
                        android::IDiagnostics* diag) {
  ConfiguredArtifact artifact{};
  for (const auto& attr : root_element->attributes) {
    if (attr.name == "name") {
      artifact.name = attr.value;
    } else if (attr.name == "abi-group") {
      artifact.abi_group = {attr.value};
    } else if (attr.name == "screen-density-group") {
      artifact.screen_density_group = {attr.value};
    } else if (attr.name == "locale-group") {
      artifact.locale_group = {attr.value};
    } else if (attr.name == "android-sdk") {
      artifact.android_sdk = {attr.value};
    } else if (attr.name == "gl-texture-group") {
      artifact.gl_texture_group = {attr.value};
    } else if (attr.name == "device-feature-group") {
      artifact.device_feature_group = {attr.value};
    } else {
      diag->Note(android::DiagMessage()
                 << "Unknown artifact attribute: " << attr.name << " = " << attr.value);
    }
  }
  config->artifacts.push_back(artifact);
  return true;
};

bool ArtifactFormatTagHandler(PostProcessingConfiguration* config, Element* root_element,
                              android::IDiagnostics* /* diag */) {
  for (auto& node : root_element->children) {
    xml::Text* t;
    if ((t = NodeCast<xml::Text>(node.get())) != nullptr) {
      config->artifact_format.emplace(TrimWhitespace(t->text));
      break;
    }
  }
  return true;
};

bool AbiGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                        android::IDiagnostics* diag) {
  std::string label = GetLabel(root_element, diag);
  if (label.empty()) {
    return false;
  }

  bool valid = true;
  OrderedEntry<Abi>& entry = config->abi_groups[label];
  std::optional<int32_t> order = GetVersionCodeOrder(root_element, diag);
  if (!order) {
    valid = false;
  } else {
    entry.order = order.value();
  }
  auto& group = entry.entry;

  // Special case for empty abi-group tag. Label will be used as the ABI.
  if (root_element->GetChildElements().empty()) {
    auto abi = kStringToAbiMap.find(label);
    if (abi == kStringToAbiMap.end()) {
      return false;
    }
    group.push_back(abi->second);
    return valid;
  }

  for (auto* child : root_element->GetChildElements()) {
    if (child->name != "abi") {
      diag->Error(android::DiagMessage() << "Unexpected element in ABI group: " << child->name);
      valid = false;
    } else {
      for (auto& node : child->children) {
        xml::Text* t;
        if ((t = NodeCast<xml::Text>(node.get())) != nullptr) {
          auto abi = kStringToAbiMap.find(TrimWhitespace(t->text));
          if (abi != kStringToAbiMap.end()) {
            group.push_back(abi->second);
          } else {
            diag->Error(android::DiagMessage() << "Could not parse ABI value: " << t->text);
            valid = false;
          }
          break;
        }
      }
    }
  }

  return valid;
};

bool ScreenDensityGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                                  android::IDiagnostics* diag) {
  std::string label = GetLabel(root_element, diag);
  if (label.empty()) {
    return false;
  }

  bool valid = true;
  OrderedEntry<ConfigDescription>& entry = config->screen_density_groups[label];
  std::optional<int32_t> order = GetVersionCodeOrder(root_element, diag);
  if (!order) {
    valid = false;
  } else {
    entry.order = order.value();
  }
  auto& group = entry.entry;

  // Special case for empty screen-density-group tag. Label will be used as the screen density.
  if (root_element->GetChildElements().empty()) {
    ConfigDescription config_descriptor;
    bool parsed = ConfigDescription::Parse(label, &config_descriptor);
    if (parsed &&
        (config_descriptor.CopyWithoutSdkVersion().diff(ConfigDescription::DefaultConfig()) ==
            android::ResTable_config::CONFIG_DENSITY)) {
      // Copy the density with the minimum SDK version stripped out.
      group.push_back(config_descriptor.CopyWithoutSdkVersion());
    } else {
      diag->Error(android::DiagMessage()
                  << "Could not parse config descriptor for empty screen-density-group: " << label);
      valid = false;
    }

    return valid;
  }

  for (auto* child : root_element->GetChildElements()) {
    if (child->name != "screen-density") {
      diag->Error(android::DiagMessage()
                  << "Unexpected root_element in screen density group: " << child->name);
      valid = false;
    } else {
      for (auto& node : child->children) {
        xml::Text* t;
        if ((t = NodeCast<xml::Text>(node.get())) != nullptr) {
          ConfigDescription config_descriptor;
          android::StringPiece text = TrimWhitespace(t->text);
          bool parsed = ConfigDescription::Parse(text, &config_descriptor);
          if (parsed &&
              (config_descriptor.CopyWithoutSdkVersion().diff(ConfigDescription::DefaultConfig()) ==
               android::ResTable_config::CONFIG_DENSITY)) {
            // Copy the density with the minimum SDK version stripped out.
            group.push_back(config_descriptor.CopyWithoutSdkVersion());
          } else {
            diag->Error(android::DiagMessage()
                        << "Could not parse config descriptor for screen-density: " << text);
            valid = false;
          }
          break;
        }
      }
    }
  }

  return valid;
};

bool LocaleGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                           android::IDiagnostics* diag) {
  std::string label = GetLabel(root_element, diag);
  if (label.empty()) {
    return false;
  }

  bool valid = true;
  OrderedEntry<ConfigDescription>& entry = config->locale_groups[label];
  std::optional<int32_t> order = GetVersionCodeOrder(root_element, diag);
  if (!order) {
    valid = false;
  } else {
    entry.order = order.value();
  }
  auto& group = entry.entry;

  // Special case to auto insert a locale for an empty group. Label will be used for locale.
  if (root_element->GetChildElements().empty()) {
    ConfigDescription config_descriptor;
    bool parsed = ConfigDescription::Parse(label, &config_descriptor);
    if (parsed &&
        (config_descriptor.CopyWithoutSdkVersion().diff(ConfigDescription::DefaultConfig()) ==
            android::ResTable_config::CONFIG_LOCALE)) {
      // Copy the locale with the minimum SDK version stripped out.
      group.push_back(config_descriptor.CopyWithoutSdkVersion());
    } else {
      diag->Error(android::DiagMessage()
                  << "Could not parse config descriptor for empty screen-density-group: " << label);
      valid = false;
    }

    return valid;
  }

  for (auto* child : root_element->GetChildElements()) {
    if (child->name != "locale") {
      diag->Error(android::DiagMessage()
                  << "Unexpected root_element in screen density group: " << child->name);
      valid = false;
    } else {
      for (auto& node : child->children) {
        xml::Text* t;
        if ((t = NodeCast<xml::Text>(node.get())) != nullptr) {
          ConfigDescription config_descriptor;
          android::StringPiece text = TrimWhitespace(t->text);
          bool parsed = ConfigDescription::Parse(text, &config_descriptor);
          if (parsed &&
              (config_descriptor.CopyWithoutSdkVersion().diff(ConfigDescription::DefaultConfig()) ==
               android::ResTable_config::CONFIG_LOCALE)) {
            // Copy the locale with the minimum SDK version stripped out.
            group.push_back(config_descriptor.CopyWithoutSdkVersion());
          } else {
            diag->Error(android::DiagMessage()
                        << "Could not parse config descriptor for screen-density: " << text);
            valid = false;
          }
          break;
        }
      }
    }
  }

  return valid;
};

bool AndroidSdkTagHandler(PostProcessingConfiguration* config, Element* root_element,
                          android::IDiagnostics* diag) {
  AndroidSdk entry = AndroidSdk::ForMinSdk(-1);
  bool valid = true;
  for (const auto& attr : root_element->attributes) {
    bool valid_attr = false;
    if (attr.name == "label") {
      entry.label = attr.value;
      valid_attr = true;
    } else if (attr.name == "minSdkVersion") {
      std::optional<int> version = ResourceUtils::ParseSdkVersion(attr.value);
      if (version) {
        valid_attr = true;
        entry.min_sdk_version = version.value();
      }
    } else if (attr.name == "targetSdkVersion") {
      std::optional<int> version = ResourceUtils::ParseSdkVersion(attr.value);
      if (version) {
        valid_attr = true;
        entry.target_sdk_version = version;
      }
    } else if (attr.name == "maxSdkVersion") {
      std::optional<int> version = ResourceUtils::ParseSdkVersion(attr.value);
      if (version) {
        valid_attr = true;
        entry.max_sdk_version = version;
      }
    }

    if (!valid_attr) {
      diag->Error(android::DiagMessage()
                  << "Invalid attribute: " << attr.name << " = " << attr.value);
      valid = false;
    }
  }

  if (entry.min_sdk_version == -1) {
    diag->Error(android::DiagMessage() << "android-sdk is missing minSdkVersion attribute");
    valid = false;
  }

  // TODO: Fill in the manifest details when they are finalised.
  for (auto node : root_element->GetChildElements()) {
    if (node->name == "manifest") {
      if (entry.manifest) {
        diag->Warn(android::DiagMessage() << "Found multiple manifest tags. Ignoring duplicates.");
        continue;
      }
      entry.manifest = {AndroidManifest()};
    }
  }

  config->android_sdks[entry.label] = entry;
  return valid;
};

bool GlTextureGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                              android::IDiagnostics* diag) {
  std::string label = GetLabel(root_element, diag);
  if (label.empty()) {
    return false;
  }

  bool valid = true;
  OrderedEntry<GlTexture>& entry = config->gl_texture_groups[label];
  std::optional<int32_t> order = GetVersionCodeOrder(root_element, diag);
  if (!order) {
    valid = false;
  } else {
    entry.order = order.value();
  }
  auto& group = entry.entry;

  GlTexture result;
  for (auto* child : root_element->GetChildElements()) {
    if (child->name != "gl-texture") {
      diag->Error(android::DiagMessage()
                  << "Unexpected element in GL texture group: " << child->name);
      valid = false;
    } else {
      for (const auto& attr : child->attributes) {
        if (attr.name == "name") {
          result.name = attr.value;
          break;
        }
      }

      for (auto* element : child->GetChildElements()) {
        if (element->name != "texture-path") {
          diag->Error(android::DiagMessage()
                      << "Unexpected element in gl-texture element: " << child->name);
          valid = false;
          continue;
        }
        for (auto& node : element->children) {
          xml::Text* t;
          if ((t = NodeCast<xml::Text>(node.get())) != nullptr) {
            result.texture_paths.emplace_back(TrimWhitespace(t->text));
          }
        }
      }
    }
    group.push_back(result);
  }

  return valid;
};

bool DeviceFeatureGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                                  android::IDiagnostics* diag) {
  std::string label = GetLabel(root_element, diag);
  if (label.empty()) {
    return false;
  }

  bool valid = true;
  OrderedEntry<DeviceFeature>& entry = config->device_feature_groups[label];
  std::optional<int32_t> order = GetVersionCodeOrder(root_element, diag);
  if (!order) {
    valid = false;
  } else {
    entry.order = order.value();
  }
  auto& group = entry.entry;

  for (auto* child : root_element->GetChildElements()) {
    if (child->name != "supports-feature") {
      diag->Error(android::DiagMessage()
                  << "Unexpected root_element in device feature group: " << child->name);
      valid = false;
    } else {
      for (auto& node : child->children) {
        xml::Text* t;
        if ((t = NodeCast<xml::Text>(node.get())) != nullptr) {
          group.emplace_back(TrimWhitespace(t->text));
          break;
        }
      }
    }
  }

  return valid;
};

}  // namespace handler
}  // namespace configuration

}  // namespace aapt
