//-----------------------------------------------------------------------------

#include "Landmark_guidance_gl.h"

#include <map>

#include <stb_image/stb_image.h>

#include <graphene/utility/Landmark_guidance.h>

//-----------------------------------------------------------------------------

using namespace graphene;
using namespace utility;

namespace graphene
{
namespace gl
{

//-----------------------------------------------------------------------------

Landmark_guidance_gl::Landmark_guidance_gl()
{

}

//-----------------------------------------------------------------------------

Landmark_guidance_gl::~Landmark_guidance_gl()
{
    clear();
}

//-----------------------------------------------------------------------------


bool Landmark_guidance_gl::valid()
{
    return landmark_images_.size() > 0;
}

//-----------------------------------------------------------------------------

bool Landmark_guidance_gl::load(Landmark_guidance& landmark_guidance)
{
    clear();

    // Filename based cache for already loaded images
    std::map<std::string, Landmark_image> texture_cache;

    landmark_images_.reserve(landmark_guidance.filenames.size());

    for (const std::string& fn_image : landmark_guidance.filenames)
    {
        auto find_result = texture_cache.find(fn_image);
        if (find_result != texture_cache.end())
        {
            // Copy existing landmark image
            landmark_images_.push_back(find_result->second);
        }
        else
        {
            // Generate and load new texture
            Landmark_image lm_image = {};

            glGenTextures(1, &lm_image.texture_handle);
            glBindTexture(GL_TEXTURE_2D, lm_image.texture_handle);

            stbi_set_flip_vertically_on_load(false);
            unsigned char* image_data =
                stbi_load(fn_image.c_str(), &lm_image.width, &lm_image.height, NULL, 4);

            if (image_data == NULL)
            {
                printf("[ERROR] Cannot load %s\n", fn_image.c_str());
            }

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lm_image.width, lm_image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);

            texture_cache[fn_image] = lm_image;

            landmark_images_.push_back(lm_image);

            // Delete CPU Memory
            stbi_image_free(image_data);
        }
    }

    return true;
}

//-----------------------------------------------------------------------------

void Landmark_guidance_gl::clear()
{
    for (Landmark_image& landmark_image : landmark_images_)
    {
        glDeleteTextures(1, &landmark_image.texture_handle);
    }

    landmark_images_.resize(0);
}

Landmark_image& Landmark_guidance_gl::get(size_t landmark)
{
    return landmark_images_[landmark];
}

//-----------------------------------------------------------------------------

}
}

//-----------------------------------------------------------------------------
