// **********************************************************************
//
// Copyright (c) 2002
// IONA Technologies, Inc.
// Waltham, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_ORB_CONTROL_H
#define OB_ORB_CONTROL_H

#include <OB/TypeCodeConst_fwd.h>
#include <OB/ORBControl_fwd.h>
#include <OB/OBORB_fwd.h>
#include <OB/ORBInstance_fwd.h>
#include <OB/OBPOAManager_fwd.h>
#include <OB/POAInterface_fwd.h>
#include <OB/Reactor_fwd.h>

#include <OB/Client.h>

namespace OB
{

//
// The ORBControl class
//
class ORBControl : public RefCount, public JTCMonitor
{
    //
    // The ORB Instance
    //
    OB::ORBInstance_var orbInstance_;

    //
    // The ORBControl state
    //
    enum State
    {
	StateNotRunning,
	StateRunning,
	StateServerShutdown,
	StateClientShutdown,
	StateDestroyed
    };
    State state_;

    //
    // Has shutdown been called?
    //
    bool shutdown_;

    //
    // The reactor
    //
    Reactor_var reactor_;

    //
    // The Root POA
    //
    PortableServer::POA_var rootPOA_;

    //
    // The thread id of the main thread (that is the first thread that
    // calls run, perform_work or work_pending.
    //
    JTCThreadId mainThread_;

    //
    // Complete shutdown of the ORB, if necessary. Return true if the
    // shutdown is complete.
    //
    void completeServerShutdown()
	throw();

    //
    // Validate the state
    //
    void validateState()
	throw(CORBA::SystemException);

    void blockServerShutdownComplete()
	throw();

public:

    ORBControl();
    virtual ~ORBControl();

    static inline ORBControl_ptr _duplicate(ORBControl_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline ORBControl_ptr _nil()
    { return 0; }
    
    //
    // Destroy the ObjectFactory
    //
    void destroy()
	throw(CORBA::SystemException);

    //
    // Set the ORBInstance object
    //
    void setORBInstance(ORBInstance_ptr);

    //
    // Determine if there if the ORB needs the main thread to perform
    // some work
    //
    bool workPending()
	throw(CORBA::SystemException);
    
    //
    // Perform one unit of work
    //
    void performWork()
	throw(CORBA::SystemException);

    //
    // Run the ORB event loop
    //
    void run()
	throw(CORBA::SystemException);

    //
    // Shutdown the server side of the ORB
    //
    void shutdownServer(bool)
	throw(CORBA::SystemException);

    //
    // Shutdown the server (if necessary) & client side of the ORB
    //
    void shutdownServerClient()
	throw(CORBA::SystemException);

    //
    // Initialize the Root POA
    //
    void initializeRootPOA(CORBA::ORB_ptr)
	throw(CORBA::SystemException);
};

} // End of namespace OB

namespace CORBA
{

inline void
release(OB::ORBControl_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline Boolean
is_nil(OB::ORBControl_ptr p)
{
    return p == 0;
}

} // End of namespace CORBA

#endif
