/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
 * Copyright 2018 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
#ifndef OSGEARTH_IMGUI_TEXTURE_INSPECTOR_GUI
#define OSGEARTH_IMGUI_TEXTURE_INSPECTOR_GUI

#include "ImGui"
#include <osg/NodeVisitor>

namespace osgEarth {
    namespace GUI
    {
        class TextureInspectorGUI : public BaseGUI
        {
        public:
            TextureInspectorGUI() : 
                BaseGUI("Texture Inspector")
            {
                //nop
            }

            void setNode(osg::Node* node)
            {
                _root = node;
            }

        private:
            class FindTexturesVisitor : public osg::NodeVisitor
            {
            public:
                FindTexturesVisitor() :
                    osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
                {
                }

                void apply(osg::Node& node)
                {
                    auto stateset = node.getStateSet();
                    if (stateset)
                    {
                        for (unsigned int i = 0; i < stateset->getTextureAttributeList().size(); ++i)
                        {
                            osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(stateset->getTextureAttribute(i, osg::StateAttribute::TEXTURE));
                            if (texture)
                            {
                                _textures.insert(texture);
                            }
                        }
                    }
                    traverse(node);
                }

                typedef std::set< osg::ref_ptr< osg::Texture2D > > TextureSet;
                TextureSet _textures;
            };

        public:
            void draw(osg::RenderInfo& ri) override
            {
                if (!isVisible())
                    return;

                if (ImGui::Begin(name(), visible()))
                {
                    if (_root.valid() == false)
                        _root = ri.getCurrentCamera();

                    if (ImGui::Button("Refresh"))
                    {
                        _textures.clear();
                        FindTexturesVisitor findTextures;
                        ri.getCurrentCamera()->accept(findTextures);
                        std::copy(findTextures._textures.begin(), findTextures._textures.end(), std::back_inserter(_textures));
                    }
                    ImGui::Text("Found %d textures", _textures.size());
                    ImGuiStyle& style = ImGui::GetStyle();
                    float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
                    unsigned int textureWidth = 50;
                    for (unsigned int i = 0; i < _textures.size(); ++i)
                    {
                        auto t = _textures[i];
                        std::string name = t.get()->getName();
                        if (name.empty())
                        {
                            name = "Texture";
                        }

                        ImGui::PushID(t.get());
                        ImGui::BeginGroup();
                        ImGui::Text(name.c_str());
                        ImGuiUtil::Texture(t.get(), ri, textureWidth);
                        ImGui::EndGroup();

                        float last_button_x2 = ImGui::GetItemRectMax().x;
                        float next_button_x2 = last_button_x2 + style.ItemSpacing.x + textureWidth; // Expected position if next button was on same line
                        if (i + 1 < _textures.size() && next_button_x2 < window_visible_x2)
                            ImGui::SameLine();

                        ImGui::PopID();
                        if (ImGui::IsItemHovered())
                        {
                            ImGui::BeginTooltip();
                            ImGui::Text("%dx%d", t.get()->getTextureWidth(), t.get()->getTextureHeight());
                            osg::Image* image = t.get()->getImage();
                            if (image && !image->getFileName().empty())
                            {
                                ImGui::Text(image->getFileName().c_str());
                            }
                            ImGui::EndTooltip();
                        }

                    }
                    ImGui::End();
                }
            }

            std::vector< osg::ref_ptr< osg::Texture2D > > _textures;
            osg::observer_ptr<osg::Node> _root;
        };
    }
}

#endif // OSGEARTH_IMGUI_TEXTURE_INSPECTOR_GUI
