#ifndef AsyncCommandProcessorH
#define AsyncCommandProcessorH

#include "communication/AbstractDeviceController.h"
#include "communication/Command.h"
#include "communication/CommandParser.h"
#include "communication/CommandProcessorStatistics.h"
#include "communication/ReplyMonitor.h"
#include "device/DisconnectionException.h"
#include "util/ThreadPoolCachedEx.h"
#include "util/AgThread.h"
#include "util/Util.h"
#include "util/Pointers.h"
#include <boost/thread/thread.hpp>
#include <boost/enable_shared_from_this.hpp>

class  AsyncCommandProcessor : public AgThread, public boost::enable_shared_from_this<AsyncCommandProcessor>
{
private:
    AbstractDeviceController* controller;
    std::list<ReplyMonitorPtr>  sentCommandsQueue;
	CommandProcessorStatisticsPtr statistics;
    boost::mutex sentCommandsQueueMutex_;
    boost::mutex mutex_;

    bool bRunning;

    void init();
	void sendCommandImplementation(CommandPtr cmd);
    ReplyMonitorPtr sendCommand(CommandPtr cmd);
    CommandPtr waitReplyMonitor(ReplyMonitorPtr mon);
    void addSentCommand(ReplyMonitorPtr mon);
    void processError(int priority, const AgString & message, const AggreGateException& ex);

protected:
    virtual void run();

public:
	CommandPtr sendSyncCommand(CommandPtr cmd);
	void sendUnrepliedCommand(CommandPtr cmd);
	void resetSentCommandTimeouts();
    bool isActive();

    virtual void start();
    void finishThread();

    std::list< ReplyMonitorPtr >  getActiveCommands();	
    AbstractDeviceController* getController();
	CommandProcessorStatisticsPtr getStatistics();

    AsyncCommandProcessor(AbstractDeviceController* controller);
};
#endif
