#include <gltexturecubemap.hpp>

#include <ostream>

#include <globject.hpp>
#include <gltexturend.hpp>

// NOLINTNEXTLINE
#define STR_EXCEPTION GLObject<>::Exception
#include <str.hpp>


/// TGA


GLTextureCubemap GLTextureCubemap::tga_read(
    Paths const & paths,
    GLenum        format,
    GLenum        internal_format,
    GLenum        wrap,
    GLenum        min_filter,
    GLenum        mag_filter
)
try
{
    check_cubemap_paths_(paths);
    auto texture = GLTextureCubemap(
        str_paths_(paths),
        TGA::read(paths[0]).size(),
        internal_format,
        wrap,
        min_filter,
        mag_filter
    );
    for (auto face = GLuint{0}; face < faces_; ++face)
        texture.data(
            TGA::read(path_prefix_(paths[face], prefix())).data(),
            GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
            format
        );
    return texture;
}
catch (...)
{
    STR_THROW_NESTED(
        "Failed to read GLTextureCubemap TGA " << str_paths_(paths) << ":"
    );
}


void GLTextureCubemap::tga_write(
    Paths const & paths,
    GLenum        format
) const
try
{
    check_cubemap_paths_(paths);
    for (auto face = GLuint{0}; face < faces_; ++face)
        TGA(size(), data(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, format))
            .write(path_prefix_(paths[face], prefix()));
}
catch (...)
{
    STR_THROW_NESTED(
        "Failed to write GLTextureCubemap TGA " << str_paths_(paths) << ":"
    );
}


/// Check


void GLTextureCubemap::check_cubemap_paths_(Paths const & paths)
{
    if (paths.size() != faces_)
        STR_THROW(
            "Expected number of paths " << GLuint{faces_} << ", " <<
            "got "                      << paths.size()   << "."
        );
}


void GLTextureCubemap::check_cubemap_size_() const
{
    if (size()[0] != size()[1])
        STR_THROW(
            "Expected size " << "to be square"    << ", " <<
            "got "           << str_size_(size()) << "."
        );
}