#include <iostream>

#include "kekengine.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <BulletCollision/CollisionShapes/btBoxShape.h>
#include <BulletCollision/btBulletCollisionCommon.h>
#include <BulletCollision/btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>

#include "internal.h"
#include "internal/physics.h"

using namespace kek;

static ButtonElement *button;
static KeyboardCapture capture = KEK_INVALID_ID;

void periodicCallback(GLFWwindow *window, void *data){

}

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

}

void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods, void *data){

}

void onButtonClick(void *data) {
	button->color = Colors::RED;
	capture = Input::captureKeyboardInput(KeyCharCallback([](GLFWwindow *window, unsigned int codepoint, void *data) {
		std::u32string str = Unicode::convertStdToU32(button->text->getText());
		if(codepoint == KEK_INPUT_DELETE) {
			str = str.substr(0, str.length() - 1);
		}else {
			str.push_back(codepoint);
		}
		button->text->setText(Unicode::convertU32ToStd(str));
	}, nullptr), KeyCallback([](GLFWwindow *window, int key, int scancode, int action, int mods, void *data) {
		if(key == GLFW_KEY_ENTER && action == GLFW_PRESS) {
			Input::uncaptureKeyboardInput(capture);
		}
	}, nullptr), Callable([](void *data) {
		button->color = Colors::WHITE;
	}, nullptr));
}

int main(int argc, char **argv) {
	if(Engine::init() != KEK_SUCCESS) return 1;

	Scene *scene = new Scene();

	GameObject *floor = new GameObject();
	{
		std::shared_ptr<Texture> tex = Texture::load("image/white.png");
		floor->addMesh(genCubeMesh(100, 1, 100, tex, tex, tex));
		btCollisionShape *shape = new btBoxShape(btVector3(50,0.5,50));
		floor->addPhysics(shape, 0, btCollisionObject::CF_STATIC_OBJECT);
		scene->addObject(floor);
	}

	Mesh *mesh = ObjParser::loadMesh("object/sphere/Sphere.obj");
	GameObject *test = new GameObject();
	btCollisionShape *shape = new btSphereShape(1);
	test->addPhysics(shape, 10);
	test->addMesh(mesh);
	test->moveTo(glm::vec3(0,5,0));
	scene->addObject(test);

	Mesh *mesh2 = ObjParser::loadMesh("object/cube_colored/Cube.obj");
	GameObject *test3 = new GameObject();
	btCollisionShape *shape2 = new btBoxShape(btVector3(1,1,1));
	test3->addPhysics(shape2, 0, btCollisionObject::CF_STATIC_OBJECT);
	test3->addMesh(mesh2);
	test3->moveTo(glm::vec3(2, 1, 2));
	scene->addObject(test3);

	for(int i = 0; i < 10; i++) {
		GameObject *test2 = new GameObject();
		btCollisionShape *shape = new btBoxShape(btVector3(1,1,1));
		test2->addPhysics(shape, 10);
		test2->addMesh(ObjParser::loadMesh("object/cube_colored/Cube.obj"));
		test2->moveTo(glm::vec3(1.0f, 5.0f, 3 * i));
		scene->addObject(test2);
	}

	PointLight *light = new PointLight(glm::vec3(1), 1, 0, 1);
	light->moveTo(glm::vec3(0,1,0));
	scene->lights->add(light);

	//DirectionalLight *l = new DirectionalLight(glm::vec3(1), glm::vec3(1, -1, 1));
	//scene->lights->add(l);

	//SpotLight *spot = new SpotLight(glm::vec3(1), glm::vec3(0, 0, -1), 1, 0, 1, glm::radians(8.0f), glm::radians(15.0f));
	//spot->moveTo(glm::vec3(0, 0, 5));
	//scene->lights->add(spot);

	Engine::setActiveScene(scene);

	Input::addPeriodicCallback(PeriodicCallback(periodicCallback, nullptr));
	Input::addKeyListener(KeyCallback(keyCallback, nullptr));
	Input::addMouseButtonListener(MouseButtonCallback(mouseButtonCallback, nullptr));

	button = new ButtonElement(uiPx(10), uiPx(100), uiPx(200), uiPx(50));
	button->text->color = Colors::BLACK;
	button->color = Colors::WHITE;
	button->hoverColor = Colors::GRAY;
	button->text->setText("Hello There!");
	button->onClick = Callable(onButtonClick, nullptr);
	UI::addElement(button);

	if(Engine::start() != KEK_SUCCESS) return 1;
	return 0;
}
