#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>

#include "hash.h"
#include "base.h"
#include "move.h"
#include "entities.h"
#include "display.h"
#include "proj.h"

projectile* bullets ;
int bullets_id ;

int MAX_PROJ = 2048 ;

void init_proj() {
    bullets = malloc(sizeof(projectile)*MAX_PROJ);
    for(int k = 0; k < MAX_PROJ; k++) {
        bullets[k].pos = malloc(sizeof(cube_0));
        bullets[k].vel = malloc(sizeof(pt_2d));
        bullets[k].acc = malloc(sizeof(pt_2d));
        bullets[k].ttl = malloc(sizeof(double));
    }
}

void free_proj() {
    for(int k = 0; k < MAX_PROJ; k++) {
        free(bullets[k].acc);
        free(bullets[k].vel);
        free(bullets[k].pos);
        free(bullets[k].ttl);
    }
    free(bullets);
}

void resetProj() {
    bullets_id = 0;
}

void appendProj(double x, double y, double z, double w, double h, double d, double vx, double vy, double vz, double ax, double ay, double az, int red, int green, int blue, int dmg, double ttl) {
    if(bullets_id < MAX_PROJ) {
        fill_cube_0(bullets[bullets_id].pos, x, y, z, w, h, d, 0.0, 0.0, red, green, blue);
        bullets[bullets_id].vel->x = vx;
        bullets[bullets_id].vel->y = vy;
        bullets[bullets_id].vel->z = vz;
        bullets[bullets_id].acc->x = ax;
        bullets[bullets_id].acc->y = ay;
        bullets[bullets_id].acc->z = az;
        *(bullets[bullets_id].ttl) = ttl;
        bullets[bullets_id].damage = dmg;

        bullets_id += 1;
    }
}

void removeProj(int k) {
    if(k >= 0 && k < bullets_id) {
        copy_cube(bullets[bullets_id-1].pos, bullets[k].pos);

        bullets[k].damage = bullets[bullets_id-1].damage;
        *(bullets[k].ttl) = *(bullets[bullets_id-1].ttl);

        bullets[k].acc->x = bullets[bullets_id-1].acc->x;
        bullets[k].acc->y = bullets[bullets_id-1].acc->y;
        bullets[k].acc->z = bullets[bullets_id-1].acc->z;
        bullets[k].vel->x = bullets[bullets_id-1].vel->x;
        bullets[k].vel->y = bullets[bullets_id-1].vel->y;
        bullets[k].vel->z = bullets[bullets_id-1].vel->z;

        bullets_id -= 1;
    }
}

void gl_renderProj() {
    gl_resetTexture();
    for(int k = 0; k < bullets_id; k++) {
        gl_renderCube(bullets[k].pos, 0.0, 0.0, 0.0);
    }
}

void move_cube(cube_0* cb, double dx, double dy, double dz) {
    cb->x += dx;
    cb->y += dy;
    cb->z += dz;
}

void updateProj(float dtime) {
    //printf("%d\n", bullets_id);
    for(int k = 0; k < bullets_id; k++) {
        *(bullets[k].ttl) -= 50.0*(double)dtime;
        if(*(bullets[k].ttl) <= 0.0 || is_colliding_with_map(bullets[k].pos) || is_colliding_with_tp(bullets[k].pos)) {
            removeProj(k);
            k -= 1;
        } else if(distance_pt_cube_0_3d(camx, camy, camz, bullets[k].pos) <= min_dist) {
            player_hp -= bullets[k].damage;
            removeProj(k);
            k -= 1;
        } else {
            bullets[k].vel->x += ((double)dtime)*bullets[k].acc->x;
            bullets[k].vel->y += ((double)dtime)*bullets[k].acc->y;
            bullets[k].vel->z += ((double)dtime)*bullets[k].acc->z;
            move_cube(bullets[k].pos, ((double)dtime)*bullets[k].vel->x, ((double)dtime)*bullets[k].vel->y, ((double)dtime)*bullets[k].vel->z);
        }
    }
}