#include "pch.h"
#include "app.h"
#include "action.h"
#include "node_dialog_open.h"
#include "node_dialog_browse.h"
#include "node_dialog_resize.h"
#include "node_dialog_cloud.h"
#include "node_about.h"
#include "node_changelog.h"
#include "node_usermanual.h"

std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title)
{
    auto pb = std::make_shared<NodeProgressBar>();
    pb->m_manager = &layout;
    pb->init();
    pb->create();
    pb->loaded();
    pb->m_progress->SetWidthP(0);
    pb->m_title->set_text(title.c_str());
    layout[main_id]->add_child(pb);
    return pb;
}

void App::message_box(const std::string &title, const std::string& text)
{
    async_start();
    auto* m = layout[main_id]->add_child<NodeMessageBox>();
    m->m_title->set_text(title.c_str());
    m->m_message->set_text(text.c_str());
    m->btn_ok->m_text->set_text("Ok");
    m->btn_cancel->destroy();
    layout[main_id]->update();
    async_redraw();
    async_end();
}

void App::dialog_usermanual()
{
    auto dialog = std::make_shared<NodeUserManual>();
    dialog->m_manager = &layout;
    dialog->init();
    dialog->create();
    dialog->loaded();

    layout[main_id]->add_child(dialog);
    layout[main_id]->update();
}

void App::dialog_changelog()
{
    auto dialog = std::make_shared<NodeChangelog>();
    dialog->m_manager = &layout;
    dialog->init();
    dialog->create();
    dialog->loaded();

    layout[main_id]->add_child(dialog);
    layout[main_id]->update();
}

void App::dialog_about()
{
    auto dialog = std::make_shared<NodeAbout>();
    dialog->m_manager = &layout;
    dialog->init();
    dialog->create();
    dialog->loaded();

    layout[main_id]->add_child(dialog);
    layout[main_id]->update();
}

void App::dialog_newdoc()
{
    auto show_dialog = [this] {
        async_start();
        auto dialog = std::make_shared<NodeDialogNewDoc>();
        dialog->m_manager = &layout;
        dialog->init();
        dialog->create();
        dialog->loaded();
        dialog->input->set_text("name");

        layout[main_id]->add_child(dialog);
        layout[main_id]->update();

        App::I.showKeyboard();

        dialog->btn_ok->on_click = [this, dialog](Node*)
        {
            std::string name = dialog->input->m_string;
            std::string path = work_path + "/" + name + ".ppi";

            if (name.empty())
            {
                message_box("Warning", "You need to specify a name to file.");
                return;
            }

            auto action = [this, dialog, name, path] {
                std::array<int, 6> resolutions{ 512, 1024, 1536, 2048, 4096, 8192 };
                int res = resolutions[dialog->m_resolution->m_current_index];
                doc_name = name;
                doc_path = path;
                doc_filename = name + ".ppi";
                doc_dir = work_path;

                layers->clear();
                canvas->m_canvas->m_layers.clear();
                canvas->m_canvas->m_order.clear();
                canvas->m_canvas->resize(res, res);
                canvas->reset_camera();
                ActionManager::clear();

                canvas->m_canvas->layer_add("Default");
                layers->add_layer("Default");

                canvas->m_canvas->m_unsaved = true;
                canvas->m_canvas->m_newdoc = false;
                title_update();

                dialog->destroy();
                App::I.hideKeyboard();
            };

            if (Asset::exist(path))
            {
                // ask confirm is file already exist
                auto msgbox = new NodeMessageBox();
                msgbox->m_manager = &layout;
                msgbox->init();
                msgbox->m_title->set_text("Warning");
                msgbox->m_message->set_text("A document with this name already exists, continue?");
                msgbox->btn_ok->on_click = [this, msgbox, action](Node*) {
                    action();
                    msgbox->destroy();
                };
                layout[main_id]->add_child(msgbox);
            }
            else
            {
                action();
            }

        };
        dialog->btn_cancel->on_click = [this, dialog](Node*)
        {
            dialog->destroy();
            App::I.hideKeyboard();
        };
        async_end();
    };

    if (canvas)
    {
        if (Canvas::I->m_unsaved)
        {
            auto m = layout[main_id]->add_child<NodeMessageBox>();
            m->m_title->set_text("Unsaved document");
            m->m_message->set_text("Would you like to save this document before closing?");
            m->btn_ok->m_text->set_text("Yes");
            m->btn_cancel->m_text->set_text("No");
            m->btn_ok->on_click = [this, m, show_dialog](Node*) {
                Canvas::I->project_save([this, m, show_dialog](bool success){
                    if (success)
                        show_dialog();
                    else
                        message_box("Saving Error", "There was a problem saving the document");
                });
                m->destroy();
            };
            m->btn_cancel->on_click = [this, m, show_dialog](Node*) {
                show_dialog();
                m->destroy();
            };
        }
        else
        {
            show_dialog();
        }
    }
}

// DEPRECATED
void App::dialog_open()
{
    auto show_dialog = [this] {
        async_start();
        // load thumbnail test
        auto dialog = std::make_shared<NodeDialogOpen>();
        dialog->m_manager = &layout;
        dialog->init();
        dialog->create();
        dialog->loaded();

        layout[main_id]->add_child(dialog);
        layout[main_id]->update();

        dialog->btn_ok->on_click = [this, dialog](Node*)
        {
//            canvas->reset_camera();
//            layers->clear();
//            doc_name = dialog->selected_name;
//            canvas->m_canvas->project_open(dialog->selected_path, [this](bool success) {
//                // on complete
//                async_start();
//                title_update();
//                for (auto& i : canvas->m_canvas->m_order)
//                    layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str());
//                async_end();
//            });
//            dialog->destroy();
//            ActionManager::clear();
        };
        async_end();
    };

    if (canvas)
    {
        if (Canvas::I->m_unsaved)
        {
            auto m = layout[main_id]->add_child<NodeMessageBox>();
            m->m_title->set_text("Unsaved document");
            m->m_message->set_text("Would you like to save this document before closing?");
            m->btn_ok->m_text->set_text("Yes");
            m->btn_cancel->m_text->set_text("No");
            m->btn_ok->on_click = [this,m,show_dialog](Node*){
                Canvas::I->project_save([this,m,show_dialog](bool success){
                    if (success)
                        show_dialog();
                    else
                        message_box("Saving Error", "There was a problem saving the document");
                });
                m->destroy();
            };
            m->btn_cancel->on_click = [this,m,show_dialog](Node*) {
                show_dialog();
                m->destroy();
            };
        }
        else
        {
            show_dialog();
        }
    }
}

void App::dialog_browse()
{
    auto show_dialog = [this] {
        async_start();
        // load thumbnail test
        auto dialog = std::make_shared<NodeDialogBrowse>();
        dialog->m_manager = &layout;
#ifdef __IOS__
        dialog->search_paths = {work_path, data_path + "/Inbox"};
#else
        dialog->search_paths = {work_path};
#endif
        dialog->init();
        dialog->create();
        dialog->loaded();

        layout[main_id]->add_child(dialog);
        layout[main_id]->update();

        dialog->btn_ok->on_click = [this, dialog](Node*)
        {
            if (dialog->is_selected())
            {
                open_document(dialog->selected_path);
                dialog->destroy();
            }
        };
        async_end();
    };

    if (canvas)
    {
        if (Canvas::I->m_unsaved)
        {
            auto m = layout[main_id]->add_child<NodeMessageBox>();
            m->m_title->set_text("Unsaved document");
            m->m_message->set_text("Would you like to save this document before closing?");
            m->btn_ok->m_text->set_text("Yes");
            m->btn_cancel->m_text->set_text("No");
            m->btn_ok->on_click = [this, m, show_dialog](Node*) {
                Canvas::I->project_save([this, m, show_dialog](bool success){
                    if (success)
                        show_dialog();
                    else
                        message_box("Saving Error", "There was a problem saving the document");
                });
                m->destroy();
            };
            m->btn_cancel->on_click = [this, m, show_dialog](Node*) {
                show_dialog();
                m->destroy();
            };
        }
        else
        {
            show_dialog();
        }
    }
}

void App::dialog_save_ver()
{
    if (!check_license())
    {
        message_box("License", "This function is disabled in demo mode.");
        return;
    }

    int current = 0;
    std::string next = doc_name + ".01";
    std::string base = doc_name;

    std::regex r(R"((.*)\.(\w{2})$)");
    std::smatch m;
    if (std::regex_search(doc_name, m, r))
    {
        base = m[1].str();
        current = atoi(m[2].str().c_str());
    }

    for (int i = current + 1; i < 99; i++)
    {
        static char tmp_name[256];
        sprintf(tmp_name, "%s.%02d", base.c_str(), i);
        next = tmp_name;
        if (Asset::exist(doc_dir + "/" + next + ".ppi"))
            continue;
        break;
    }

    doc_name = next;
    doc_path = doc_dir + "/" + next + ".ppi";
    title_update();
    canvas->m_canvas->project_save(doc_path);
}

void App::dialog_save()
{
    if (!check_license())
    {
        message_box("License", "This function is disabled in demo mode.");
        return;
    }
    
    if (canvas)
    {
        auto dialog = std::make_shared<NodeDialogSave>();
        dialog->m_manager = &layout;
        dialog->init();
        dialog->create();
        dialog->loaded();
        dialog->input->set_text(doc_name);

        App::I.showKeyboard();

        dialog->btn_ok->on_click = [this, dialog](Node*)
        {
            std::string name = dialog->input->m_string;
            std::string path = work_path + "/" + name + ".ppi";

            if (name.empty())
            {
                message_box("Warning", "You need to specify a name to file.");
                return;
            }

            auto action = [this, dialog, name, path] {
                canvas->m_canvas->project_save(path);
                doc_name = name;
                doc_path = path;
                doc_dir = work_path;
                title_update();
                dialog->destroy();
                App::I.hideKeyboard();
            };

            if (Asset::exist(path))
            {
                // ask confirm is file already exist
                auto msgbox = new NodeMessageBox();
                msgbox->m_manager = &layout;
                msgbox->init();
                msgbox->m_title->set_text("Warning");
                msgbox->m_message->set_text(("Are you sure you want to overwrite " + name + "?").c_str());
                msgbox->btn_ok->on_click = [this, msgbox, action](Node*) {
                    action();
                    msgbox->destroy();
                };
                layout[main_id]->add_child(msgbox);
            }
            else
            {
                action();
            }
        };
        dialog->btn_cancel->on_click = [this, dialog](Node*)
        {
            dialog->destroy();
            App::I.hideKeyboard();
        };

        layout[main_id]->add_child(dialog);
        layout[main_id]->update();
    }
}

void App::dialog_export(std::string ext)
{
    if (!check_license())
    {
        message_box("License", "This function is disabled in demo mode.");
        return;
    }

    if (canvas)
    {
        // TODO: use picker
        canvas->m_canvas->export_equirectangular(work_path + "/" + doc_name + ext, [this]{
#if defined(__IOS__)
            message_box("Export JPG", "Image exported to Photos");
#elif defined(__OSX__)
            message_box("Export JPG", "Image exported to Pictures/PanoPainter folder");
#elif defined(_WIN32)
            message_box("Export JPG", "Image exported to " + work_path);
#endif
        });
    }
}

void App::dialog_export_layers()
{
    if (!check_license())
    {
        message_box("License", "This function is disabled in demo mode.");
        return;
    }

    if (canvas)
    {
        // TODO: use picker
        canvas->m_canvas->export_layers(doc_name, [this] {
#if defined(__IOS__)
            message_box("Export JPG", "Image exported to Photos");
#elif defined(__OSX__)
            message_box("Export JPG", "Image exported to Pictures/PanoPainter folder");
#elif defined(_WIN32)
            message_box("Export JPG", "Image exported to " + work_path);
#endif
        });
    }
}

void App::dialog_resize()
{
    auto dialog = std::make_shared<NodeDialogResize>();
    dialog->m_manager = &layout;
    dialog->init();
    dialog->create();
    dialog->loaded();

    layout[main_id]->add_child(dialog);
    layout[main_id]->update();

    dialog->btn_ok->on_click = [this,dialog](Node*)
    {
        int res = dialog->get_resolution();
        if (canvas)
            canvas->m_canvas->resize(res, res);
        App::I.title_update();
        ActionManager::clear();
        dialog->destroy();
    };
}

void App::dialog_export_cubes()
{
	if (canvas)
	{
		canvas->m_canvas->export_cubes();
	}
}

void App::dialog_layer_rename()
{
    auto dialog = std::make_shared<NodeDialogLayerRename>();
    dialog->m_manager = &layout;
    dialog->init();
    dialog->create();
    dialog->loaded();
    dialog->input->set_text(layers->m_current_layer->m_label_text);

    App::I.showKeyboard();

    layout[main_id]->add_child(dialog);
    layout[main_id]->update();

    dialog->btn_ok->on_click = [this,dialog](Node*)
    {
        layers->m_current_layer->set_name(dialog->get_name().c_str());
        canvas->m_canvas->m_layers[canvas->m_canvas->m_current_layer_idx]->m_name = dialog->get_name();
        dialog->destroy();
        App::I.hideKeyboard();
    };
    dialog->btn_cancel->on_click = [this, dialog](Node*)
    {
        dialog->destroy();
        App::I.hideKeyboard();
    };
}
