#include "protocol/RemoteContextManager.h"
#include "IllegalStateException.h"
#include "util/MessageFormat.h"

RemoteContextManager::RemoteContextManager(AbstractAggreGateDeviceController* controller, AggreGateDevice* /*server*/, bool async)
    : DefaultContextManager(async)
{
    initialized = false;
    initializing = false;
    this->controller = controller;
}

void RemoteContextManager::initialize()
{
	if(initialized || initializing) {
        return;
    }

    initializing = true;

    try
    {
        controller->AbstractDeviceController::connect();
    }catch(AggreGateException ex) {
        initializing = false;
        throw ex;
    }

    initializing = false;
    initialized = true;
}

void RemoteContextManager::stop()
{
    initialized = false;
    DefaultContextManager::stop();
}

AbstractAggreGateDeviceController *RemoteContextManager::getController()
{
    return controller;
}

void RemoteContextManager::sendAddListener(const AgString & context, const AgString & event, ContextEventListenerPtr listener)
{
    try
    {
        AgString filterText = listener->getFilter() != NULL ? listener->getFilter()->getText() : "";
        getController()->sendCommandAndCheckReplyCode(AggreGateCommandUtils::addEventListenerOperation(
                                                          context, event, listener->getListenerCode(), filterText));
    }catch (AggreGateException ex) {
        AgString msg = MessageFormat::format(Cres::get()->getString("conErrAddingListener"), event, context);
        throw  IllegalStateException(msg + ": " + ex.getMessage(), ex.getDetails());
    }
}

void RemoteContextManager::sendRemoveListener(const AgString & context, const AgString & event, ContextEventListenerPtr listener)
{
    try
    {
        AgString filter = listener->getFilter() != NULL ? listener->getFilter()->getText() : "";
        getController()->sendCommandAndCheckReplyCode(AggreGateCommandUtils::removeEventListenerOperation(
                                                          context, event, listener->getListenerCode(), filter));
    }
    catch (AggreGateException ex)
    {
        AgString msg = MessageFormat::format(Cres::get()->getString("conErrRemovingListener"), event, context);
        throw IllegalStateException(msg + ": " + ex.getMessage(), ex.getDetails());
    }
}

void RemoteContextManager::addListenerToContext(ProxyContextPtr con, const AgString & event, ContextEventListenerPtr listener,
                                                bool mask, bool /*weak*/)
{
    con->addEventListener(event, listener, false, !mask);
}

void RemoteContextManager::addListenerToContext(ContextPtr con, const AgString & event, ContextEventListenerPtr listener,
                                                bool mask, bool weak)
{ 
    addListenerToContext(boost::static_pointer_cast< ProxyContext >(con), event, listener, mask, weak);
}

void RemoteContextManager::removeListenerFromContext(ProxyContextPtr con, const AgString & event, ContextEventListenerPtr listener, bool mask)
{
    con->removeEventListener(event, listener, !mask);
}

void RemoteContextManager::removeListenerFromContext(ContextPtr con, const AgString & event, ContextEventListenerPtr listener, bool mask)
{ 
    removeListenerFromContext(boost::static_pointer_cast< ProxyContext >(con), event, listener, mask);
}

void RemoteContextManager::addMaskEventListener(const AgString & mask, const AgString & event, ContextEventListenerPtr listener)
{
    DefaultContextManager::addMaskEventListener(mask, event, listener);
    sendAddListener(mask, event, listener);
}

void RemoteContextManager::removeMaskEventListener(const AgString & mask, const AgString & event, ContextEventListenerPtr listener)
{
    DefaultContextManager::removeMaskEventListener(mask, event, listener);
	sendRemoveListener(mask, event, listener);
}

void RemoteContextManager::contextRemoved(ProxyContextPtr con)
{
    UNUSED(con);
    // We don't store listeners from removed contexts because server do that itself
}

void RemoteContextManager::contextRemoved(ContextPtr con)
{ 
    contextRemoved(boost::static_pointer_cast< ProxyContext >(con));
}
