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

 Copyright 2012 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 *************************************/

#pragma once

#include <iostream>

#include "Cached.h"

class MvTask;

//! Implements communication with other Metview modules
/*! Most of the methods are private. These are to be used
 *  via friend class MvTask.\n \n
 *  Currently used by PlotMod (and uPlot).
 *  For a simple example, see file \c src/libMetview/Demo.cc
 */
class MvClient
{
    friend class MvTask;

    MvTask* Tasks;

    void notify(MvTask* from);

    // No copy
    MvClient(const MvClient&);
    int operator=(const MvClient&);

    //! Callback received when a task has finished
    /*! This is a pure virtual method that needs to be
	 *  implemented in the derived class
	 */
    virtual void endOfTask(MvTask* from) = 0;

    //! Message from task
    virtual void progress(const char*) {}

public:
    //! Constructor
    MvClient();

    //! Destructor
    virtual ~MvClient();
};

typedef void (MvClient::*endOfTaskProc)(MvTask*);


//! Abstract base class for MvServiceTask and MvShellTask
/*! These classes, together with MvClient, implement communication
 *  and sending tasks to other Metview modules.\n \n
 *  Currently used by PlotMod (and uPlot).
 *  For a simple example, see file \c src/libMetview/Demo.cc
 */
class MvTask
{
    friend class MvClient;
    MvClient* Client;
    MvTask* Next;
    err Error;
    Cached TaskName;

    // No copy
    MvTask(const MvTask&);
    int operator=(const MvTask&);

    // Cannot be delete, call the done() method

    virtual void abort(void) {}


protected:
    void done(void);             // Call when job is done
    void progress(const char*);  // Pass info to client
    void setError(err e) { Error = e; }
    virtual ~MvTask();

public:
    //! Constructor, creates a Task and adds it to the clients list
    MvTask(MvClient* client, const char* taskName = 0);

    //! Implements the execution of a task
    /*! This is a pure virtual method that needs to be
	 *  implemented in the derived class
	 */
    virtual void run(void) = 0;

    //! Returns the error/success code
    /*! Type \c err is defined in \c mars.h
	 */
    err getError() { return Error; }

    //! Returns the task name, or "(?)" if name not given
    const char* taskName() { return TaskName; }
};
