#include "PivotGui.h"

#include "Matrix.h"
#include "Solver.h"
#include <imgui.h>
#include <sstream>

static std::string equationsResultImage;

static Matrix LoadMatrixFromStdVect(const std::vector<std::vector<int>>& data) {
	Matrix result {data.size(), data.empty() ? 0 : data[0].size()};
	for (std::size_t i = 0; i < result.GetRawCount(); i++) {
		for (std::size_t j = 0; j < result.GetColumnCount(); j++) {
			result.at(i, j) = static_cast<Matrix::Element>(data[i][j]);
		}
	}
	return result;
}

static std::string ElementToString(Matrix::Element e) {
	std::stringstream ss;
	ss << e;
	return ss.str();
}

static std::string PrintVect(const Vect& vect) {
	if (vect.GetCardinal() == 0)
		return "{0}";

	std::string result = "Vect( ";
	for (std::size_t i = 0; i < vect.GetCardinal(); i++) {
		Matrix vector = vect.GetVector(i);
		result += " (";
		for (std::size_t j = 0; j < vect.GetDimension(); j++) {
			result += ElementToString(vector.at(j, 0)) + ", ";
		}
		result = result.substr(0, result.size() - 2);
		result += " ), ";
	}
	result = result.substr(0, result.size() - 2);
	result += "  )";
	return result;
}

void PivotGui::Init() {}

void PivotGui::Render() {
	ImGuiIO& io = ImGui::GetIO();

	static std::vector<std::vector<int>> matrixValues;
	static int matrixSizeX = 4;
	static int matrixSizeY = 4;
	static Solver solver;

	static bool refresh = true;

	// divisions des fenetres
	ImVec2 topLeftWindowSize(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.8f);
	ImVec2 topRightWindowSize(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.8f);
	ImVec2 bottomWindowSize(io.DisplaySize.x, io.DisplaySize.y * 0.2f);

	// Begin fenetre top left
	ImGui::SetNextWindowSize(topLeftWindowSize);
	ImGui::SetNextWindowPos(ImVec2(0, 0));	// Position at the top-left corner
	ImGui::Begin("Left Top Window", nullptr,
		ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar);

	// Get window position
	ImVec2 windowPos = ImGui::GetWindowPos();

	ImGui::Text("Matrice initiale:");

	if (ImGui::InputInt("##RowsMatriceInitiale", &matrixSizeY))
		refresh = true;
	matrixSizeY = std::max(1, matrixSizeY);
	ImGui::SameLine();
	ImGui::Text("Lignes");


	if (ImGui::InputInt("##ColumnsMatriceInitiale", &matrixSizeX))
		refresh = true;
	matrixSizeX = std::max(1, matrixSizeX);
	ImGui::SameLine();
	ImGui::Text("Colonnes");

	ImGui::NewLine();

	ImGui::BeginChild("MatriceInitiale", ImVec2(topLeftWindowSize.x, io.DisplaySize.y * 0.7f), false);

	// Resize matrixValues and initialize new elements to 0

	if (refresh) {
		matrixValues.resize(matrixSizeY);
		for (auto& row : matrixValues) {
			row.resize(matrixSizeX, 0);
		}
	}

	for (int y = 0; y < matrixSizeY; y++) {
		for (int x = 0; x < matrixSizeX; x++) {
			if (x > 0)
				ImGui::SameLine();
			ImGui::PushID(y * matrixSizeX + x);
			ImGui::PushItemWidth(30);  // Adjust this value to change the cell size
			if (ImGui::InputInt("", &matrixValues[y][x], 0, 0, ImGuiInputTextFlags_CharsDecimal))
				refresh = true;
			ImGui::PopItemWidth();
			ImGui::PopID();
		}
	}

	// Display the equationsResult strings in the GUI if they are not empty
	if (!equationsResultImage.empty()) {
		ImGui::TextWrapped(equationsResultImage.c_str());
	}

	ImGui::EndChild();	// End Matrice initiale

	ImGui::End();  // End fenetre top left

	// Begin fenetre top right
	ImGui::SetNextWindowSize(topRightWindowSize);
	ImGui::SetNextWindowPos(ImVec2(windowPos.x + topLeftWindowSize.x, 0));	// Position at the top-right corner
	ImGui::Begin("Right Top Window", nullptr,
		ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar);

	// rajouter le code pour la partie top right

	static std::string result = "";

	ImGui::TextWrapped(result.c_str());

	ImGui::End();  // End fenetre top right

	// Begin fenetre bas
	ImGui::SetNextWindowSize(bottomWindowSize);
	ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y * 0.8f));  // Position at the bottom-left corner
	ImGui::Begin("Bottom Part", nullptr,
		ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar);

	if (refresh) {

		// Calculate the kernel and image
		Vect image = solver.Image(LoadMatrixFromStdVect(matrixValues));
		Matrix linearSystem = image.GetLinearSystem();

		// Store the equationsResult strings in the global variable
		equationsResultImage = "Equations cartesiennes de l'espace vectoriel (Image):\n";
		for (size_t i = 0; i < linearSystem.GetRawCount(); ++i) {
			for (size_t j = 0; j < linearSystem.GetColumnCount(); ++j) {
				equationsResultImage +=
					ElementToString(linearSystem.at(i, j)) + "*" + std::string {static_cast<char>('a' + j)} + " + ";
			}
			equationsResultImage = equationsResultImage.substr(0, equationsResultImage.size() - 3) + " = 0\n";
		}

		result = std::string("Noyau: ") + "\n" + PrintVect(solver.Kernel(LoadMatrixFromStdVect(matrixValues))) + "\n" + "\n" +
				 "Rang: " + "\n" + std::to_string(solver.Rank(LoadMatrixFromStdVect(matrixValues))) + "\n" + "\n" + "Image: " + "\n" +
				 PrintVect(image);
	}

	refresh = false;
	ImGui::End();  // End fenetre bas
}

void PivotGui::Destroy() {}