/* Bug Elliot Lee <sopwith@redhat.com> with any problem reports. GPL'd. */
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "CosTime.h"

/* The following is mostly taken from CosTime-impl.c as
 * generated by "orbit-idl -Eskeleton_impl CosTime.idl"
 */

#include "CosTime.h"

/*** App-specific servant structures ***/

typedef struct {
   POA_CosTime_UTO servant;
   PortableServer_POA poa;
   TimeBase_TimeT attr_time;

   TimeBase_InaccuracyT attr_inaccuracy;

   TimeBase_TdfT attr_tdf;

   TimeBase_UtcT attr_utc_time;

} impl_POA_CosTime_UTO;

typedef struct {
   POA_CosTime_TIO servant;
   PortableServer_POA poa;
   TimeBase_IntervalT attr_time_interval;

} impl_POA_CosTime_TIO;

typedef struct {
   POA_CosTime_TimeService servant;
   PortableServer_POA poa;

} impl_POA_CosTime_TimeService;

/*** Implementation stub prototypes ***/

static void impl_CosTime_UTO__destroy(impl_POA_CosTime_UTO * servant,
				      CORBA_Environment * ev);

TimeBase_TimeT
impl_CosTime_UTO__get_time(impl_POA_CosTime_UTO * servant,
			   CORBA_Environment * ev);

TimeBase_InaccuracyT
impl_CosTime_UTO__get_inaccuracy(impl_POA_CosTime_UTO * servant,
				 CORBA_Environment * ev);

TimeBase_TdfT
impl_CosTime_UTO__get_tdf(impl_POA_CosTime_UTO * servant,
			  CORBA_Environment * ev);

TimeBase_UtcT
impl_CosTime_UTO__get_utc_time(impl_POA_CosTime_UTO * servant,
			       CORBA_Environment * ev);

CosTime_UTO
impl_CosTime_UTO_absolute_time(impl_POA_CosTime_UTO * servant,
			       CORBA_Environment * ev);

CosTime_TimeComparison
impl_CosTime_UTO_compare_time(impl_POA_CosTime_UTO * servant,
			      CosTime_ComparisonType comparison_type,
			      CosTime_UTO uto,
			      CORBA_Environment * ev);

CosTime_TIO
impl_CosTime_UTO_time_to_interval(impl_POA_CosTime_UTO * servant,
				  CosTime_UTO uto,
				  CORBA_Environment * ev);

CosTime_TIO
impl_CosTime_UTO_interval(impl_POA_CosTime_UTO * servant,
			  CORBA_Environment * ev);

static void impl_CosTime_TIO__destroy(impl_POA_CosTime_TIO * servant,
				      CORBA_Environment * ev);

TimeBase_IntervalT
impl_CosTime_TIO__get_time_interval(impl_POA_CosTime_TIO * servant,
				    CORBA_Environment * ev);

CORBA_boolean
impl_CosTime_TIO_spans(impl_POA_CosTime_TIO * servant,
		       CosTime_UTO time,
		       CosTime_TIO * overlap,
		       CORBA_Environment * ev);

CORBA_boolean
impl_CosTime_TIO_overlaps(impl_POA_CosTime_TIO * servant,
			  CosTime_TIO interval,
			  CosTime_TIO * overlap,
			  CORBA_Environment * ev);

CosTime_UTO
impl_CosTime_TIO_time(impl_POA_CosTime_TIO * servant,
		      CORBA_Environment * ev);

static void
impl_CosTime_TimeService__destroy(impl_POA_CosTime_TimeService * servant,
				  CORBA_Environment * ev);

CosTime_UTO
impl_CosTime_TimeService_universal_time(impl_POA_CosTime_TimeService * servant,
					CORBA_Environment * ev);

CosTime_UTO
impl_CosTime_TimeService_secure_universal_time(impl_POA_CosTime_TimeService * servant,
					       CORBA_Environment * ev);

CosTime_UTO
impl_CosTime_TimeService_new_universal_time(impl_POA_CosTime_TimeService * servant,
					    TimeBase_TimeT thetime,
					    TimeBase_InaccuracyT inaccuracy,
					    TimeBase_TdfT tdf,
					    CORBA_Environment * ev);

CosTime_UTO
impl_CosTime_TimeService_uto_from_utc(impl_POA_CosTime_TimeService * servant,
				      TimeBase_UtcT * utc,
				      CORBA_Environment * ev);

CosTime_TIO
impl_CosTime_TimeService_new_interval(impl_POA_CosTime_TimeService * servant,
				      TimeBase_TimeT lower,
				      TimeBase_TimeT upper,
				      CORBA_Environment * ev);

/*** epv structures ***/

static PortableServer_ServantBase__epv impl_CosTime_UTO_base_epv =
{
   NULL,			/* _private data */
   (gpointer) & impl_CosTime_UTO__destroy,	/* finalize routine */
   NULL,			/* default_POA routine */
};
static POA_CosTime_UTO__epv impl_CosTime_UTO_epv =
{
   NULL,			/* _private */
   (gpointer) & impl_CosTime_UTO__get_time,
   (gpointer) & impl_CosTime_UTO__get_inaccuracy,
   (gpointer) & impl_CosTime_UTO__get_tdf,
   (gpointer) & impl_CosTime_UTO__get_utc_time,
   (gpointer) & impl_CosTime_UTO_absolute_time,
   (gpointer) & impl_CosTime_UTO_compare_time,
   (gpointer) & impl_CosTime_UTO_time_to_interval,
   (gpointer) & impl_CosTime_UTO_interval,
};
static PortableServer_ServantBase__epv impl_CosTime_TIO_base_epv =
{
   NULL,			/* _private data */
   (gpointer) & impl_CosTime_TIO__destroy,	/* finalize routine */
   NULL,			/* default_POA routine */
};
static POA_CosTime_TIO__epv impl_CosTime_TIO_epv =
{
   NULL,			/* _private */
   (gpointer) & impl_CosTime_TIO__get_time_interval,
   (gpointer) & impl_CosTime_TIO_spans,
   (gpointer) & impl_CosTime_TIO_overlaps,
   (gpointer) & impl_CosTime_TIO_time,
};
static PortableServer_ServantBase__epv impl_CosTime_TimeService_base_epv =
{
   NULL,			/* _private data */
   (gpointer) & impl_CosTime_TimeService__destroy,	/* finalize routine */
   NULL,			/* default_POA routine */
};
static POA_CosTime_TimeService__epv impl_CosTime_TimeService_epv =
{
   NULL,			/* _private */
   (gpointer) & impl_CosTime_TimeService_universal_time,
   (gpointer) & impl_CosTime_TimeService_secure_universal_time,
   (gpointer) & impl_CosTime_TimeService_new_universal_time,
   (gpointer) & impl_CosTime_TimeService_uto_from_utc,
   (gpointer) & impl_CosTime_TimeService_new_interval,
};

/*** vepv structures ***/

static POA_CosTime_UTO__vepv impl_CosTime_UTO_vepv =
{
   &impl_CosTime_UTO_base_epv,
   &impl_CosTime_UTO_epv,
};
static POA_CosTime_TIO__vepv impl_CosTime_TIO_vepv =
{
   &impl_CosTime_TIO_base_epv,
   &impl_CosTime_TIO_epv,
};
static POA_CosTime_TimeService__vepv impl_CosTime_TimeService_vepv =
{
   &impl_CosTime_TimeService_base_epv,
   &impl_CosTime_TimeService_epv,
};

/*** implementations ***/

static CosTime_UTO 
impl_CosTime_UTO__create(PortableServer_POA poa,
			 TimeBase_TimeT timet,
			 TimeBase_InaccuracyT inaccuracy,
			 TimeBase_TdfT tdf,
			 CORBA_Environment * ev)
{
   CosTime_UTO retval;
   impl_POA_CosTime_UTO *newservant;
   PortableServer_ObjectId *objid;

   newservant = g_new0(impl_POA_CosTime_UTO, 1);
   newservant->servant.vepv = &impl_CosTime_UTO_vepv;
   newservant->poa = poa;
   POA_CosTime_UTO__init((PortableServer_Servant) newservant, ev);
   objid = PortableServer_POA_activate_object(poa, newservant, ev);
   CORBA_free(objid);
   retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);

   return retval;
}

/* You shouldn't call this routine directly without first deactivating the servant... */
static void
impl_CosTime_UTO__destroy(impl_POA_CosTime_UTO * servant, CORBA_Environment * ev)
{

   POA_CosTime_UTO__fini((PortableServer_Servant) servant, ev);
   g_free(servant);
}

TimeBase_TimeT
impl_CosTime_UTO__get_time(impl_POA_CosTime_UTO * servant,
			   CORBA_Environment * ev)
{
   TimeBase_TimeT retval;

   return retval;
}

TimeBase_InaccuracyT
impl_CosTime_UTO__get_inaccuracy(impl_POA_CosTime_UTO * servant,
				 CORBA_Environment * ev)
{
   TimeBase_InaccuracyT retval;

   return retval;
}

TimeBase_TdfT
impl_CosTime_UTO__get_tdf(impl_POA_CosTime_UTO * servant,
			  CORBA_Environment * ev)
{
   TimeBase_TdfT retval;

   return retval;
}

TimeBase_UtcT
impl_CosTime_UTO__get_utc_time(impl_POA_CosTime_UTO * servant,
			       CORBA_Environment * ev)
{
   TimeBase_UtcT retval;

   return retval;
}

CosTime_UTO
impl_CosTime_UTO_absolute_time(impl_POA_CosTime_UTO * servant,
			       CORBA_Environment * ev)
{
   CosTime_UTO retval;

   return retval;
}

CosTime_TimeComparison
impl_CosTime_UTO_compare_time(impl_POA_CosTime_UTO * servant,
			      CosTime_ComparisonType comparison_type,
			      CosTime_UTO uto,
			      CORBA_Environment * ev)
{
   CosTime_TimeComparison retval;

   return retval;
}

CosTime_TIO
impl_CosTime_UTO_time_to_interval(impl_POA_CosTime_UTO * servant,
				  CosTime_UTO uto,
				  CORBA_Environment * ev)
{
   CosTime_TIO retval;

   return retval;
}

CosTime_TIO
impl_CosTime_UTO_interval(impl_POA_CosTime_UTO * servant,
			  CORBA_Environment * ev)
{
   CosTime_TIO retval;

   return retval;
}

static CosTime_TIO 
impl_CosTime_TIO__create(PortableServer_POA poa,
			 TimeBase_IntervalT intv,
			 CORBA_Environment * ev)
{
   CosTime_TIO retval;
   impl_POA_CosTime_TIO *newservant;
   PortableServer_ObjectId *objid;

   newservant = g_new0(impl_POA_CosTime_TIO, 1);
   newservant->servant.vepv = &impl_CosTime_TIO_vepv;
   newservant->poa = poa;
   POA_CosTime_TIO__init((PortableServer_Servant) newservant, ev);
   objid = PortableServer_POA_activate_object(poa, newservant, ev);
   CORBA_free(objid);
   retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);

   return retval;
}

/* You shouldn't call this routine directly without first deactivating the servant... */
static void
impl_CosTime_TIO__destroy(impl_POA_CosTime_TIO * servant, CORBA_Environment * ev)
{

   POA_CosTime_TIO__fini((PortableServer_Servant) servant, ev);
   g_free(servant);
}

TimeBase_IntervalT
impl_CosTime_TIO__get_time_interval(impl_POA_CosTime_TIO * servant,
				    CORBA_Environment * ev)
{
   TimeBase_IntervalT retval;

   return retval;
}

CORBA_boolean
impl_CosTime_TIO_spans(impl_POA_CosTime_TIO * servant,
		       CosTime_UTO time,
		       CosTime_TIO * overlap,
		       CORBA_Environment * ev)
{
   CORBA_boolean retval;

   return retval;
}

CORBA_boolean
impl_CosTime_TIO_overlaps(impl_POA_CosTime_TIO * servant,
			  CosTime_TIO interval,
			  CosTime_TIO * overlap,
			  CORBA_Environment * ev)
{
   CORBA_boolean retval;

   return retval;
}

CosTime_UTO
impl_CosTime_TIO_time(impl_POA_CosTime_TIO * servant,
		      CORBA_Environment * ev)
{
   CosTime_UTO retval;

   return retval;
}

static CosTime_TimeService 
impl_CosTime_TimeService__create(PortableServer_POA poa, CORBA_Environment * ev)
{
   CosTime_TimeService retval;
   impl_POA_CosTime_TimeService *newservant;
   PortableServer_ObjectId *objid;

   newservant = g_new0(impl_POA_CosTime_TimeService, 1);
   newservant->servant.vepv = &impl_CosTime_TimeService_vepv;
   newservant->poa = poa;

   POA_CosTime_TimeService__init((PortableServer_Servant) newservant, ev);

   objid = PortableServer_POA_activate_object(poa, newservant, ev);
   CORBA_free(objid); /* not needed ever again */
   retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);

   return retval;
}

/* You shouldn't call this routine directly without first deactivating the servant... */
static void
impl_CosTime_TimeService__destroy(impl_POA_CosTime_TimeService * servant, CORBA_Environment * ev)
{
   POA_CosTime_TimeService__fini((PortableServer_Servant) servant, ev);
   g_free(servant);
}

CosTime_UTO
impl_CosTime_TimeService_universal_time(impl_POA_CosTime_TimeService * servant,
					CORBA_Environment * ev)
{
   CosTime_UTO retval;
   struct timeval tval;
   TimeBase_TimeT tbtime;

   /* Get current time, and then convert it to TimeBase_TimeT */
   gettimeofday(&tval, NULL);

   tbtime = (((tval.tv_sec * 1000000) + tval.tv_usec)*10);
   /* now it is the number of 100ns units since 1970 */
   tbtime += 0 /* XXX finish */;

   return impl_CosTime_UTO__create(servant->poa,
				   tbtime, 0,
				   timezone/60,
				   ev);
}

CosTime_UTO
impl_CosTime_TimeService_secure_universal_time(impl_POA_CosTime_TimeService * servant,
					       CORBA_Environment * ev)
{
   CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_CosTime_TimeUnavailable, NULL);

   return CORBA_OBJECT_NIL;
}

CosTime_UTO
impl_CosTime_TimeService_new_universal_time(impl_POA_CosTime_TimeService * servant,
					    TimeBase_TimeT thetime,
					    TimeBase_InaccuracyT inaccuracy,
					    TimeBase_TdfT tdf,
					    CORBA_Environment * ev)
{
   return impl_CosTime_UTO__create(servant->poa,
				   thetime, inaccuracy,
				   tdf,
				   ev);
}

CosTime_UTO
impl_CosTime_TimeService_uto_from_utc(impl_POA_CosTime_TimeService * servant,
				      TimeBase_UtcT * utc,
				      CORBA_Environment * ev)
{
   return impl_CosTime_UTO__create(servant->poa,
				   utc->time, inaccuracy,
				   tdf,
				   ev);
}

CosTime_TIO
impl_CosTime_TimeService_new_interval(impl_POA_CosTime_TimeService * servant,
				      TimeBase_TimeT lower,
				      TimeBase_TimeT upper,
				      CORBA_Environment * ev)
{
  TimeBase_IntervalT intv;

  intv.lower_bound = lower;
  intv.upper_bound = upper;

  return impl_CosTime_TIO__create(servant->poa, intv, ev);
}


int
main (int argc, char *argv[])
{
  CORBA_ORB orb;
  CORBA_Environment ev;
  CosTime_TimeService factory;
  CORBA_char *objref;
  PortableServer_POA root_poa;
  PortableServer_POAManager pm;
  struct sigaction act;
  sigset_t         empty_mask;
  
  sigemptyset(&empty_mask);
  act.sa_handler = signal_handler;
  act.sa_mask    = empty_mask;
  act.sa_flags   = 0;
  
  sigaction(SIGINT,  &act, 0);
  sigaction(SIGHUP,  &act, 0);
  sigaction(SIGSEGV, &act, 0);
  sigaction(SIGABRT, &act, 0);
  
  act.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &act, 0);
  time_t ttmp;

  ttmp = 0;
  localtime(&ttmp); /* set 'timezone' and 'tzname' variables */

  CORBA_exception_init (&ev);
  
  orb = CORBA_ORB_init (&argc, argv, "orbit-local-orb", &ev);

  root_poa = (PortableServer_POA)
    CORBA_ORB_resolve_initial_references (orb, "RootPOA", &ev);

  factory = impl_CosTime_TimeService__create(root_poa, 
					     &ev);

  objref = CORBA_ORB_object_to_string (orb, factory, &ev);

  g_print ("%s\n", objref);
  fflush (stdout);

  CORBA_free (objref);

  /* Don't release it so that the same-address-space info will stay around */
#if 0
  CORBA_Object_release (factory, &ev);
#endif

  pm = PortableServer_POA__get_the_POAManager (root_poa, &ev);
  PortableServer_POAManager_activate (pm, &ev);

  CORBA_ORB_run (orb, &ev);
  return 0;
}
