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

#include <algorithm>
#include <map>
#include <string>

#include "android-base/logging.h"
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/TypeWrappers.h"

#include "ResourceTable.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "Source.h"
#include "ValueVisitor.h"
#include "unflatten/ResChunkPullParser.h"
#include "util/Util.h"

namespace aapt {

using namespace android;

using ::android::base::StringPrintf;

namespace {

// Visitor that converts a reference's resource ID to a resource name, given a mapping from
// resource ID to resource name.
class ReferenceIdToNameVisitor : public ValueVisitor {
 public:
  using ValueVisitor::Visit;

  explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceName>* mapping)
      : mapping_(mapping) {
    CHECK(mapping_ != nullptr);
  }

  void Visit(Reference* reference) override {
    if (!reference->id || !reference->id.value().is_valid()) {
      return;
    }

    ResourceId id = reference->id.value();
    auto cache_iter = mapping_->find(id);
    if (cache_iter != mapping_->end()) {
      reference->name = cache_iter->second;
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ReferenceIdToNameVisitor);

  const std::map<ResourceId, ResourceName>* mapping_;
};

}  // namespace

BinaryResourceParser::BinaryResourceParser(IAaptContext* context, ResourceTable* table,
                                           const Source& source, const void* data, size_t len,
                                           io::IFileCollection* files)
    : context_(context),
      table_(table),
      source_(source),
      data_(data),
      data_len_(len),
      files_(files) {
}

bool BinaryResourceParser::Parse() {
  ResChunkPullParser parser(data_, data_len_);

  if (!ResChunkPullParser::IsGoodEvent(parser.Next())) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "corrupt resources.arsc: " << parser.error());
    return false;
  }

  if (parser.chunk()->type != android::RES_TABLE_TYPE) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << StringPrintf("unknown chunk of type 0x%02x",
                                                      static_cast<int>(parser.chunk()->type)));
    return false;
  }

  if (!ParseTable(parser.chunk())) {
    return false;
  }

  if (parser.Next() != ResChunkPullParser::Event::kEndDocument) {
    if (parser.event() == ResChunkPullParser::Event::kBadDocument) {
      context_->GetDiagnostics()->Warn(
          DiagMessage(source_) << "invalid chunk trailing RES_TABLE_TYPE: " << parser.error());
    } else {
      context_->GetDiagnostics()->Warn(
          DiagMessage(source_) << StringPrintf(
              "unexpected chunk of type 0x%02x trailing RES_TABLE_TYPE",
              static_cast<int>(parser.chunk()->type)));
    }
  }
  return true;
}

/**
 * Parses the resource table, which contains all the packages, types, and
 * entries.
 */
bool BinaryResourceParser::ParseTable(const ResChunk_header* chunk) {
  const ResTable_header* table_header = ConvertTo<ResTable_header>(chunk);
  if (!table_header) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "corrupt ResTable_header chunk");
    return false;
  }

  ResChunkPullParser parser(GetChunkData(&table_header->header),
                            GetChunkDataLen(&table_header->header));
  while (ResChunkPullParser::IsGoodEvent(parser.Next())) {
    switch (util::DeviceToHost16(parser.chunk()->type)) {
      case android::RES_STRING_POOL_TYPE:
        if (value_pool_.getError() == NO_INIT) {
          status_t err = value_pool_.setTo(
              parser.chunk(), util::DeviceToHost32(parser.chunk()->size));
          if (err != NO_ERROR) {
            context_->GetDiagnostics()->Error(
                DiagMessage(source_) << "corrupt string pool in ResTable: "
                                     << value_pool_.getError());
            return false;
          }

          // Reserve some space for the strings we are going to add.
          table_->string_pool.HintWillAdd(value_pool_.size(),
                                          value_pool_.styleCount());
        } else {
          context_->GetDiagnostics()->Warn(
              DiagMessage(source_) << "unexpected string pool in ResTable");
        }
        break;

      case android::RES_TABLE_PACKAGE_TYPE:
        if (!ParsePackage(parser.chunk())) {
          return false;
        }
        break;

      default:
        context_->GetDiagnostics()->Warn(
            DiagMessage(source_) << "unexpected chunk type "
                                 << static_cast<int>(util::DeviceToHost16(parser.chunk()->type)));
        break;
    }
  }

  if (parser.event() == ResChunkPullParser::Event::kBadDocument) {
    context_->GetDiagnostics()->Error(
        DiagMessage(source_) << "corrupt resource table: " << parser.error());
    return false;
  }
  return true;
}

bool BinaryResourceParser::ParsePackage(const ResChunk_header* chunk) {
  constexpr size_t kMinPackageSize =
      sizeof(ResTable_package) - sizeof(ResTable_package::typeIdOffset);
  const ResTable_package* package_header = ConvertTo<ResTable_package, kMinPackageSize>(chunk);
  if (!package_header) {
    context_->GetDiagnostics()->Error(DiagMessage(source_) << "corrupt ResTable_package chunk");
    return false;
  }

  uint32_t package_id = util::DeviceToHost32(package_header->id);
  if (package_id > std::numeric_limits<uint8_t>::max()) {
    context_->GetDiagnostics()->Error(
        DiagMessage(source_) << "package ID is too big (" << package_id << ")");
    return false;
  }

  // Extract the package name.
  size_t len = strnlen16((const char16_t*)package_header->name,
                         arraysize(package_header->name));
  std::u16string package_name;
  package_name.resize(len);
  for (size_t i = 0; i < len; i++) {
    package_name[i] = util::DeviceToHost16(package_header->name[i]);
  }

  ResourceTablePackage* package = table_->CreatePackage(
      util::Utf16ToUtf8(package_name), static_cast<uint8_t>(package_id));
  if (!package) {
    context_->GetDiagnostics()->Error(
        DiagMessage(source_) << "incompatible package '" << package_name
                             << "' with ID " << package_id);
    return false;
  }

  // There can be multiple packages in a table, so
  // clear the type and key pool in case they were set from a previous package.
  type_pool_.uninit();
  key_pool_.uninit();

  ResChunkPullParser parser(GetChunkData(&package_header->header),
                            GetChunkDataLen(&package_header->header));
  while (ResChunkPullParser::IsGoodEvent(parser.Next())) {
    switch (util::DeviceToHost16(parser.chunk()->type)) {
      case android::RES_STRING_POOL_TYPE:
        if (type_pool_.getError() == NO_INIT) {
          status_t err = type_pool_.setTo(
              parser.chunk(), util::DeviceToHost32(parser.chunk()->size));
          if (err != NO_ERROR) {
            context_->GetDiagnostics()->Error(DiagMessage(source_)
                                              << "corrupt type string pool in "
                                              << "ResTable_package: "
                                              << type_pool_.getError());
            return false;
          }
        } else if (key_pool_.getError() == NO_INIT) {
          status_t err = key_pool_.setTo(
              parser.chunk(), util::DeviceToHost32(parser.chunk()->size));
          if (err != NO_ERROR) {
            context_->GetDiagnostics()->Error(DiagMessage(source_)
                                              << "corrupt key string pool in "
                                              << "ResTable_package: "
                                              << key_pool_.getError());
            return false;
          }
        } else {
          context_->GetDiagnostics()->Warn(DiagMessage(source_) << "unexpected string pool");
        }
        break;

      case android::RES_TABLE_TYPE_SPEC_TYPE:
        if (!ParseTypeSpec(parser.chunk())) {
          return false;
        }
        break;

      case android::RES_TABLE_TYPE_TYPE:
        if (!ParseType(package, parser.chunk())) {
          return false;
        }
        break;

      case android::RES_TABLE_LIBRARY_TYPE:
        if (!ParseLibrary(parser.chunk())) {
          return false;
        }
        break;

      default:
        context_->GetDiagnostics()->Warn(
            DiagMessage(source_) << "unexpected chunk type "
                                 << static_cast<int>(util::DeviceToHost16(parser.chunk()->type)));
        break;
    }
  }

  if (parser.event() == ResChunkPullParser::Event::kBadDocument) {
    context_->GetDiagnostics()->Error(
        DiagMessage(source_) << "corrupt ResTable_package: " << parser.error());
    return false;
  }

  // Now go through the table and change local resource ID references to
  // symbolic references.
  ReferenceIdToNameVisitor visitor(&id_index_);
  VisitAllValuesInTable(table_, &visitor);
  return true;
}

bool BinaryResourceParser::ParseTypeSpec(const ResChunk_header* chunk) {
  if (type_pool_.getError() != NO_ERROR) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "missing type string pool");
    return false;
  }

  const ResTable_typeSpec* type_spec = ConvertTo<ResTable_typeSpec>(chunk);
  if (!type_spec) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "corrupt ResTable_typeSpec chunk");
    return false;
  }

  if (type_spec->id == 0) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "ResTable_typeSpec has invalid id: "
                                      << type_spec->id);
    return false;
  }
  return true;
}

bool BinaryResourceParser::ParseType(const ResourceTablePackage* package,
                                     const ResChunk_header* chunk) {
  if (type_pool_.getError() != NO_ERROR) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "missing type string pool");
    return false;
  }

  if (key_pool_.getError() != NO_ERROR) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "missing key string pool");
    return false;
  }

  // Specify a manual size, because ResTable_type contains ResTable_config, which changes
  // a lot and has its own code to handle variable size.
  const ResTable_type* type = ConvertTo<ResTable_type, kResTableTypeMinSize>(chunk);
  if (!type) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "corrupt ResTable_type chunk");
    return false;
  }

  if (type->id == 0) {
    context_->GetDiagnostics()->Error(DiagMessage(source_)
                                      << "ResTable_type has invalid id: "
                                      << (int)type->id);
    return false;
  }

  ConfigDescription config;
  config.copyFromDtoH(type->config);

  const std::string type_str = util::GetString(type_pool_, type->id - 1);

  const ResourceType* parsed_type = ParseResourceType(type_str);
  if (!parsed_type) {
    context_->GetDiagnostics()->Error(
        DiagMessage(source_) << "invalid type name '" << type_str
                             << "' for type with ID " << (int)type->id);
    return false;
  }

  TypeVariant tv(type);
  for (auto it = tv.beginEntries(); it != tv.endEntries(); ++it) {
    const ResTable_entry* entry = *it;
    if (!entry) {
      continue;
    }

    const ResourceName name(
        package->name, *parsed_type,
        util::GetString(key_pool_, util::DeviceToHost32(entry->key.index)));

    const ResourceId res_id(package->id.value(), type->id,
                            static_cast<uint16_t>(it.index()));

    std::unique_ptr<Value> resource_value;
    if (entry->flags & ResTable_entry::FLAG_COMPLEX) {
      const ResTable_map_entry* mapEntry = static_cast<const ResTable_map_entry*>(entry);

      // TODO(adamlesinski): Check that the entry count is valid.
      resource_value = ParseMapEntry(name, config, mapEntry);
    } else {
      const Res_value* value =
          (const Res_value*)((const uint8_t*)entry + util::DeviceToHost32(entry->size));
      resource_value = ParseValue(name, config, *value);
    }

    if (!resource_value) {
      context_->GetDiagnostics()->Error(
          DiagMessage(source_) << "failed to parse value for resource " << name
                               << " (" << res_id << ") with configuration '"
                               << config << "'");
      return false;
    }

    if (!table_->AddResourceAllowMangled(name, res_id, config, {}, std::move(resource_value),
                                         context_->GetDiagnostics())) {
      return false;
    }

    if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0) {
      Symbol symbol;
      symbol.state = SymbolState::kPublic;
      symbol.source = source_.WithLine(0);
      if (!table_->SetSymbolStateAllowMangled(name, res_id, symbol, context_->GetDiagnostics())) {
        return false;
      }
    }

    // Add this resource name->id mapping to the index so
    // that we can resolve all ID references to name references.
    auto cache_iter = id_index_.find(res_id);
    if (cache_iter == id_index_.end()) {
      id_index_.insert({res_id, name});
    }
  }
  return true;
}

bool BinaryResourceParser::ParseLibrary(const ResChunk_header* chunk) {
  DynamicRefTable dynamic_ref_table;
  if (dynamic_ref_table.load(reinterpret_cast<const ResTable_lib_header*>(chunk)) != NO_ERROR) {
    return false;
  }

  const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table.entries();
  const size_t count = entries.size();
  for (size_t i = 0; i < count; i++) {
    table_->included_packages_[entries.valueAt(i)] =
        util::Utf16ToUtf8(StringPiece16(entries.keyAt(i).string()));
  }
  return true;
}

std::unique_ptr<Item> BinaryResourceParser::ParseValue(const ResourceNameRef& name,
                                                       const ConfigDescription& config,
                                                       const android::Res_value& value) {
  std::unique_ptr<Item> item = ResourceUtils::ParseBinaryResValue(name.type, config, value_pool_,
                                                                  value, &table_->string_pool);
  if (files_ != nullptr && item != nullptr) {
    FileReference* file_ref = ValueCast<FileReference>(item.get());
    if (file_ref != nullptr) {
      file_ref->file = files_->FindFile(*file_ref->path);
      if (file_ref->file == nullptr) {
        context_->GetDiagnostics()->Warn(DiagMessage() << "resource " << name << " for config '"
                                                        << config << "' is a file reference to '"
                                                        << *file_ref->path
                                                        << "' but no such path exists");
      }
    }
  }
  return item;
}

std::unique_ptr<Value> BinaryResourceParser::ParseMapEntry(
    const ResourceNameRef& name, const ConfigDescription& config,
    const ResTable_map_entry* map) {
  switch (name.type) {
    case ResourceType::kStyle:
      return ParseStyle(name, config, map);
    case ResourceType::kAttrPrivate:
    // fallthrough
    case ResourceType::kAttr:
      return ParseAttr(name, config, map);
    case ResourceType::kArray:
      return ParseArray(name, config, map);
    case ResourceType::kPlurals:
      return ParsePlural(name, config, map);
    case ResourceType::kId:
      // Special case: An ID is not a bag, but some apps have defined the auto-generated
      // IDs that come from declaring an enum value in an attribute as an empty map...
      // We can ignore the value here.
      return util::make_unique<Id>();
    default:
      context_->GetDiagnostics()->Error(DiagMessage() << "illegal map type '" << ToString(name.type)
                                                      << "' (" << (int)name.type << ")");
      break;
  }
  return {};
}

std::unique_ptr<Style> BinaryResourceParser::ParseStyle(
    const ResourceNameRef& name, const ConfigDescription& config,
    const ResTable_map_entry* map) {
  std::unique_ptr<Style> style = util::make_unique<Style>();
  if (util::DeviceToHost32(map->parent.ident) != 0) {
    // The parent is a regular reference to a resource.
    style->parent = Reference(util::DeviceToHost32(map->parent.ident));
  }

  for (const ResTable_map& map_entry : map) {
    if (Res_INTERNALID(util::DeviceToHost32(map_entry.name.ident))) {
      continue;
    }

    Style::Entry style_entry;
    style_entry.key = Reference(util::DeviceToHost32(map_entry.name.ident));
    style_entry.value = ParseValue(name, config, map_entry.value);
    if (!style_entry.value) {
      return {};
    }
    style->entries.push_back(std::move(style_entry));
  }
  return style;
}

std::unique_ptr<Attribute> BinaryResourceParser::ParseAttr(
    const ResourceNameRef& name, const ConfigDescription& config,
    const ResTable_map_entry* map) {
  const bool is_weak =
      (util::DeviceToHost16(map->flags) & ResTable_entry::FLAG_WEAK) != 0;
  std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);

  // First we must discover what type of attribute this is. Find the type mask.
  auto type_mask_iter =
      std::find_if(begin(map), end(map), [](const ResTable_map& entry) -> bool {
        return util::DeviceToHost32(entry.name.ident) ==
               ResTable_map::ATTR_TYPE;
      });

  if (type_mask_iter != end(map)) {
    attr->type_mask = util::DeviceToHost32(type_mask_iter->value.data);
  }

  for (const ResTable_map& map_entry : map) {
    if (Res_INTERNALID(util::DeviceToHost32(map_entry.name.ident))) {
      switch (util::DeviceToHost32(map_entry.name.ident)) {
        case ResTable_map::ATTR_MIN:
          attr->min_int = static_cast<int32_t>(map_entry.value.data);
          break;
        case ResTable_map::ATTR_MAX:
          attr->max_int = static_cast<int32_t>(map_entry.value.data);
          break;
      }
      continue;
    }

    if (attr->type_mask &
        (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) {
      Attribute::Symbol symbol;
      symbol.value = util::DeviceToHost32(map_entry.value.data);
      symbol.symbol = Reference(util::DeviceToHost32(map_entry.name.ident));
      attr->symbols.push_back(std::move(symbol));
    }
  }

  // TODO(adamlesinski): Find i80n, attributes.
  return attr;
}

std::unique_ptr<Array> BinaryResourceParser::ParseArray(
    const ResourceNameRef& name, const ConfigDescription& config,
    const ResTable_map_entry* map) {
  std::unique_ptr<Array> array = util::make_unique<Array>();
  for (const ResTable_map& map_entry : map) {
    array->elements.push_back(ParseValue(name, config, map_entry.value));
  }
  return array;
}

std::unique_ptr<Plural> BinaryResourceParser::ParsePlural(
    const ResourceNameRef& name, const ConfigDescription& config,
    const ResTable_map_entry* map) {
  std::unique_ptr<Plural> plural = util::make_unique<Plural>();
  for (const ResTable_map& map_entry : map) {
    std::unique_ptr<Item> item = ParseValue(name, config, map_entry.value);
    if (!item) {
      return {};
    }

    switch (util::DeviceToHost32(map_entry.name.ident)) {
      case ResTable_map::ATTR_ZERO:
        plural->values[Plural::Zero] = std::move(item);
        break;
      case ResTable_map::ATTR_ONE:
        plural->values[Plural::One] = std::move(item);
        break;
      case ResTable_map::ATTR_TWO:
        plural->values[Plural::Two] = std::move(item);
        break;
      case ResTable_map::ATTR_FEW:
        plural->values[Plural::Few] = std::move(item);
        break;
      case ResTable_map::ATTR_MANY:
        plural->values[Plural::Many] = std::move(item);
        break;
      case ResTable_map::ATTR_OTHER:
        plural->values[Plural::Other] = std::move(item);
        break;
    }
  }
  return plural;
}

}  // namespace aapt
