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

 Copyright 2014 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 "Metview.h"

#include "MetviewTask.h"
#include "IconObject.h"
#include "Log.h"
//#include "Editor.h"
#include "Request.h"
#include "Dependancy.h"
#include "IconFactory.h"
#include "IconClass.h"

//=================================================================

MetviewTask::MetviewTask(const std::string& service, const Action& action, IconObject* o) :
    service_(service),
    action_(action),
    object_(o),
    error_(false),
    waiting_(0)
{
}

MetviewTask::~MetviewTask()
{
    std::cout << "MetviewTask::~MetviewTask " << *object_ << std::endl;
}

void MetviewTask::start()
{
    if (!object_->iconClass().skipDepandancies(action_.name())) {
        const std::set<DependancyH>& dep = object_->dependancies();

        Action action("prepare", "*");

        for (const auto& j : dep) {
            Task* t = j->action(action);
            if (t) {
                tasks_[t] = j;
                waiting_++;
                t->add(this);
            }
        }
    }

    check();
}

void MetviewTask::check()
{
    if (waiting_)
        return;

#if 0
	if(error_)
	{
		Task::failure();
		return;
	}
#endif

    MvRequest r = object_->fullRequest();
    const char* null = nullptr;

    if (null == r("_NAME"))
        r("_NAME") = object_->fullName().c_str();
    if (null == r("_CLASS"))
        r("_CLASS") = object_->className().c_str();
    if (null == r("_ACTION"))
        r("_ACTION") = action_.name().c_str();
    if (null == r("_SERVICE"))
        r("_SERVICE") = service_.c_str();

    // Add extra information from the dropped target object
    if (context_)
        r("_CONTEXT") = context_;

    std::cout << " ---> send " << *this << std::endl;
    r.print();

    if (error_)
        Task::failure(r);
    else
        callService(service_, r);

    std::cout << " <--- send " << *this << std::endl;
}

// Sends a special progress message back to Desktop to indicate that the
// GUI app started up. Desktop then turns the icon green. Otherwise the icon would stay
// orange and all other actions would be blocked on it until the GUI finishes!!
// Ideally we should send a reply back to Desktop but this CAN ONLY BE SENT when
// the forked process (the GUI) has finished!!!

void MetviewTask::progress(const Request& r)
{
    if (const char* v = r.getVerb()) {
        // When a GUI_STARTED request is received in progress() it means
        // the interactive (GUI) app we requested for has been started up and we can
        // regard this task as finished and can tun the icon green so that it could
        // receive another action. This typically happens when we start up an examiner.
        if (strcmp(v, "GUI_STARTED") == 0) {
            Task::success(r);
        }
    }
}

void MetviewTask::reply(const Request& r, int err)
{
#if 0
	if(err) 
		Task::failure();
#endif

    std::cout << " ---> reply " << *this << std::endl;
    r.print();
    std::cout << "action = " << action_.name() << std::endl;
    std::cout << " <--- reply " << *this << std::endl;

    if (r) {
        IconObjectH o = IconFactory::createTemporary(object_, r);
        TaskH t = o->action(action_);
    }

    if (err)
        Task::failure(r);
    else
        Task::success(r);
}

void MetviewTask::message(const std::string& s)
{
    Log::info(object_) << s << std::endl;
}

void MetviewTask::success(Task* t, const Request& r)
{
    std::cout << "MetviewTask::success " << *t << std::endl;
    tasks_[t]->success(r);
    waiting_--;
    check();
}

void MetviewTask::failure(Task* t, const Request& r)
{
    std::cout << "MetviewTask::failure " << *t << std::endl;
    error_ = true;
    tasks_[t]->failure(r);
    waiting_--;
    check();
}

void MetviewTask::print(std::ostream& s) const
{
    s << "MetviewTask["
      << service_
      << ","
      << action_.name()
      << ","
      << action_.mode()
      << ","
      << *object_
      << "]";
}
