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

#include "Diagnostics.h"
#include "android-base/logging.h"
#include "androidfw/StringPiece.h"
#include "io/StringStream.h"
#include "test/Common.h"
#include "util/Util.h"

using ::aapt::configuration::Abi;
using ::aapt::configuration::AndroidSdk;
using ::aapt::configuration::ConfiguredArtifact;
using ::aapt::configuration::GetOrCreateGroup;
using ::aapt::io::StringInputStream;
using ::android::ConfigDescription;
using ::android::StringPiece;

namespace aapt {
namespace test {

ResourceTableBuilder& ResourceTableBuilder::AddSimple(StringPiece name, const ResourceId& id) {
  return AddValue(name, id, util::make_unique<Id>());
}

ResourceTableBuilder& ResourceTableBuilder::AddSimple(StringPiece name,
                                                      const ConfigDescription& config,
                                                      const ResourceId& id) {
  return AddValue(name, config, id, util::make_unique<Id>());
}

ResourceTableBuilder& ResourceTableBuilder::AddReference(StringPiece name, StringPiece ref) {
  return AddReference(name, {}, ref);
}

ResourceTableBuilder& ResourceTableBuilder::AddReference(StringPiece name, const ResourceId& id,
                                                         StringPiece ref) {
  return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
}

ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, StringPiece str) {
  return AddString(name, {}, str);
}

ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, const ResourceId& id,
                                                      StringPiece str) {
  return AddValue(name, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
}

ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, const ResourceId& id,
                                                      const ConfigDescription& config,
                                                      StringPiece str) {
  return AddValue(name, config, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
}

ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, StringPiece path,
                                                             io::IFile* file) {
  return AddFileReference(name, {}, path, file);
}

ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, const ResourceId& id,
                                                             StringPiece path, io::IFile* file) {
  auto file_ref = util::make_unique<FileReference>(table_->string_pool.MakeRef(path));
  file_ref->file = file;
  return AddValue(name, id, std::move(file_ref));
}

ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, StringPiece path,
                                                             const ConfigDescription& config,
                                                             io::IFile* file) {
  auto file_ref = util::make_unique<FileReference>(table_->string_pool.MakeRef(path));
  file_ref->file = file;
  return AddValue(name, config, {}, std::move(file_ref));
}

ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name,
                                                     std::unique_ptr<Value> value) {
  return AddValue(name, {}, std::move(value));
}

ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name, const ResourceId& id,
                                                     std::unique_ptr<Value> value) {
  return AddValue(name, {}, id, std::move(value));
}

ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name,
                                                     const ConfigDescription& config,
                                                     const ResourceId& id,
                                                     std::unique_ptr<Value> value) {
  ResourceName res_name = ParseNameOrDie(name);
  NewResourceBuilder builder(res_name);
  builder.SetValue(std::move(value), config).SetAllowMangled(true);
  if (id.id != 0U) {
    builder.SetId(id);
  }

  CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
  return *this;
}

ResourceTableBuilder& ResourceTableBuilder::SetSymbolState(StringPiece name, const ResourceId& id,
                                                           Visibility::Level level,
                                                           bool allow_new) {
  ResourceName res_name = ParseNameOrDie(name);
  NewResourceBuilder builder(res_name);
  builder.SetVisibility({level}).SetAllowNew({}).SetAllowMangled(true);
  if (id.id != 0U) {
    builder.SetId(id);
  }

  CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
  return *this;
}

ResourceTableBuilder& ResourceTableBuilder::SetOverlayable(StringPiece name,
                                                           const OverlayableItem& overlayable) {
  ResourceName res_name = ParseNameOrDie(name);
  CHECK(table_->AddResource(
      NewResourceBuilder(res_name).SetOverlayable(overlayable).SetAllowMangled(true).Build(),
      GetDiagnostics()));
  return *this;
}

ResourceTableBuilder& ResourceTableBuilder::Add(NewResource&& res) {
  CHECK(table_->AddResource(std::move(res), GetDiagnostics()));
  return *this;
}

android::StringPool* ResourceTableBuilder::string_pool() {
  return &table_->string_pool;
}

std::unique_ptr<ResourceTable> ResourceTableBuilder::Build() {
  return std::move(table_);
}

std::unique_ptr<Reference> BuildReference(StringPiece ref, const std::optional<ResourceId>& id) {
  std::unique_ptr<Reference> reference = util::make_unique<Reference>(ParseNameOrDie(ref));
  reference->id = id;
  return reference;
}

std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type, uint32_t data) {
  android::Res_value value = {};
  value.size = sizeof(value);
  value.dataType = type;
  value.data = data;
  return util::make_unique<BinaryPrimitive>(value);
}

AttributeBuilder::AttributeBuilder()
    : attr_(util::make_unique<Attribute>(android::ResTable_map::TYPE_ANY)) {
}

AttributeBuilder& AttributeBuilder::SetTypeMask(uint32_t typeMask) {
  attr_->type_mask = typeMask;
  return *this;
}

AttributeBuilder& AttributeBuilder::SetWeak(bool weak) {
  attr_->SetWeak(weak);
  return *this;
}

AttributeBuilder& AttributeBuilder::AddItem(StringPiece name, uint32_t value) {
  attr_->symbols.push_back(
      Attribute::Symbol{Reference(ResourceName({}, ResourceType::kId, name)), value});
  return *this;
}

std::unique_ptr<Attribute> AttributeBuilder::Build() {
  return std::move(attr_);
}

StyleBuilder& StyleBuilder::SetParent(StringPiece str) {
  style_->parent = Reference(ParseNameOrDie(str));
  return *this;
}

StyleBuilder& StyleBuilder::AddItem(StringPiece str, std::unique_ptr<Item> value) {
  style_->entries.push_back(Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)});
  return *this;
}

StyleBuilder& StyleBuilder::AddItem(StringPiece str, const ResourceId& id,
                                    std::unique_ptr<Item> value) {
  AddItem(str, std::move(value));
  style_->entries.back().key.id = id;
  return *this;
}

std::unique_ptr<Style> StyleBuilder::Build() {
  return std::move(style_);
}

StyleableBuilder& StyleableBuilder::AddItem(StringPiece str, const std::optional<ResourceId>& id) {
  styleable_->entries.push_back(Reference(ParseNameOrDie(str)));
  styleable_->entries.back().id = id;
  return *this;
}

std::unique_ptr<Styleable> StyleableBuilder::Build() {
  return std::move(styleable_);
}

std::unique_ptr<xml::XmlResource> BuildXmlDom(StringPiece str) {
  std::string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
  input.append(str.data(), str.size());
  StringInputStream in(input);
  StdErrDiagnostics diag;
  std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, android::Source("test.xml"));
  CHECK(doc != nullptr && doc->root != nullptr) << "failed to parse inline XML string";
  return doc;
}

std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context,
                                                            StringPiece str) {
  std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str);
  doc->file.name.package = context->GetCompilationPackage();
  return doc;
}

ArtifactBuilder& ArtifactBuilder::SetName(const std::string& name) {
  artifact_.name = name;
  return *this;
}

ArtifactBuilder& ArtifactBuilder::SetVersion(int version) {
  artifact_.version = version;
  return *this;
}

ArtifactBuilder& ArtifactBuilder::AddAbi(configuration::Abi abi) {
  artifact_.abis.push_back(abi);
  return *this;
}

ArtifactBuilder& ArtifactBuilder::AddDensity(const ConfigDescription& density) {
  artifact_.screen_densities.push_back(density);
  return *this;
}

ArtifactBuilder& ArtifactBuilder::AddLocale(const ConfigDescription& locale) {
  artifact_.locales.push_back(locale);
  return *this;
}

ArtifactBuilder& ArtifactBuilder::SetAndroidSdk(int min_sdk) {
  artifact_.android_sdk = {AndroidSdk::ForMinSdk(min_sdk)};
  return *this;
}

configuration::OutputArtifact ArtifactBuilder::Build() {
  return artifact_;
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAbiGroup(
    const std::string& label, std::vector<configuration::Abi> abis) {
  return AddGroup(label, &config_.abi_groups, std::move(abis));
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDensityGroup(
    const std::string& label, std::vector<std::string> densities) {
  std::vector<ConfigDescription> configs;
  for (const auto& density : densities) {
    configs.push_back(test::ParseConfigOrDie(density));
  }
  return AddGroup(label, &config_.screen_density_groups, configs);
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddLocaleGroup(
    const std::string& label, std::vector<std::string> locales) {
  std::vector<ConfigDescription> configs;
  for (const auto& locale : locales) {
    configs.push_back(test::ParseConfigOrDie(locale));
  }
  return AddGroup(label, &config_.locale_groups, configs);
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDeviceFeatureGroup(
    const std::string& label) {
  return AddGroup(label, &config_.device_feature_groups);
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddGlTextureGroup(
    const std::string& label) {
  return AddGroup(label, &config_.gl_texture_groups);
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAndroidSdk(
    std::string label, int min_sdk) {
  config_.android_sdks[label] = AndroidSdk::ForMinSdk(min_sdk);
  return *this;
}

PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddArtifact(
    configuration::ConfiguredArtifact artifact) {
  config_.artifacts.push_back(std::move(artifact));
  return *this;
}

configuration::PostProcessingConfiguration PostProcessingConfigurationBuilder::Build() {
  return config_;
}

}  // namespace test
}  // namespace aapt
