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

#ifndef OB_DII_H
#define OB_DII_H

#include <OB/DII_fwd.h>
#include <OB/Object_fwd.h>
#include <OB/OBObject_fwd.h>
#include <OB/NamedValue_fwd.h>
#include <OB/Environment_fwd.h>
#include <OB/Context_fwd.h>
#include <OB/MarshalStubImpl_fwd.h>
#include <OB/Downcall_fwd.h>
#include <OB/TypeCode_fwd.h>

#include <OB/AnyDeclaration.h>

#include <OB/list.h>

namespace OBCORBA
{

class ORB_impl; // For the friend declaration

} // End namespace OBCORBA

namespace CORBA
{

//
// The ExceptionList class
//
class ExceptionList : public OB::RefCount
{
    //
    // Hide copy-constructor and assignment operator
    //
    ExceptionList(const ExceptionList&);
    void operator=(const ExceptionList&);

    OB_STL::list<TypeCode_var> typeCodes_;
    
protected:

    ExceptionList() { };

    friend class ::OBCORBA::ORB_impl; // ORB_impl creates ExcpetionList
    friend class Request; // Request creates ExceptionList

public:

    //
    // Standard IDL to C++ Mapping
    //
    static inline ExceptionList_ptr _duplicate(ExceptionList_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline ExceptionList_ptr _nil()
    { return 0; }

    ULong count() const;
    
    void add(TypeCode_ptr);
    void add_consume(TypeCode_ptr);

    TypeCode_ptr item(ULong);

    void remove(ULong);
};

inline void
release(ExceptionList_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline Boolean
is_nil(ExceptionList_ptr p)
{
    return p == 0;
}

//
// The ContextList class
//
class ContextList : public OB::RefCount
{
    //
    // Hide copy-constructor and assignment operator
    //
    ContextList(const ContextList&);
    void operator=(const ContextList&);

    OB_STL::list<String_var> strings_;

protected:

    ContextList() { };

    friend class ::OBCORBA::ORB_impl; // ORB_impl creates ContextList
    friend class Request; // Request creates ExceptionList

public:

    //
    // Standard IDL to C++ Mapping
    //
    static inline ContextList_ptr _duplicate(ContextList_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline ContextList_ptr _nil()
    { return 0; }

    ULong count() const;
    
    void add(const char*);
    void add_consume(char*);

    const char* item(ULong);

    void remove(ULong);
};

inline void
release(ContextList_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline Boolean
is_nil(ContextList_ptr p)
{
    return p == 0;
}

//
// The Request class
//
class Request : public OB::RefCount
{
    //
    // Hide copy-constructor and assignment operator
    //
    Request(const Request&);
    void operator=(const Request&);

    OBCORBA::Object_var target_;
    String_var operation_;
    NVList_var arguments_;
    NamedValue_var result_;
    Environment_var environment_;
    ExceptionList_var exceptions_;
    ContextList_var contexts_;
    Context_var ctx_;
    OB::MarshalStubImpl_var marshalStub_;
    OB::Downcall_var downcall_;

    enum RequestState
    {
        RequestStateUnsent,
        RequestStatePending,
        RequestStateSent,
        RequestStateReceiving,
        RequestStateReceived,
        RequestStateDone
    };
    RequestState state_;
    bool pollable_; // Can this request be polled?
    bool polling_; // Is poll_response in progress?
    JTCMonitor stateMutex_;

    void marshal();
    void unmarshal();

protected:

    Request(OBCORBA::Object_ptr, const char*, NVList_ptr,
	    NamedValue_ptr, ExceptionList_ptr,
	    ContextList_ptr);

    Request(OBCORBA::Object_ptr, const char*, NVList_ptr,
	    NamedValue_ptr);

    Request(OBCORBA::Object_ptr, const char*);

    virtual ~Request();
    
    friend class ::OBCORBA::Object; // Objects may create Requests

public:

    //
    // Standard IDL to C++ Mapping
    //
    static inline Request_ptr _duplicate(Request_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline Request_ptr _nil()
    { return 0; }

    CORBA::Object_ptr target() const;
    const char* operation() const;
    NVList_ptr arguments();
    NamedValue_ptr result();
    Environment_ptr env();
    ExceptionList_ptr exceptions();
    ContextList_ptr contexts();

    void ctx(Context_ptr);
    Context_ptr ctx() const;

    Any& add_in_arg();
    Any& add_in_arg(const char*);
    Any& add_inout_arg();
    Any& add_inout_arg(const char*);
    Any& add_out_arg();
    Any& add_out_arg(const char*);
    void set_return_type(TypeCode_ptr);
    Any& return_value();

    void invoke();
    void send_oneway();
    void send_deferred();
    void get_response();
    Boolean poll_response();

    //
    // ORBacus internal functions
    // Application programs must not use these functions directly
    //
    bool _OB_completed() const;
};

inline void
release(Request_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline Boolean
is_nil(Request_ptr p)
{
    return p == 0;
}

} // End of namespace CORBA

#endif
