
/*
 * bonobo.c --
 *
 * This file implements some bonobo functions
 *
 * Copyright (c) 2001 - 2002 P.G. Baum
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
   History:
   2001-11: Begin of developement
 */

#include "gnocl.h"
#include <bonobo.h>
#include <libgnorba/gnorba.h>
#include <string.h>
#include <assert.h>

extern CORBA_Environment gnoclEv;

static int getActivationFlag( Tcl_Interp *interp, Tcl_Obj *obj,
      GoadActivationFlags *flag )
{
   char *flagsTxt[] = { "shlib", "remote", "existingOnly", "newOnly", 
         "async", NULL };
   GoadActivationFlags flags[] = { GOAD_ACTIVATE_SHLIB,
	GOAD_ACTIVATE_REMOTE, GOAD_ACTIVATE_EXISTING_ONLY,
	GOAD_ACTIVATE_NEW_ONLY, GOAD_ACTIVATE_ASYNC };

   int idx;
   if( Tcl_GetIndexFromObj( interp, obj, flagsTxt, "selection modes",
         TCL_EXACT, &idx ) != TCL_OK )
      return TCL_ERROR;

   *flag = flags[idx];

   return TCL_OK;
}

static int activateService( Tcl_Interp *interp, int objc, 
      Tcl_Obj * const objv[], int repo )
{
   typedef struct 
   {
      Gnocl_ObjBool flag;
   } ActivationOptions;
   ActivationOptions params;
   GnoclWidgetOptions options[] =
   {
      { "-type", GNOCL_OBJ, GNOCL_OFFSET( ActivationOptions, flag ) },
      { NULL, 0, 0 }
   };
   GoadActivationFlags flag = GOAD_ACTIVATE_REMOTE;
   CORBA_Object obj;

   if( objc < 3 )
   {
      Tcl_WrongNumArgs( interp, 2, objv, repo ? 
            "repoID ?-option val ... ?" : "serviceID ?-option val ... ?" );
      return TCL_ERROR;
   }

   memset( &params, 0, sizeof( params ) );
   if( gnoclParseAllWidgetOpts( interp, objc, objv, 2,
         options, (char *)&params ) != TCL_OK )
      return TCL_ERROR;
   if( params.flag.changed )
   {
      if( getActivationFlag( interp, params.flag.val, &flag ) != TCL_OK )
         return TCL_ERROR;
   }

   if( repo )
      obj = goad_server_activate_with_repo_id( NULL, 
            Tcl_GetString( objv[2] ), flag, NULL );
   else
      obj = goad_server_activate_with_id( NULL, 
            Tcl_GetString( objv[2] ), flag, NULL );
   if( flag == GOAD_ACTIVATE_EXISTING_ONLY )
   {
      Tcl_SetObjResult( interp, Tcl_NewIntObj( obj != CORBA_OBJECT_NIL ) );
   }
   else if( obj == CORBA_OBJECT_NIL )
   {
      Tcl_SetResult( interp, "Activation failed", TCL_STATIC );
      return TCL_ERROR;
   }

   return TCL_OK;
}

static int listServices( Tcl_Interp *interp, int objc, 
      Tcl_Obj * const objv[] )
{
   if( objc != 2 )
   {
      Tcl_WrongNumArgs( interp, 2, objv, NULL );
      return TCL_ERROR;
   }
   else
   {
      GoadServerList *gsl = goad_server_list_get( );
      GoadServer *list = gsl->list;
      Tcl_Obj *resList = Tcl_NewListObj( 0, NULL );

      for( ; list->repo_id; ++list )
      {
         Tcl_Obj *lList = Tcl_NewListObj( 0, NULL );
         Tcl_Obj *interfaces = Tcl_NewListObj( 0, NULL );
         int k = 0;
         const char *cp = NULL;
         /* ID */
         Tcl_ListObjAppendElement( interp, lList,
               Tcl_NewStringObj( list->server_id, -1 ) );

         /* type */
         switch( list->type )
         {
            case GOAD_SERVER_SHLIB:   cp = "shlib"; break;
            case GOAD_SERVER_EXE:     cp = "exe"; break;
            case GOAD_SERVER_RELAY:   cp = "relay"; break;
            case GOAD_SERVER_FACTORY: cp = "factory"; break;
         }
         Tcl_ListObjAppendElement( interp, lList,
               Tcl_NewStringObj( cp, -1 ) );

         /* Interfaces */
         while( list->repo_id[k] )
         {
            Tcl_ListObjAppendElement( interp, interfaces,
                  Tcl_NewStringObj( list->repo_id[k++], -1 ) );
         }
         Tcl_ListObjAppendElement( interp, lList, interfaces );

         /* Description */
         Tcl_ListObjAppendElement( interp, lList,
               Tcl_NewStringObj( list->description, -1 ) );
         Tcl_ListObjAppendElement( interp, resList, lList );
      }

      Tcl_SetObjResult( interp, resList );
      goad_server_list_free( gsl );
   }

   return TCL_OK;
}

static int getObject( Tcl_Interp *interp, int objc, 
      Tcl_Obj * const objv[] )
{
   Bonobo_Unknown obj;

   BonoboUIContainer *uic = bonobo_ui_container_new ();
   GtkWidget    *control = bonobo_widget_new_control(
         "OAFIID:Bonobo_Sample_Calculator", BONOBO_OBJREF (uic));
      printf( "control == %p\n", control );


   if( objc < 2 )
   {
      Tcl_WrongNumArgs( interp, 2, objv, "name interface" );
      return TCL_ERROR;
   }
#if 1
   obj = bonobo_get_object( Tcl_GetString( objv[2] ),
         Tcl_GetString( objv[3] ), &gnoclEv );
#else
   Bonobo_MonikerContext context;
   context = bonobo_context_get( "Activation", NULL);

   if (context == CORBA_OBJECT_NIL)
	g_error (_("Internal error, no activation context"));

   obj = Bonobo_MonikerContext_getObject (
         Tcl_GetString( objv[2] ), Tcl_GetString( objv[3] ), &gnoclEv );
#endif
   if( obj == CORBA_OBJECT_NIL )
      printf( "could not load %s %s\n", Tcl_GetString( objv[2] ),
            Tcl_GetString( objv[3] ) );
   else
      printf( "success!\n" );

   return TCL_OK;
}

int gnoclBonoboCmd( ClientData data, Tcl_Interp *interp,
      int objc, Tcl_Obj * const objv[] )
{
   /* bonobo command */
   static char *cmd[] = { "listServices", 
         "activateService", "activateRepoID", "getObject", NULL };
   enum optIdx { ListServicesIdx, 
         ActivateServiceIdx, ActivateRepoIDIdx, GetObjectIdx };
   int idx;

   if( objc < 2 )
   {
      Tcl_WrongNumArgs( interp, 1, objv, "subcommand ?-option val ...?" );
      return TCL_ERROR;
   }

   if( Tcl_GetIndexFromObj( interp, objv[1], cmd, "subcommand", TCL_EXACT,
         &idx ) != TCL_OK )
      return TCL_ERROR;
   switch( idx )
   {
      case ListServicesIdx:
            return listServices( interp, objc, objv );
      case ActivateServiceIdx:
      case ActivateRepoIDIdx:
            return activateService( interp, objc, objv, 
                  idx == ActivateRepoIDIdx );
      case GetObjectIdx:
            return getObject( interp, objc, objv );
   }
   return TCL_OK;
}

