#include "pch.h"
#include "app.h"
#include "app_core/document_cloud.h"
#include "util.h"
#include "node_progress_bar.h"
#include "node_dialog_cloud.h"

void App::cloud_upload()
{
    const bool has_canvas = canvas != nullptr;
    const auto plan = pp::app::plan_cloud_upload(
        has_canvas,
        has_canvas && Canvas::I->m_newdoc,
        has_canvas && Canvas::I->m_unsaved);

    switch (plan.action)
    {
    case pp::app::CloudUploadAction::unavailable_no_canvas:
        return;
    case pp::app::CloudUploadAction::show_save_required_warning:
        message_box("Warning", "This document needs to be saved before upload.");
        return;
    case pp::app::CloudUploadAction::prompt_publish:
        break;
    }

        auto upload_thread = [this] {
            BT_SetTerminate();

            if (Canvas::I->m_unsaved)
            {
                Canvas::I->project_save_thread(doc_path, true);
            }
            
            auto pb = show_progress("Uploading");

            upload(doc_path, doc_filename, [this,pb](float p){
                pb->set_progress(p);
            });
            
            pb->destroy();
            message_box("Success", "This document has been succesfully uploaded.");
        };

        auto m = message_box("Publish document", "Would you like to upload to the public domain?");
        m->btn_ok->m_text->set_text("Yes");
        m->btn_cancel->m_text->set_text("No");
        m->btn_ok->on_click = [this, m, upload_thread](Node*) {
            std::thread(upload_thread).detach();
            m->destroy();
        };
        m->btn_cancel->on_click = [this, m, upload_thread](Node*) {
            m->destroy();
        };
}

void App::cloud_upload_all()
{
    std::thread([this] {
        BT_SetTerminate();

        auto names = Asset::list_files(data_path, ".*\\.ppi");
        const auto plan = pp::app::plan_cloud_bulk_upload(names.size(), layout.m_loaded);

        gl_state gl;
        std::shared_ptr<NodeProgressBar> pb;
        if (plan.show_progress)
            pb = show_progress("Export Pano Image", plan.progress_total);

        for (const auto& n : names)
        {
            std::string path = data_path + "/" + n;
            upload(path);

            if (plan.show_progress)
                pb->increment();
        }

        if (plan.show_progress)
            pb->destroy();

    }).detach();
}

void App::cloud_browse()
{
    const auto browse_plan = pp::app::plan_cloud_browse(canvas != nullptr);
    switch (browse_plan)
    {
    case pp::app::CloudBrowseAction::unavailable_no_canvas:
        return;
    case pp::app::CloudBrowseAction::show_browser:
        break;
    }

    // load thumbnail test
    auto dialog = std::make_shared<NodeDialogCloud>();
    dialog->set_manager(&layout);
    dialog->init();
    dialog->create();
    dialog->loaded();

    layout[main_id]->add_child(dialog);

    dialog->btn_ok->on_click = [this, dialog](Node*)
    {
        const auto selection_plan = pp::app::plan_cloud_download_selection(dialog->selected_file);
        if (selection_plan == pp::app::CloudDownloadSelectionAction::wait_for_selection)
            return;
        dialog->destroy();
        std::thread([this, dialog] {
            BT_SetTerminate();

            auto* m = layout[main_id]->add_child<NodeMessageBox>();
            m->m_title->set_text("Downloading");
            m->m_message->set_text("Download in progress");
            std::string url = "https://panopainter.com/cloud/cloud-dwl.php?file=" + dialog->selected_file;
            download(url, dialog->selected_path, [this,m](float p){
                static char progress[256];
                sprintf(progress, "Download in progress %.2f%%", p * 100.f);
                m->m_message->set_text(progress);
            });
            
            canvas->reset_camera();
            layers->clear();
            
            canvas->m_canvas->project_open_thread(dialog->selected_path);
            
            doc_name = dialog->selected_name;
            title_update();
            for (auto& l : canvas->m_canvas->m_layers)
                layers->add_layer(l->m_name.c_str(), false);
            ActionManager::clear();
            m->destroy();
        }).detach();
    };
}
