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

#include <assert.h>
#include <stdlib.h>
#include <string.h>

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

#include <OB/OBNaming.h>

#include "TestListener_impl.h"
#include "TestObject_impl.h"
#include "TestMacro.h"

//
// Dispatch events until the listener has received the callback
//
#define WAIT(reactor,listener) \
    while(! listener -> isValid()) \
	reactor -> dispatchOneEvent(250);

//
// Test extended callback features
//
void
TestCallbacks(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root)
{
    CosNaming_OBNamingContext_var ext =
        CosNaming_OBNamingContext::_narrow(root);
    assert(! CORBA_is_nil(ext));

    OBReactor* reactor = OBReactor::instance();

    assert(ext -> callbacks_active());

    TestListener_impl* listener = new TestListener_impl();
    ext -> add_listener(listener);

    TestObject_var test = new TestObject_impl;
    CosNaming_Name name1, name2;
    CosNaming_NamingContext_var context;

    //
    // Test BindingListener::object_added
    //
    name1.length(1);
    name1[0].id = CORBA_string_dup("name1");
    name1[0].kind = CORBA_string_dup("kind1");
    listener -> expect(TestListener_impl::OBJECT_ADDED, ext, test, name1[0]);
    SUCCEED(ext -> bind(name1, test));
    WAIT(reactor, listener);
    name2.length(1);
    name2[0].id = CORBA_string_dup("name2");
    name2[0].kind = CORBA_string_dup("kind2");
    listener -> expect(TestListener_impl::OBJECT_ADDED, ext, test, name2[0]);
    SUCCEED(ext -> bind(name2, test));
    WAIT(reactor, listener);

    //
    // Test BindingListener::object_removed
    //
    listener -> expect(TestListener_impl::OBJECT_REMOVED, ext,
		       CORBA_Object::_nil(), name2[0]);
    SUCCEED(ext -> unbind(name2));
    WAIT(reactor, listener);
    listener -> expect(TestListener_impl::OBJECT_REMOVED, ext,
		       CORBA_Object::_nil(), name1[0]);
    SUCCEED(ext -> unbind(name1));
    WAIT(reactor, listener);

    //
    // Test BindingListener::object_changed
    //
    name1.length(1);
    name1[0].id = CORBA_string_dup("name1");
    name1[0].kind = CORBA_string_dup("kind1");
    listener -> expect(TestListener_impl::OBJECT_ADDED, ext, test, name1[0]);
    SUCCEED(ext -> bind(name1, test));
    WAIT(reactor, listener);
    listener -> expect(TestListener_impl::OBJECT_CHANGED, ext,
		       CORBA_Object::_nil(), name1[0]);
    SUCCEED(ext -> rebind(name1, CORBA_Object::_nil()));
    WAIT(reactor, listener);
    listener -> expect(TestListener_impl::OBJECT_REMOVED, ext,
		       CORBA_Object::_nil(), name1[0]);
    SUCCEED(ext -> unbind(name1));
    WAIT(reactor, listener);

    //
    // Test BindingListener::context_added
    //
    context = ext -> new_context();
    name1.length(1);
    name1[0].id = CORBA_string_dup("context1");
    name1[0].kind = CORBA_string_dup("kind1");
    listener -> expect(TestListener_impl::CONTEXT_ADDED, ext, context,
		       name1[0]);
    SUCCEED(ext -> bind_context(name1, context));
    WAIT(reactor, listener);
    name2.length(1);
    name2[0].id = CORBA_string_dup("context2");
    name2[0].kind = CORBA_string_dup("kind2");
    listener -> expect(TestListener_impl::CONTEXT_ADDED, ext, context,
		       name2[0]);
    SUCCEED(ext -> bind_context(name2, context));
    WAIT(reactor, listener);

    //
    // Test BindingListener::context_removed
    //
    listener -> expect(TestListener_impl::CONTEXT_REMOVED, ext,
		       CORBA_Object::_nil(), name2[0]);
    SUCCEED(ext -> unbind(name2));
    WAIT(reactor, listener);
    listener -> expect(TestListener_impl::CONTEXT_REMOVED, ext,
		       CORBA_Object::_nil(), name1[0]);
    SUCCEED(ext -> unbind(name1));
    WAIT(reactor, listener);

    //
    // Test BindingListener::context_changed
    //
    name1.length(1);
    name1[0].id = CORBA_string_dup("context1");
    name1[0].kind = CORBA_string_dup("kind1");
    listener -> expect(TestListener_impl::CONTEXT_ADDED, ext, context,
		       name1[0]);
    SUCCEED(ext -> bind_context(name1, context));
    WAIT(reactor, listener);
    CosNaming_NamingContext_var ctx = root -> new_context();
    listener -> expect(TestListener_impl::CONTEXT_CHANGED, ext, ctx, name1[0]);
    SUCCEED(ext -> rebind_context(name1, ctx));
    WAIT(reactor, listener);
    listener -> expect(TestListener_impl::CONTEXT_REMOVED, ext,
		       CORBA_Object::_nil(), name1[0]);
    SUCCEED(ext -> unbind(name1));
    WAIT(reactor, listener);

    SUCCEED(ctx -> destroy());
    SUCCEED(context -> destroy());

    SUCCEED(ext -> remove_listener(listener));
    CORBA_release(listener);
}
