#include <iostream>

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

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

#include "internal.h"
#include "internal/physics.h"
#include "ui.h"
#include "uielements.h"
#include "utils.h"

using namespace kek;

static ButtonElement *button;

void periodicCallback(PeriodicEvent event, void *data) {
}

void keyCallback(KeyEvent event, void *data) {
}

void mouseButtonCallback(MouseButtonEvent event, void *data) {
}

void onButtonClick(void *data) {
	if(button->color == Colors::RED) {
		button->color = Colors::GREEN;
		button->hoverColor = Colors::GREEN.darker();
	} else {
		button->color = Colors::RED;
		button->hoverColor = Colors::RED.darker();
	}
}

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);
	}

	GameObject *wall = new GameObject();
	{
		std::shared_ptr<Texture> tex = Texture::load("image/white.png");
		wall->addMesh(genCubeMesh(1, 10, 50, tex, tex, tex));
		btCollisionShape *shape = new btBoxShape(btVector3(0.5, 5, 25));
		wall->addPhysics(shape, 0, btCollisionObject::CF_STATIC_OBJECT);
		wall->moveTo(glm::vec3(0, 2.5, 0));
		wall->rotate(M_PI / 4, glm::vec3(0, 0, 1));
		scene->addObject(wall);
	}

	/*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, 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);

	ButtonElement *button2 = new ButtonElement(uiPx(10), uiPx(125), uiPx(200), uiPx(50));
	button2->text->color = Colors::WHITE;
	button2->color = Colors::ORANGE;
	button2->hoverColor = Colors::RED;
	button2->text->setText("Hi there!");
	UI::addElement(button2);

	ButtonElement *button3 = new ButtonElement(uiPx(10), uiPx(100), uiPx(200), uiPx(50));
	button3->origin = Origin::BOTTOM_LEFT;
	RectangleElement *rect = new RectangleElement(uiPx(0), uiPx(0), uiPw(0.5), uiPh(0.5));
	button3->addChild(rect);
	UI::addElement(button3);

	RectangleElement *rect2 = new RectangleElement(uiPx(0), uiSh(0.5), uiPx(500), uiPx(250));
	rect2->origin = Origin::LEFT_CENTER;
	rect2->enableClipping = true;
	UI::addElement(rect2);

	TextFieldElement *textField = new TextFieldElement(uiPx(0), uiPh(1) - uiPx(10), uiPx(500));
	textField->origin = kek::Origin::BOTTOM_LEFT;
	textField->color = Colors::GREEN;
	textField->focusColor = Colors::RED;
	textField->textElement->color = Colors::WHITE;

	struct es {
		ButtonElement *b;
		TextFieldElement *t;

		~es() {
			std::cout << "oh nyo, I got destroyed" << std::endl;
		}
	} e;

	e.b = button3;
	e.t = textField;

	textField->onSubmit = SubmitCallback([](std::string text, void *data) {
		es *ep = (es *) data;
		ep->b->text->setText(text);
		ep->t->setText("");
		ep->t->onSubmit = SubmitCallback();
	},
		&e);
	rect2->addChild(textField);

	TextElement *text = new TextElement(uiPx(0), uiPx(0));
	text->setText("Lorem ipsum dolorg");
	text->textMode = TextMode::ORIGIN;
	text->textBounds = TextBounds::SMALLEST;

	UIBounds bounds = text->getBounds();
	RectangleElement *box = new RectangleElement(uiPx(bounds.x), uiPx(bounds.y), uiPx(bounds.w), uiPx(bounds.h));
	box->color = Colors::GRAY;
	rect2->addChild(box);
	rect2->addChild(text);

	UIWindow *window = new UIWindow(uiPx(0), uiPx(0), uiPx(720), uiPx(480));
	UI::addElement(window);

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