#include "communication/ReplyMonitor.h"
#include "communication/Command.h"
#include "util/simpleobject/AgString.h"
#include "util/Log.h"

//#include "QDebug"
//#include <Windows.h>

ReplyMonitor::ReplyMonitor(CommandPtr command)
{
    this->command = command;
    this->startTime = boost::posix_time::microsec_clock::local_time();
    this->time = startTime;
    this->terminated = false;
    this->timeoutReset = false;
	this->reply_is_done = false;
}

CommandPtr ReplyMonitor::getCommand()
{
    return command;
}

CommandPtr ReplyMonitor::getReply()
{
    return reply;
}

void ReplyMonitor::setReply(CommandPtr reply)
{
	{
		boost::unique_lock<boost::mutex> lockMtx(lock);
		this->reply = reply;
		reply_is_done = true;
	}
    commandReceivedCondition.notify_one();

    //boost::posix_time::time_duration dur = boost::posix_time::microsec_clock::local_time() - time;
    //AGDEBUG(DBG_DEBUG, "COMMANDS",  "Command replied in " + AgString::fromInt64(dur.total_milliseconds()) + " ms: command '" + command->toString() + "', reply '" + reply->toString() + "'");

    //AgString s = "Command replied: " + command->toString();
    //qDebug() << QString::fromUtf8(s.toUtf8().c_str());
}

void ReplyMonitor::terminate()
{
	{
		boost::unique_lock<boost::mutex> lockMtx(lock);
	    terminated = true;
		reply_is_done = true;
	}
    commandReceivedCondition.notify_one();
}

void ReplyMonitor::reset()
{

}

bool ReplyMonitor::waitReply(int64_t timeout)
{
    UNUSED(timeout);
    boost::unique_lock<boost::mutex> lockMtx(lock);
    if (!reply_is_done)
    {
        boost::system_time const timeoutMs = boost::get_system_time()+ boost::posix_time::milliseconds(timeout);
        if (!commandReceivedCondition.timed_wait(lockMtx, timeoutMs))
        {
            //timeout
            return false;
        }
    }


    if (reply != NULL) {
        return true;
    }
    if (terminated){
        return false;
    }
    timeoutReset = false;

    return reply != NULL;
}

boost::posix_time::ptime ReplyMonitor::getTime()
{
    return time;
}

boost::posix_time::ptime ReplyMonitor::getStartTime()
{
    return startTime;
}


AgString ReplyMonitor::toString()
{
    return "ReplyMonitor [command: " + command->toString() + ", reply: " + reply->toString() + "]";
}
