#define MICO_CONF_IMR
#include <CORBA-SMALL.h>
#include <iostream.h>
#include <fstream.h>
#include <sstream>
#include <unistd.h>
#include <sys/time.h>
#include <fstream.h>
#include <string.h>
#include "dictionary.h"

// create objects on demand when requested by a bind()
#define OBJECT_CREATION_ON_DEMAND

/*
 * Dictionary implementation
 */

class Dictionary_impl : virtual public Dictionary_skel {
private:
	string _dictFile;
public:
    Dictionary_impl (const CORBA::BOA::ReferenceData &refdata)
	: Dictionary_skel (refdata)
    {
	    _dictFile = "dict.fl";
    }

    Dictionary_impl (CORBA::Object_ptr obj)
        : Dictionary_skel (obj)
    {
	CORBA::BOA_var boa = _boa();
	CORBA::BOA::ReferenceData_var id = boa->get_id (this);
	CORBA::String_var str = CORBA::ORB::tag_to_string (id);
	_dictFile = "dict.fl";
    }

    wpair* lookup(const char * word)
    {
		char  tmp[1000];
		string wd, meaning;

		ifstream in(_dictFile.c_str());
		if(!in)
		{
			cerr << "Unable to open dictionary." << endl << flush;
			return NULL;
		}

		wpair *w = new wpair();
		w->word = CORBA::string_dup(word);
		w->meaning = CORBA::string_dup("");
	
		while(!in.eof())
		{
			in.getline(tmp, 1000);
		
			istringstream istr(tmp);
			istr >> wd;
		
			if(wd == word)
			{
				istr >> meaning;
				w->meaning = CORBA::string_dup(meaning.c_str());
				break;
			}
		}
		
		cout << "Returning from Dictionary 'lookup'. Word = " << w->word << " AND  meaning = " << w->meaning << ".\n" << flush;
		
		return w;
    }
};

/*
 * Dictionary object restorer
 */

class DictionaryLoader : public CORBA::BOAObjectRestorer {
public:
    CORBA::Boolean restore (CORBA::Object_ptr obj)
    {
        if (!strcmp (obj->_repoid(), "IDL:Dictionary:1.0")) {
            (void)new Dictionary_impl (obj);
            return TRUE;
        }
        cout << "Cannot restore " << obj->_repoid() << " objects" << endl;
        return FALSE;
    }
#ifdef OBJECT_CREATION_ON_DEMAND
    CORBA::Boolean bind (const char *repoid, const CORBA::ORB::ObjectTag &tag)
    {
        if (!strcmp (repoid, "IDL:Dictionary:1.0")) {
	    cout << "Creating server in bind... " << endl;
	    (void)new Dictionary_impl (tag);
	    return TRUE;
	}
	return FALSE;
    }
#endif
};


int main( int argc, char *argv[] )
{
    cout << "Server init." << endl;

    DictionaryLoader loader;
    CORBA::ORB_var orb = CORBA::ORB_init( argc, argv, "mico-local-orb" );
    CORBA::BOA_var boa = orb->BOA_init (argc, argv, "mico-local-boa");

    if (!boa->restoring()) {
#ifndef OBJECT_CREATION_ON_DEMAND
	cout << "Creating server in main... " << endl;
	CORBA::ORB::ObjectTag_var tag = CORBA::ORB::string_to_tag ("foobar");
	/*
	 * create an dictionary object whose ReferenceData equals "foobar".
	 */
        Dictionary_ptr acc = new Dictionary_impl (tag);
#endif
    }
    boa->impl_is_ready (CORBA::ImplementationDef::_nil());
    orb->run ();

    return 0;
}
