/***************************** LICENSE START ***********************************

 Copyright 2013 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <cstdlib>

#include <QDebug>
#include <QPalette>
#include <QSettings>

#include "MvQDesktop.h"

#include "MvQBookmarks.h"
#include "MvQDrawerPanel.h"
#include "MvQEditorListMenu.h"
#include "MvQFileBrowser.h"
#include "MvQMessageBox.h"
#include "MvQRecentIcons.h"

#include "ConfigLoader.h"
#include "Drop.h"
#include "IconClass.h"
#include "IconObject.h"
#include "Folder.h"
#include "Items.h"
#include "Path.h"
#include "Protocol.h"
#include "MvRequest.h"
#include "MvTemplates.h"
#include "WsType.h"

static void drop_request(svcid* id, request* r, void* data);
static void reply_request(svcid* id, request* r, void* data);

MvQDesktop::MvQDesktop(int& argc, char** argv, std::string appName) :
    MvQApplication(argc, argv, appName.c_str(), {"desktop", "examiner", "editor", "window", "find"})
{
}

MvQDesktop::~MvQDesktop() = default;

void MvQDesktop::init()
{
    //---------------------------
    // Load resources
    //---------------------------

    ConfigLoader::init();

    //-----------------------------
    // Protocol
    //-----------------------------

    Protocol::init();

    // Register this service
    // registerTMvServe(*this,0);

    //-----------------------
    // Special folders
    //-----------------------

    Items::createAll();

    //-------------------------------------
    // Bookmarks - this needs the items!
    //-------------------------------------

    MvQBookmarks::init();

    //-------------------------------------
    // Most recent icons list
    //-------------------------------------

    MvQRecentIcons::init();

    //------------------------------
    // Start browsers
    //------------------------------

    MvQFileBrowser::init();

    //-------------------------------------
    // Dock icon menu - only works on Mac
    //-------------------------------------

    MvQEditorListMenu::initDockMenu();

    //-------------------------------------
    // Weather Symbol types
    //-------------------------------------

    WsType::init(WsType::DesktopMode);

    //------------------------------------------------
    // Add drop callback to handle drops to uPlot
    //------------------------------------------------

    add_drop_callback(MvApplication::getService(), nullptr, drop_request, nullptr);

    add_reply_callback(MvApplication::getService(), nullptr, reply_request, nullptr);
}


// This request is sent from uPlot when an icon is dropped from Desktop to uPlot.
static void drop_request(svcid* id, request* r, void* /*data*/)
{
    // print_all_requests(r);

    MvRequest req = get_subrequest(r, "HEADER", 0);

    // Service name
    const char* serviceCh = get_svc_source(id);
    if (!serviceCh)
        return;

    std::string serviceName(serviceCh);
    req("_SERVICE") = serviceCh;

    // Context
    req("_CONTEXT") = get_subrequest(r, "_CONTEXT", 0);

    // Mode
    MvRequest mode = get_subrequest(r, "MODE", 0);

    std::set<IconObject*> icons;

    // Icons
    int cnt = req.iterInit("ICON_NAME");
    for (int i = 0; i < cnt; i++) {
        // Icon name
        const char* iconChName = nullptr;
        req.iterGetNextValue(iconChName);

        // Find the iconobject
        if (iconChName) {
            std::string iconName(iconChName);
            IconObject* obj = IconObject::search(iconName);
            if (obj)
                icons.insert(obj);
        }
    }

    // Action type
    int action = atoi(get_value(r, "ACTION", 0));

    if (action == 3) {
        // Who will delete it????
        new Drop(icons, req, serviceName, mode);
    }
}

static void reply_request(svcid*, request* r, void* /*data*/)
{
    // cout << "reply" << std::endl;
    // print_all_requests(r);

    if (r) {
        bool hasError = (strcmp(r->name, "ERROR") == 0);
        if (!hasError && strcmp(r->name, "MESSAGE") == 0) {
            if (const char* ch = get_value(r, "ERR_CODE", 0)) {
                hasError = (std::atoi(ch) == 1);
            }
        }

        if (hasError) {
            MvRequest req(r);
            // MvQMessageBox m(r);
            int cnt = req.iterInit("ICON_NAME");
            for (int i = 0; i < cnt; i++) {
                // Icon name
                const char* iconChName = nullptr;
                req.iterGetNextValue(iconChName);

                // Find the iconobject and notify an error
                if (iconChName) {
                    std::string iconName(iconChName);
                    IconObject* obj = IconObject::search(iconName);
                    if (obj)
                        obj->notifyError();
                }
            }
        }
    }
}

// Serve Method
// called by MvTransaction to process the request
void MvQDesktop::serve(MvProtocol& /*proto*/, MvRequest& inRequest)
{
    inRequest.print();

    // Create a new context, based on the input Request
    // PmContext * context = new PmContext ( proto, inRequest );

    // Increment the reference counting
    // context->Attach();

    // Execute the context
    // context->Execute();showBrowsers()

    // Decrement the reference counting
    //	context->Detach();
}


void MvQDesktop::showBrowsers()
{
    MvQFileBrowser::showBrowsers();
}
