//
// C++ Implementation: signal_manager
//
// Description:
//
//
// Author: Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include "me_signal.h"
#include "abstractslot.h"
#include "storage.h"
#include <map>
#include <iostream>

#define LOG_SIGNAL std::cerr<<"SIGNAL:"
//#include <multimap>
typedef std::multimap<SignalName, SlotName> SignalMap;
typedef std::map<SlotName, AbstractSlot*> SlotMap;
SignalMap _signal_map_;
SlotMap _slot_map_;

void connect ( const SignalName &signal_name, const SlotName &slot_name )
{
    _signal_map_.insert ( make_pair ( signal_name, slot_name ) );
//    LOG_SIGNAL << "\"" << signal_name << "\" connected to \"" << slot_name << "\"" << std::endl;
}
bool rise_signal ( SignalName &signal_name, SlotArgs *params )
{
    SignalMap::iterator cslot;
    SignalMap::iterator end_slot;
    cslot = _signal_map_.lower_bound ( signal_name );
    end_slot = _signal_map_.upper_bound ( signal_name );
    if ( cslot == _signal_map_.end() ) return false;
    for ( ; cslot != end_slot && cslot != _signal_map_.end(); )
    {
        SlotMap::iterator slot;
        slot = _slot_map_.find ( cslot->second );
        if ( slot == _slot_map_.end() ) return false;
        if ( ! slot->second ) return false;
        ++cslot;
        if ( slot->second->_invoke ( params ) )
        {
            return true;
        }
    }
    return false;
}
bool register_slot ( const SlotName &slot_name, AbstractSlot *slot )
{
    if ( _slot_map_.find ( slot_name ) != _slot_map_.end() ) return false;
    _slot_map_.insert ( make_pair ( slot_name, slot ) );
//    LOG_SIGNAL << "Registered slot: \"" << slot_name << "\"" << std::endl;
    return true;
}

void disconnect ( const SignalName &signal_name, const SlotName &slot_name )
{
    SignalMap::iterator cslot;
    SignalMap::iterator end_slot;
    cslot = _signal_map_.lower_bound ( signal_name );
    end_slot = _signal_map_.upper_bound ( signal_name );
    for ( ; cslot != end_slot && cslot != _signal_map_.end(); )
    {
        if ( cslot->second != slot_name )
        {
            cslot++;
            continue; //��� �� ��� ����.
        }
        // ����� ������ ����. ������ ���������� � ������
//        LOG_SIGNAL << "\"" << signal_name << "\" disconnected from \"" << cslot->second << "\"" << std::endl;
        _signal_map_.erase ( cslot++ );
    }
}

bool send_signal_to ( SignalName & signal_name, SlotArgs * params, SlotName & slot_name )
{
    SlotMap::iterator slot;
    slot = _slot_map_.find ( slot_name );
    if ( slot == _slot_map_.end() ) return false;
    slot->second->_invoke ( params );

    return true;
}

bool unregister_slot ( const SlotName &slot_name )
{
    SlotMap::iterator slot_iterator;
    if ( ( slot_iterator = _slot_map_.find ( slot_name ) ) == _slot_map_.end() ) return false;
//    LOG_SIGNAL << "Unregistering slot: \"" << slot_name << "\"" << std::endl;
    _slot_map_.erase ( slot_iterator );
    //Почистим список сигналов
    SignalMap::iterator signal_iterator;
    for ( signal_iterator = _signal_map_.begin(); signal_iterator != _signal_map_.end(); )
    {
        if ( signal_iterator->second == slot_name )
        {
            _signal_map_.erase ( signal_iterator++ );
        }
        else ++signal_iterator;
    }
    return true;
}
