#ifndef SERVER
#include "common.hpp"
#include <cstring>
#include <raymath.h>
#include <iostream>
#include <filesystem>
#include "yaml-cpp/yaml.h"
#define CONFIG_LOC "config.yaml"

static bool IsMouseMoving() {
    return GetMouseDelta().x > 0.01f || GetMouseDelta().y > 0.01f;
}

// Config

std::map <std::string, int> controls = {
    {"forward", KEY_W},
    {"left", KEY_A},
    {"back", KEY_S},
    {"right", KEY_D},
    {"jump", KEY_SPACE},
    {"shift", KEY_LEFT_SHIFT},
    {"speed_up", KEY_LEFT_CONTROL},
    {"fly", KEY_V},
    {"inventory", KEY_E},
    {"chat", KEY_APOSTROPHE}
};

bool swap_mouse = false; // H1N1 mode (wink)
bool InputGetKeyDown(const std::string name) {
    return IsKeyDown(controls.at(name));
}
bool InputGetKeyPressed(const std::string name) {
    return IsKeyPressed(controls.at(name));
}
bool InputGetLMB() {
    if(swap_mouse) {
        return IsMouseButtonPressed(MOUSE_RIGHT_BUTTON);
    }
    else {
        return IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
    }
}
bool InputGetLMBDown() {
    if(swap_mouse) {
        return IsMouseButtonDown(MOUSE_RIGHT_BUTTON);
    }
    else {
        return IsMouseButtonDown(MOUSE_LEFT_BUTTON);
    }
}
bool InputGetRMB() {
    if(swap_mouse) {
        return IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
    }
    else {
        return IsMouseButtonPressed(MOUSE_RIGHT_BUTTON);
    }
}
Vector2 InputGetWalkAxis() {
    bool isJoystick = IsGamepadAvailable(0);
    float x = 0;
    float y = 0;
    if(isJoystick) {
        x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X);
        y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y);
        if(abs(x) < 0.5f) {
            x = 0;
        }
        if(abs(y) < 0.5f) {
            y = 0;
        }
    }
    
    if (InputGetKeyDown("forward")) { y =  1; }
    if (InputGetKeyDown("back")) { y = -1; }
    if (InputGetKeyDown("right")) { x =  1; }
    if (InputGetKeyDown("left")) { x = -1; }

    return {x, y};
}
Vector2 InputGetLookAxis() {
    bool isJoystick = IsGamepadAvailable(0);
    float x = 0;
    float y = 0;
    if(isJoystick) {
        x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X);
        y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y);
        if(abs(x) < 0.1f) {
            x = 0;
        }
        if(abs(y) < 0.1f) {
            y = 0;
        }
        return {x, y};
    }
    else {
        return GetMouseDelta();
    }
}
Vector2 InputGetDPAD() {
    bool isJoystick = IsGamepadAvailable(0);
    float x = 0.0f;
    float y = 0.0f;
    if(isJoystick) {
        if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_UP)) { y =  1; }
        if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) { y = -1; }
        if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) { x =  1; }
        if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) { x = -1; }
    }
    return {x, y};
}
void InputWriteControls() {
    YAML::Emitter out;
    out << YAML::BeginMap;

    out << YAML::Key << "Mapped controls";
    out << YAML::Value << controls;
    out << YAML::Key << "Swap mouse buttons";
    out << YAML::Value << swap_mouse;
    
    out << YAML::EndMap;
    FILE* file = fopen(CONFIG_LOC, "w" );
    fprintf( file, out.c_str());
    fclose( file );
}
void InputInit() {
    if(!FileExists(CONFIG_LOC)) {
        InputWriteControls();
    }
    else {
        YAML::Node config = YAML::LoadFile(CONFIG_LOC);
        const std::map<std::string, int> _controls = config["Mapped controls"].as<std::map<std::string, int>>();
        for (auto const& [key, val] : _controls)
        {
            controls[key] = val;
        }

        
        swap_mouse = config["Swap mouse buttons"].as<bool>();
    }
}
void InputUpdate() {

}

#endif