/*
 * 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 "android-base/file.h"
#include "android-base/logging.h"
#include "androidfw/ConfigDescription.h"

#include "Diagnostics.h"
#include "ResourceUtils.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";

/** A default noop diagnostics context. */
class NoopDiagnostics : public IDiagnostics {
 public:
  void Log(Level level, DiagMessageActual& actualMsg) override {}
};
NoopDiagnostics noop_;

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

  if (label.empty()) {
    diag->Error(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, IDiagnostics* diag) {
  const xml::Attribute* version = element->FindAttribute("", "version-code-order");
  if (version == nullptr) {
    std::string label = GetLabel(element, diag);
    diag->Error(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(const StringPiece& placeholder, const std::optional<StringPiece>& value,
                        std::string* name, 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(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(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(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, 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, 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,
                                               IDiagnostics* diag) {
  if (!artifact.name && !config.artifact_format) {
    diag->Error(
        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(DiagMessage() << "Could not determine split APK artifact name");
    return {};
  }

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

  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(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(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(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(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(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(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,
                                                                IDiagnostics* diag) {
  StringInputStream in(contents);
  std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, diag, 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(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(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(DiagMessage() << "Could not process XML document");
    return {};
  }

  return {config};
}

const 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, const StringPiece& apk_name,
                                      IDiagnostics* diag) {
  const StringPiece ext = file::GetExtension(apk_name);
  size_t end_index = apk_name.to_string().rfind(ext.to_string());
  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.to_string());
    }
  }

  return result;
}

std::optional<std::string> ConfiguredArtifact::ToArtifactName(const StringPiece& format,
                                                              const StringPiece& apk_name,
                                                              IDiagnostics* diag) const {
  std::optional<std::string> base = ToBaseName(format.to_string(), 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(const StringPiece& apk_name,
                                                    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(
    const 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).to_string();
  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(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,
                        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(DiagMessage() << "Unknown artifact attribute: " << attr.name << " = "
                               << attr.value);
    }
  }
  config->artifacts.push_back(artifact);
  return true;
};

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

bool AbiGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                        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(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).to_string());
          if (abi != kStringToAbiMap.end()) {
            group.push_back(abi->second);
          } else {
            diag->Error(DiagMessage() << "Could not parse ABI value: " << t->text);
            valid = false;
          }
          break;
        }
      }
    }
  }

  return valid;
};

bool ScreenDensityGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                                  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(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(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;
          const 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(DiagMessage()
                        << "Could not parse config descriptor for screen-density: " << text);
            valid = false;
          }
          break;
        }
      }
    }
  }

  return valid;
};

bool LocaleGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                           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(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(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;
          const 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(DiagMessage()
                        << "Could not parse config descriptor for screen-density: " << text);
            valid = false;
          }
          break;
        }
      }
    }
  }

  return valid;
};

bool AndroidSdkTagHandler(PostProcessingConfiguration* config, Element* root_element,
                          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(DiagMessage() << "Invalid attribute: " << attr.name << " = " << attr.value);
      valid = false;
    }
  }

  if (entry.min_sdk_version == -1) {
    diag->Error(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(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,
                              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(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(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.push_back(TrimWhitespace(t->text).to_string());
          }
        }
      }
    }
    group.push_back(result);
  }

  return valid;
};

bool DeviceFeatureGroupTagHandler(PostProcessingConfiguration* config, Element* root_element,
                                  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(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.push_back(TrimWhitespace(t->text).to_string());
          break;
        }
      }
    }
  }

  return valid;
};

}  // namespace handler
}  // namespace configuration

}  // namespace aapt
