/*
 * 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 "util/Maybe.h"
#include "Resource.h"
#include "StringPool.h"

#include <array>
#include <androidfw/ResourceTypes.h>
#include <ostream>
#include <vector>

namespace aapt {

struct RawValueVisitor;

/**
 * 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.
 */
struct Value {
	virtual ~Value() = default;

    /**
     * Whether or not this is an Item.
     */
    virtual bool isItem() const;

    /**
     * Whether this value is weak and can be overridden without
     * warning or error. Default for base class is false.
     */
    virtual bool isWeak() const;

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

    /**
     * Clone the value.
     */
    virtual Value* clone(StringPool* newPool) const = 0;

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

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

/**
 * A resource item with a single value. This maps to android::ResTable_entry.
 */
struct Item : public Value {
    /**
     * An Item is, of course, an Item.
     */
    virtual bool isItem() const override;

    /**
     * Clone the Item.
     */
    virtual Item* clone(StringPool* newPool) const override = 0;

    /**
     * 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* outValue) const = 0;
};

/**
 * Inherit from this to get visitor accepting implementations for free.
 */
template <typename Derived>
struct BaseItem : public Item {
    void accept(RawValueVisitor* visitor) 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 BaseItem<Reference> {
    enum class Type {
        kResource,
        kAttribute,
    };

    Maybe<ResourceName> name;
    Maybe<ResourceId> id;
    Reference::Type referenceType;
    bool privateReference = false;

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

    bool flatten(android::Res_value* outValue) const override;
    Reference* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

/**
 * An ID resource. Has no real value, just a place holder.
 */
struct Id : public BaseItem<Id> {
    bool isWeak() const override;
    bool flatten(android::Res_value* out) const override;
    Id* clone(StringPool* newPool) 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 BaseItem<RawString> {
    StringPool::Ref value;

    RawString(const StringPool::Ref& ref);

    bool flatten(android::Res_value* outValue) const override;
    RawString* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

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

    String(const StringPool::Ref& ref);

    bool flatten(android::Res_value* outValue) const override;
    String* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

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

    StyledString(const StringPool::StyleRef& ref);

    bool flatten(android::Res_value* outValue) const override;
    StyledString* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

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

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

    bool flatten(android::Res_value* outValue) const override;
    FileReference* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

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

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

    bool flatten(android::Res_value* outValue) const override;
    BinaryPrimitive* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

struct Attribute : public BaseValue<Attribute> {
    struct Symbol {
        Reference symbol;
        uint32_t value;
    };

	bool weak;
    uint32_t typeMask;
    uint32_t minInt;
    uint32_t maxInt;
    std::vector<Symbol> symbols;

    Attribute(bool w, uint32_t t = 0u);

    bool isWeak() const override;
    Attribute* clone(StringPool* newPool) const override;
    void printMask(std::ostream* out) const;
    void print(std::ostream* out) const override;
};

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

    Maybe<Reference> parent;

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

    std::vector<Entry> entries;

    Style* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

struct Array : public BaseValue<Array> {
    std::vector<std::unique_ptr<Item>> items;

    Array* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

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

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

    Plural* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

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

    Styleable* clone(StringPool* newPool) const override;
    void print(std::ostream* out) const override;
};

/**
 * Stream operator for printing Value objects.
 */
inline ::std::ostream& operator<<(::std::ostream& out, const Value& value) {
    value.print(&out);
    return out;
}

inline ::std::ostream& operator<<(::std::ostream& out, const Attribute::Symbol& s) {
    if (s.symbol.name) {
        out << s.symbol.name.value().entry;
    } else {
        out << "???";
    }
    return out << "=" << s.value;
}

} // namespace aapt

#endif // AAPT_RESOURCE_VALUES_H
