#include "TextModel.h"
#include <regex>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#ifdef __ANDROID__
#include <android/log.h>
#endif
namespace ZL
{


	VertexDataStruct LoadFromTextFile(const std::string& fileName,  const std::string& ZIPFileName)
	{
		VertexDataStruct result;
		std::ifstream filestream;
		std::istringstream zipStream;
	
		if (!ZIPFileName.empty())
		{
			std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
			std::string fileContents(fileData.begin(), fileData.end());
			zipStream.str(fileContents);
		}
		else
		{
			filestream.open(fileName);
		}
	
		// Создаем ссылку f на нужный поток – после этого код ниже остается без изменений
		std::istream& f = (!ZIPFileName.empty()) ? static_cast<std::istream&>(zipStream) : static_cast<std::istream&>(filestream);
	

		//Skip first 5 lines
		std::string tempLine;	

		std::getline(f, tempLine);

		static const std::regex pattern_count(R"(\d+)");
		static const std::regex pattern_float(R"([-]?\d+\.\d+)");
		static const std::regex pattern_int(R"([-]?\d+)");


		std::smatch match;

		int numberVertices;

		if (std::regex_search(tempLine, match, pattern_count)) {
			std::string number_str = match.str();
			numberVertices = std::stoi(number_str);
		}
		else {
			std::cout << "No number found in the input string: " << tempLine << std::endl;
			throw std::runtime_error("No number found in the input string.");
		}

		std::vector<Vector3f> vertices;

		vertices.resize(numberVertices);
		for (int i = 0; i < numberVertices; i++)
		{
			std::getline(f, tempLine);

			std::vector<float> floatValues;

			auto b = tempLine.cbegin();
			auto e = tempLine.cend();
			while (std::regex_search(b, e, match, pattern_float)) {
				floatValues.push_back(std::stof(match.str()));
				b = match.suffix().first;
			}

			vertices[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
		}

		std::cout << "UV Coordinates" << std::endl;

		std::getline(f, tempLine); //===UV Coordinates:

		std::getline(f, tempLine); //triangle count
		int numberTriangles;

		if (std::regex_search(tempLine, match, pattern_count)) {
			std::string number_str = match.str();
			numberTriangles = std::stoi(number_str);
		}
		else {
			std::cout << "-No number found in the input string: " << tempLine << std::endl;
			throw std::runtime_error("-No number found in the input string.");
		}


		// Now process UVs
		std::vector<std::array<Vector2f, 3>> uvCoords;

		uvCoords.resize(numberTriangles);

		for (int i = 0; i < numberTriangles; i++)
		{
			std::getline(f, tempLine); //Face 0

			int uvCount;
			std::getline(f, tempLine);
			if (std::regex_search(tempLine, match, pattern_count)) {
				std::string number_str = match.str();
				uvCount = std::stoi(number_str);
			}
			else {
				std::cout << "2 No number found in the input string: " << tempLine << std::endl;
				throw std::runtime_error("2 No number found in the input string.");
			}

			if (uvCount != 3)
			{
				std::cout << "UV count is not 3 for triangle " << i << ": " << uvCount << std::endl;
				throw std::runtime_error("more than 3 uvs");
			}

			std::vector<float> floatValues;

			for (int j = 0; j < 3; j++)
			{
				std::getline(f, tempLine); //UV <Vector (-0.3661, -1.1665)>
				
				auto b = tempLine.cbegin();
				auto e = tempLine.cend();
				floatValues.clear();
				while (std::regex_search(b, e, match, pattern_float)) {
					floatValues.push_back(std::stof(match.str()));
					b = match.suffix().first;
				}

				if (floatValues.size() != 2)
				{
					std::cout << "UV count is not 2: " << j << " " << floatValues.size() << std::endl;
					throw std::runtime_error("more than 2 uvs---");
				}

				uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] };
			}
		}

		//std::cout << "Normals go" << std::endl;

		std::getline(f, tempLine); //===Normals:


		std::vector<Vector3f> normals;

		normals.resize(numberVertices);
		for (int i = 0; i < numberVertices; i++)
		{
			std::getline(f, tempLine);

			std::vector<float> floatValues;

			auto b = tempLine.cbegin();
			auto e = tempLine.cend();
			while (std::regex_search(b, e, match, pattern_float)) {
				floatValues.push_back(std::stof(match.str()));
				b = match.suffix().first;
			}

			normals[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
		}

		//std::cout << "Triangles go:" << std::endl;

		std::getline(f, tempLine); //===Triangles: 3974


		std::vector<std::array<int, 3>> triangles;

		triangles.resize(numberTriangles);
		for (int i = 0; i < numberTriangles; i++)
		{
			std::getline(f, tempLine);

			std::vector<int> intValues;

			auto b = tempLine.cbegin();
			auto e = tempLine.cend();
			while (std::regex_search(b, e, match, pattern_int)) {
				intValues.push_back(std::stoi(match.str()));
				b = match.suffix().first;
			}

			triangles[i] = { intValues[0], intValues[1], intValues[2] };
		}


		std::cout << "Process vertices" << std::endl;



		// Now let's process vertices

		for (int i = 0; i < numberTriangles; i++)
		{
			
			result.PositionData.push_back(vertices[triangles[i][0]]);
			result.PositionData.push_back(vertices[triangles[i][1]]);
			result.PositionData.push_back(vertices[triangles[i][2]]);

			result.TexCoordData.push_back(uvCoords[i][0]);
			result.TexCoordData.push_back(uvCoords[i][1]);
			result.TexCoordData.push_back(uvCoords[i][2]);

		}

		//Swap from Blender format to OpenGL format
		for (int i = 0; i < result.PositionData.size(); i++)
		{
			Vector3f tempVec = result.PositionData[i];
			result.PositionData[i](0) = tempVec(1);
			result.PositionData[i](1) = tempVec(2);
			result.PositionData[i](2) = tempVec(0);

		}

		return result;

	}

	VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName)
	{
		VertexDataStruct result;
		std::istringstream f;

		// --- 1. Открытие потока (без изменений) ---
		if (!ZIPFileName.empty())
		{
			std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
			std::string fileContents(fileData.begin(), fileData.end());
            f.str(fileContents);
		}
		else
		{
#ifdef __ANDROID__
            // Для Android используем SDL_RWops для чтения файлов
            __android_log_print(ANDROID_LOG_INFO, "TextModel",
                                "LoadFromTextFile02 called for Android: %s", fileName.c_str());
#endif
            // Читаем файл с помощью readTextFile
            std::string fileContent = readTextFile(fileName);
            if (fileContent.empty()) {
#ifdef __ANDROID__
                __android_log_print(ANDROID_LOG_ERROR, "TextModel",
                                    "Failed to read file: %s", fileName.c_str());
#endif
                throw std::runtime_error("Failed to read file: " + fileName);
            }

#ifdef __ANDROID__
            __android_log_print(ANDROID_LOG_INFO, "TextModel",
                                "File read successfully, size: %zu", fileContent.size());
#endif
            f.str(fileContent);
		}

		std::string tempLine;
		std::smatch match;

		// Обновленные регулярки
		// pattern_float стал чуть надежнее для чисел вида "0" или "-1" без точки, если вдруг Python округлит до int
		static const std::regex pattern_count(R"(\d+)");
		static const std::regex pattern_float(R"([-+]?\d*\.?\d+([eE][-+]?\d+)?)"); 
		static const std::regex pattern_int(R"([-]?\d+)");

		// --- 2. Парсинг Вершин (Pos + Norm + UV) ---

		// Ищем заголовок ===Vertices
		while (std::getline(f, tempLine)) {
			if (tempLine.find("===Vertices") != std::string::npos) break;
		}

		int numberVertices = 0;
		if (std::regex_search(tempLine, match, pattern_count)) {
			numberVertices = std::stoi(match.str());
		}
		else {
			std::cout << "Vertices header not found or invalid: " << tempLine << std::endl;
			throw std::runtime_error("Vertices header not found or invalid.");
		}

		// Временные буферы для хранения "уникальных" вершин перед разверткой по индексам
		std::vector<Vector3f> tempPositions(numberVertices);
		std::vector<Vector3f> tempNormals(numberVertices);
		std::vector<Vector2f> tempUVs(numberVertices);

		for (int i = 0; i < numberVertices; i++)
		{
			std::getline(f, tempLine);
			// Строка вида: V 0: Pos(x, y, z) Norm(x, y, z) UV(u, v)

			std::vector<float> floatValues;
			floatValues.reserve(8); // Ожидаем ровно 8 чисел (3 pos + 3 norm + 2 uv)

			auto b = tempLine.cbegin();
			auto e = tempLine.cend();
			while (std::regex_search(b, e, match, pattern_float)) {
				floatValues.push_back(std::stof(match.str()));
				b = match.suffix().first;
			}

			// Проверка целостности строки (ID вершины regex может поймать первым, но нас интересуют данные)
			// Обычно ID идет первым (0), потом 3+3+2 float. Итого 9 чисел, если считать ID.
			// Ваш Python пишет "V 0:", regex поймает 0. Потом 8 флоатов.

			// Если regex ловит ID вершины как float (что вероятно), нам нужно смещение.
			// ID - floatValues[0]
			// Pos - [1], [2], [3]
			// Norm - [4], [5], [6]
			// UV - [7], [8]

			if (floatValues.size() < 9) {
				std::cout << "Malformed vertex line at index " << i << ": " << tempLine << std::endl;
				throw std::runtime_error("Malformed vertex line at index " + std::to_string(i));
			}

			tempPositions[i] = Vector3f{ floatValues[1], floatValues[2], floatValues[3] };
			tempNormals[i] = Vector3f{ floatValues[4], floatValues[5], floatValues[6] };
			tempUVs[i] = Vector2f{ floatValues[7], floatValues[8] };
		}

		// --- 3. Парсинг Треугольников (Индексов) ---

		// Пропускаем пустые строки до заголовка треугольников
		while (std::getline(f, tempLine)) {
			if (tempLine.find("===Triangles") != std::string::npos) break;
		}

		int numberTriangles = 0;
		if (std::regex_search(tempLine, match, pattern_count)) {
			numberTriangles = std::stoi(match.str());
		}
		else {
			std::cout << "Triangles header not found or invalid: " << tempLine << std::endl;
			throw std::runtime_error("Triangles header not found.");
		}

		// Резервируем память в result, чтобы избежать лишних аллокаций
		result.PositionData.reserve(numberTriangles * 3);
		result.NormalData.reserve(numberTriangles * 3);
		result.TexCoordData.reserve(numberTriangles * 3);

		for (int i = 0; i < numberTriangles; i++)
		{
			std::getline(f, tempLine);
			// Строка вида: Tri: 0 1 2

			std::vector<int> indices;
			indices.reserve(3);

			auto b = tempLine.cbegin();
			auto e = tempLine.cend();
			while (std::regex_search(b, e, match, pattern_int)) {
				indices.push_back(std::stoi(match.str()));
				b = match.suffix().first;
			}

			if (indices.size() != 3) {
				std::cout << "Malformed triangle line at index " << i << ": " << tempLine << std::endl;
				throw std::runtime_error("Malformed triangle line at index " + std::to_string(i));
			}

			// --- 4. Заполнение VertexDataStruct (Flattening) ---
			// Берем данные из временных буферов по индексам и кладем в итоговый массив

			for (int k = 0; k < 3; k++) {
				int idx = indices[k];
				result.PositionData.push_back(tempPositions[idx]);
				result.NormalData.push_back(tempNormals[idx]);
				result.TexCoordData.push_back(tempUVs[idx]);
			}
		}

		// --- 5. Конвертация координат (Blender -> OpenGL/Engine) ---
		// Сохраняем вашу логику смены осей: X->Z, Y->X, Z->Y

		for (size_t i = 0; i < result.PositionData.size(); i++)
		{
			Vector3f originalPos = result.PositionData[i];
			result.PositionData[i](0) = originalPos(1); // New X = Old Y
			result.PositionData[i](1) = originalPos(2); // New Y = Old Z
			result.PositionData[i](2) = originalPos(0); // New Z = Old X

			Vector3f originalNorm = result.NormalData[i];
			result.NormalData[i](0) = originalNorm(1);
			result.NormalData[i](1) = originalNorm(2);
			result.NormalData[i](2) = originalNorm(0);
		}

		std::cout << "Model loaded: " << numberVertices << " verts, " << numberTriangles << " tris." << std::endl;

		return result;
	}




}