#pragma once

#include <Array.h>
#include <Punkt.h>
#include <Vec3.h>

#include "CaveGenerator.h"
#include "Noise.h"

class NoiseWorm3D : public Framework::ReferenceCounter
{
private:
    Framework::Punkt startChunk;
    Framework::Vec3<int> minAffected;
    Framework::Vec3<int> maxAffected;

    Framework::Array<Framework::Vec3<float>> keyPoints;
    Framework::Array<float> size;
    NoiseWorm3D();

public:
    NoiseWorm3D(Noise* pitch,
        Noise* yaw,
        Noise* size,
        Framework::Vec3<int> startPos,
        int distant,
        int minRad,
        int maxRad);
    Framework::Punkt getStartChunkCenter();
    void getPartAffectedByChunk(
        int x, int y, Framework::RCArray<NoiseWorm3D>* zResult);
    bool isInside(int x, int y, int z);
};

class WormCaveChunkGenerator : public CaveChunkGenerator
{
private:
    Framework::RCArray<NoiseWorm3D> worms;

public:
    WormCaveChunkGenerator(Framework::RCArray<NoiseWorm3D> worms);
    bool isInCave(int x, int y, int z) override;
};

class WormCaveGenerator : public CaveGenerator
{
private:
    int maxDistant;
    int minDistant;
    int maxRadius;
    int minRadius;
    float cavePosibillity;
    Noise* wormStartNoise;
    Framework::RCArray<NoiseWorm3D> cache;
    Framework::Array<Framework::Punkt> noWormChunks;

    NoiseWorm3D* zWormOfChunk(int x, int y);

public:
    WormCaveGenerator(int minDistant,
        int maxDistant,
        int minRadius,
        int maxRadius,
        float cavePosibillityPerChunk,
        int seed);
    ~WormCaveGenerator();

    CaveChunkGenerator* getGeneratorForChunk(int x, int y) override;
};