#include "pch.h"

#include "legacy_cloud_services.h"

#include "app.h"
#include "canvas.h"
#include "node_dialog_cloud.h"
#include "node_progress_bar.h"
#include "util.h"

namespace pp::panopainter {
namespace {

class LegacyCloudServices final : public pp::app::CloudServices {
public:
    explicit LegacyCloudServices(App& app) noexcept
        : app_(app)
    {
    }

    void show_save_required_warning() override
    {
        app_.message_box("Warning", "This document needs to be saved before upload.");
    }

    void prompt_publish(bool save_before_upload) override
    {
        auto* app = &app_;
        auto upload_thread = [app, save_before_upload] {
            BT_SetTerminate();

            if (save_before_upload)
            {
                Canvas::I->project_save_thread(app->doc_path, true);
            }

            auto pb = app->show_progress("Uploading");

            app->upload(app->doc_path, app->doc_filename, [pb](float p) {
                pb->set_progress(p);
            });

            pb->destroy();
            app->message_box("Success", "This document has been succesfully uploaded.");
        };

        auto m = app_.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 = [m, upload_thread](Node*) {
            std::thread(upload_thread).detach();
            m->destroy();
        };
        m->btn_cancel->on_click = [m](Node*) {
            m->destroy();
        };
    }

    void begin_bulk_upload(int progress_total, bool show_progress) override
    {
        bulk_progress_.reset();
        if (show_progress) {
            bulk_progress_ = app_.show_progress("Export Pano Image", progress_total);
        }
    }

    void upload_all_bulk_files() override
    {
        auto names = Asset::list_files(app_.data_path, ".*\\.ppi");
        [[maybe_unused]] gl_state gl;
        for (const auto& n : names)
        {
            std::string path = app_.data_path + "/" + n;
            app_.upload(path);

            if (bulk_progress_) {
                bulk_progress_->increment();
            }
        }
    }

    void end_bulk_upload() override
    {
        if (bulk_progress_) {
            bulk_progress_->destroy();
        }
        bulk_progress_.reset();
    }

    void show_browser() override
    {
        auto dialog = std::make_shared<NodeDialogCloud>();
        dialog->set_manager(&app_.layout);
        dialog->init();
        dialog->create();
        dialog->loaded();

        app_.layout[app_.main_id]->add_child(dialog);

        auto* app = &app_;
        dialog->btn_ok->on_click = [app, dialog](Node*) {
            const auto selection_plan = pp::app::plan_cloud_download_selection(dialog->selected_file);
            const auto status = execute_legacy_cloud_download_selection_action(*app, selection_plan, *dialog);
            if (!status.ok())
                LOG("Cloud download selection action failed: %s", status.message);
        };
    }

    void start_download(const pp::app::CloudDownloadRequest& request) override
    {
        auto* app = &app_;
        std::thread([app, request] {
            BT_SetTerminate();

            auto* m = app->layout[app->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=" + request.selected_file;
            app->download(url, request.selected_path, [m](float p) {
                static char progress[256];
                sprintf(progress, "Download in progress %.2f%%", p * 100.f);
                m->m_message->set_text(progress);
            });

            app->canvas->reset_camera();
            app->layers->clear();

            app->canvas->m_canvas->project_open_thread(request.selected_path);

            app->doc_name = request.selected_name;
            app->title_update();
            for (auto& l : app->canvas->m_canvas->m_layers)
                app->layers->add_layer(l->m_name.c_str(), false);
            ActionManager::clear();
            m->destroy();
        }).detach();
    }

private:
    App& app_;
    std::shared_ptr<NodeProgressBar> bulk_progress_;
};

} // namespace

pp::foundation::Status execute_legacy_cloud_upload_plan(
    App& app,
    const pp::app::CloudUploadPlan& plan)
{
    LegacyCloudServices services(app);
    return pp::app::execute_cloud_upload_plan(plan, services);
}

pp::foundation::Status execute_legacy_cloud_bulk_upload_plan(
    App& app,
    const pp::app::CloudBulkUploadPlan& plan)
{
    LegacyCloudServices services(app);
    return pp::app::execute_cloud_bulk_upload_plan(plan, services);
}

pp::foundation::Status execute_legacy_cloud_browse_action(
    App& app,
    pp::app::CloudBrowseAction action)
{
    LegacyCloudServices services(app);
    return pp::app::execute_cloud_browse_action(action, services);
}

pp::foundation::Status execute_legacy_cloud_download_selection_action(
    App& app,
    pp::app::CloudDownloadSelectionAction action,
    NodeDialogCloud& dialog)
{
    pp::app::CloudDownloadRequest request {
        .selected_file = dialog.selected_file,
        .selected_path = dialog.selected_path,
        .selected_name = dialog.selected_name,
    };
    if (action == pp::app::CloudDownloadSelectionAction::start_download) {
        dialog.destroy();
    }
    LegacyCloudServices services(app);
    return pp::app::execute_cloud_download_selection_action(action, services, request);
}

} // namespace pp::panopainter
