#include <opengl-playground/opengltexture.hpp>

#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#include <iostream>
#include <filesystem>

OpenGlTexture::OpenGlTexture(const std::string &texture_path)
{
	glGenTextures(1, &this->texture);
	glBindTexture(GL_TEXTURE_2D, this->texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	this->texture_path = texture_path;
	this->blend = 1.0f;
}

OpenGlTexture::OpenGlTexture() : OpenGlTexture("")
{

}

OpenGlTexture::~OpenGlTexture()
{
	glDeleteTextures(1, &this->texture);
}

void OpenGlTexture::setRGBDataFromBytes(unsigned int width, unsigned int height, char *buffer)
{
	this->use();
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
	glGenerateMipmap(GL_TEXTURE_2D);
}

void OpenGlTexture::loadFromImagePath(const std::string &base_directory)
{
	int width, height, nrChannels;
	std::filesystem::path base_path(base_directory);
	std::filesystem::path tex_path(this->texture_path);
	std::string filename;

	if (tex_path.is_relative())
		filename = base_path / tex_path;
	else
		filename = tex_path;

	unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0);
	if (data) {
		GLenum format = 0;
		if (nrChannels == 1)
		    format = GL_RED;
		else if (nrChannels == 3)
		    format = GL_RGB;
		else if (nrChannels == 4)
		    format = GL_RGBA;

		this->use();
		glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	} else {
		std::cout << "Texture loading of " << this->getPath() << " failed" << std::endl;
	}
	stbi_image_free(data);
}

void OpenGlTexture::use(unsigned int slot)
{
	glActiveTexture(GL_TEXTURE0 + slot);
	this->use();
}

void OpenGlTexture::use()
{
	glBindTexture(GL_TEXTURE_2D, this->texture);
}

const std::string &OpenGlTexture::getPath()
{
	return this->texture_path;
}

