/*
 * Copyright 2009- ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation
 * nor does it submit to any jurisdiction.
 */

#ifndef ecflow_viewer_VTask_HPP
#define ecflow_viewer_VTask_HPP

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "ecflow/attribute/Zombie.hpp"
#include "ecflow/node/NodeFwd.hpp"

// #include "VReply.hpp"
class VReply;

class Node;
class VNode;
class VTaskObserver;

// This class defines a task that can be sent to the server to be executed.
// A VTask can only be created through the static create methods that return back
// a shared pointer of VTask. So VTask can only exist as a shared pointer.

class VTask;
typedef std::shared_ptr<VTask> VTask_ptr;

class VTask : public std::enable_shared_from_this<VTask> {
public:
    enum Type {
        NoTask,
        CommandTask,
        OverviewTask,
        WhySyncTask,
        ManualTask,
        ScriptTask,
        JobTask,
        MessageTask,
        OutputTask,
        StatsTask,
        NewsTask,
        SyncTask,
        ResetTask,
        SuiteAutoRegisterTask,
        SuiteListTask,
        ScriptEditTask,
        ScriptPreprocTask,
        ScriptSubmitTask,
        HistoryTask,
        LogOutTask,
        ZombieListTask,
        ZombieCommandTask,
        ServerVersionTask,
        JobStatusFileTask,
        JobStatusTask,
        PlugTask
    };
    enum Status { NOSTATUS, QUEUED, RUNNING, FINISHED, CANCELLED, ABORTED, REJECTED };

    virtual ~VTask();

    Type type() const { return type_; }
    const std::string& typeString() const;
    VNode* node() const { return node_; }
    Status status() { return status_; }
    const std::string& targetPath() const { return targetPath_; }

    const std::string& param(const std::string& key) const;
    const std::map<std::string, std::string>& params() const { return params_; }
    const std::vector<std::string>& command() const { return command_; }
    const std::string& commandAsStr() const { return commandAsStr_; }
    const std::vector<std::string>& contents() const { return contents_; }
    const NameValueVec& vars() const { return vars_; }
    VReply* reply() const { return reply_; }
    const Zombie& zombie() const { return zombie_; }

    void param(const std::string& key, const std::string& val) { params_[key] = val; }
    void command(const std::vector<std::string>& cmd) { command_ = cmd; }
    void commandAsStr(const std::string& cmd) { commandAsStr_ = cmd; }
    void contents(const std::vector<std::string>& c) { contents_ = c; }
    void vars(const NameValueVec& v) { vars_ = v; }
    void setZombie(const Zombie&);

    // When it is called the observers are notified about the change in status.
    void status(Status s, bool broadcast = true);

    void aborted(const std::string&, bool /*broadcast*/ = true) {}
    void broadcast();
    void removeObserver(VTaskObserver*);

    static VTask_ptr create(Type t, VTaskObserver* obs = nullptr);
    static VTask_ptr create(Type t, VNode* node, VTaskObserver* obs = nullptr);

protected:
    explicit VTask(Type t, VTaskObserver* obs = nullptr);
    VTask(Type t, VNode* node, VTaskObserver* obs = nullptr);

    Type type_;
    Status status_;
    std::map<std::string, std::string> params_;
    std::vector<std::string> command_;
    std::string commandAsStr_;
    std::vector<std::string> contents_;
    NameValueVec vars_;
    std::string targetPath_;
    VNode* node_;
    std::vector<VTaskObserver*> observers_;
    VReply* reply_;
    Zombie zombie_;
};

#endif /* ecflow_viewer_VTask_HPP */
