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

//! Abstract intermediate class, derived from MvProtocol
/*! Thus MvService inherits MvProtocol responsibilities.
 *  MvService is an abstract class because
 *  its method \c serve is a pure virtual method.
 *  A new class must be derived from MvService for each command
 *  the module must execute. The derived class must provide the method
 *  \c serve, which is responsible for the execution of the command.
 */

class MvService : public MvProtocol
{
    boolean HasModes, saveToPool_;

protected:
    void hasModes() { HasModes = true; }

    //! A higher level transparent callback function
    /*! This method is automatically called by the callback function
     *  when a command arrives. It forks the process and checks in the pool
     *  if the command has already been executed.
     *  If not, it calls method \c serve.
     */
    virtual void _call_serve(svcid* id, request* r);

    //! Synchronous call to another service
    /*! This method sends request \c in to service pointed by \c name
     *  and synchronously waits for the answer in request \c out
     */
    err callService(char* name, MvRequest& in, MvRequest& out);

    //! Links this icon to another
    /*! This method tells pool service to create a dependency between
     *  the object currently being executed and the object identified
     *  by variable \c name.
     */
    void linkTo(char*);

    virtual MvRequest buildMode(MvRequest&);

    void clearStaticId();

public:
    //! Constuctor
    /*! The constructor registers a static method \c MvProtocol::_serve
     *  to be called when the module receives the command pointed by name
     */
    MvService(const char* name);

    //! Pure virtual method
    /*! This is the virtual method that must be implemented in the derived class
     *  to process the incoming command. The incoming command is in \c in
     *  and the result command must be stored in \c out
     */
    virtual void serve(MvRequest& in, MvRequest& out) = 0;

    // Create "mode" services

    void addModeService(char* name, char* param);
    void modeServe(MvRequest&, MvRequest&, svcid*);

    void saveToPool(boolean xx) { saveToPool_ = xx; }
    void acknowledgeGuiStartup();
};

//! Abstract base class for TMvServiceFactory
/*! Template class TMvServiceFactory is to be used for
 *  implementing concrete factories
 */
class MvServiceFactory
{
    static MvServiceFactory* head_;
    MvServiceFactory* next_;

public:
    //! Constructor
    MvServiceFactory();

    //! Pure virtual method needs to be implemented in the derived class
    virtual void installService() = 0;

    //! Calls installService() for each factory in the list
    static void installServices();
};

//! Template class inherited from MvServiceFactory
template <class T>
class TMvServiceFactory : public MvServiceFactory
{
public:
    //! Installs a new service of type \c T
    virtual void installService() { new T(); }
};
