/*
 * tclgeomapTime.c --
 *
 *	This file defines the structures and functions that add the ability
 *	to manage time Tclgeomap.
 * 
 * Copyright (c) 2006 Gordon D. Carrie.  All rights reserved.
 * 
 * Licensed under the Open Software License version 2.1
 * 
 * Please address questions and feedback to user0@tkgeomap.org
 *
 * @(#) $Id: tclgeomapTime.c,v 1.6 2006/10/10 17:46:09 tkgeomap Exp $
 *
 ********************************************
 *
 */

#include "tclgeomap.h"
#include "tclgeomapInt.h"

/*
 * Forward declarations
 */

static int callback _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *CONST objv[]));
static int jul_to_cal _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *CONST objv[]));
static int cal_to_jul _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *CONST objv[]));
static int incr _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *CONST objv[]));
static int cmp _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *CONST objv[]));
static int diff _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *CONST objv[]));

/*
 *------------------------------------------------------------------------
 *
 * TclgeomapTimeInit --
 *
 *	This procedure initializes the Tclgeomap_Time interface and provides
 *	the tclgeotime package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	The "geomap::time" command is added to the interpreter.
 *
 *------------------------------------------------------------------------
 */

int
TclgeomapTimeInit(interp)
    Tcl_Interp *interp;		/* Current Tcl interpreter */
{
    static int loaded;		/* Tell if package already loaded */

    if (loaded) {
	return TCL_OK;
    }
#ifdef USE_TCL_STUBS
    if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
	return TCL_ERROR;
    }
#endif
    Tcl_CreateObjCommand(interp, "::geomap::time", callback, NULL, NULL);
    loaded = 1;
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * callback --
 *
 *	This is the callback for the "geomap::time" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	This procedure invokes the callback corresponding to the first
 *	argument given to the "geomap::time" command.  Side effects depend
 *	on the subcommand called.
 *
 *------------------------------------------------------------------------
 */

int
callback(clientData, interp, objc, objv)
    ClientData clientData;	/* Not used */
    Tcl_Interp *interp;		/* Current interpreter */
    int objc;			/* Number of arguments */
    Tcl_Obj *const objv[];	/* Argument objects */
{
    char *nmPtr[] = {
	"jul_to_cal", "cal_to_jul", "incr", "cmp", "diff", NULL
    };
    Tcl_ObjCmdProc *procPtr[] = {
	jul_to_cal, cal_to_jul, incr, cmp, diff
    };
    int i;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], nmPtr, "subcommand", 0, &i)
	    != TCL_OK) {
	return TCL_ERROR;
    }
    return (procPtr[i])(NULL, interp, objc, objv);
}

/*
 *------------------------------------------------------------------------
 *
 * jul_to_cal --
 *
 *	This is the callback for the "geomap::time jul_to_cal" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 * 	Interpreter result will be set.  See the user documentation.
 *
 *------------------------------------------------------------------------
 */

int
jul_to_cal(clientData, interp, objc, objv)
    ClientData clientData;		/* Not used */
    Tcl_Interp *interp;			/* The current interpreter */
    int objc;				/* Number of arguments */
    Tcl_Obj *const objv[];		/* Argument objects */
{
    Tcl_Obj *dayObj, *secObj;		/* Julian day and seconds from command
					 * line */
    int day;				/* Julian day from command line */
    double second;			/* Seconds from command line */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "{julian_day second}");
	return TCL_ERROR;
    }
    if (Tcl_ListObjIndex(interp, objv[2], 0, &dayObj) != TCL_OK || !dayObj) {
	Tcl_AppendResult(interp, "Julian time must be in form {day second}",
		NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, dayObj, &day) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_ListObjIndex(interp, objv[2], 1, &secObj) != TCL_OK || !secObj) {
	Tcl_AppendResult(interp, "Julian time must be in form {day second}",
		NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetDoubleFromObj(interp, secObj, &second) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,
	    Tclgeomap_NewGeoTimeObj(GeoTime_JulSet(day, second)));
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * cal_to_jul --
 *
 *	This is the callback for the "geomap::time cal_to_jul" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 * 	Interpreter result will be set.  See the user documentation.
 *
 *------------------------------------------------------------------------
 */

int
cal_to_jul(clientData, interp, objc, objv)
    ClientData clientData;		/* Not used */
    Tcl_Interp *interp;			/* The current interpreter */
    int objc;				/* Number of arguments */
    Tcl_Obj *const objv[];		/* Argument objects */
{
    struct GeoTime_Jul jul;		/* Days and seconds in cal */
    Tcl_Obj *result;			/* Return value {day sec} */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"{year month day hour minute second}");
	return TCL_ERROR;
    }
    if (Tclgeomap_GetGeoTimeFromObj(interp, objv[2], &jul)) {
	return TCL_ERROR;
    }
    result = Tcl_NewObj();
    Tcl_ListObjAppendElement(NULL, result, Tcl_NewIntObj(jul.day));
    Tcl_ListObjAppendElement(NULL, result, Tcl_NewDoubleObj(jul.second));
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * incr --
 *
 *	This is the callback for the "geomap::time incr" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 * 	Interpreter result will be set.  See the user documentation.
 *
 *------------------------------------------------------------------------
 */

int
incr(clientData, interp, objc, objv)
    ClientData clientData;		/* Not used */
    Tcl_Interp *interp;			/* The current interpreter */
    int objc;				/* Number of arguments */
    Tcl_Obj *const objv[];		/* Argument objects */
{
    struct GeoTime_Jul jul;		/* Time from command line */
    double dt;				/* Time increment */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"{year month day hour minute second} seconds");
	return TCL_ERROR;
    }
    if (Tclgeomap_GetGeoTimeFromObj(interp, objv[2], &jul)) {
	return TCL_ERROR;
    }
    if (Tcl_GetDoubleFromObj(interp, objv[3], &dt)) {
	return TCL_ERROR;
    }
    GeoTime_Incr(&jul, dt);
    Tcl_SetObjResult(interp, Tclgeomap_NewGeoTimeObj(jul));
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * cmp --
 *
 *	This is the callback for the "geomap::time cmp" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 * 	Interpreter result will be set.  See the user documentation.
 *
 *------------------------------------------------------------------------
 */

int
cmp(clientData, interp, objc, objv)
    ClientData clientData;		/* Not used */
    Tcl_Interp *interp;			/* The current interpreter */
    int objc;				/* Number of arguments */
    Tcl_Obj *const objv[];		/* Argument objects */
{
    struct GeoTime_Jul jul1, jul2;	/* Times from command line */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"{year1 month1 day1 hour1 minute1 second1} "
		"{year2 month2 day2 hour2 minute2 second2}");
	return TCL_ERROR;
    }
    if (Tclgeomap_GetGeoTimeFromObj(interp, objv[2], &jul1)) {
	return TCL_ERROR;
    }
    if (Tclgeomap_GetGeoTimeFromObj(interp, objv[3], &jul2)) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(GeoTime_Cmp(jul1, jul2)));
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * diff --
 *
 *	This is the callback for the "geomap::time diff" command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 * 	Interpreter result will be set.  See the user documentation.
 *
 *------------------------------------------------------------------------
 */

int
diff(clientData, interp, objc, objv)
    ClientData clientData;		/* Not used */
    Tcl_Interp *interp;			/* The current interpreter */
    int objc;				/* Number of arguments */
    Tcl_Obj *const objv[];		/* Argument objects */
{
    struct GeoTime_Jul jul1, jul2;	/* Times from command line */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"{year1 month1 day1 hour1 minute1 second1} "
		"{year2 month2 day2 hour2 minute2 second2}");
	return TCL_ERROR;
    }
    if (Tclgeomap_GetGeoTimeFromObj(interp, objv[2], &jul1)) {
	return TCL_ERROR;
    }
    if (Tclgeomap_GetGeoTimeFromObj(interp, objv[3], &jul2)) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(GeoTime_Diff(jul1, jul2)));
    return TCL_OK;
}


syntax highlighted by Code2HTML, v. 0.9.1