// **********************************************************************
//
// 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/CosTypedEventChannelAdmin_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 <TEC_ProxyPushSupplier_impl.h>
#include <TEC_TypedConsumerAdmin_impl.h>
#include <TEC_TypedEventChannel_impl.h>

// ----------------------------------------------------------------------
// TEC_TypedConsumerAdmin_impl constructor and destructor
// ----------------------------------------------------------------------

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

TEC_TypedConsumerAdmin_impl::~TEC_TypedConsumerAdmin_impl()
{
#ifdef OB_TRACE
    OBMessageViewer::instance() -> trace(2, "Destroy TypedConsumerAdmin");
#endif
}

// ----------------------------------------------------------------------
// TEC_TypedConsumerAdmin_impl public member implementation
// ----------------------------------------------------------------------

CosEventChannelAdmin_ProxyPushSupplier_ptr
TEC_TypedConsumerAdmin_impl::obtain_push_supplier()
{
    throw CORBA_NO_IMPLEMENT();
    return CosEventChannelAdmin_ProxyPushSupplier::_nil();
}

CosEventChannelAdmin_ProxyPullSupplier_ptr
TEC_TypedConsumerAdmin_impl::obtain_pull_supplier()
{
    throw CORBA_NO_IMPLEMENT();
    return CosEventChannelAdmin_ProxyPullSupplier::_nil();
}

CosEventChannelAdmin_ProxyPushSupplier_ptr
TEC_TypedConsumerAdmin_impl::obtain_typed_push_supplier(const char* typeId)
{
    JTCSynchronized sync(*this);

    if(destroyed_)
        throw CORBA_OBJECT_NOT_EXIST();

    //
    // Attempt to assign this type id to the channel.
    //
    if(!channel_ -> assignTypeId(typeId))
	throw CosTypedEventChannelAdmin_NoSuchImplementation();

    TEC_ProxyPushSupplier_impl* p =
        new TEC_ProxyPushSupplier_impl(orb_, this, nextId_++);
    proxies_.append(p);

    return CosEventChannelAdmin_ProxyPushSupplier::_duplicate(p);
}

CosTypedEventChannelAdmin_TypedProxyPullSupplier_ptr
TEC_TypedConsumerAdmin_impl::obtain_typed_pull_supplier(const char*)
{
    throw CORBA_NO_IMPLEMENT();
    return CosTypedEventChannelAdmin_TypedProxyPullSupplier::_nil();
}

void
TEC_TypedConsumerAdmin_impl::receive(Event_impl* event)
{
    JTCSynchronized sync(*this);
    for(CORBA_ULong i = 0; i < proxies_.length(); ++i)
        proxies_[i] -> receive(event);
}

void
TEC_TypedConsumerAdmin_impl::removeProxy(ProxySupplier_impl* p)
{
    JTCSynchronized sync(*this);
    
    //
    // Find the element, and 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
TEC_TypedConsumerAdmin_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);
}
