#include <stdio.h>

#ifdef DMALLOC
#include <dmalloc.h>
#endif

#include "tcltk.h"
#include "defines.h"
#include "illist.h"
#include "complete.h"
#include "mytcl.h"
#include "serverdcc.h"
#include "window.h"
#include "history.h"
#include "network.h"
#include "echo.h"
#include "hash.h"
#include "messages.h"
#include "format.h"

// The unique numbers for identifying items with
int statusnum=0;
int channum=0;
int querynum=0;
int chatnum=0;
int acceptnum=0;
int filenum=0;

// The pathname to the current window
char currentwindow[20];

// List of Windows in client
ilist<twindow> windows;

// Global history list
ilist<tcommand> history;
int historyposition=-1;
char *historycommand=0;

// Formating and Location listings
hash formats;
hash activate;
hash locations;

int main(int argc, char **argv) {
  twindow window;
  int n;
  int foundi=0;
  int argc2=argc;
  char **argv2;

#ifdef SOCKS
  // Socks Idenfication Call
  SOCKSinit(argv[0]);
#endif

  if(!(argv2=(char **)malloc(argc*sizeof(char *)))) {
    fprintf(stderr,M_OUT_OF_MEMORY);
    exit(1);
  }
  
  for(n=0;n<argc;n++) {
    if(!(argv2[n]=strdup(argv[n]))) {
      fprintf(stderr,M_OUT_OF_MEMORY);
      exit(1);
    }
  }

  // Initialize temporary interpreter with TT
  if(TT_Init(&argc2,argv2)==TCL_ERROR) {
    fprintf(stderr,M_TCL_TK_INIT_FAILED);
    exit(1);
  }

  TT_Install_Command(version);

  // Check for the -i option to force installation script.
  for(n=0;n<argc2;n++) {
    if(!strcmp(argv2[n],"-i")) foundi=1;
  }

  for(n=0;n<argc2;n++) {
    free(argv2[n]);
  }
  free(argv2);
  
  // Run installation script
  TT_EvalF(TT_ARGS,"set FOUNDI %d",foundi);
  TT_EvalF(TT_ARGS,"set DATADIR %q",DATADIR);
  TT_Eval(TT_ARGS,"source $DATADIR/common/install.tcl");
  
  Tk_MainLoop();

  Tcl_DeleteInterp(TT_Interp);

  // Re-initialize TT and Install Commands
  if(TT_Init(&argc,argv)==TCL_ERROR) {
    fprintf(stderr,M_TCL_TK_INIT_FAILED);
    exit(1);
  }

  // Rename commands so they can be replaced
  TT_Eval(TT_ARGS,"rename exit die");
  TT_Eval(TT_ARGS,"rename unknown unknown_original");

  // COMPLETE
  TT_Install_Command(n_complete);
  TT_Install_ObjCommand(complete);
  TT_Install_ObjCommand(expandmatch);
  TT_Install_ObjCommand(getpwents);

  // TCL
  TT_Install_Command(activebutton);
  TT_Install_Command(bgerror);
  TT_Install_Command(callproc);
  TT_Install_Command(channel);
  TT_Install_Command(configtags);
  TT_Install_Command(connect);
  TT_Install_Command(closewindow);
  TT_Install_Command(currentindex);
  TT_Install_Command(currentwindow);
  TT_Install_Command(disconnect);
  TT_Install_ObjCommand(echo);
  TT_Install_ObjCommand(echotags);
  TT_Install_ObjCommand(escape);
  TT_Install_Command(exit);
  TT_Install_Command(fdisplay);
  TT_Install_Command(fgetformat);
  TT_Install_Command(fgetpathnames);
  TT_Install_Command(flocation);
  TT_Install_Command(fparse);
  TT_Install_Command(fset);
  TT_Install_ObjCommand(gettags);
  TT_Install_Command(hist);
  TT_Install_Command(histdown);
  TT_Install_Command(histup);
  TT_Install_Command(idle);
  TT_Install_Command(index);
  TT_Install_Command(ischannel);
  //TT_Install_Command(memory);
  TT_Install_Command(microtime);
  TT_Install_Command(newserver);
  TT_Install_Command(nextwindow);
  TT_Install_Command(parseentry);
  TT_Install_Command(popup);
  TT_Install_Command(previouswindow);
  TT_Install_Command(renamewindow);
  TT_Install_Command(say);
  TT_Install_Command(selectednicks);
  TT_Install_Command(selectedmodenicks);
  TT_Install_Command(serverindex);
  TT_Install_Command(servers);
  TT_Install_Command(shutdown);
  TT_Install_ObjCommand(title);
  TT_Install_Command(totop);
  TT_Install_Command(version);
  TT_Install_Command(windowindex);
  TT_Install_Command(windowname);
  TT_Install_Command(windows);
  TT_Install_Command(windowtype);
  TT_Install_Command(__template__acceptlist);
  TT_Install_Command(__template__channelmode);
  TT_Install_Command(__template__channels);
  TT_Install_Command(__template__connected);
  TT_Install_Command(__template__createchannel);
  TT_Install_Command(__template__createquery);
  TT_Install_Command(__template__dcc);
  TT_Install_Command(__template__dccquote);
  TT_Install_Command(__template__fdisplay);
  TT_Install_Command(__template__fgetpathnames);
  TT_Install_Command(__template__fixnicklist);
  TT_Install_Command(__template__fparse);
  TT_Install_Command(__template__index);
  TT_Install_Command(__template__ison);
  TT_Install_Command(__template__isop);
  TT_Install_Command(__template__isvoice);
  TT_Install_Command(__template__killdcc);
  TT_Install_Command(__template__modenicks);
  TT_Install_Command(__template__modes);
  TT_Install_Command(__template__mynick);
  TT_Install_Command(__template__nicks);
  TT_Install_Command(__template__onchannel);
  TT_Install_Command(__template__pathname);
  TT_Install_Command(__template__popup);
  TT_Install_Command(__template__queries);
  TT_Install_Command(__template__quote);
  TT_Install_Command(__template__script);
  TT_Install_Command(__template__server);
  TT_Install_Command(__template__topic);
  TT_Install_Command(__template__unscript);
  TT_Install_Command(__template__userhost);
  TT_Install_ObjCommand(__template__userlist);

  //TT_Install_Command(__template__ialstats);
  //TT_Install_Command(__template__ialclear);

  // Fire up the background name lookup engine
  init_ar();

  // Init format/location hashes
  hash_create(&formats);
  hash_create(&activate);
  hash_create(&locations);

  // Make various namespaces exist
  TT_Eval(TT_ARGS,"namespace eval ::internal {}");
  TT_Eval(TT_ARGS,"namespace eval ::dynamic {}");

  // Set the variable that knows if we have a main window to stuff errors in
  TT_Eval(TT_ARGS,"set ::internal::done_main_window 0");

  // Set up the alias command
  TT_Eval(TT_ARGS,"\
    proc alias { name script } {\n\
      uplevel \"\n\
        proc alias_$name { arg } { $script }\n\
      \"\n\
    }\
  ");

  // Load the global file for various useful functions.
  TT_Eval(TT_ARGS,"source $env(HOME)/.quirc/global.tcl");

  // Load the default config file.
  TT_Eval(TT_ARGS,"source $env(HOME)/.quirc/variables.tcl");

  // Load the Dynamic Config File
  TT_Eval(TT_ARGS,"if { [file exists \"$env(HOME)/.quirc/dynamic.tcl\"] } { namespace eval ::dynamic { source \"$env(HOME)/.quirc/dynamic.tcl\" } }");

  TT_Eval(TT_ARGS,"\
    proc ::ic { color type } {\n\
      if { [string first \",\" $color]!=-1 } {\n\
	set pre [lindex [split $color \",\"] 0]\n\
	set post [lindex [split $color \",\"] 1]\n\
	if { [string length $post]==1 } {\n\
	  return \"$pre,0$post\"\n\
	} else {\n\
	  return $color\n\
	}\n\
      } else {\n\
	if { $color==\"\" } {\n\
	  set color [set ::dynamic::theme_${type}_foreground]\n\
	}\n\
	if { [string length [set ::dynamic::theme_${type}_background]]==1 } {\n\
	  return \"$color,0[set ::dynamic::theme_${type}_background]\"\n\
	} else {\n\
	  return \"$color,[set ::dynamic::theme_${type}_background]\"\n\
	}\n\
      }\n\
    }\
  ");


  // Load default.tcl before we load the regular theme file.  This way, any
  // extras will just appear as their defaults.
  TT_Eval(TT_ARGS,"source $env(HOME)/.quirc/themes/default.tcl");
  
  // Load the theme file 
  TT_Eval(TT_ARGS,"source $env(HOME)/.quirc/themes/$::dynamic::theme");

  // Load the GUI code file
  TT_Eval(TT_ARGS,"source $env(HOME)/.quirc/qwidgets.tcl");

  // Load the global scripts
  TT_Eval(TT_ARGS,"foreach script $::dynamic::default_globalscripts { source $env(HOME)/.quirc/$script }");

  // Make the Main Window Frame and Set up the Window List Box
  TT_Eval(TT_ARGS,"GUI_Init_Phase_1");

  // Create MAIN Window
  strcpy(window.name,"Main Status");
  strcpy(window.pathname,".main");
  window.server=0;
  window.dcc=0;
  n=windows.insert_ascending(window); 
  TT_EvalF(TT_ARGS,"Init_Window .main \"Main Status\" %d main {}",n);
 
  // Set up the rest of the intial GUI stuff
  TT_Eval(TT_ARGS,"GUI_Init_Phase_2");

  // Start the initial server
  if(TT_Int(TT_ARGS,"set ::dynamic::first_time")) {
    TT_Eval(TT_ARGS,"totop 0");
    TT_Eval(TT_ARGS,"if { [info commands ::event_first_time]!={} } { ::event_first_time } else { echo \"Uh oh... somebody forgot to include an event_first_time.\" }");
  } else {
    TT_Eval(TT_ARGS,"\
      if { [info commands ::event_client_start]!={} } {\n\
        totop 0\n\
        event_client_start\n\
      } else {\n\
        newserver\n\
      }\
    ");
  }

  Tk_MainLoop();

  // When exit gets called, this is not run.  However, it is run when the
  // delete event occurs.
  TT_Eval(TT_ARGS,"shutdown");

  return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1