/*
 *****************************************************
 *
 *  SaVi by Robert Thurman (thurman@geom.umn.edu) and
 *          Patrick Worfolk (worfolk@alum.mit.edu).
 *
 *  Copyright (c) 1997 by The Geometry Center.
 *  This file is part of SaVi.  SaVi is free software;
 *  you can redistribute it and/or modify it only under
 *  the terms given in the file COPYRIGHT which you should
 *  have received along with this file.  SaVi may be
 *  obtained from:
 *  http://savi.sourceforge.net/
 *  http://www.geom.uiuc.edu/locate/SaVi
 *
 *****************************************************
 *
 * tcl_utils.c
 *
 * $Id: tcl_utils.c,v 1.13 2005/02/12 15:52:33 lloydwood Exp $
 */

#include "constants.h"
#include "sats.h"
#include "utils.h"
#include "globals.h"
#include "tcl_utils.h"
#include "tkPlot.h"

static Tk_Window mainWindow;	/* The main window for the application. */

/* we want to bypass Tcl_Eval for speed in some case, so store some cmd info */
static Tcl_CmdInfo update_info;

static unsigned int tcl_app_init(void);
static unsigned int prepend_to_auto_path(const char []);

/*
 * tcl_init
 *
 * Initialisation of tcl interface
 */
unsigned int
tcl_init(Tcl_Interp * interpreter)
{
  if (Tcl_Init(interpreter) == TCL_ERROR) {
    error_format("tcl_init: Error in Tcl_Init: %s", interpreter->result);
    return FALSE;
  }
  return TRUE;
}

/*
 * tk_init
 *
 * Initialization of tk interface
 */
unsigned int
tk_init(Tcl_Interp * interpreter)
{
  char * screenName = NULL;
  static char baseName[] = "Satellites";
  static char className[] = "";

  if (Tk_Init(interpreter) == TCL_ERROR) {
    error_format("tk_init: Error in Tk_Init: %s", interpreter->result);
    return FALSE;
  }
  if (Plot_Init(interpreter) == TCL_ERROR) {
    error_format("tk_init: Error in Plot_Init: %s", interpreter->result);
    return FALSE;
  }
  if (!tcl_app_init()) {
    error_format("tk_init: Error in app_init: %s", interpreter->result);
    return FALSE;
  }

#if ( (TK_MAJOR_VERSION > 4) || ( (TK_MAJOR_VERSION == 4) && (TK_MINOR_VERSION > 0)) )
  if (!(mainWindow = Tk_CreateWindow(interpreter, screenName, baseName, className))) {
    error_format("tk_init: Can't create main wainWindow: %s", interpreter->result);
    return FALSE;
  }
#else
  if (!(mainWindow = Tk_CreateMainWindow(interpreter, screenName, baseName, className))) {
    error_format("tk_init: Can't create main wainWindow: %s", interpreter->result);
    return FALSE;
  }
#endif

  return (tk_update());
}

/*
 * tcl_app_init
 *
 * Application specific initialization commands for tcl/tk
 *
 */
static unsigned int
tcl_app_init()
{
  CentralBody *pcb = get_constellation()->pcb;
  static char command0[] = "satellites";
  static char command1[] = "savi";
  static char update[] = "update";
  static char var0[] = "delta_t";
  static char var1[] = "coverage_angle";
  static char var2[] = "IM_W";
  static char var3[] = "IM_H";
  static char var4[] = "params(Radius)";
  static char var5[] = "params(Mu)";
  static char var6[] = "params(Omega)";
  static char var7[] = "params(J2)";
  static char var8[] = "tracks_interval";
  static char var9[] = "FS_D";
  static char var10[] = "DIV0";
  static char var11[] = "DIV1";
  static char var12[] = "DIV2";
  static char var13[] = "DIV3";
  static char var14[] = "DIV4";
  static char var15[] = "DEC0";
  static char var16[] = "DEC1";
  static char var17[] = "DEC2";
  static char var18[] = "DEC3";
  static char var19[] = "DEC4";
  static char var20[] = "coverage_projection";
  static char var21[] = "Longitude_Center_Line";
  static char var22[] = "coverage_display_center_longitude";
  static char var23[] = "first_filename";
  static char var24[] = "use_X";
  static char var25[] = "debug";

  unsigned int test;

  /* add directory of tcl code */
  prepend_to_auto_path(TCL_DIR);

  /* add special commands */
  Tcl_CreateCommand(interp, command0, satCmd, (ClientData) NULL,
		    (Tcl_CmdDeleteProc *) NULL);
  Tcl_CreateCommand(interp, command1, satCmd, (ClientData) NULL,
		    (Tcl_CmdDeleteProc *) NULL);

  /* get info on some commands for optimization */
  Tcl_GetCommandInfo(interp, update, &update_info);

  /* link some variables */
  Tcl_LinkVar(interp, var0, (char *) &delta_t, TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var1, (char *) &coverage_angle, TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var2, (char *) &Image_Width, TCL_LINK_INT | TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, var3, (char *) &Image_Height, TCL_LINK_INT | TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, var4, (char *) &(pcb->radius), TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var5, (char *) &(pcb->mu), TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var6, (char *) &(pcb->rotation_rate), TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var7, (char *) &(pcb->J2), TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var8, (char *) &tracks_interval, TCL_LINK_DOUBLE);
  Tcl_LinkVar(interp, var9, (char *) &Fisheye_Diameter, TCL_LINK_INT | TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, var10, (char *) &DIV0, TCL_LINK_INT);
  Tcl_LinkVar(interp, var11, (char *) &DIV1, TCL_LINK_INT);
  Tcl_LinkVar(interp, var12, (char *) &DIV2, TCL_LINK_INT);
  Tcl_LinkVar(interp, var13, (char *) &DIV3, TCL_LINK_INT);
  Tcl_LinkVar(interp, var14, (char *) &DIV4, TCL_LINK_INT);
  Tcl_LinkVar(interp, var15, (char *) &DEC0, TCL_LINK_INT);
  Tcl_LinkVar(interp, var16, (char *) &DEC1, TCL_LINK_INT);
  Tcl_LinkVar(interp, var17, (char *) &DEC2, TCL_LINK_INT);
  Tcl_LinkVar(interp, var18, (char *) &DEC3, TCL_LINK_INT);
  Tcl_LinkVar(interp, var19, (char *) &DEC4, TCL_LINK_INT);
  Tcl_LinkVar(interp, var20, (char *) &coverage_projection, TCL_LINK_INT);
  Tcl_LinkVar(interp, var21, (char *) &Longitude_Center_Line, TCL_LINK_INT);
  Tcl_LinkVar(interp, var22, (char *) &coverage_display_center_longitude, TCL_LINK_INT);
  Tcl_LinkVar(interp, var23, (char *) &first_filename, TCL_LINK_STRING | TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, var24, (char *) &use_X, TCL_LINK_INT | TCL_LINK_READ_ONLY);
  Tcl_LinkVar(interp, var25, (char *) &debug, TCL_LINK_INT | TCL_LINK_READ_ONLY);
  /* execute initialization */
  {
    static char buf0_0[] = "set geomview_module 0";
    static char buf0_1[] = "set geomview_module 1";
    static char buf1[] = "app_init";

    if (geomview_module) {
      test = tcl_script(buf0_1);
    } else {
      test = tcl_script(buf0_0);
    }
    if (test) {
      test = tcl_script(buf1);
    }
  }

  return test;
}

/*
 * autopath is the directory list variable which tcl uses to
 * look for unknown commands
 */
static unsigned int
prepend_to_auto_path(const char path[])
{
  char buf[256];

  sprintf(buf, "set auto_path [linsert $auto_path 0 %s]", path);
  return tcl_script(buf);
}


/*
 * tcl_script
 *
 * execute script in tcl
 */
unsigned int
tcl_script(char script[])
{
  if (Tcl_GlobalEval(interp, script) == TCL_ERROR) {
    error_format("tcl_error: %s", interp->result);
    return FALSE;
  }
  return TRUE;
}


/*
 * tk_update
 *
 * Routine to process tk events
 *
 */
unsigned int
tk_update()
{
  static char update[] = "update";
  char *argv[1];
  int argc = 1;

  argv[0] = update;
  (*update_info.proc) (update_info.clientData, interp, argc, argv);

#if ( (TK_MAJOR_VERSION > 4) || ( (TK_MAJOR_VERSION == 4) && (TK_MINOR_VERSION > 0)) )
  if (Tk_GetNumMainWindows() > 0)
    return TRUE;
#else
  if (tk_NumMainWindows > 0)
    return TRUE;
#endif
  return FALSE;
}


/*
 * returns ClientData for a tcl object
 */
ClientData get_ClientData(char *obj)
{
  Tcl_CmdInfo info;

  if (Tcl_GetCommandInfo(interp, obj, &info))
    return info.clientData;

  /*
   *a useful method for testing and debugging of Tcl is
   * to print bad object name strings obj to stderr here.
   */
  return NULL;
}
