#include <stdio.h>
#include <fstream.h>

#include "HelloWorldImpl.h"

#define DEFAULT_IOR_OUTPUT_FILE "HelloWorld.ior"

int main(int argc, char* argv[])
{
    const char* ior_output_file = DEFAULT_IOR_OUTPUT_FILE;
    CORBA::ORB_var orb;

    // Initialize the ORB
    try {
        orb = CORBA::ORB_init (argc, argv, "");
    }
    catch (CORBA::SystemException exception) {
        cerr << "CORBA::ORB_init";
        return -1;
    }

    // Get the Root POA object reference
    CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA");

    // Narrow the object reference to a POA reference
    PortableServer::POA_var root_poa;
    try {
        root_poa = PortableServer::POA::_narrow (obj.in ());
    }
    catch (CORBA::SystemException exception) {
        cerr << "PortableServer::POA::_narrow";
        return -1;
    }
  
    // Create a Helloworld Implementation object in root_poa
    HelloWorldImpl hello_world_impl (root_poa.in());

    // create an object ID.
    PortableServer::ObjectId_var hello_world_oid =
      PortableServer::string_to_ObjectId ("HelloWorld");

    // assign the new object ID to our implementation object.
    try {
        root_poa->activate_object_with_id (hello_world_oid.in(), 
                                           &hello_world_impl);
    }
    catch (CORBA::SystemException exception) {
        cerr << "PortableServer::POA::activate_object_with_id";
        return -1;
    }
  
    // now, fetch the CORBA object that was bound to our implementation object.
    CORBA::Object_var hello_world;
    try {
        hello_world = root_poa->id_to_reference (hello_world_oid.in());
    }
    catch (CORBA::SystemException exception) {
        cerr << "PortableServer::POA::id_to_reference";
        return -1;
    }

    // Get the IOR of the CORBA object.
    CORBA::String_var hello_world_ior;
    try {
        hello_world_ior = orb->object_to_string (hello_world.in());
    }
    catch (CORBA::SystemException exception) {
        cerr << "CORBA::ORB::object_to_string";
        return -1;
    }

    // If the ior_output_file exists, output the IOR to it, so our clients
    // could read it and use it to access the object.
    if (ior_output_file != 0) {
	ofstream f(ior_output_file);

	if (f.good()) {
	    f << hello_world_ior.in() << flush;
	}
	else {
	    cerr << "Cannot open output file for writing IOR: '"
		<< ior_output_file << "'" << endl;
	    return -1;
	}
    }
  
    // get the POA manager from the root POA.
    PortableServer::POAManager_var poa_manager;
    try {
        poa_manager = root_poa->the_POAManager();
    }
    catch (CORBA::SystemException exception) {
	cerr << "PortableServer::POA::the_POAManager";
        return -1;
    }
  
    // set the state of the poa_manager to active i.e ready to process requests
    try {
        poa_manager->activate();
    }
    catch (CORBA::SystemException exception) {
        cerr << "PortableServer::POAManager::activate";
        return -1;
    }

    // Run the ORB. This causes the server to enter a loop of processing
    // client requests. This loop most likely uses a select() or poll()
    // call to block until a request arrives, and then processes it.
    orb->run();

    // Destroy the rootPOA and its children
    try {
        root_poa->destroy (1, 1);
    }
    catch (CORBA::SystemException exception) {
        cerr << "PortableServer::POA::destroy";
        return -1;
    }

    return 0;
}
