#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <math.h>
#include "include/input.h"
#include "include/logger.h"
#include "include/matrix.h"
#include "include/player.h"
#include "include/render.h"
#include <stdio.h>

int wwidth = 640, wheight = 480;
double mouseX, mouseY;
extern Player player;

#define _MOUSESEN 0.0005
#define __MOVESPEED_BASE (1.5/TARGETTPS) // 1.5m/s
#define __MOVESPEED (glfwGetKey(main_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS ? __MOVESPEED_BASE*1.5: __MOVESPEED_BASE)
#define _MOVESPEED (__MOVESPEED*deltaTime)
#define __unit_vector (vec4){0, 0, 0}

void reloadShaders();
int waiting = 0;

extern float deltaTime;
extern int skibiloper, advanced;

extern struct object **objects;

// so the problem is that glfw only handles 1 event at a time so mouse & keyboard at the same time = only one, usually mouse, so the callbacks are useless
void update() {

    // TODO more complex
    if (glfwGetKey(main_window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_F1) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_F3) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_F9) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_F12) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_PAUSE) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS &&
        glfwGetKey(main_window, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS
    ) {
        skibiloper = 1;
        logData(LOGLEVEL_CRIT, "Developer detected, gl nigga", __FILE__, __LINE__, NULL);
    }

    if(glfwGetKey(main_window, GLFW_KEY_F5) == GLFW_PRESS) advanced = 1;
    if (glfwGetKey(main_window, GLFW_KEY_F6) == GLFW_PRESS) advanced = 0;

    glfwGetWindowSize(main_window, &wwidth, &wheight);
    glfwGetCursorPos(main_window, &mouseX, &mouseY);
    // ##### KEYBOARD #####
    // ## Debug ##
    if ((glfwGetKey(main_window, GLFW_KEY_PAUSE) == GLFW_PRESS ? (waiting = 1,0):waiting)) {
        reloadShaders();
        waiting = !waiting;
    } 
    /*if (glfwGetKey(main_window, GLFW_KEY_PAGE_UP) == GLFW_PRESS) {
        char name[512] = {0};
        printf("Path to model location: ");
        scanf("%s", name);
        loadModel(name);
    }*/
    // ## Movement ##

    if(glfwGetKey(main_window, GLFW_KEY_ESCAPE)) glfwSetWindowShouldClose(main_window, GLFW_TRUE);
    if (glfwGetKey(main_window, GLFW_KEY_W) == GLFW_PRESS) {
        player.position = addVec4(player.position, rotateVec4((vec4){0, 0, -_MOVESPEED, 0}, player.rotation));
    }
    if (glfwGetKey(main_window, GLFW_KEY_S) == GLFW_PRESS) {
        player.position = addVec4(player.position, rotateVec4((vec4){0, 0, _MOVESPEED, 0}, player.rotation));
    }
    if (glfwGetKey(main_window, GLFW_KEY_A) == GLFW_PRESS) {
        player.position = addVec4(player.position, rotateVec4((vec4){-_MOVESPEED, 0, 0, 0}, player.rotation));
    }
    if (glfwGetKey(main_window, GLFW_KEY_D) == GLFW_PRESS) {
        player.position = addVec4(player.position, rotateVec4((vec4){_MOVESPEED, 0, 0, 0}, player.rotation));
    }
    if (glfwGetKey(main_window, GLFW_KEY_SPACE) == GLFW_PRESS) {
        player.position = addVec4(player.position, rotateVec4((vec4){0, _MOVESPEED, 0, 0}, player.rotation));
    }
    if (glfwGetKey(main_window, GLFW_KEY_C) == GLFW_PRESS) {
        player.position = addVec4(player.position, rotateVec4((vec4){0, -_MOVESPEED, 0, 0}, player.rotation));
    }

    if (glfwGetKey(main_window, GLFW_KEY_DOWN)) {
        objects[1]->position.y -=_MOVESPEED;
    }
    if (glfwGetKey(main_window, GLFW_KEY_UP)) {
        objects[1]->position.y +=_MOVESPEED;
    }
    if (glfwGetKey(main_window, GLFW_KEY_LEFT)) {
        objects[1]->position.x -=_MOVESPEED;
    }
    if (glfwGetKey(main_window, GLFW_KEY_RIGHT)) {
        objects[1]->position.x +=_MOVESPEED;
    }

    player.rotation = (vec4){-mouseY*_MOUSESEN, -mouseX*_MOUSESEN, 0, 1};
}

void mousePosCallback(GLFWwindow* window, double xpos, double ypos) {
}

void keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{

}
void windowCloseCallback(GLFWwindow *window) {
    glfwSetWindowShouldClose(window, GLFW_TRUE);
}
void windowResizedCallback(GLFWwindow* window, int width, int height) {
    glfwSetWindowSize(window, width, height);
    logData(LOGLEVEL_DEBUG, "Window resized", __FILE__, __LINE__, NULL);
    wwidth = width;
    wheight = height;
    glViewport(0,0,width, height);
}