#include "arc/input/keyboard.h"
#include "keyboard.h"
#include "input.h"
#include "arc/math/point.h"
#include "arc/std/errno.h"
#include <stdlib.h>
#include <stdint.h>
#include <SDL_keyboard.h>
#include <SDL_events.h>

void ARC_Keyboard_CreateWithInput(ARC_Keyboard **keyboard, ARC_Input *input){
    *keyboard = (ARC_Keyboard *)malloc(sizeof(ARC_Keyboard));
    (*keyboard)->event = input->event;
    (*keyboard)->keys  = (ARC_KeyboardState *)malloc(sizeof(ARC_KeyboardState) * ARC_KEYBOARD_BUTTON_NUM);

    (*keyboard)->released = NULL;

    for(uint8_t i = 0; i < ARC_KEYBOARD_BUTTON_NUM; i++){
        (*keyboard)->keys[i] = ARC_KEY_NONE;
    }
}

void ARC_Keyboard_Destroy(ARC_Keyboard *keyboard){
    free(keyboard->keys);

    free(keyboard);
}

void ARC_Keyboard_Update(ARC_Keyboard *keyboard){
    if(keyboard->released){
        *keyboard->released = ARC_KEY_NONE;
        keyboard->released = NULL;
    }

    if(keyboard->event->type != SDL_KEYDOWN && keyboard->event->type != SDL_KEYUP){
        return;
    }

    if(keyboard->event->key.keysym.sym >= 239 || keyboard->event->key.keysym.sym < 0){
        return;
    }

    if(keyboard->event->type == SDL_KEYDOWN){
        keyboard->keys[keyboard->event->key.keysym.sym] = ARC_KEY_PRESSED;
        return;
    }

    keyboard->keys[keyboard->event->key.keysym.sym] = ARC_KEY_RELEASED;
    keyboard->released = (keyboard->keys + keyboard->event->key.keysym.sym);
}

ARC_KeyboardState ARC_Keyboard_GetState(ARC_Keyboard *keyboard, enum ARC_KeyboardKey key){
    switch(key){
        case ARC_KEY_A: return keyboard->keys[SDLK_a];
        case ARC_KEY_B: return keyboard->keys[SDLK_b];
        case ARC_KEY_C: return keyboard->keys[SDLK_c];
        case ARC_KEY_D: return keyboard->keys[SDLK_d];
        case ARC_KEY_E: return keyboard->keys[SDLK_e];
        case ARC_KEY_F: return keyboard->keys[SDLK_f];
        case ARC_KEY_G: return keyboard->keys[SDLK_g];
        case ARC_KEY_H: return keyboard->keys[SDLK_h];
        case ARC_KEY_I: return keyboard->keys[SDLK_i];
        case ARC_KEY_J: return keyboard->keys[SDLK_j];
        case ARC_KEY_K: return keyboard->keys[SDLK_k];
        case ARC_KEY_L: return keyboard->keys[SDLK_l];
        case ARC_KEY_M: return keyboard->keys[SDLK_m];
        case ARC_KEY_N: return keyboard->keys[SDLK_n];
        case ARC_KEY_O: return keyboard->keys[SDLK_o];
        case ARC_KEY_P: return keyboard->keys[SDLK_p];
        case ARC_KEY_Q: return keyboard->keys[SDLK_q];
        case ARC_KEY_R: return keyboard->keys[SDLK_r];
        case ARC_KEY_S: return keyboard->keys[SDLK_s];
        case ARC_KEY_T: return keyboard->keys[SDLK_t];
        case ARC_KEY_U: return keyboard->keys[SDLK_u];
        case ARC_KEY_V: return keyboard->keys[SDLK_v];
        case ARC_KEY_W: return keyboard->keys[SDLK_w];
        case ARC_KEY_X: return keyboard->keys[SDLK_x];
        case ARC_KEY_Y: return keyboard->keys[SDLK_y];
        case ARC_KEY_Z: return keyboard->keys[SDLK_z];

        case ARC_KEY_0: return keyboard->keys[SDLK_0];
        case ARC_KEY_1: return keyboard->keys[SDLK_1];
        case ARC_KEY_2: return keyboard->keys[SDLK_2];
        case ARC_KEY_3: return keyboard->keys[SDLK_3];
        case ARC_KEY_4: return keyboard->keys[SDLK_4];
        case ARC_KEY_5: return keyboard->keys[SDLK_5];
        case ARC_KEY_6: return keyboard->keys[SDLK_6];
        case ARC_KEY_7: return keyboard->keys[SDLK_7];
        case ARC_KEY_8: return keyboard->keys[SDLK_8];
        case ARC_KEY_9: return keyboard->keys[SDLK_9];

        case ARC_KEY_SPACE: return keyboard->keys[SDLK_SPACE ];
        case ARC_KEY_ESC:   return keyboard->keys[SDLK_ESCAPE];
        case ARC_KEY_ENTER: return keyboard->keys[SDLK_RETURN];

        default: return ARC_KEY_NONE;
    }
}