/*****************************************************************************
******************************************************************************
**<AUTO>
**
** FILE:	tclTarget.c
**
**<HTML>
**	This file contains TCL functions to select spectroscopic targets.
**</HTML>
**</AUTO>
**
**
** ENVIRONMENT:
**	ANSI C.
**
******************************************************************************
******************************************************************************
*/

#include "taCalibObj.h"
#include "taGalaxies.h"
#include "taQuasars.h"
#include "taSerendipity.h"
#include "taStars.h"
#include "taCatalogs.h"
#include "taStandards.h"
#include "taRosat.h"
#include "taDiag.h"


/*============================================================================
**<AUTO EXTRACT>
**
** TCL VERB: targetSelect
**
**<HTML>
**	This routine accepts either a HANDLE to a CHAIN of calibrated objects
**	(TA_CALIB_OBJ) or a HANDLE to a single calibrated object (TA_CALIB_OBJ)
**	as its first argument.  If a CHAIN is passed in, then it will select
**	spectroscopic targets from all PRIMARY and SECONDARY objects in the
**	chain, setting
**	the target selection bit for each target selection criterion it meets;
**	if an object satisifies any of the target selection criteria, then the
**	target bit in its status bit mask is also set.  Optionally, if matching
**	to either the FIRST, ROSAT, and/or USNO catalogs was requested via
**	tunable	parameters, then the FIRST, ROSAT, and/or USNO information
**	fields are reset (the matching is done before selecting targets).
**	If a single object is passed in, then likewise will be done for that
**	single object regardless of whether or not it is a primary or
**	secondary object.  Targets will be selected only for those
**	criterion for which the tunable parameters are specified.
**	The target bit masks and the target bit in the status
**	bit mask are unset on entry.
**</HTML>
**</AUTO>
**============================================================================
*/
static char targetSelectCmd[] = "targetSelect";
static int targetSelectFlg = FTCL_ARGV_NO_LEFTOVERS;
static ftclArgvInfo targetSelectTbl[] = {
   {NULL, FTCL_ARGV_HELP, NULL, NULL,
    "Select spectroscopic targets from all primary and secondary objects in a chain of calibrated objects or for a single calibrated object\n"},
   {"<obj>", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to CHAIN of TA_CALIB_OBJ, or a single TA_CALIB_OBJ"},
   {"-galaxies", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to Galaxies tunable parameters (TA_GALAXIES_PARAMS"},
   {"-quasars", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to Quasars tunable parameters (TA_QUASARS_PARAMS"},
   {"-serendipity", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to Serendipity tunable parameters (TA_SERENDIPITY_PARAMS"},
   {"-rosat", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to ROSAT tunable parameters (TA_ROSAT_PARAMS"},
   {"-stars", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to Stars tunable parameters (TA_STARS_PARAMS"},
   {"-standards", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to Standards tunable parameters (TA_STANDARDS_PARAMS"},
   {"-first", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to FIRST catalog (TA_FIRST_CATALOG)"},
   {"-crosat", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to ROSAT catalog (TA_ROSAT_CATALOG)"},
   {"-usno", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to USNO catalog (TA_USNO_CATALOG)"},
   {"-diag", FTCL_ARGV_STRING, NULL, NULL,
    "Handle to running diagnsotics (TA_DIAG)"},
   {NULL, FTCL_ARGV_END, NULL, NULL, NULL}
};

static int
tclTargetSelect (ClientData clientData,
		 Tcl_Interp *interp,
		 int argc,
		 char **argv)
{
  char *objHandle = NULL;
  CHAIN *chain = NULL;
  TA_CALIB_OBJ *obj = NULL;
  TA_GALAXIES_PARAMS *galaxies = NULL;
  char *galaxiesHandle = NULL;
  TA_QUASARS_PARAMS *quasars = NULL;
  char *quasarsHandle = NULL;
  TA_SERENDIPITY_PARAMS *serendipity = NULL;
  char *serendipityHandle = NULL;
  TA_ROSAT_PARAMS *rosat = NULL;
  char *rosatHandle = NULL;
  TA_STARS_PARAMS *stars = NULL;
  char *starsHandle = NULL;
  TA_STANDARDS_PARAMS *standards = NULL;
  char *standardsHandle = NULL;
  char *firstCatHandle = NULL;
  TA_FIRST_CATALOG *firstCat = NULL;
  char *rosatCatHandle = NULL;
  TA_ROSAT_CATALOG *rosatCat = NULL;
  char *usnoCatHandle = NULL;
  TA_USNO_CATALOG *usnoCat = NULL;
  char *diagHandle = NULL;
  TA_DIAG *diag = NULL;
  int status;

  /* Parse the arguments */
  targetSelectTbl[1].dst = &objHandle;
  targetSelectTbl[2].dst = &galaxiesHandle;
  targetSelectTbl[3].dst = &quasarsHandle;
  targetSelectTbl[4].dst = &serendipityHandle;
  targetSelectTbl[5].dst = &rosatHandle;
  targetSelectTbl[6].dst = &starsHandle;
  targetSelectTbl[7].dst = &standardsHandle;
  targetSelectTbl[8].dst = &firstCatHandle;
  targetSelectTbl[9].dst = &rosatCatHandle;
  targetSelectTbl[10].dst = &usnoCatHandle;
  targetSelectTbl[11].dst = &diagHandle;
  if ((status = shTclParseArgv(interp, &argc, argv, targetSelectTbl,
			       targetSelectFlg,
			       targetSelectCmd))
      != FTCL_ARGV_SUCCESS)
    return status;
   
  /* Get handle to chain/object */
  if (shTclAddrGetFromName (interp, objHandle, (void **)&chain, "CHAIN")
      == TCL_OK)
    {
      /* Verify that chain is for TA_CALIB_OBJ */
      if (shChainTypeGet(chain) != shTypeGetFromName("TA_CALIB_OBJ"))
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": input CHAIN not of type TA_CALIB_OBJ", NULL);
	  return TCL_ERROR;
	}
    }
  else if (shTclAddrGetFromName (interp, objHandle, (void **)&obj,
				 "TA_CALIB_OBJ") != TCL_OK)
    {
      Tcl_AppendResult(interp, targetSelectCmd,
		       ": error getting handle to chain/obj", NULL);
      return TCL_ERROR;
    }
  
  /* Get handle for each specified set of tunable parameters */
  if (ftcl_ArgIsPresent(argc, argv, "-galaxies", targetSelectTbl) ==1)
    {
      /* Get handle to galaxies parameters */
      if (shTclAddrGetFromName (interp, galaxiesHandle, (void **)&galaxies,
				"TA_GALAXIES_PARAMS") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to galaxies params", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-quasars", targetSelectTbl) == 1)
    {
      /* Get handle to quasars parameters */
      if (shTclAddrGetFromName (interp, quasarsHandle, (void **)&quasars,
				"TA_QUASARS_PARAMS") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to quasars params", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc,argv,"-serendipity",targetSelectTbl)== 1)
    {
      /* Get handle to serendipity parameters */
      if (shTclAddrGetFromName (interp,serendipityHandle,(void **)&serendipity,
				"TA_SERENDIPITY_PARAMS") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to serendipity params",
			   NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc,argv,"-rosat",targetSelectTbl)== 1)
    {
      /* Get handle to rosat parameters */
      if (shTclAddrGetFromName (interp,rosatHandle,(void **)&rosat,
				"TA_ROSAT_PARAMS") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to rosat params",
			   NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-stars", targetSelectTbl) == 1)
    {
      /* Get handle to stars parameters */
      if (shTclAddrGetFromName (interp, starsHandle, (void **)&stars,
				"TA_STARS_PARAMS") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to stars params", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-standards", targetSelectTbl) == 1)
    {
      /* Get handle to stars parameters */
      if (shTclAddrGetFromName (interp, standardsHandle, (void **)&standards,
				"TA_STANDARDS_PARAMS") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to standards params", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-first", targetSelectTbl) == 1)
    {
      /* Get handle to FIRST catalog */
      if (shTclAddrGetFromName (interp, firstCatHandle, (void **)&firstCat,
				"TA_FIRST_CATALOG") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to FIRST catalog", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-crosat", targetSelectTbl) == 1)
    {
      /* Get handle to ROSAT catalog */
      if (shTclAddrGetFromName (interp, rosatCatHandle, (void **)&rosatCat,
				"TA_ROSAT_CATALOG") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to ROSAT catalog", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-usno", targetSelectTbl) == 1)
    {
      /* Get handle to USNO catalog */
      if (shTclAddrGetFromName (interp, usnoCatHandle, (void **)&usnoCat,
				"TA_USNO_CATALOG") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to USNO catalog", NULL);
	  return TCL_ERROR;
	}
    }
  if (ftcl_ArgIsPresent(argc, argv, "-diag", targetSelectTbl) == 1)
    {
      /* Get handle to diagnostics */
      if (shTclAddrGetFromName (interp, diagHandle, (void **)&diag,
				"TA_DIAG") != TCL_OK)
	{
	  Tcl_AppendResult(interp, targetSelectCmd,
			   ": error getting handle to diagnostics", NULL);
	  return TCL_ERROR;
	}
    }

  /* Select targets */
  if (obj != NULL)
    status = taTargetSelectFromObj(obj, galaxies, quasars, serendipity, rosat,
				   stars, standards, firstCat, rosatCat,
				   usnoCat);
  else
    status = taTargetSelectFromChain(chain, galaxies, quasars, serendipity,
				     rosat, stars, standards, firstCat,
				     rosatCat, usnoCat, diag);
  if (status != SH_SUCCESS)
    {
      shTclInterpAppendWithErrStack(interp);
      return TCL_ERROR;
    }

  /* Successful return */
  Tcl_SetResult(interp, "", TCL_VOLATILE);
  return TCL_OK;
}


/*****************************************************************************
 *
 * Declare my new tcl verbs to tcl
 */
void
taTclTargetDeclare(Tcl_Interp *interp) 
{
  char *tclHelpFacil = "ta";
  shTclDeclare(interp, targetSelectCmd,
	       (Tcl_CmdProc *)tclTargetSelect,
	       (ClientData) 0,	(Tcl_CmdDeleteProc *)NULL, tclHelpFacil,
	       shTclGetArgInfo(interp, targetSelectTbl, targetSelectFlg,
			       targetSelectCmd),
	       shTclGetUsage(interp, targetSelectTbl, targetSelectFlg,
			     targetSelectCmd));
}
