/* -*-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_NETWORK_MONITOR_GUI
#define OSGEARTH_IMGUI_NETWORK_MONITOR_GUI

#include <osgEarth/NetworkMonitor>
#include "ImGui"

namespace osgEarth {
    namespace GUI
    {

        class NetworkMonitorGUI : public BaseGUI
        {
        public:
            NetworkMonitorGUI() :
                BaseGUI("Network Monitor"),
                _showOnlyActiveRequests(true),
                _showOnlyFailedRequests(false)
            {
                memset(_filter, 0, sizeof(_filter));
            }

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

                if (ImGui::Begin(name(), visible()))
                {
                    NetworkMonitor::setEnabled(true);

                    NetworkMonitor::Requests requests;
                    NetworkMonitor::getRequests(requests);

                    // Compute the time duration for all of the requests
                    osg::Timer_t startTime;
                    double totalTime = 0.0;
                    if (!requests.empty())
                    {
                        startTime = requests.begin()->second.startTime;
                        if (requests.rbegin()->second.isComplete)
                        {
                            totalTime = osg::Timer::instance()->delta_m(startTime, requests.rbegin()->second.endTime);
                        }
                        else
                        {
                            totalTime = osg::Timer::instance()->delta_m(startTime, osg::Timer::instance()->tick());
                        }
                    }

                    ImGui::Checkbox("Active", &_showOnlyActiveRequests);
                    
                    ImGui::SameLine();
                    ImGui::Checkbox("Failed", &_showOnlyFailedRequests);

                    ImGui::SameLine();
                    if (ImGui::Button("Clear"))
                    {
                        NetworkMonitor::clear();
                    }

                    ImGui::SameLine();
                    if (ImGui::Button("Save"))
                    {
                        NetworkMonitor::saveCSV(requests, "network_requests.csv");
                    }

                    ImGui::SameLine();
                    ImGui::InputText("Filter", _filter, 128);

                    ImGui::Text("%d requests", requests.size());
                    ImGui::SameLine();
                    ImGui::Text("Total time = %.1f s", totalTime / 1000.0);

                    ImGui::BeginChild("Columns");
                    ImGui::Columns(5, "requests");

                    ImGui::SetColumnWidth(0, 300.f);
                    ImGui::SetColumnWidth(1, 100.f);
                    ImGui::SetColumnWidth(2, 100.f);
                    ImGui::SetColumnWidth(3, 100.f);
                    //ImGui::SetColumnWidth(0, 100.f);


                    ImGui::Separator();
                    //ImGui::Text("Start time"); ImGui::NextColumn();
                    //ImGui::Text("End time"); ImGui::NextColumn();
                    ImGui::Text("Layer"); ImGui::NextColumn();
                    ImGui::Text("Time(ms)"); ImGui::NextColumn();
                    ImGui::Text("Type"); ImGui::NextColumn();
                    ImGui::Text("Status"); ImGui::NextColumn();
                    ImGui::Text("Path"); ImGui::NextColumn();
                    ImGui::Separator();


                    std::string filterLower = osgEarth::toLower(_filter);

                    for (NetworkMonitor::Requests::iterator itr = requests.begin(); itr != requests.end(); ++itr)
                    {
                        if (!_showOnlyActiveRequests || !itr->second.isComplete)
                        {
                            if (!filterLower.empty())
                            {
                                std::string uriLower = osgEarth::toLower(itr->second.uri);
                                std::string statusLower = osgEarth::toLower(itr->second.status);
                                std::string layerLower = osgEarth::toLower(itr->second.layer);
                                std::string typeLower = osgEarth::toLower(itr->second.type);

                                if (strstr(uriLower.c_str(), filterLower.c_str()) == NULL &&
                                    strstr(statusLower.c_str(), filterLower.c_str()) == NULL &&
                                    strstr(layerLower.c_str(), filterLower.c_str()) == NULL &&
                                    strstr(typeLower.c_str(), filterLower.c_str()) == NULL)
                                {
                                    continue;
                                }
                            }

                            ImVec4 color = ImVec4(1.0, 1.0, 1.0, 1.0);
                            bool failed = false;
                            bool canceled = false;
                            if (itr->second.isComplete)
                            {
                                if (itr->second.status.find("OK") != std::string::npos)
                                {
                                    color = ImVec4(0, 1, 0, 1); // green
                                }
                                else if (itr->second.status.find("Canceled") != std::string::npos)
                                {
                                    color = ImVec4(.5,.5,.5,1); // grey
                                    canceled = true;
                                }
                                else
                                {
                                    // Color bad requests red
                                    color = ImVec4(1, 0, 0, 1);
                                    failed = true;
                                }
                            }

                            if (_showOnlyFailedRequests && !failed)
                                continue;

                            ImGui::PushID(itr->first);

                            double startMS = osg::Timer::instance()->delta_m(startTime, itr->second.startTime);
                            double endMS = 0.0;
                            if (itr->second.isComplete)
                            {
                                endMS = osg::Timer::instance()->delta_m(startTime, itr->second.endTime);
                            }
                            else
                            {
                                endMS = osg::Timer::instance()->delta_m(startTime, osg::Timer::instance()->tick());
                            }

                            ImGui::Text(itr->second.layer.c_str()); ImGui::NextColumn();
                            char buf[64];
                            sprintf(buf, "%.1lf", itr->second.getDuration());
                            ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(buf).x
                                - ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
                            ImGui::Text(buf); ImGui::NextColumn();
                            //ImGui::Text("%.2lf ms", startMS); ImGui::NextColumn();
                            //ImGui::Text("%.2lf ms", endMS); ImGui::NextColumn();
                            ImGui::Text(itr->second.type.c_str()); ImGui::NextColumn();
                            ImGui::Text(itr->second.status.c_str()); ImGui::NextColumn();

                            if (ImGui::SmallButton("Copy"))
                            {
                                ImGui::SetClipboardText(itr->second.uri.c_str());
                            }
                            ImGui::SameLine();
                            ImGui::TextColored(color, "%s (%d)", itr->second.uri.c_str(), itr->second.count);  ImGui::NextColumn();
                            ImGui::PopID();
                        }
                    }
                    ImGui::Columns(1);
                    ImGui::Separator();

                    // Keep scroll position at the bottom so we can see new network requests as they come in if they are scrolled to the bottom already
                    if (ImGui::GetScrollY() == ImGui::GetScrollMaxY())
                    {
                        ImGui::SetScrollHereY(1.0);
                    }
                    ImGui::EndChild();

                    ImGui::End();
                }
                else
                {
                    NetworkMonitor::setEnabled(false);
                }
            }

            bool _showOnlyActiveRequests;
            bool _showOnlyFailedRequests;
            char _filter[128];
        };
    }
}

#endif // OSGEARTH_IMGUI_NOTIFY_GUI
