// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// xmksrchtblcb.C
//
// Author:               Sameer Nene
// Date:                 09/12/94
// Version:              1.0.0
// Modification History:
//   04/10/96: Fixed scoping problem to work with new ANSI C++ definition
//
// Notes:
//   X module for computation of Search structures
//   
// ----------------------------------------------------------------------------

#define NO_XMSTRINGS

#include <ctype.h>
#include <strstream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Xm/FileSB.h>
#include <Xm/List.h>
#include <Xm/MessageB.h>
#include <Xm/SelectioB.h>
#include <Xm/TextF.h>
#include <Xm/Xm.h>
#include "errorscope.h"
#include "fileiter.h"
#include "persscheme.h"
#include "fullsearch.h"
#include "partialsearch.h"
#include "binarysearch.h"
#include "ioutil.h"
#include "list.h"
#include "xreporter.h"
#include "vector.h"
#include "dataset.h"
#include "stringary.h"
#include "xmksrchtbl.h"
#include "fileinfo.h"
#include "parser.h"

extern void err_dlg(Widget, const char*);
extern void fillList(Widget, const List<FileInfo* > &);
extern void get_path(XmFileSelectionBoxCallbackStruct*, char**, char**);

void popup_cb(Widget, XtPointer p1, XtPointer)
{
  XtPopup(Widget(p1), XtGrabNone);
}

void pulldown_cb(Widget w, XtPointer, XtPointer)
{
  XtPopdown(XtParent(XtParent(w)));
}

void quit_cb(Widget, XtPointer, XtPointer)
{
  exit(0);
}

void typeoptionB_cb(Widget, XtPointer p1, XtPointer)
{
  *((int *)p1) = FileInfo::BINARY;
}

void typeoptionT_cb(Widget, XtPointer p1, XtPointer)
{
  *((int *)p1) = FileInfo::TEXT;
}

void typeoptionES_cb(Widget, XtPointer p1, XtPointer)
{
  *((int *)p1) = MainCbLocal::EXHAUSTIVE_SEARCH;
}

void typeoptionHS_cb(Widget, XtPointer p1, XtPointer)
{
  *((int *)p1) = MainCbLocal::HEURISTIC_SEARCH;
}

void typeoptionBS_cb(Widget, XtPointer p1, XtPointer)
{
  *((int *)p1) = MainCbLocal::BINARY_SEARCH;
}

void hmenu_cb(Widget w, XtPointer, XtPointer)
{
  XmString mesg = XmStringCreateLtoR("Copyright \xA9 Columbia University, 1994. All Rights Reserved.\nSameer Nene, Shree Nayar, Hiroshi Murase", XmSTRING_DEFAULT_CHARSET);
  Widget dlg;

  dlg = XmCreateInformationDialog(XtParent(w), "About", NULL, 0);
  XtVaSetValues(dlg,
		XmNmessageString, mesg,
		XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL,
		NULL);
  XtUnmanageChild(XmMessageBoxGetChild(dlg, XmDIALOG_CANCEL_BUTTON));
  XtUnmanageChild(XmMessageBoxGetChild(dlg, XmDIALOG_HELP_BUTTON));
  
  XmStringFree(mesg);
  XtManageChild(dlg);
}

void loadDataSetOk_cb(Widget w, XtPointer p3, XtPointer p1)
{
  char *dir, *name, *p2;
  MainCbLocal *data = (MainCbLocal*)p3;
  FileInfo *fi;
  
  get_path((XmFileSelectionBoxCallbackStruct *)p1, &dir, &name);

  for(p2 = dir; isspace(*p2); ++p2);
  if(*p2 == '\0') {
    err_dlg(XtParent(w), "Please supply Directory Name");
    delete[] dir;
    delete[] name;
    return;
  }

  for(p2 = name; isspace(*p2); ++p2);
  if(*p2 == '\0') {
    err_dlg(XtParent(w), "Please supply Vector Set Name");
    delete[] dir;
    delete[] name;
    return;
  }

  fi = new FileInfo(dir, name, data -> d_type);

  ListManip<FileInfo* > m(&(data -> d_list));
  for(; m; ++m)
    if(strcmp(m() -> getName(), name) == 0) {
      delete m();
      m.remove();
      break;
    }
  m.insert(fi);

  fillList(data -> d_listw, data -> d_list);

  delete[] dir;
  delete[] name;
}

void delItem_cb(Widget, XtPointer p1, XtPointer)
{
  char *p2;
  int i, *pos_list = 0, pos_cnt;
  XmString *names;
  MainCbLocal *data = (MainCbLocal*)p1;
  
  XmListGetSelectedPos(data -> d_listw, &pos_list, &pos_cnt);
  XtVaGetValues(data -> d_listw, XmNitems, &names, NULL);

  for(i = 0; i < pos_cnt; ++i) {
    XmStringGetLtoR(names[pos_list[i] - 1], XmSTRING_DEFAULT_CHARSET, &p2);
    for(ListManip<FileInfo* > m(&(data -> d_list)); m; ++m)
      if(strcmp(m() -> getName(), p2) == 0) {
	delete m();
	m.remove();
	break;
      }
    XtFree(p2);
  }

  fillList(data -> d_listw, data -> d_list);
}

void compute_cb(Widget w, XtPointer p1, XtPointer)
{
  char *p2, *p3, errmessg[256], buf[1024], **argv = 0;
  ostrstream ostr(errmessg, 256);
  ErrorScope::Error error;
  MainCbLocal *data = (MainCbLocal*)p1;
  int i, k, n, t, v, argc;
  Vector rangemin, rangemax;
  DataSet ds;
  PersistentSearchScheme *ss;

  p2 = XmTextFieldGetString(data -> d_text);
  argc = 0;
  if((p3 = strtok(p2, " \t")) != 0)
    while(p3 != 0) {
      ++argc;
      p3 = strtok(0, " \t");
    }
  XtFree(p2);

  if(argc == 0) {
    ostr << "Please specify parameters";
    err_dlg(XtParent(w), errmessg);
    return;
  }

  p2 = XmTextFieldGetString(data -> d_text);
  argv = new char*[argc + 2]; // extra leading and trailing dummy arguments
  argc = 0;
  strcpy(argv[argc++] = new char[strlen("dummy") + 1], "dummy");
  if((p3 = strtok(p2, " \t")) != 0) {
    while(p3 != 0) {
      strcpy(argv[argc++] = new char[strlen(p3) + 1], p3);
      p3 = strtok(0, " \t");
    }
    strcpy(argv[argc++] = new char[strlen("dummy") + 1], "dummy");
  }
  XtFree(p2);
  
  CommandParser cp(argc, argv);
  if((error = cp.error()) != ErrorScope::OK) {
    ostr << error;
    err_dlg(XtParent(w), errmessg);
    for(i = 0; i < argc; delete[] argv[i++]);
    delete[] argv;
    return;
  }

  if((n = cp.getNumValueParams()) == 0) {
    ostr << ErrorScope::PARAMETER_ERROR;
    err_dlg(XtParent(w), errmessg);
    for(i = 0; i < argc; delete[] argv[i++]);
    delete[] argv;
    return;
  }

  for(ListIter<FileInfo* > it(data -> d_list); it; ++it) {
    p2 = strcat(strcpy(p2 = new char[strlen(it() -> getDirName()) + strlen(it() -> getName()) + 1], it() -> getDirName()), it() -> getName());
    if((error = IOUtil::get(&ds, p2)) != ErrorScope::OK) {
      ostr << error << ": " << p2;
      delete[] p2;
      err_dlg(XtParent(w), errmessg);
      for(i = 0; i < argc; delete[] argv[i++]);
      delete[] argv;
      return;
    }
    v = cp.getNumValues(0);
    if(n == 1)
      if(v == 2 || (v == 3 && cp.getValue(0, 0) == ds().getSize())) {
	ds.setDimension(1);
	rangemin.length(1);
	rangemax.length(1);
	ds.setSize(0, ds().getSize());
	rangemin.element(0, cp.getValue(0, 0));
	rangemax.element(0, cp.getValue(0, 1));
      }
      else {
	ostr << ErrorScope::PARAMETER_ERROR;
	err_dlg(XtParent(w), errmessg);
	for(i = 0; i < argc; delete[] argv[i++]);
	delete[] argv;
	delete[] p2;	
	return;
      }
    else if(v == 2 && n == ds.getSize()) {
      rangemin.length(n);
      rangemax.length(n);
      for(k = 0; k < n; ++k) {
	if(cp.getNumValues(k) != 2) {
	  ostr << ErrorScope::PARAMETER_ERROR;
	  err_dlg(XtParent(w), errmessg);
	  for(i = 0; i < argc; delete[] argv[i++]);
	  delete[] argv;
	  delete[] p2;	
	  return;
	}
	rangemin.element(k, cp.getValue(k, 0));
	rangemax.element(k, cp.getValue(k, 1));
      }
    }
    else if(v == 3) {
      ds.setDimension(n);
      rangemin.length(n);
      rangemax.length(n);
      for(k = 0, t = 1; k < n; ++k) {
	if(cp.getNumValues(k) != 3) {
	  ostr << ErrorScope::PARAMETER_ERROR;
	  err_dlg(XtParent(w), errmessg);
	  for(i = 0; i < argc; delete[] argv[i++]);
	  delete[] argv;
	  delete[] p2;	
	  return;
	}
	t *= int(v = int(cp.getValue(k, 0)));
	ds.setSize(k, int(v));
	rangemin.element(k, cp.getValue(k, 1));
	rangemax.element(k, cp.getValue(k, 2));
      }
      if(t != ds().getSize()) {
	ostr << ErrorScope::PARAMETER_ERROR;
	err_dlg(XtParent(w), errmessg);
	for(i = 0; i < argc; delete[] argv[i++]);
	delete[] argv;
	delete[] p2;	
	return;
      }
    }
    else {
      ostr << ErrorScope::PARAMETER_ERROR;
      err_dlg(XtParent(w), errmessg);
      for(i = 0; i < argc; delete[] argv[i++]);
      delete[] argv;
      delete[] p2;	
      return; 
    }

    strcat(strcpy(buf, "Computing Search Structure for "), p2);
    XReporter::showWaitCursor(data -> d_topshell);

    switch(data -> d_srchtype) {
    case MainCbLocal::EXHAUSTIVE_SEARCH:
      ss = new FullSearch(ds, rangemin, rangemax);
      break;
    case MainCbLocal::HEURISTIC_SEARCH:
      ss = new PartialSearch(ds, rangemin, rangemax);
      break;
    case MainCbLocal::BINARY_SEARCH:
      ss = new BinarySearch(ds, rangemin, rangemax);
      break;
    default:
      ss = 0; // core dump
    }

    if((p3 = strrchr(strcpy(buf, p2), '.')) != 0)
      *p3 = 0;
    if((error = IOUtil::put(*ss, strcat(buf, ".tbl"))) != ErrorScope::OK) {
      ostr << error << ": " << buf;
      delete[] p2;
      err_dlg(XtParent(w), errmessg);
      for(i = 0; i < argc; delete[] argv[i++]);
      delete[] argv;
      delete ss;
      XReporter::showNormalCursor(data -> d_topshell);
      return; 
    }
    
    delete[] p2;
    delete ss;
    XReporter::showNormalCursor(data -> d_topshell);
  }

  for(i = 0; i < argc; delete[] argv[i++]);
  delete[] argv;
}
