// Copyright (C) 1999-2015
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"

#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <sstream>
using namespace std;

#include <tcl.h>
#include <tk.h>

#define DEBUGS(x) {FILE* fp=fopen("debug.txt","a+");fprintf(fp,"%s\n",x);fclose(fp);}

extern "C" {
  int SAOAppInit(Tcl_Interp *interp);
  int SAOLocalMainHook(int* argc, char*** argv);

  void TclSetStartupScriptFileName(const char*);

  int Tkblt_Init(Tcl_Interp*);
  int Tktable_Init(Tcl_Interp*);
  //  int Tclcheckdns_Init(Tcl_Interp*);
  int Tksao_Init(Tcl_Interp*);
  int Tkhtml1_Init(Tcl_Interp*);
  int Tkmpeg_Init(Tcl_Interp*);

  int Tkimg_Init(Tcl_Interp*);
  int Zlibtcl_Init(Tcl_Interp*);
  int Jpegtcl_Init(Tcl_Interp*);
  int Tkimgjpeg_Init(Tcl_Interp*);
  int Tifftcl_Init(Tcl_Interp*);
  int Tkimgtiff_Init(Tcl_Interp*);
  int Pngtcl_Init(Tcl_Interp*);
  int Tkimgpng_Init(Tcl_Interp*);
  int Tkimggif_Init(Tcl_Interp*);
  int Tkimgwindow_Init(Tcl_Interp*);

  int Tclxpa_Init(Tcl_Interp*);
  //  int Tcliis_Init(Tcl_Interp*);

  int Tclxml_Init(Tcl_Interp*);
  int Tclxml_libxml2_Init(Tcl_Interp*);

  //  int Signal_ext_Init(Tcl_Interp*);

  int Tkwin32_Init(Tcl_Interp*);
}

Tcl_Interp *global_interp;

void internalError(const char* msg)
{
  Tcl_SetVar2(global_interp, "ds9", "msg", msg, TCL_GLOBAL_ONLY);
  Tcl_SetVar2(global_interp, "ds9", "msg,level", "error", TCL_GLOBAL_ONLY);
}

#define PATHSIZE 2048
int SAOLocalMainHook(int* argcPtr, char*** argvPtr)
{
  // sync C++ io calls with C io calls
  ios::sync_with_stdio();

  // use exec path
  char** argv = *argvPtr;
  char ss[PATHSIZE];
  strncpy(ss,argv[0],PATHSIZE);

  // now remove "/ds9.exe"
  char* ptr = ss+strlen(ss);
  while (*ptr != '/' && ptr != ss)
    ptr--;
  *ptr = '\0';

  char rr[PATHSIZE];

  // so that tcl and tk know where to find their libs
  // we do it here before InitLibraryPath is called
  {
    strncpy(rr,ss,PATHSIZE);
    strncat(rr,"/tcl8.6",PATHSIZE);
    ostringstream str;
    str << "TCL_LIBRARY=" << rr << ends;
    putenv((char*)str.str().c_str());
  }
  
  {
    strncpy(rr,ss,PATHSIZE);
    strncat(rr,"/tk8.6",PATHSIZE);
    ostringstream str;
    str << "TK_LIBRARY=" << rr << ends;
    putenv((char*)str.str().c_str());
  }
  
  // do this first
  Tcl_FindExecutable((*argvPtr)[0]);

  // and add startup script
  strncpy(rr,ss,PATHSIZE);
  strncat(rr,"/library/ds9.tcl",PATHSIZE);
  Tcl_Obj *path = Tcl_NewStringObj(rr,-1);
  Tcl_SetStartupScript(path, NULL);
  
  return TCL_OK;
}

int SAOAppInit(Tcl_Interp *interp)
{
  // save interp for cputs function
  global_interp = interp;

  // Initialize Tcl and Tk
  if (Tcl_Init(interp) == TCL_ERROR)
    return TCL_ERROR;

  // Tk
  if (Tk_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage(interp,"Tk", Tk_Init, Tk_SafeInit);

  // Tkblt
  if (Tkblt_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage(interp, "tkblt", Tkblt_Init, 
		    (Tcl_PackageInitProc*)NULL);

  // Tktable
  if (Tktable_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "Tktable", Tktable_Init, 
		     (Tcl_PackageInitProc*)NULL);

  // Tclcheckdns
  //  if (Tclcheckdns_Init(interp) == TCL_ERROR)
  //    return TCL_ERROR;
  //  Tcl_StaticPackage (interp, "tclcheckdns", Tclcheckdns_Init, 
  //		     (Tcl_PackageInitProc*)NULL);

  // Tksao
  if (Tksao_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "tksao", Tksao_Init,
  		     (Tcl_PackageInitProc*)NULL);

  // Tkhtml1
  if (Tkhtml1_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "tkhtml1", Tkhtml1_Init,
  		     (Tcl_PackageInitProc*)NULL);

  // Tclxpa
  if (Tclxpa_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "Tclxpa", Tclxpa_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Tcliis
  //  if (Tcliis_Init(interp) == TCL_ERROR)
  //    return TCL_ERROR;
  //  Tcl_StaticPackage (interp, "tcliis", Tcliis_Init, 
  //		     (Tcl_PackageInitProc*)NULL);

  // Tkmpeg
  if (Tkmpeg_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "tkmpeg", Tkmpeg_Init, 
		     (Tcl_PackageInitProc*)NULL);

  // Tclxml
  if (Tclxml_Init(interp) == TCL_ERROR)
    return TCL_ERROR;

  // Tkimg
  if (Tkimg_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "img", Tkimg_Init,
		     (Tcl_PackageInitProc*)NULL);

  // zlibtcl
  if (Zlibtcl_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "zlibtcl", Zlibtcl_Init,
		     (Tcl_PackageInitProc*)NULL);

  // jpegtcl
  if (Jpegtcl_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "jpegtcl", Jpegtcl_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Tkimgjpeg
  if (Tkimgjpeg_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "jpeg", Tkimgjpeg_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Tifftcl
  if (Tifftcl_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "tifftcl", Tifftcl_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Tkimgtiff
  if (Tkimgtiff_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "tiff", Tkimgtiff_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Pngtcl
  if (Pngtcl_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "pngtcl", Pngtcl_Init,
  		     (Tcl_PackageInitProc*)NULL);

  // Tkimgpng
  if (Tkimgpng_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "png", Tkimgpng_Init,
  		     (Tcl_PackageInitProc*)NULL);

  // Tkimggif
  if (Tkimggif_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "gif", Tkimggif_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Tkimgwindow
  if (Tkimgwindow_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
  Tcl_StaticPackage (interp, "window", Tkimgwindow_Init,
		     (Tcl_PackageInitProc*)NULL);

  // Signal_Ext
  //  if (Signal_ext_Init(interp) == TCL_ERROR)
  //    return TCL_ERROR;
  //  Tcl_StaticPackage (interp, "signal", Signal_ext_Init, 
  //		     (Tcl_PackageInitProc*)NULL);

  // Tkwin32
  if (Tkwin32_Init(interp) == TCL_ERROR)
    return TCL_ERROR;
    Tcl_StaticPackage (interp, "tkwin32", Tkwin32_Init,
		       (Tcl_PackageInitProc*)NULL);

  return TCL_OK;
}