// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <OB/CORBA.h>
#include <OB/Util.h>
#include <OB/Properties.h>

#include <OB/CosEventChannelAdmin_skel.h>

#include <ProxySupplier_impl.h>
#include <ProxyState.h>
#include <PropagatorBaseThread.h> // SGI 7.0/7.1 needs this, and PusherBase...
#include <PusherBaseThread.h>
#include <EC_ProxyPushSupplier_impl.h>
#include <EC_ProxyPullSupplier_impl.h>
#include <EC_ConsumerAdmin_impl.h>

// ----------------------------------------------------------------------
// EC_ConsumerAdmin_impl constructor and destructor
// ----------------------------------------------------------------------

EC_ConsumerAdmin_impl::EC_ConsumerAdmin_impl(
    CORBA_ORB_ptr orb,
    EC_EventChannel_impl* e)
    : orb_(CORBA_ORB::_duplicate(orb)),
      channel_(e),
      nextId_(0),
      destroyed_(false)
{
}

EC_ConsumerAdmin_impl::~EC_ConsumerAdmin_impl()
{
#ifdef OB_TRACE
    OBMessageViewer::instance() -> trace(2, "Destroy ConsumerAdmin");
#endif
    assert(proxies_.length() == 0);
}

// ----------------------------------------------------------------------
// EC_ConsumerAdmin_impl public member implementation
// ----------------------------------------------------------------------

CosEventChannelAdmin_ProxyPushSupplier_ptr
EC_ConsumerAdmin_impl::obtain_push_supplier()
{
    JTCSynchronized sync(*this);

    if(destroyed_)
        throw CORBA_OBJECT_NOT_EXIST();
    
    EC_ProxyPushSupplier_impl* p =
        new EC_ProxyPushSupplier_impl(orb_, this, nextId_++);
    proxies_.append(p);
    return CosEventChannelAdmin_ProxyPushSupplier::_duplicate(p);
}

CosEventChannelAdmin_ProxyPullSupplier_ptr
EC_ConsumerAdmin_impl::obtain_pull_supplier()
{
    JTCSynchronized sync(*this);

    if(destroyed_)
        throw CORBA_OBJECT_NOT_EXIST();
    
    EC_ProxyPullSupplier_impl* p =
        new EC_ProxyPullSupplier_impl(orb_, this, nextId_++);
    proxies_.append(p);
    return CosEventChannelAdmin_ProxyPullSupplier::_duplicate(p);
}

void
EC_ConsumerAdmin_impl::receive(Event_impl* event)
{
    JTCSynchronized sync(*this);

    //
    // Propogate the event to each proxy.
    //
    for(CORBA_ULong i = 0; i < proxies_.length(); ++i)
        proxies_[i] -> receive(event);
}

void
EC_ConsumerAdmin_impl::removeProxy(ProxySupplier_impl* p)
{
    JTCSynchronized sync(*this);
    
    //
    // Find the element, remove it from the sequence.
    //
    for(CORBA_ULong i = 0; i < proxies_.length(); ++i)
        if(proxies_[i] == p)
        {
            p -> release();
            proxies_.remove(i);
            return;
        }
    assert(false);
}

void
EC_ConsumerAdmin_impl::disconnect()
{
    JTCSynchronized sync(*this);

    assert(!destroyed_);
    destroyed_ = true;

    //
    // disconnect each proxy.
    //
    for(CORBA_ULong i = 0; i < proxies_.length(); ++i)
    {
        proxies_[i] -> disconnect();
        proxies_[i] -> release();
    }
    proxies_.length(0);

    //
    // Disconnect the servant from the ORB.
    //
    orb_ -> disconnect(this);
}
