#pragma once

#define PARTICLESYSTEM typeid(ParticleSystem).name()

#include <random>
#include <vector>
#include "Vector3.hpp"
#include "Color.hpp"
#include "MathF.hpp"
#include "elements/BehaviourScript.hpp"

namespace TSE
{
    struct Particle
    {
    public:
        Vector3 position;
        float size;
        float rotationRad;
        Color color;

        float lifetime;
        Vector3 direction;
        float rotDirection;
    };

    class ParticleSystem : public BehaviourScript
    {
    public:
        //Random Rotation
        bool startWithRandomRotationDirection = false;
        float rotationDirection = 1; //1 or -1 //-> used if not random
        bool startWithRandomRotation = false;
        float minRotationRad = 0;
        float maxrotationRad = 2 * TSE_PI; //-> used if not random
        //Random Size
        bool startWithRandomSize = false;
        float minSize = 1;
        float maxSize = 2; //-> used if not random
        //Random Lifetime
        bool startWithRandomLifetime = false;
        float minLifetime = 1; // -> smallest possible lifetime
        float maxLifetime = 2; // -> biggest possible lifetime -> also the lifetime if not random
        //Color over Lifetime
        bool changeColorOverLifetime = false;
        Color startColor = Color::white;
        Color endColor = Color::white;
        //Speed over Lifetime
        bool changeSpeedOverLifetime = false;
        float startSpeed = 1;
        float endSpeed = 0.5f;
        //Ratationspeed over Lifetime
        bool changeRotationspeedOverLifetime = false;
        float startRotationSpeed = 1;
        float endRotationSpeed = 0.5f;
        //Rest
        uint particleCount = 10;
        bool startWithSimulatedParicles = false;

        //Spawn Area
        Vector3 offset;
        float conePlane = 1;
        float radius = 1;
        Vector3 forward = Vector3::forward;

    private:
        std::vector<Particle*> particles;
        float time;
        std::mt19937 rng;
        bool firstFrame = true;

    public:
        void OnUpdate() override;
        void Start() override;
        inline const char* GetName() override
        {
            return "Particle System";
        }
        const std::vector<Particle*>& GetParticles();

    private:
        void MoveParticle(Particle*& particle);
        void RotateParticle(Particle*& particle);
        void ColorParticle(Particle*& particle);
        void CreateParticle();
        float PlaneAsCosAlpha();
        bool InVolume(const Vector3& x);
        void BuildTangent(Vector3& t, Vector3& b);
        Vector3 SampleDirection(float u1, float u2);
        Vector3 samplePointInVolume(float u1, float u2, float u3);

        Vector3 SamplePointInVolume(std::mt19937& rng);
    };
    
} // namespace TSE
