//===-- Listener.cpp --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Listener.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Event.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/lldb-private-log.h"
#include <algorithm>

using namespace lldb;
using namespace lldb_private;

Listener::Listener(const char *name) :
    m_name (name),
    m_broadcasters(),
    m_broadcasters_mutex (Mutex::eMutexTypeRecursive),
    m_events (),
    m_events_mutex (Mutex::eMutexTypeRecursive),
    m_cond_wait()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    if (log)
        log->Printf ("%p Listener::Listener('%s')", this, m_name.c_str());
}

Listener::~Listener()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    Mutex::Locker locker (m_broadcasters_mutex);
    
    size_t num_managers = m_broadcaster_managers.size();
    
    for (size_t i = 0; i < num_managers; i++)
        m_broadcaster_managers[i]->RemoveListener(*this);
        
    if (log)
        log->Printf ("%p Listener::~Listener('%s')", this, m_name.c_str());
    Clear();
}

void
Listener::Clear()
{
    Mutex::Locker locker(m_broadcasters_mutex);
    broadcaster_collection::iterator pos, end = m_broadcasters.end();
    for (pos = m_broadcasters.begin(); pos != end; ++pos)
        pos->first->RemoveListener (this, pos->second.event_mask);
    m_broadcasters.clear();
    m_cond_wait.SetValue (false, eBroadcastNever);
    m_broadcasters.clear();
    Mutex::Locker event_locker(m_events_mutex);
    m_events.clear();
}

uint32_t
Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
{
    if (broadcaster)
    {
        // Scope for "locker"
        // Tell the broadcaster to add this object as a listener
        {
            Mutex::Locker locker(m_broadcasters_mutex);
            m_broadcasters.insert(std::make_pair(broadcaster, BroadcasterInfo(event_mask)));
        }

        uint32_t acquired_mask = broadcaster->AddListener (this, event_mask);

        if (event_mask != acquired_mask)
        {

        }
        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
        if (log)
            log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
                         this,
                         broadcaster,
                         event_mask,
                         acquired_mask,
                         m_name.c_str());

        return acquired_mask;

    }
    return 0;
}

uint32_t
Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask, HandleBroadcastCallback callback, void *callback_user_data)
{
    if (broadcaster)
    {
        // Scope for "locker"
        // Tell the broadcaster to add this object as a listener
        {
            Mutex::Locker locker(m_broadcasters_mutex);
            m_broadcasters.insert(std::make_pair(broadcaster, BroadcasterInfo(event_mask, callback, callback_user_data)));
        }

        uint32_t acquired_mask = broadcaster->AddListener (this, event_mask);

        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
        if (log)
            log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x, callback = %p, user_data = %p) acquired_mask = 0x%8.8x for %s",
                        this, broadcaster, event_mask, callback, callback_user_data, acquired_mask, m_name.c_str());

        return acquired_mask;
    }
    return 0;
}

bool
Listener::StopListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
{
    if (broadcaster)
    {
        // Scope for "locker"
        {
            Mutex::Locker locker(m_broadcasters_mutex);
            m_broadcasters.erase (broadcaster);
        }
        // Remove the broadcaster from our set of broadcasters
        return broadcaster->RemoveListener (this, event_mask);
    }

    return false;
}

// Called when a Broadcaster is in its destuctor. We need to remove all
// knowledge of this broadcaster and any events that it may have queued up
void
Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
{
    // Scope for "broadcasters_locker"
    {
        Mutex::Locker broadcasters_locker(m_broadcasters_mutex);
        m_broadcasters.erase (broadcaster);
    }

    // Scope for "event_locker"
    {
        Mutex::Locker event_locker(m_events_mutex);
        // Remove all events for this broadcaster object.
        event_collection::iterator pos = m_events.begin();
        while (pos != m_events.end())
        {
            if ((*pos)->GetBroadcaster() == broadcaster)
                pos = m_events.erase(pos);
            else
                ++pos;
        }

        if (m_events.empty())
            m_cond_wait.SetValue (false, eBroadcastNever);

    }
}

void
Listener::BroadcasterManagerWillDestruct (BroadcasterManager *manager)
{
    // Just need to remove this broadcast manager from the list of managers:
    broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end();
    iter = find(m_broadcaster_managers.begin(), end_iter, manager);
    if (iter != end_iter)
        m_broadcaster_managers.erase (iter);
}

void
Listener::AddEvent (EventSP &event_sp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
    if (log)
        log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})", this, m_name.c_str(), event_sp.get());

    // Scope for "locker"
    {
        Mutex::Locker locker(m_events_mutex);
        m_events.push_back (event_sp);
    }
    m_cond_wait.SetValue (true, eBroadcastAlways);
}

class EventBroadcasterMatches
{
public:
    EventBroadcasterMatches (Broadcaster *broadcaster) :
        m_broadcaster (broadcaster)    {
    }

    bool operator() (const EventSP &event_sp) const
    {
        if (event_sp->BroadcasterIs(m_broadcaster))
            return true;
        else
            return false;
    }

private:
    Broadcaster *m_broadcaster;

};

class EventMatcher
{
public:
    EventMatcher (Broadcaster *broadcaster, const ConstString *broadcaster_names, uint32_t num_broadcaster_names, uint32_t event_type_mask) :
        m_broadcaster (broadcaster),
        m_broadcaster_names (broadcaster_names),
        m_num_broadcaster_names (num_broadcaster_names),
        m_event_type_mask (event_type_mask)
    {
    }

    bool operator() (const EventSP &event_sp) const
    {
        if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
            return false;

        if (m_broadcaster_names)
        {
            bool found_source = false;
            const ConstString &event_broadcaster_name = event_sp->GetBroadcaster()->GetBroadcasterName();
            for (uint32_t i=0; i<m_num_broadcaster_names; ++i)
            {
                if (m_broadcaster_names[i] == event_broadcaster_name)
                {
                    found_source = true;
                    break;
                }
            }
            if (!found_source)
                return false;
        }

        if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType())
            return true;
        return false;
    }

private:
    Broadcaster *m_broadcaster;
    const ConstString *m_broadcaster_names;
    const uint32_t m_num_broadcaster_names;
    const uint32_t m_event_type_mask;
};


bool
Listener::FindNextEventInternal
(
    Broadcaster *broadcaster,   // NULL for any broadcaster
    const ConstString *broadcaster_names, // NULL for any event
    uint32_t num_broadcaster_names,
    uint32_t event_type_mask,
    EventSP &event_sp,
    bool remove)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));

    Mutex::Locker lock(m_events_mutex);

    if (m_events.empty())
        return false;


    Listener::event_collection::iterator pos = m_events.end();

    if (broadcaster == NULL && broadcaster_names == NULL && event_type_mask == 0)
    {
        pos = m_events.begin();
    }
    else
    {
        pos = std::find_if (m_events.begin(), m_events.end(), EventMatcher (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask));
    }

    if (pos != m_events.end())
    {
        event_sp = *pos;
        
        if (log)
            log->Printf ("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, broadcaster_names=%p[%u], event_type_mask=0x%8.8x, remove=%i) event %p",
                         this,
                         GetName(),
                         broadcaster,
                         broadcaster_names,
                         num_broadcaster_names,
                         event_type_mask,
                         remove,
                         event_sp.get());

        if (remove)
        {
            m_events.erase(pos);

            if (m_events.empty())
                m_cond_wait.SetValue (false, eBroadcastNever);
        }
        
        // Unlock the event queue here.  We've removed this event and are about to return
        // it so it should be okay to get the next event off the queue here - and it might
        // be useful to do that in the "DoOnRemoval".
        lock.Unlock();
        
        // Don't call DoOnRemoval if you aren't removing the event...
        if (remove)
            event_sp->DoOnRemoval();
            
        return true;
    }

    event_sp.reset();
    return false;
}

Event *
Listener::PeekAtNextEvent ()
{
    EventSP event_sp;
    if (FindNextEventInternal (NULL, NULL, 0, 0, event_sp, false))
        return event_sp.get();
    return NULL;
}

Event *
Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster)
{
    EventSP event_sp;
    if (FindNextEventInternal (broadcaster, NULL, 0, 0, event_sp, false))
        return event_sp.get();
    return NULL;
}

Event *
Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask)
{
    EventSP event_sp;
    if (FindNextEventInternal (broadcaster, NULL, 0, event_type_mask, event_sp, false))
        return event_sp.get();
    return NULL;
}


bool
Listener::GetNextEventInternal
(
    Broadcaster *broadcaster,   // NULL for any broadcaster
    const ConstString *broadcaster_names, // NULL for any event
    uint32_t num_broadcaster_names,
    uint32_t event_type_mask,
    EventSP &event_sp
)
{
    return FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true);
}

bool
Listener::GetNextEvent (EventSP &event_sp)
{
    return GetNextEventInternal (NULL, NULL, 0, 0, event_sp);
}


bool
Listener::GetNextEventForBroadcaster (Broadcaster *broadcaster, EventSP &event_sp)
{
    return GetNextEventInternal (broadcaster, NULL, 0, 0, event_sp);
}

bool
Listener::GetNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp)
{
    return GetNextEventInternal (broadcaster, NULL, 0, event_type_mask, event_sp);
}


bool
Listener::WaitForEventsInternal
(
    const TimeValue *timeout,
    Broadcaster *broadcaster,   // NULL for any broadcaster
    const ConstString *broadcaster_names, // NULL for any event
    uint32_t num_broadcaster_names,
    uint32_t event_type_mask,
    EventSP &event_sp
)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
    bool timed_out = false;

    if (log)
    {
        log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s",
                    this, timeout, m_name.c_str());
    }

    while (1)
    {
        // Note, we don't want to lock the m_events_mutex in the call to GetNextEventInternal, since the DoOnRemoval
        // code might require that new events be serviced.  For instance, the Breakpoint Command's 
        if (GetNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp))
                return true;

        {
            // Reset condition value to false, so we can wait for new events to be
            // added that might meet our current filter
            // But first poll for any new event that might satisfy our condition, and if so consume it,
            // otherwise wait.
            
            Mutex::Locker event_locker(m_events_mutex);
            const bool remove = false;
            if (FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, remove))
                continue;
            else
                m_cond_wait.SetValue (false, eBroadcastNever);
        }

        if (m_cond_wait.WaitForValueEqualTo (true, timeout, &timed_out))
            continue;

        else if (timed_out)
        {
            log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
            if (log)
                log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s", this, m_name.c_str());
            break;
        }
        else
        {
            log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
            if (log)
                log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s", this, m_name.c_str());
            break;
        }
    }

    return false;
}

bool
Listener::WaitForEventForBroadcasterWithType
(
    const TimeValue *timeout,
    Broadcaster *broadcaster,
    uint32_t event_type_mask,
    EventSP &event_sp
)
{
    return WaitForEventsInternal (timeout, broadcaster, NULL, 0, event_type_mask, event_sp);
}

bool
Listener::WaitForEventForBroadcaster
(
    const TimeValue *timeout,
    Broadcaster *broadcaster,
    EventSP &event_sp
)
{
    return WaitForEventsInternal (timeout, broadcaster, NULL, 0, 0, event_sp);
}

bool
Listener::WaitForEvent (const TimeValue *timeout, EventSP &event_sp)
{
    return WaitForEventsInternal (timeout, NULL, NULL, 0, 0, event_sp);
}

//Listener::broadcaster_collection::iterator
//Listener::FindBroadcasterWithMask (Broadcaster *broadcaster, uint32_t event_mask, bool exact)
//{
//    broadcaster_collection::iterator pos;
//    broadcaster_collection::iterator end = m_broadcasters.end();
//    for (pos = m_broadcasters.find (broadcaster);
//        pos != end && pos->first == broadcaster;
//        ++pos)
//    {
//        if (exact)
//        {
//            if ((event_mask & pos->second.event_mask) == event_mask)
//                return pos;
//        }
//        else
//        {
//            if (event_mask & pos->second.event_mask)
//                return pos;
//        }
//    }
//    return end;
//}

size_t
Listener::HandleBroadcastEvent (EventSP &event_sp)
{
    size_t num_handled = 0;
    Mutex::Locker locker(m_broadcasters_mutex);
    Broadcaster *broadcaster = event_sp->GetBroadcaster();
    broadcaster_collection::iterator pos;
    broadcaster_collection::iterator end = m_broadcasters.end();
    for (pos = m_broadcasters.find (broadcaster);
        pos != end && pos->first == broadcaster;
        ++pos)
    {
        BroadcasterInfo info = pos->second;
        if (event_sp->GetType () & info.event_mask)
        {
            if (info.callback != NULL)
            {
                info.callback (event_sp, info.callback_user_data);
                ++num_handled;
            }
        }
    }
    return num_handled;
}

uint32_t
Listener::StartListeningForEventSpec (BroadcasterManager &manager, 
                             const BroadcastEventSpec &event_spec)
{
    // The BroadcasterManager mutex must be locked before m_broadcasters_mutex 
    // to avoid violating the lock hierarchy (manager before broadcasters).
    Mutex::Locker manager_locker(manager.m_manager_mutex);
    Mutex::Locker locker(m_broadcasters_mutex);

    uint32_t bits_acquired = manager.RegisterListenerForEvents(*this, event_spec);
    if (bits_acquired)
        m_broadcaster_managers.push_back(&manager);
        
    return bits_acquired;
}
    
bool
Listener::StopListeningForEventSpec (BroadcasterManager &manager, 
                             const BroadcastEventSpec &event_spec)
{
    Mutex::Locker locker(m_broadcasters_mutex);
    return manager.UnregisterListenerForEvents (*this, event_spec);

}
    

