//===-- SBBroadcaster.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/Broadcaster.h"
#include "lldb/Core/Log.h"

#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBEvent.h"

using namespace lldb;
using namespace lldb_private;


SBBroadcaster::SBBroadcaster () :
    m_opaque_sp (),
    m_opaque_ptr (NULL)
{
}

SBBroadcaster::SBBroadcaster (const char *name) :
    m_opaque_sp (new Broadcaster (NULL, name)),
    m_opaque_ptr (NULL)
{
    m_opaque_ptr = m_opaque_sp.get();
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API | LIBLLDB_LOG_VERBOSE));

    if (log)
        log->Printf ("SBBroadcaster::SBBroadcaster (name=\"%s\") => SBBroadcaster(%p)",
                     name, static_cast<void*>(m_opaque_ptr));
}

SBBroadcaster::SBBroadcaster (lldb_private::Broadcaster *broadcaster, bool owns) :
    m_opaque_sp (owns ? broadcaster : NULL),
    m_opaque_ptr (broadcaster)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API | LIBLLDB_LOG_VERBOSE));

    if (log)
        log->Printf ("SBBroadcaster::SBBroadcaster (broadcaster=%p, bool owns=%i) => SBBroadcaster(%p)",
                     static_cast<void*>(broadcaster), owns,
                     static_cast<void*>(m_opaque_ptr));
}

SBBroadcaster::SBBroadcaster (const SBBroadcaster &rhs) :
    m_opaque_sp (rhs.m_opaque_sp),
    m_opaque_ptr (rhs.m_opaque_ptr) 
{
}

const SBBroadcaster &
SBBroadcaster::operator = (const SBBroadcaster &rhs)
{
    if (this != &rhs)
    {
        m_opaque_sp = rhs.m_opaque_sp;
        m_opaque_ptr = rhs.m_opaque_ptr;
    }
    return *this;
}

SBBroadcaster::~SBBroadcaster()
{
    reset (NULL, false);
}

void
SBBroadcaster::BroadcastEventByType (uint32_t event_type, bool unique)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBBroadcaster(%p)::BroadcastEventByType (event_type=0x%8.8x, unique=%i)",
                     static_cast<void*>(m_opaque_ptr), event_type, unique);

    if (m_opaque_ptr == NULL)
        return;

    if (unique)
        m_opaque_ptr->BroadcastEventIfUnique (event_type);
    else
        m_opaque_ptr->BroadcastEvent (event_type);
}

void
SBBroadcaster::BroadcastEvent (const SBEvent &event, bool unique)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    if (log)
        log->Printf ("SBBroadcaster(%p)::BroadcastEventByType (SBEvent(%p), unique=%i)",
                     static_cast<void*>(m_opaque_ptr),
                     static_cast<void*>(event.get()), unique);

    if (m_opaque_ptr == NULL)
        return;

    EventSP event_sp = event.GetSP ();
    if (unique)
        m_opaque_ptr->BroadcastEventIfUnique (event_sp);
    else
        m_opaque_ptr->BroadcastEvent (event_sp);
}

void
SBBroadcaster::AddInitialEventsToListener (const SBListener &listener, uint32_t requested_events)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (log)
        log->Printf ("SBBroadcaster(%p)::AddInitialEventsToListener (SBListener(%p), event_mask=0x%8.8x)",
                     static_cast<void*>(m_opaque_ptr),
                     static_cast<void*>(listener.get()), requested_events);
    if (m_opaque_ptr)
        m_opaque_ptr->AddInitialEventsToListener (listener.m_opaque_sp, requested_events);
}

uint32_t
SBBroadcaster::AddListener (const SBListener &listener, uint32_t event_mask)
{
    if (m_opaque_ptr)
        return m_opaque_ptr->AddListener (listener.m_opaque_sp, event_mask);
    return 0;
}

const char *
SBBroadcaster::GetName () const
{
    if (m_opaque_ptr)
        return m_opaque_ptr->GetBroadcasterName().GetCString();
    return NULL;
}

bool
SBBroadcaster::EventTypeHasListeners (uint32_t event_type)
{
    if (m_opaque_ptr)
        return m_opaque_ptr->EventTypeHasListeners (event_type);
    return false;
}

bool
SBBroadcaster::RemoveListener (const SBListener &listener, uint32_t event_mask)
{
    if (m_opaque_ptr)
        return m_opaque_ptr->RemoveListener (listener.m_opaque_sp, event_mask);
    return false;
}

Broadcaster *
SBBroadcaster::get () const
{
    return m_opaque_ptr;
}

void
SBBroadcaster::reset (Broadcaster *broadcaster, bool owns)
{
    if (owns)
        m_opaque_sp.reset (broadcaster);
    else
        m_opaque_sp.reset ();
    m_opaque_ptr = broadcaster;
}


bool
SBBroadcaster::IsValid () const
{
    return m_opaque_ptr != NULL;
}

void
SBBroadcaster::Clear ()
{
    m_opaque_sp.reset();
    m_opaque_ptr = NULL;
}

bool
SBBroadcaster::operator == (const SBBroadcaster &rhs) const
{
    return m_opaque_ptr == rhs.m_opaque_ptr;
    
}

bool
SBBroadcaster::operator != (const SBBroadcaster &rhs) const
{
    return m_opaque_ptr != rhs.m_opaque_ptr;
}

bool
SBBroadcaster::operator < (const SBBroadcaster &rhs) const
{
    return m_opaque_ptr < rhs.m_opaque_ptr;
}
