/*
 * 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.
 */

#ifndef AAPT_RESOURCE_VALUES_H
#define AAPT_RESOURCE_VALUES_H

#include <array>
#include <limits>
#include <ostream>
#include <vector>

#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"

#include "Diagnostics.h"
#include "Resource.h"
#include "StringPool.h"
#include "ValueTransformer.h"
#include "io/File.h"
#include "text/Printer.h"

namespace aapt {

class ValueVisitor;
class ConstValueVisitor;

// A resource value. This is an all-encompassing representation
// of Item and Map and their subclasses. The way to do
// type specific operations is to check the Value's type() and
// cast it to the appropriate subclass. This isn't super clean,
// but it is the simplest strategy.
class Value {
 public:
  virtual ~Value() = default;

  // Whether this value is weak and can be overridden without warning or error. Default is false.
  bool IsWeak() const {
    return weak_;
  }

  void SetWeak(bool val) {
    weak_ = val;
  }

  // Whether the value is marked as translatable. This does not persist when flattened to binary.
  // It is only used during compilation phase.
  void SetTranslatable(bool val) {
    translatable_ = val;
  }

  // Default true.
  bool IsTranslatable() const {
    return translatable_;
  }

  // Returns the source where this value was defined.
  const Source& GetSource() const {
    return source_;
  }

  void SetSource(const Source& source) {
    source_ = source;
  }

  void SetSource(Source&& source) {
    source_ = std::move(source);
  }

  // Returns the comment that was associated with this resource.
  const std::string& GetComment() const {
    return comment_;
  }

  void SetComment(const android::StringPiece& str) {
    comment_ = str.to_string();
  }

  void SetComment(std::string&& str) {
    comment_ = std::move(str);
  }

  virtual bool Equals(const Value* value) const = 0;

  // Calls the appropriate overload of ValueVisitor.
  virtual void Accept(ValueVisitor* visitor) = 0;

  // Calls the appropriate overload of ConstValueVisitor.
  virtual void Accept(ConstValueVisitor* visitor) const = 0;

  // Transform this Value into another Value using the transformer.
  std::unique_ptr<Value> Transform(ValueTransformer& transformer) const;

  // Human readable printout of this value.
  virtual void Print(std::ostream* out) const = 0;

  // Human readable printout of this value that may omit some information for the sake
  // of brevity and readability. Default implementation just calls Print().
  virtual void PrettyPrint(text::Printer* printer) const;

  friend std::ostream& operator<<(std::ostream& out, const Value& value);

 protected:
  Source source_;
  std::string comment_;
  bool weak_ = false;
  bool translatable_ = true;

 private:
  virtual Value* TransformValueImpl(ValueTransformer& transformer) const = 0;
};

// Inherit from this to get visitor accepting implementations for free.
template <typename Derived>
struct BaseValue : public Value {
  void Accept(ValueVisitor* visitor) override;
  void Accept(ConstValueVisitor* visitor) const override;
};

// A resource item with a single value. This maps to android::ResTable_entry.
struct Item : public Value {
  // Fills in an android::Res_value structure with this Item's binary representation.
  // Returns false if an error occurred.
  virtual bool Flatten(android::Res_value* out_value) const = 0;

  // Transform this Item into another Item using the transformer.
  std::unique_ptr<Item> Transform(ValueTransformer& transformer) const;

 private:
  virtual Item* TransformItemImpl(ValueTransformer& transformer) const = 0;
};

// Inherit from this to get visitor accepting implementations for free.
template <typename Derived>
struct BaseItem : public Item {
  void Accept(ValueVisitor* visitor) override;
  void Accept(ConstValueVisitor* visitor) const override;
};

// A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE.
// A reference can be symbolic (with the name set to a valid resource name) or be
// numeric (the id is set to a valid resource ID).
struct Reference : public TransformableItem<Reference, BaseItem<Reference>> {
  enum class Type : uint8_t {
    kResource,
    kAttribute,
  };

  std::optional<ResourceName> name;
  std::optional<ResourceId> id;
  std::optional<uint32_t> type_flags;
  Reference::Type reference_type;
  bool private_reference = false;
  bool is_dynamic = false;
  bool allow_raw = false;

  Reference();
  explicit Reference(const ResourceNameRef& n, Type type = Type::kResource);
  explicit Reference(const ResourceId& i, Type type = Type::kResource);
  Reference(const ResourceNameRef& n, const ResourceId& i);

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out_value) const override;
  void Print(std::ostream* out) const override;
  void PrettyPrint(text::Printer* printer) const override;

  // Prints the reference without a package name if the package name matches the one given.
  void PrettyPrint(const android::StringPiece& package, text::Printer* printer) const;
};

bool operator<(const Reference&, const Reference&);
bool operator==(const Reference&, const Reference&);

// An ID resource. Has no real value, just a place holder.
struct Id : public TransformableItem<Id, BaseItem<Id>> {
  Id() {
    weak_ = true;
  }

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out) const override;
  void Print(std::ostream* out) const override;
};

// A raw, unprocessed string. This may contain quotations, escape sequences, and whitespace.
// This shall *NOT* end up in the final resource table.
struct RawString : public TransformableItem<RawString, BaseItem<RawString>> {
  StringPool::Ref value;

  explicit RawString(const StringPool::Ref& ref);

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out_value) const override;
  void Print(std::ostream* out) const override;
};

// Identifies a range of characters in a string that are untranslatable.
// These should not be pseudolocalized. The start and end indices are measured in bytes.
struct UntranslatableSection {
  // Start offset inclusive.
  size_t start;

  // End offset exclusive.
  size_t end;
};

inline bool operator==(const UntranslatableSection& a, const UntranslatableSection& b) {
  return a.start == b.start && a.end == b.end;
}

inline bool operator!=(const UntranslatableSection& a, const UntranslatableSection& b) {
  return a.start != b.start || a.end != b.end;
}

struct String : public TransformableItem<String, BaseItem<String>> {
  StringPool::Ref value;

  // Sections of the string to NOT translate. Mainly used
  // for pseudolocalization. This data is NOT persisted
  // in any format.
  std::vector<UntranslatableSection> untranslatable_sections;

  explicit String(const StringPool::Ref& ref);

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out_value) const override;
  void Print(std::ostream* out) const override;
  void PrettyPrint(text::Printer* printer) const override;
};

struct StyledString : public TransformableItem<StyledString, BaseItem<StyledString>> {
  StringPool::StyleRef value;

  // Sections of the string to NOT translate. Mainly used
  // for pseudolocalization. This data is NOT persisted
  // in any format.
  std::vector<UntranslatableSection> untranslatable_sections;

  explicit StyledString(const StringPool::StyleRef& ref);

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out_value) const override;
  void Print(std::ostream* out) const override;
};

struct FileReference : public TransformableItem<FileReference, BaseItem<FileReference>> {
  StringPool::Ref path;

  // A handle to the file object from which this file can be read.
  // This field is NOT persisted in any format. It is transient.
  io::IFile* file = nullptr;

  // FileType of the file pointed to by `file`. This is used to know how to inflate the file,
  // or if to inflate at all (just copy).
  ResourceFile::Type type = ResourceFile::Type::kUnknown;

  FileReference() = default;
  explicit FileReference(const StringPool::Ref& path);

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out_value) const override;
  void Print(std::ostream* out) const override;
};

// Represents any other android::Res_value.
struct BinaryPrimitive : public TransformableItem<BinaryPrimitive, BaseItem<BinaryPrimitive>> {
  android::Res_value value;

  BinaryPrimitive() = default;
  explicit BinaryPrimitive(const android::Res_value& val);
  BinaryPrimitive(uint8_t dataType, uint32_t data);

  bool Equals(const Value* value) const override;
  bool Flatten(android::Res_value* out_value) const override;
  void Print(std::ostream* out) const override;
  void PrettyPrint(text::Printer* printer) const override;
};

struct Attribute : public TransformableValue<Attribute, BaseValue<Attribute>> {
  struct Symbol {
    Reference symbol;
    uint32_t value;
    uint8_t type;

    friend std::ostream& operator<<(std::ostream& out, const Symbol& symbol);
  };

  uint32_t type_mask;
  int32_t min_int;
  int32_t max_int;
  std::vector<Symbol> symbols;

  explicit Attribute(uint32_t t = 0u);

  bool Equals(const Value* value) const override;

  // Returns true if this Attribute's format is compatible with the given Attribute. The basic
  // rule is that TYPE_REFERENCE can be ignored for both of the Attributes, and TYPE_FLAGS and
  // TYPE_ENUMS are never compatible.
  bool IsCompatibleWith(const Attribute& attr) const;

  std::string MaskString() const;
  static std::string MaskString(uint32_t type_mask);

  void Print(std::ostream* out) const override;
  bool Matches(const Item& item, DiagMessage* out_msg = nullptr) const;
};

struct Style : public TransformableValue<Style, BaseValue<Style>> {
  struct Entry {
    Reference key;
    std::unique_ptr<Item> value;

    friend std::ostream& operator<<(std::ostream& out, const Entry& entry);
  };

  std::optional<Reference> parent;

  // If set to true, the parent was auto inferred from the style's name.
  bool parent_inferred = false;

  std::vector<Entry> entries;

  bool Equals(const Value* value) const override;
  void Print(std::ostream* out) const override;

  // Merges `style` into this Style. All identical attributes of `style` take precedence, including
  // the parent, if there is one.
  void MergeWith(Style* style, StringPool* pool);
};

struct Array : public TransformableValue<Array, BaseValue<Array>> {
  std::vector<std::unique_ptr<Item>> elements;

  bool Equals(const Value* value) const override;
  void Print(std::ostream* out) const override;
};

struct Plural : public TransformableValue<Plural, BaseValue<Plural>> {
  enum { Zero = 0, One, Two, Few, Many, Other, Count };

  std::array<std::unique_ptr<Item>, Count> values;

  bool Equals(const Value* value) const override;
  void Print(std::ostream* out) const override;
};

struct Styleable : public TransformableValue<Styleable, BaseValue<Styleable>> {
  std::vector<Reference> entries;

  bool Equals(const Value* value) const override;
  void Print(std::ostream* out) const override;
  void MergeWith(Styleable* styleable);
};

struct Macro : public TransformableValue<Macro, BaseValue<Macro>> {
  std::string raw_value;
  StyleString style_string;
  std::vector<UntranslatableSection> untranslatable_sections;

  struct Namespace {
    std::string alias;
    std::string package_name;
    bool is_private;

    bool operator==(const Namespace& right) const {
      return alias == right.alias && package_name == right.package_name &&
             is_private == right.is_private;
    }
  };

  std::vector<Namespace> alias_namespaces;

  bool Equals(const Value* value) const override;
  void Print(std::ostream* out) const override;
};

template <typename T>
typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<(
    std::ostream& out, const std::unique_ptr<T>& value) {
  if (value == nullptr) {
    out << "NULL";
  } else {
    value->Print(&out);
  }
  return out;
}

struct CloningValueTransformer : public ValueTransformer {
  explicit CloningValueTransformer(StringPool* new_pool);

  std::unique_ptr<Reference> TransformDerived(const Reference* value) override;
  std::unique_ptr<Id> TransformDerived(const Id* value) override;
  std::unique_ptr<RawString> TransformDerived(const RawString* value) override;
  std::unique_ptr<String> TransformDerived(const String* value) override;
  std::unique_ptr<StyledString> TransformDerived(const StyledString* value) override;
  std::unique_ptr<FileReference> TransformDerived(const FileReference* value) override;
  std::unique_ptr<BinaryPrimitive> TransformDerived(const BinaryPrimitive* value) override;
  std::unique_ptr<Attribute> TransformDerived(const Attribute* value) override;
  std::unique_ptr<Style> TransformDerived(const Style* value) override;
  std::unique_ptr<Array> TransformDerived(const Array* value) override;
  std::unique_ptr<Plural> TransformDerived(const Plural* value) override;
  std::unique_ptr<Styleable> TransformDerived(const Styleable* value) override;
  std::unique_ptr<Macro> TransformDerived(const Macro* value) override;
};

}  // namespace aapt

#endif  // AAPT_RESOURCE_VALUES_H
