#include "common.hpp"
#include <list>
#include <rlgl.h>

std::list<Particle> particles;
extern Camera3D camera;
extern Texture2D terrain;
static void DrawParticle(Particle particle, Color color)
{
    Vector3 position = particle.position;
    float x = position.x;
    float y = position.y;
    float z = position.z;
    float width = 0.25f;
    float height = width;
    float length = height;
    UVCorners corners = GetUVTex(particle.data[0], width, width, width, width);
    UVCorners front = corners;
    UVCorners back = corners;
    UVCorners top = corners;
    UVCorners bottom = corners;
    UVCorners left = corners;
    UVCorners right = corners;
    // Set desired texture to be enabled while drawing following vertex data
    rlSetTexture(terrain.id);
    rlBegin(RL_QUADS);
        rlColor4ub(color.r, color.g, color.b, color.a);
        // Front Face
        rlNormal3f(0.0f, 0.0f, 1.0f);       // Normal Pointing Towards Viewer
        rlTexCoord2f(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2);  // Bottom Left Of The Texture and Quad
        rlTexCoord2f(front.corner1.x, front.corner1.y); rlVertex3f(x + width/2, y - height/2, z + length/2);  // Bottom Right Of The Texture and Quad
        rlTexCoord2f(front.corner2.x, front.corner2.y); rlVertex3f(x + width/2, y + height/2, z + length/2);  // Top Right Of The Texture and Quad
        rlTexCoord2f(front.corner3.x, front.corner3.y); rlVertex3f(x - width/2, y + height/2, z + length/2);  // Top Left Of The Texture and Quad
        // Back Face
        rlNormal3f(0.0f, 0.0f, - 1.0f);     // Normal Pointing Away From Viewer
        rlTexCoord2f(back.corner1.x, back.corner1.y); rlVertex3f(x - width/2, y - height/2, z - length/2);  // Bottom Right Of The Texture and Quad
        rlTexCoord2f(back.corner2.x, back.corner2.y); rlVertex3f(x - width/2, y + height/2, z - length/2);  // Top Right Of The Texture and Quad
        rlTexCoord2f(back.corner3.x, back.corner3.y); rlVertex3f(x + width/2, y + height/2, z - length/2);  // Top Left Of The Texture and Quad
        rlTexCoord2f(back.corner0.x, back.corner0.y); rlVertex3f(x + width/2, y - height/2, z - length/2);  // Bottom Left Of The Texture and Quad
        // Top Face
        rlNormal3f(0.0f, 1.0f, 0.0f);       // Normal Pointing Up
        rlTexCoord2f(top.corner3.x, top.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2);  // Top Left Of The Texture and Quad
        rlTexCoord2f(top.corner0.x, top.corner0.y); rlVertex3f(x - width/2, y + height/2, z + length/2);  // Bottom Left Of The Texture and Quad
        rlTexCoord2f(top.corner1.x, top.corner1.y); rlVertex3f(x + width/2, y + height/2, z + length/2);  // Bottom Right Of The Texture and Quad
        rlTexCoord2f(top.corner2.x, top.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2);  // Top Right Of The Texture and Quad
        // Bottom Face
        rlNormal3f(0.0f, - 1.0f, 0.0f);     // Normal Pointing Down
        rlTexCoord2f(bottom.corner2.x, bottom.corner2.y); rlVertex3f(x - width/2, y - height/2, z - length/2);  // Top Right Of The Texture and Quad
        rlTexCoord2f(bottom.corner3.x, bottom.corner3.y); rlVertex3f(x + width/2, y - height/2, z - length/2);  // Top Left Of The Texture and Quad
        rlTexCoord2f(bottom.corner0.x, bottom.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2);  // Bottom Left Of The Texture and Quad
        rlTexCoord2f(bottom.corner1.x, bottom.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2);  // Bottom Right Of The Texture and Quad
        // Right face
        rlNormal3f(1.0f, 0.0f, 0.0f);       // Normal Pointing Right
        rlTexCoord2f(right.corner1.x, right.corner1.y); rlVertex3f(x + width/2, y - height/2, z - length/2);  // Bottom Right Of The Texture and Quad
        rlTexCoord2f(right.corner2.x, right.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2);  // Top Right Of The Texture and Quad
        rlTexCoord2f(right.corner3.x, right.corner3.y); rlVertex3f(x + width/2, y + height/2, z + length/2);  // Top Left Of The Texture and Quad
        rlTexCoord2f(right.corner0.x, right.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2);  // Bottom Left Of The Texture and Quad
        // Left Face
        rlNormal3f( - 1.0f, 0.0f, 0.0f);    // Normal Pointing Left
        rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(x - width/2, y - height/2, z - length/2);  // Bottom Left Of The Texture and Quad
        rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2);  // Bottom Right Of The Texture and Quad
        rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(x - width/2, y + height/2, z + length/2);  // Top Right Of The Texture and Quad
        rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2);  // Top Left Of The Texture and Quad
    rlEnd();

    rlSetTexture(0);
}
void ParticlesUpdate(float dt, Chunk world[]) {
    particles.remove_if([](Particle x) { return x.lifetime > 200; });
    for (Particle &part : particles)
    {
        part.lifetime++;
        if(part.physicsType == Phys_Falling) {
            Vector3 velocityTgt = Vector3Clamp(Vector3Add(part.velocity, {0, -dt * 9.8f, 0}), {-30.0f, -30.0f, 0-30.0f}, {30.0f, 30.0f, 30.0f});

            Vector3 tgt = Vector3Add(part.position, Vector3Scale(velocityTgt, dt));
            Vector3 vis = Vector3Add(tgt, {0.5f, 0.4f, 0.5f});
            Vector3 final = part.position;
            if(!GetBlock(world, (int)vis.x, (int)final.y, (int)final.z)) {
                final.x = tgt.x;
            }
            if(!GetBlock(world, (int)final.x, (int)vis.y, (int)final.z)) {
                final.y = tgt.y;
            }
            else {
                velocityTgt.y = 0;
            }
            if(!GetBlock(world, (int)final.x, (int)final.y, (int)vis.z)) {
                final.z = tgt.z;
            }
            for (Particle &part2 : particles)
            {
                if(Vector3DistanceSqr(part.position, part2.position) < 0.25f*0.25f) {
                    Vector3 force = Vector3Normalize(Vector3Subtract(part.position, part2.position)) * dt * 25;
                    part.velocity += force;
                    part2.velocity -= force;
                }
            }
            part.position = final;
            part.velocity = velocityTgt;
        }
    }
}
void ParticlesDraw() {
    for (Particle part : particles)
    {
        DrawParticle(part, WHITE);
    }
}
void AddParticle(Particle part) {
    particles.push_back(part);
}
Particle NewParticle(Vector3 position) {
    Particle part;
    part.physicsType = Phys_Falling;
    part.position = position;
    part.texture = terrain;
    return part;
}