#ifndef TREE_HPP_
#define TREE_HPP_

#include <Decoration/Decoration.hpp>

/**
 * @brief Describes a tree decoration.
 */
class Tree : public Decoration
{
public:
    typedef std::function<double(const TerrainGenerator::Cell&, GeneratorNode)> Weighter;

    /**
     * @brief Describes the sculpture of a specific tree type.
     */
    class Sculpture
    {
    private:
        int minHeight;
        int maxHeight;
        std::string logBlock;

        int minRadius;
        int maxRadius;
        std::string leafBlock;

        void buildTrunk(ISculptor &sculptor, glm::ivec3 pos, int bottomZ, int topZ);
        void buildLeaves(ISculptor &sculptor, glm::ivec3 centerPos, int radius);
    
    public:
        Sculpture(
            int minHeight,
            int maxHeight,
            const char *logBlock,
            int minRadius,
            int maxRadius,
            const char *leafBlock = "main:leaves"
        );

        /**
         * @brief Build this tree.
         * 
         * @param sculptor The sculptor to build with.
         * @param radius The relative radius (0-1).
         * @param height The relative height (0-1).
         * @param pos The position of the bottom of the tree.
         */
        void build(ISculptor &sculptor, float radius, float height, glm::ivec3 pos);
    };

private:
    Weighter getCount;
    Sculpture &sculpture;

public:
    static constexpr uint8_t metaNaturalLogMask = (1 << 0);

    static Sculpture oak;
    static Sculpture birch;
    static Sculpture rubber;
    static Sculpture cactus;
    static Sculpture maple;

    /**
     * @brief Construct a tree.
     */
    Tree(
        Weighter getCount,
        Sculpture &sculpture
    );

    virtual void build(ISculptor &sculptor, GeneratorNode node, glm::ivec3 pos) override;
    virtual double getAverageDensity(const TerrainGenerator::Cell &cell, GeneratorNode node) override;
};

#endif