#include "Gui.h"
#include "ofAppRunner.h"

// @RemoteImgui begin
#include "imgui_remote.h"
// @RemoteImgui end

namespace ofxImGui
{
	//--------------------------------------------------------------
	Gui::Gui()
		: lastTime(0.0f)
		, theme(nullptr)
	{
		ImGui::CreateContext();
	}

	//--------------------------------------------------------------
	Gui::~Gui()
	{
		exit();
		ImGui::DestroyContext();
	}

	//--------------------------------------------------------------
	void Gui::setup(BaseTheme* theme_, bool autoDraw_) {
		ImGui::CreateContext();
		ImGuiIO& io = ImGui::GetIO();

		io.DisplaySize = ImVec2((float)ofGetWidth(), (float)ofGetHeight());
		io.MouseDrawCursor = false;

		autoDraw = autoDraw_;
		engine.setup(autoDraw);

		if (theme_)
		{
		    setTheme(theme_);
		}
		else
		{
		    DefaultTheme* defaultTheme = new DefaultTheme();
		    setTheme((BaseTheme*)defaultTheme);
		}

		ofDisableArbTex();

	}

	//--------------------------------------------------------------
	void Gui::exit()
	{
		engine.exit();
		if (theme)
		{
			delete theme;
			theme = nullptr;
		}
		for (size_t i = 0; i < loadedTextures.size(); i++)
		{
		    if(loadedTextures[i])
		    {
			delete loadedTextures[i];
			loadedTextures[i] = NULL;
		    }
		}
		loadedTextures.clear();

		ImGui::DestroyContext();
	}

	//--------------------------------------------------------------
	void Gui::setImGuiWindowColor(ofColor & color, float alpha) {
		// alpha range 0.0 - 1.0
		// it can be global and called once for all windows
		// or called every frame for different windows

		ImGuiStyle* style = &ImGui::GetStyle();
		style->Colors[ImGuiCol_WindowBg] = ImVec4(color, alpha);
	}

	//--------------------------------------------------------------
	void Gui::setInputTextFontColor(ofColor & color, float alpha) {
		ImGuiStyle* style = &ImGui::GetStyle();
		style->Colors[ImGuiCol_Text] = ImVec4(color, alpha);
		
		//text selected color
		//style->Colors[ImGuiCol_TextSelectedBg] = ImVec4(ofColor(0,0,255), 0.43f);
	}

	//--------------------------------------------------------------
	void Gui::setInputTextBackgroundColor(ofColor & color, float alpha) {
		ImGuiStyle* style = &ImGui::GetStyle();
		style->Colors[ImGuiCol_FrameBg] = ImVec4(color, alpha);
	}

	//--------------------------------------------------------------
	void Gui::pushInputTextDimension(float startCursorPosX, float fontSize, float inputTextWidth, float inputTextHeight) {
		
		float padY = (inputTextHeight - fontSize) / 2;
		ImGui::PushItemWidth(inputTextWidth);
		ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(startCursorPosX, padY));
	}

	//--------------------------------------------------------------
	void Gui::popInputTextDimension() {
		ImGui::PopItemWidth();
		ImGui::PopStyleVar();
	}

	//--------------------------------------------------------------
	void Gui::setTheme(BaseTheme* theme_) {
		if (theme) {
			delete theme;
			theme = nullptr;
		}
		theme = theme_;
		theme->setup();
	}

	//--------------------------------------------------------------
	GLuint Gui::loadPixels(ofPixels& pixels) {
		return engine.loadTextureImage2D(pixels.getData(), (int)pixels.getWidth(), (int)pixels.getHeight());
	}

	//--------------------------------------------------------------
	GLuint Gui::loadPixels(const std::string& imagePath) {
		ofPixels pixels;
		ofLoadImage(pixels, imagePath);
		return loadPixels(pixels);
	}

	//--------------------------------------------------------------
	GLuint Gui::loadImage(ofImage& image) {
		return loadPixels(image.getPixels());
	}

	//--------------------------------------------------------------
	GLuint Gui::loadImage(const std::string& imagePath) {
		return loadPixels(imagePath);
	}

	//--------------------------------------------------------------
	GLuint Gui::loadTexture(const std::string& imagePath) {
		ofDisableArbTex();
		ofTexture* texture = new ofTexture();
		ofLoadImage(*texture, imagePath);
		ofEnableArbTex();
		loadedTextures.push_back(texture);
		return texture->getTextureData().textureID;
	}

	//--------------------------------------------------------------
	GLuint Gui::loadTexture(ofTexture& texture, const std::string& imagePath) {
		bool isUsingArb = ofGetUsingArbTex();
		if (isUsingArb)	{
			ofDisableArbTex();
		}
		ofLoadImage(texture, imagePath);
		if (isUsingArb)	{
			ofEnableArbTex();
		}
		return texture.getTextureData().textureID;
	}

	//--------------------------------------------------------------
	void Gui::begin() {
		ImGuiIO& io = ImGui::GetIO();

		float currentTime = ofGetElapsedTimef();
		if (currentTime > lastTime)
		{
			io.DeltaTime = currentTime - lastTime;
			if(io.DeltaTime <= 0.0f) io.DeltaTime = 1.0f / 60.0f; //imgui requires delta > 0
		}
		else {
			io.DeltaTime = 1.0f / 60.f;
		}
		lastTime = currentTime;

		// Update settings
		io.MousePos = ImVec2((float)ofGetMouseX(), (float)ofGetMouseY());
		for (int i = 0; i < 5; i++) {
			io.MouseDown[i] = engine.mousePressed[i];
		}

		ImGui::RemoteUpdate();
		ImGui::RemoteInput input;
		ImGui::NewFrame();
	}

	//--------------------------------------------------------------
	void Gui::end()	{
		ImGui::Render();
	}

	//--------------------------------------------------------------
	void Gui::draw()
	{
		if (!autoDraw)
		{
			engine.draw();
		}
	}
}
