#ifndef DEVICECONTROLLERINTERFACE_H
#define DEVICECONTROLLERINTERFACE_H

#include <QtPlugin>

#include <QSettings>
#include <QString>

#include "ATBAPPplugin.h"

namespace nsDeviceControllerInterface {
    enum class PLUGIN_STATE : quint8;
    enum class RESULT_STATE : quint8;
    enum class CASH_STATE   : quint8;
}


class DeviceControllerInterface : public ATBAPPplugin
{
    Q_INTERFACES(ATBAPPplugin)

public:
    virtual ~DeviceControllerInterface() {}

    virtual nsDeviceControllerInterface::PLUGIN_STATE initDCPlugin(QObject *healthEventReceiver,
                                                                   const QSettings & settings) = 0;

    // TASKS: Cash handling -------------------------------------------------------
    /**
     * enables coin input
     * amount = "0": pay-up
     * amount > "0": pay-down
     */
    virtual void requestStartCashInput(const QString & amount) = 0;

    /**
     * called e.g. on Button "NEXT" in pay-up (direct coin input)
     */
    virtual void requestStopCashInput() = 0;

    /**
     * called e.g. on Button "NEXT" in pay-up (direct coin input)
     */
    virtual void cashCollect() = 0;
    virtual void cashAbort() = 0;



    // TASKS: printing ------------------------------------------------------------
    virtual void requestPrintTicket(const QHash<QString, QVariant> & printingData) = 0;


    // mandantory ATBAPP plugin methods:
    virtual nsDeviceControllerInterface::PLUGIN_STATE getState() = 0;
    virtual const QString & getLastError() = 0;
    virtual const QString & getLastErrorDescription() = 0;

    // return a plugin description in JSON or XML
    // -> ATBAPPplugin::getPluginInfo()

    // helpers e.g. for debug / log
    virtual const QString getString(nsDeviceControllerInterface::RESULT_STATE resultState) = 0;


signals:
    virtual void printTicketFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
                                     const QString & errorCode,
                                     const QString & errorDescription) = 0;

    /**
     * emitted on e.g. a coin input
     */
    virtual void cashInputEvent(nsDeviceControllerInterface::RESULT_STATE resultState,
                                nsDeviceControllerInterface::CASH_STATE cashState,
                                const QString & newCashValue,
                                /* additional variables? */
                                const QString & errorCode,
                                const QString & errorDescription) = 0;

    /**
     * emitted if cashInput has been stopped, e.g. in result to task requestStopCashInput():
     *  -> shutter is blocked
     *  -> no cash input is possible
     *  -> coins are in cache
     */
    virtual void cashInputFinished(nsDeviceControllerInterface::RESULT_STATE resultState,
                                     const QString & newCashValue,
                                     /*  additional variables? */
                                     const QString & errorCode,
                                     const QString & errorDescription) = 0;


    /**
     * emitted e.g. if service door is opened
     */
    virtual void requestServiceMode() = 0;

    /**
     * emitted on error
     * depending on errorCode:
     * -> interrupt selling process
     * -> machine can go to state OOO
     * -> send error event to ISMAS
     * -> ...
     */
    virtual void Error(
            /*  additional variables? */
            const QString & errorCode,
            const QString & errorDescription) = 0;

};


Q_DECLARE_INTERFACE(DeviceControllerInterface,
                    "eu.atb.ptu.plugin.DeviceControllerInterface/1.0")


namespace nsDeviceControllerInterface {

    enum class PLUGIN_STATE : quint8 {
        NOT_INITIALIZED = 0,
        INITIALIZED = 1
    };

    enum class RESULT_STATE : quint8 {
        SUCCESS = 1,                // operation was successfull
        ERROR_BACKEND,              // error from backend (e.g. backend replies with error)
        ERROR_TIMEOUT,              // the operation timed out
        ERROR_PROCESS,              // internal plugin error, should not occur (this is a bug in implementation)
        ERROR_RETRY,                // retry operation
        INFO                        // informational (e.g. display a message, log something etc.)
    };

    enum class CASH_STATE   : quint8 {
        CACHE_EMPTY,                // Cache still empty, default state
        CACHE_INPUT,                // Coins are in Cache
        OVERPAYED,
        /* t.b.d. */
    };
}

#endif // DEVICECONTROLLERINTERFACE_H
