/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                        H I S T O R Y M O D U L E . C                         *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: historymodule.c,v 1.2 2003/11/07 11:02:38 jrh Exp $
* $Log: historymodule.c,v $
* Revision 1.2  2003/11/07 11:02:38  jrh
* Release 2.4
*
* Revision 1.1  2000/12/10 15:08:44  jrh
* Initial revision
*
*/     
#include<stdio.h>
#include<unistd.h>
#include<Xm/DrawingA.h>
#include<Xm/PushBG.h>
#include<Xm/SeparatoG.h>
#include<Xm/ToggleBG.h>
#include "viewmol.h"

#define PyHistory_API_pointers 1
#define PyHistorySpec_Type_NUM 0

extern void initSpectrum(Widget, caddr_t, caddr_t);
extern void initMODiagram(Widget, caddr_t, caddr_t);
extern void initHistory(Widget, caddr_t, caddr_t);
extern void drawHistory(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void GetDiagram(Widget, caddr_t, XmToggleButtonCallbackStruct *);
extern void setMenuItem(int, int);
extern void setHistoryAnimation(Widget, caddr_t, XmAnyCallbackStruct *);
extern void selectMolecule(Widget, caddr_t, XmToggleButtonCallbackStruct *);
extern void redraw(int);
extern void setGeometry(int);
extern void saveDrawing(int, int, char *);
extern int  checkInterrupt(void);
extern void quitHistory(Widget, caddr_t, XmAnyCallbackStruct *);
extern void getScreenCoordinates(double, double, double, double *, double *,
		                                 double *);

PyHistorySpecObject *history_new(void);
static PyObject *history_show(PyObject *, PyObject *);
static PyObject *history_showEnergy(PyObject *, PyObject *);
static PyObject *history_showGradient(PyObject *, PyObject *);
static PyObject *history_showScales(PyObject *, PyObject *);
static PyObject *history_animate(PyObject *, PyObject *);
static PyObject *history_iteration(PyObject *, PyObject *);
static PyObject *history_saveDrawing(PyObject *, PyObject *);
static PyObject *history_getattr(PyHistorySpecObject *, char *);
static void history_dealloc(PyHistorySpecObject *);

extern struct WINDOW windows[];
extern struct MOLECULE *molecules;
extern int nmolecule, showForces, showInertia, label;

static char PyHistorySpec_Type__doc__[] =
  "History specification";

statichere PyTypeObject PyHistorySpec_Type = {
  PyObject_HEAD_INIT(NULL)
  0,                               /*ob_size*/
  "HistorySpec",                   /*tp_name*/
  sizeof(PyHistorySpecObject),     /*tp_basicsize*/
  0,                               /*tp_itemsize*/
  /* methods */
  (destructor)history_dealloc,     /*tp_dealloc*/
  0,                               /*tp_print*/
  (getattrfunc)history_getattr,    /*tp_getattr*/
  0,                               /*tp_setattr*/
  0,                               /*tp_compare*/
  0,                               /*tp_repr*/
  0,                               /*tp_as_number*/
  0,                               /*tp_as_sequence*/
  0,                               /*tp_as_mapping*/
  0,                               /*tp_hash*/
  0,                               /*tp_call*/
  0,                               /*tp_str*/
  0,                               /*tp_getattro*/
  0,                               /*tp_setattro*/
  /* Space for future expansion */
  0L,0L,
  /* Documentation string */
  PyHistorySpec_Type__doc__
};

#include "menudef.h"

static PyMethodDef history_methods[] = {
  {"show",             history_show,  1},
  {"showEnergy",       history_showEnergy, 1},
  {"showGradient",     history_showGradient, 1},
  {"showScales",       history_showScales, 1},
  {"animate",          history_animate, 1},
  {"iteration",        history_iteration, 1},
  {"saveDrawing",      history_saveDrawing, 1},
  {NULL,               NULL}
};

PyHistorySpecObject *history_new(void)
{
  PyHistorySpecObject *self;

  self=PyObject_NEW(PyHistorySpecObject, &PyHistorySpec_Type);
  if (self == NULL)
  {
    PyErr_NoMemory();
    return(NULL);
  }
  self->historyID=0;
  return(self);
}

static PyObject *history_show(PyObject *self, PyObject *args)
{
  PyHistorySpecObject *s;
  XmToggleButtonCallbackStruct data;
  int which, set_save;

  if (checkInterrupt()) return(NULL);
  if (!self)
  {
    Py_INCREF(Py_None);
    return(Py_None);
  }
  s=(PyHistorySpecObject *)self;
  which=s->historyID;
  if (windows[HISTORY].widget == NULL)
  {
    set_save=windows[VIEWER].set;
    windows[VIEWER].set=which;
    initHistory((Widget)0, (caddr_t)0, (caddr_t)0);
    windows[VIEWER].set=set_save;
  }
  else
  {
    windows[HISTORY].set=which;
    if (nmolecule > 1)
    {
      data.set=TRUE;
      (void)selectMolecule((Widget)0, (XtPointer)&(windows[HISTORY].selectMenu[which]),
                           &data);
    }
    redraw(HISTORY);
  }
  Py_INCREF(Py_None);
  return(Py_None);
}

static PyObject *history_showEnergy(PyObject *self, PyObject *args)
{
  XmToggleButtonCallbackStruct data;
  PyHistorySpecObject *s;
  int status, which, set_save;

  if (checkInterrupt()) return(NULL);
  if (!PyArg_ParseTuple(args, "i", &status)) return(NULL);

  if (status != TRUE && status != FALSE)
  {
    PyErr_SetString(PyExc_ValueError, "Status must be ON or OFF");
    return(NULL);
  }
  s=(PyHistorySpecObject *)self;
  which=s->historyID;
  set_save=windows[HISTORY].set;
  windows[HISTORY].set=which;
  data.set=status;
  GetDiagram((Widget)0, (caddr_t)ENERGY, &data);
  windows[HISTORY].set=set_save;
  redraw(HISTORY);
  Py_INCREF(Py_None);
  return(Py_None);
}

static PyObject *history_showGradient(PyObject *self, PyObject *args)
{
  XmToggleButtonCallbackStruct data;
  PyHistorySpecObject *s;
  int status, which, set_save;

  if (checkInterrupt()) return(NULL);
  if (!PyArg_ParseTuple(args, "i", &status)) return(NULL);

  if (status != TRUE && status != FALSE)
  {
    PyErr_SetString(PyExc_ValueError, "Status must be ON or OFF");
    return(NULL);
  }
  s=(PyHistorySpecObject *)self;
  which=s->historyID;
  set_save=windows[HISTORY].set;
  windows[HISTORY].set=which;
  data.set=status;
  GetDiagram((Widget)0, (caddr_t)GNORM, &data);
  windows[HISTORY].set=set_save;
  redraw(HISTORY);
  Py_INCREF(Py_None);
  return(Py_None);
}

static PyObject *history_showScales(PyObject *self, PyObject *args)
{
  XmToggleButtonCallbackStruct data;
  PyHistorySpecObject *s;
  int status, which, set_save;

  if (checkInterrupt()) return(NULL);
  if (!PyArg_ParseTuple(args, "i", &status)) return(NULL);

  if (status != TRUE && status != FALSE)
  {
    PyErr_SetString(PyExc_ValueError, "Status must be ON or OFF");
    return(NULL);
  }
  s=(PyHistorySpecObject *)self;
  which=s->historyID;
  set_save=windows[HISTORY].set;
  windows[HISTORY].set=which;
  data.set=status;
  GetDiagram((Widget)0, (caddr_t)SCALES, &data);
  windows[HISTORY].set=set_save;
  redraw(HISTORY);
  Py_INCREF(Py_None);
  return(Py_None);
}

static PyObject *history_animate(PyObject *self, PyObject *args)
{
  int status;

  if (checkInterrupt()) return(NULL);
  if (!PyArg_ParseTuple(args, "i", &status)) return(NULL);

  if (status != TRUE && status != FALSE)
  {
    PyErr_SetString(PyExc_ValueError, "Status must be ON or OFF");
    return(NULL);
  }
  if (status)
  {
    setHistoryAnimation((Widget)0, (caddr_t)1, (XmAnyCallbackStruct *)0);
/*  XtVaSetValues(historyMenu[HISTORY_ANIMATE & 0xff].widget, XmNset, True, NULL);*/
  }
  else
  {
    setHistoryAnimation((Widget)0, (caddr_t)2, (XmAnyCallbackStruct *)0);
/*  XtVaSetValues(historyMenu[HISTORY_ANIMATE & 0xff].widget, XmNset, False, NULL);*/
  }
  redraw(HISTORY);
  Py_INCREF(Py_None);
  return(Py_None);
}

static PyObject *history_iteration(PyObject *self, PyObject *args)
{
  PyHistorySpecObject *s;
  double xw, yw, zw;
  int which, set_save, i=(-1);

  if (checkInterrupt()) return(NULL);
  if (!PyArg_ParseTuple(args, "|i", &i)) return(NULL);

  s=(PyHistorySpecObject *)self;
  which=s->historyID;
  if (i == -1) /* get */
    return(PyInt_FromLong((long)molecules[which].cycle));
  else         /* set */
  {
    if (i < 1 || i > molecules[which].nhist)
    {
      PyErr_SetString(PyExc_ValueError, "Number of iteration out of range");
      return(NULL);
    }
    molecules[which].cycle=i;
    set_save=windows[HISTORY].set;
    windows[HISTORY].set=which;
    setGeometry(TRUE);
    drawHistory((Widget)0, (caddr_t)0, (XmDrawingAreaCallbackStruct *)0);
    getScreenCoordinates((double)(i), 0.0, 0.0, &xw, &yw, &zw);
    windows[HISTORY].mouseX=(int)xw;
    drawHistory((Widget)0, (caddr_t)0, (XmDrawingAreaCallbackStruct *)0);
    windows[HISTORY].set=set_save;
    redraw(HISTORY);
    Py_INCREF(Py_None);
    return(Py_None);
  }
}

static PyObject *history_saveDrawing(PyObject *self, PyObject *args)
{
  int format;
  char *filename;

  if (checkInterrupt()) return(NULL);
  if (!PyArg_ParseTuple(args, "is", &format, &filename)) return NULL;
  if (!access(filename, F_OK))
  {
    PyErr_SetString(PyExc_IOError, "File already exists.");
    return(NULL);
  }
  if (format != TIFFFILE && format != PNGFILE && format != HPGL &&
      format != POSTSCRIPT)
  {
    PyErr_SetString(PyExc_ValueError, "Format not recognised.");
    return(NULL);
  }
  saveDrawing(HISTORY, format, filename);
  Py_INCREF(Py_None);
  return(Py_None);
}

static void history_dealloc(PyHistorySpecObject *self)
{
  if (!self) return;
  PyMem_DEL(self);
  quitHistory((Widget)0, (caddr_t)0, (XmAnyCallbackStruct *)0);
  (void)checkInterrupt();
}

static PyObject *history_getattr(PyHistorySpecObject *self, char *name)
{
  return(Py_FindMethod(history_methods, (PyObject *)self, name));
}

void initHistoryModule(void)
{
  PyObject *module, *dict;
  static void *PyHistory_API[PyHistory_API_pointers];

  PyHistorySpec_Type.ob_type=&PyType_Type;

  module=Py_InitModule("history", history_methods);
  dict=PyModule_GetDict(module);

  PyHistory_API[PyHistorySpec_Type_NUM]=(void *)&PyHistorySpec_Type;
  PyDict_SetItemString(dict, "_C_API", PyCObject_FromVoidPtr((void *)PyHistory_API, NULL));
}
