/**
 * @file Texture.cpp
 * @author Petr Egert (egertpet@fel.cvut.cz)
 * @brief Contains Texture class implementation
 */
#ifdef __WINDOWS__
#include <windows.h>
#endif

#include <gl/gl.h>
#include <gl/glu.h>
#include <string>

#include "Texture.h"

using namespace std;
using namespace RD;

/**
 * @brief Creates a texture from the given image
 * @param img Image from which the texture should be created
 * @param genMipMap If true, mipmap is generated for the texture. (default false)
 * @return RES_OK on success, RES_INVALID_HANDLE when img is invalid, RES_ERROR otherwise
 */
Result Texture::Init(Image *img, bool genMipMap)
{
    if(!img)
    {
        return ErrorHandler::Error("Texture::Init() - invalid image handle supplied", RES_INVALID_HANDLE);
    }

    if(!img->data)
    {
        return ErrorHandler::Error("Texture::Init() - supplied image not loaded", RES_ERROR);
    }

    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);
    if(genMipMap)
    {
        gluBuild2DMipmaps(GL_TEXTURE_2D, img->bpp / 8, img->width, img->height, ((img->bpp / 8) == 3) ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, img->data);
    }
    else
    {
        glTexImage2D(GL_TEXTURE_2D, 0, img->bpp / 8, img->width, img->height, 0, ((img->bpp / 8) == 3) ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, img->data);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    }

    hasMipMap = genMipMap;

    return RES_OK;
}

/**
 * @brief Creates a texture from a file
 * @param fileName Path to the image file
 * @param genMipMap If true, mipmap is generated for the texture. (default false)
 * @return RES_OK on success, RES_ERROR otherwise
 */
Result Texture::Init(const char *fileName, bool genMipMap)
{
    Image *img = new Image();
    Result result = img->Init(fileName);
    if(result == RES_OK)
    {
        result = Init(img, genMipMap);
    }
    img->Release();
    delete img;

    if(result != RES_OK)
    {
        result = ErrorHandler::Error(string("Texture::Init(") + string(fileName) + string(") - failed to load image"), RES_ERROR);
    }

    return result;
}

/**
 * @brief Performs class deinitialization
 * @return RES_OK on success
 */
Result Texture::Release()
{
    glDeleteTextures(1, &texID);
    return RES_OK;
}

/**
 * @brief Sets the texture as active for tge current context
 */
void Texture::Set()
{
    glBindTexture(GL_TEXTURE_2D, texID);
}
