#ifndef OMIT_TK
#include <tk.h>
#else
#include <tcl.h>
#endif
#include <ctype.h>

#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <string.h>

#include <unistd.h>
#include <stdlib.h>
#ifdef OS_WIN
# include <windows.h>
#endif

#include "memFile.h"
extern memFileData *tclTkInitData[];

/*
** Do an immediate exit.  Do not attempt a clean shutdown.  Just die.
*/
static int hardExitCmd(
  void *NotUsed,             /* Client data for this command */ 
  Tcl_Interp *interp,        /* The interpreter used to report errors */
  int objc,                  /* Number of arguments */
  Tcl_Obj *const* objv       /* Values of all arguments */
){
  exit(0);
}

Tcl_Interp * memCreateInterp(int argc, char **argv){
  Tcl_Interp *interp;
  char *args;
  char buf[100];
  char paths[256], lib[100];
  int tty;
  Tcl_Obj *path, *listObjPtr, *pathObjPtr, *tmpObj;
  int rtn, listLen, i;
  Tcl_GlobTypeData type;

  /* Create a Tcl interpreter
  */
  Tcl_FindExecutable(argv[0]);
  interp = Tcl_CreateInterp();
  path = NULL;

  /* Work around bug 873311 in Tcl - avoid an infinite loop on shutdown
  ** that occurs in TclFinalizeFilesystem by just not calling that routine.
  ** The "exit" command makes no attempt to shut down Tcl, it just dies.
  */
  Tcl_CreateObjCommand(interp, "exit", hardExitCmd, 0, 0);

  if( Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1)==0 ) goto init_error;

  args = Tcl_Merge(argc-1, (const char**)(argv+1));
  Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
  ckfree(args);
  sprintf(buf, "%d", argc-1);
  Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
  Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY);
  Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
//  sprintf(buf, "set memTcl(compile-timestamp) [clock scan {%s %s}]",
//                __TIME__, __DATE__);
//  Tcl_Eval(interp, buf);
  Tcl_SetVar(interp, "memTcl(compile-timestamp", "_TIMESTAMP_", TCL_GLOBAL_ONLY);

  /*
  ** Set up variables containing version information.
  */

  /* We have to initialize the virtual filesystem before calling
  ** Tcl_Init().  Otherwise, Tcl_Init() will not be able to find
  ** its startup script files.
  */

  Memfile_Init(interp); 
  memFile_Mount(NULL, interp, "/mem", tclTkInitData);
  
  // Get the top level dirs from the mem file system.
  // Find the tcl8.x path for library, and the others are
  //  the auto_path places to search.

  listObjPtr = Tcl_NewListObj(0, NULL);
  pathObjPtr = Tcl_NewStringObj("/mem", -1);
  type.type = TCL_GLOB_TYPE_DIR;
  rtn = memFile_MatchInDirectory(NULL, listObjPtr, pathObjPtr, "*",  &type);
  
  if (rtn == TCL_ERROR) {
    printf("FAILED to find any Tcl library dirs\n");
    Tcl_Eval(interp, "puts $errorInfo");
    exit (-1);
  }
  
  Tcl_ListObjLength(interp, listObjPtr, &listLen);
  *paths = 0;
  *lib= 0;

  for (i=0; i<listLen; i++) {
    Tcl_ListObjIndex(interp, listObjPtr, i, &tmpObj);
    strcat(paths, Tcl_GetStringFromObj(tmpObj, NULL));
    strcat(paths, " ");
    if (NULL != strstr(Tcl_GetStringFromObj(tmpObj, NULL), "tcl8.")) {
      strcat(lib, Tcl_GetStringFromObj(tmpObj, NULL));
    }
  }
  
printf("SETTING PATHS: %s\n", paths);

  Tcl_SetVar(interp, "tcl_library", lib, TCL_GLOBAL_ONLY);
  Tcl_SetVar(interp, "auto_path", paths, TCL_GLOBAL_ONLY);
  
  /* Initialize Tcl and Tk
  */  
  if( Tcl_Init(interp) ) goto init_error;

  Tcl_Eval(interp, "set ::tcl::tm::paths [glob /mem/tcl8/*]");

#if defined(USE_TK)
//  if( !Tk_Init(interp) ){
//    Tcl_StaticPackage(interp, "Tk", Tk_Init, 0);
//  }
#endif
#if defined(USE_TK)
printf("ARGC: %d AV0: %s\n", argc, argv[0]);
  Tk_MainEx(argc, argv, Tk_Init, interp);
#endif

if (argc) {
//  Tcl_EvalFile(interp, "/mem/memMain.tcl");
//  printf("CREATE: RETURN FROM EVAL %xx\n", interp);
//  Tcl_Eval(interp, "puts \"CREATE ERRORINFO: $errorInfo\"");
  return (interp);
} else {
printf("INTERACIVE VIA C CODE\n"); fflush(stdout);
    tty = isatty(0);
    Tcl_SetVar(interp, "tcl_interactive", ((path == NULL) && tty) ? "1" : "0",
            TCL_GLOBAL_ONLY);
  return (interp);
}
init_error:
#if defined(OS_WIN) && defined(USE_TK)
  MessageBox(0, interp->result, "Error", MB_ICONSTOP|MB_OK);
#else
  fprintf(stderr, "%s: unable to initialize: %s\n", argv[0],
     interp->result);
#endif
  return 1;
}
