#include "opengl45_gpu_texture.hpp"
#include <utility>

namespace bp
{

opengl45_gpu_texture2d::opengl45_gpu_texture2d()
: description_()
, texture_{0}
{

}

opengl45_gpu_texture2d::opengl45_gpu_texture2d(const gpu_texture2d_description& description, GLuint texture) noexcept
: description_(description)
, texture_{texture}
{

}

opengl45_gpu_texture2d::~opengl45_gpu_texture2d()
{
    if(texture_ != 0)
    {
        glDeleteTextures(1, &texture_);
    }
}

opengl45_gpu_texture2d::opengl45_gpu_texture2d(opengl45_gpu_texture2d&& other) noexcept
: description_(other.description_)
, texture_(std::exchange(other.texture_, 0))
{

}

opengl45_gpu_texture2d& opengl45_gpu_texture2d::operator=(opengl45_gpu_texture2d&& other) noexcept
{
    if(this != &other)
    {
        if(texture_ != 0)
        {
            glDeleteTextures(1, &texture_);
        }

        texture_ = std::exchange(other.texture_, 0);
        description_ = other.description_;
    }

    return *this;
}

uint32_t opengl45_gpu_texture2d::width() const
{
    return description_.width;
}

uint32_t opengl45_gpu_texture2d::height() const
{
    return description_.height;
}

gpu_texture_format opengl45_gpu_texture2d::format() const
{
    return description_.format;
}

gpu_texture_filtering opengl45_gpu_texture2d::filtering() const
{
    return description_.filtering;
}

gpu_texture_wrapping opengl45_gpu_texture2d::wrapping() const
{
    return description_.wrapping;
}

bool opengl45_gpu_texture2d::has_mipmaps() const
{
    return description_.generate_mipmaps;
}

image opengl45_gpu_texture2d::read_pixels() const
{
    image new_image(description_.width, description_.height);

    // Here we copy the pixels from the GPU onto the CPU image
    glGetTextureImage(texture_, 0, GL_RGBA, GL_UNSIGNED_BYTE, new_image.size() * sizeof(color_rgba8), new_image.data());

    return new_image;
}

GLuint opengl45_gpu_texture2d::handle() const noexcept
{
    return texture_;
}

}