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

#include "androidfw/ResourceTypes.h"

#include "Diagnostics.h"
#include "ResourceUtils.h"
#include "SdkConstants.h"
#include "link/ReferenceLinker.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
#include "util/Util.h"
#include "xml/XmlDom.h"

namespace aapt {

namespace {

/**
 * Visits all references (including parents of styles, references in styles,
 * arrays, etc) and
 * links their symbolic name to their Resource ID, performing mangling and
 * package aliasing
 * as needed.
 */
class ReferenceVisitor : public ValueVisitor {
 public:
  using ValueVisitor::Visit;

  ReferenceVisitor(IAaptContext* context, SymbolTable* symbols, xml::IPackageDeclStack* decls,
                   CallSite* callsite)
      : context_(context), symbols_(symbols), decls_(decls), callsite_(callsite), error_(false) {}

  void Visit(Reference* ref) override {
    if (!ReferenceLinker::LinkReference(ref, context_, symbols_, decls_, callsite_)) {
      error_ = true;
    }
  }

  bool HasError() const { return error_; }

 private:
  DISALLOW_COPY_AND_ASSIGN(ReferenceVisitor);

  IAaptContext* context_;
  SymbolTable* symbols_;
  xml::IPackageDeclStack* decls_;
  CallSite* callsite_;
  bool error_;
};

/**
 * Visits each xml Element and compiles the attributes within.
 */
class XmlVisitor : public xml::PackageAwareVisitor {
 public:
  using xml::PackageAwareVisitor::Visit;

  XmlVisitor(IAaptContext* context, SymbolTable* symbols, const Source& source,
             std::set<int>* sdk_levels_found, CallSite* callsite)
      : context_(context),
        symbols_(symbols),
        source_(source),
        sdk_levels_found_(sdk_levels_found),
        callsite_(callsite),
        reference_visitor_(context, symbols, this, callsite) {}

  void Visit(xml::Element* el) override {
    // The default Attribute allows everything except enums or flags.
    constexpr const static uint32_t kDefaultTypeMask =
        0xffffffffu & ~(android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS);
    const static Attribute kDefaultAttribute(true /* weak */, kDefaultTypeMask);

    const Source source = source_.WithLine(el->line_number);
    for (xml::Attribute& attr : el->attributes) {
      // If the attribute has no namespace, interpret values as if
      // they were assigned to the default Attribute.

      const Attribute* attribute = &kDefaultAttribute;
      std::string attribute_package;

      if (Maybe<xml::ExtractedPackage> maybe_package =
              xml::ExtractPackageFromNamespace(attr.namespace_uri)) {
        // There is a valid package name for this attribute. We will look this up.
        attribute_package = maybe_package.value().package;
        if (attribute_package.empty()) {
          // Empty package means the 'current' or 'local' package.
          attribute_package = context_->GetCompilationPackage();
        }

        Reference attr_ref(ResourceNameRef(attribute_package, ResourceType::kAttr, attr.name));
        attr_ref.private_reference = maybe_package.value().private_namespace;

        std::string err_str;
        attr.compiled_attribute = ReferenceLinker::CompileXmlAttribute(
            attr_ref, context_->GetNameMangler(), symbols_, callsite_, &err_str);

        if (!attr.compiled_attribute) {
          context_->GetDiagnostics()->Error(DiagMessage(source) << "attribute '"
                                                                << attribute_package << ":"
                                                                << attr.name << "' " << err_str);
          error_ = true;
          continue;
        }

        // Find this compiled attribute's SDK level.
        const xml::AaptAttribute& aapt_attr = attr.compiled_attribute.value();
        if (aapt_attr.id) {
          // Record all SDK levels from which the attributes were defined.
          const size_t sdk_level = FindAttributeSdkLevel(aapt_attr.id.value());
          if (sdk_level > 1) {
            sdk_levels_found_->insert(sdk_level);
          }
        }
        attribute = &aapt_attr.attribute;
      }

      attr.compiled_value = ResourceUtils::TryParseItemForAttribute(attr.value, attribute);
      if (attr.compiled_value) {
        // With a compiledValue, we must resolve the reference and assign it an
        // ID.
        attr.compiled_value->SetSource(source);
        attr.compiled_value->Accept(&reference_visitor_);
      } else if ((attribute->type_mask & android::ResTable_map::TYPE_STRING) == 0) {
        // We won't be able to encode this as a string.
        DiagMessage msg(source);
        msg << "'" << attr.value << "' "
            << "is incompatible with attribute ";
        if (!attribute_package.empty()) {
          msg << attribute_package << ":";
        }
        msg << attr.name << " " << *attribute;
        context_->GetDiagnostics()->Error(msg);
        error_ = true;
      }
    }

    // Call the super implementation.
    xml::PackageAwareVisitor::Visit(el);
  }

  bool HasError() { return error_ || reference_visitor_.HasError(); }

 private:
  DISALLOW_COPY_AND_ASSIGN(XmlVisitor);

  IAaptContext* context_;
  SymbolTable* symbols_;
  Source source_;
  std::set<int>* sdk_levels_found_;
  CallSite* callsite_;
  ReferenceVisitor reference_visitor_;
  bool error_ = false;
};

}  // namespace

bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) {
  sdk_levels_found_.clear();
  CallSite callsite = {resource->file.name};
  XmlVisitor visitor(context, context->GetExternalSymbols(), resource->file.source,
                     &sdk_levels_found_, &callsite);
  if (resource->root) {
    resource->root->Accept(&visitor);
    return !visitor.HasError();
  }
  return false;
}

}  // namespace aapt
