#pragma once

#include <functional>

#include "GeneratorTemplate.h"
#include "JsonExpression.h"
#include "Noise.h"

class StructureTemplateCollection : public virtual Framework::ReferenceCounter
{
private:
    Noise* activeNoise;
    Framework::JSON::JSONObject* activeNoiseConfig;
    Noise* structureNoise;
    Framework::JSON::JSONObject* structureNoiseConfig;
    double threshold;
    Framework::RCArray<GeneratorTemplate> structures;
    Framework::Vec3<int> minAffected;
    Framework::Vec3<int> maxAffected;
    JBoolExpression* condition;

public:
    StructureTemplateCollection();
    ~StructureTemplateCollection();
    void initialize(JExpressionMemory* zMemory);
    void generateStructures(int x,
        int y,
        int z,
        int dimensionId,
        JExpressionMemory* zMemory,
        Framework::Vec3<int> minPos,
        Framework::Vec3<int> maxPos,
        Framework::RCArray<GeneratedStructure>* zResult);

    void setThreshold(double threshold);
    double getThreshold() const;
    void setCondition(JBoolExpression* condition);
    JBoolExpression* zCondition() const;
    void setActiveNoiseConfig(Framework::JSON::JSONObject* activeNoiseConfig);
    Framework::JSON::JSONObject* zActiveNoiseConfig() const;
    void setStructureNoiseConfig(
        Framework::JSON::JSONObject* structureNoiseConfig);
    Framework::JSON::JSONObject* zStructureNoiseConfig() const;
    void addStructure(GeneratorTemplate* structure);
    const Framework::RCArray<GeneratorTemplate>& getStructures() const;
    Framework::Vec3<int> getMinAffected() const;
    Framework::Vec3<int> getMaxAffected() const;
};

class StructureTemplateCollectionFactory
    : public ObjectTypeFactory<StructureTemplateCollection>
{
public:
    StructureTemplateCollectionFactory();
    StructureTemplateCollection* fromJson(
        Framework::JSON::JSONObject* zJson) const override;
    Framework::JSON::JSONObject* toJsonObject(
        StructureTemplateCollection* zObject) const override;
    JSONObjectValidationBuilder* addToValidator(
        JSONObjectValidationBuilder* builder) const override;
};