;+
; Project     :	SOHO - CDS
;
; Name        :	CPT
;
; Purpose     :	Prepares the CDS command tables from the science, flag and alternative study databases.
;
; Explanation :	CPT interrogates the sci_details, sci_flag and sci_alt databases 
;               and produces the tables needed to implement the plan on the
;               CDS.
;               It maintains five databases :
;                 series_id, which relates the internal SERIES table IDs used on board
;                            the spacecraft to the IDs and parameters used in the science plan;
;                 raster_id, which relates the internal RASTER table IDs used on board
;                            the spacecraft to the IDs and parameters used in the science plan;
;                 dexwin_id, which relates the internal data extraction window table IDs used on board
;                            the spacecraft to the IDs and parameters used in the science plan;
;                 vdswin_id, which relates the internal VDS window table IDs used on board
;                            the spacecraft to the IDs and parameters used in the science plan;
;                 commprep,  which indicates which tables are currently 
;                            loaded on the CDS and where they are loaded.
;               The emergency study is loaded if the /EMERGENCY keyword is used.
;
;               CPT uses structure arrays to contain table information generated. 
;
;               SERIES structures have the tags :
;                    series.vs       = character string indicating the software version
;                                      of the code used to create the table.
;                    series.id       = integer planning database ID for the table.
;                    series.var      = integer planning database variation for the table.
;                    series.cdhsx    = the internal CDHS index where the table is loaded
;                    series.cdhsid   = the internal CDHS ID used to reference the table
;                    series.time     = the observation time of the study using the table
;                                      taken from the sci_details database
;                    series.ok       = an integer flag indicating whether table has already 
;                                      been loaded onto the CDS.
;                    series.reus     = a character indicating whether the table is re-usable 
;                                      or not .
;                    series.sft      = a character indicating whether solar feature tracking
;                                      is to be used. 
;                    series.istate   = structure giving the state at the start of the study
;                    series.fstate   = structure giving the state at the end   of the study
;                    series.nsubs    = integer giving the number of tables spanned by the
;                                      study.
;                    series.tt       = integer indicating whether study timetagged
;                    series.rpt      = character indicating whether series is to be repeated 
;                                      indefinitely.
;                    series.repn     = an integer indicating how many times the last RASTER is 
;                                      to be repeated and various IEF flags. 
;                    series.range    = integer giving the range from the home position that mirror
;                                      and slit adjustments can be made for pointing.
;                                      Outside of this OPS movements are used.
;                    series.dsolx    = deferred solar x pointing for study
;                    series.dsoly    = deferred solar y pointing for study
;                    series.flagst   = character indicating whether study is a flag study or not
;                    series.nextst   = cdhs id of following study
;
;               RASTER structures have the tags :
;                    raster.vs       = character string indicating the software version
;                                      of the code used to create the table.
;                    raster.id       = integer planning database ID for the table.
;                    raster.var      = integer planning database variation for the table.
;                    raster.cdhsx    = the internal CDHS index where the table is loaded
;                    raster.cdhsid   = the internal CDHS ID used to reference the table
;                    raster.time     = the observation time of the study using the table
;                                      taken from the sci_details database
;                    raster.ok       = an integer flag indicating whether table has already 
;                                      been loaded onto the CDS.
;                    raster.repn     = an integer indicating how many times the RASTER is 
;                                      to be repeated and various IEF flags. 
;                    raster.slitn    = integer giving the slit number to be used for the 
;                                      raster.
;                    raster.solx     = solar x pointing for raster
;                    raster.soly     = solar y pointing for raster
;                    raster.dexwid   = integer giving the internal CDHS ID for the data 
;                                      extraction table.
;                    raster.vdswid   = integer giving the internal CDHS ID for the VDS
;                                      windows table.
;                    raster.detector = character giving the detector used ie. 'N' or 'G'.
;                    raster.exptm    = integer giving the exposure time in units defined below
;                    raster.units    = integer giving the units of the exposure time
;                    raster.mirrorspan= mirror span of raster in mirror steps.
;                    raster.slitspan = slit span of raster in slit steps.
;                    raster.gis      = [4]INT array indicating which GIS detectors in use.
;
;               DEXWIN tables have the tags :
;                    dexwin.vs        = character string indicating the software version
;                                       of the code used to create the table.
;                    dexwin.id        = integer planning database ID for the table.
;                    dexwin.cdhsx     = the internal CDHS index where the table is loaded
;                    dexwin.cdhsid    = the internal CDHS ID used to reference the table
;                    dexwin.time      = the observation time of the study using the table
;                                       taken from the sci_details database
;                    dexwin.ok        = an integer flag indicating whether table has already 
;                                       been loaded onto the CDS.
;                    dexwin.version   = integer giving the version number of the VDS calibration parameters
;                    dexwin.gis       = flags indicating whether each GIS detector is used.
;
;               VDSWIN tables have the tags :
;                    vdswin.vs        = character string indicating the software version
;                                       of the code used to create the table.
;                    vdswin.id        = integer planning database ID for the table.
;                    vdswin.cdhsx     = the internal CDHS index where the table is loaded
;                    vdswin.cdhsid    = the internal CDHS ID used to reference the table
;                    vdswin.time      = the observation time of the study using the table
;                                       taken from the sci_details database
;                    vdswin.ok        = an integer flag indicating whether table has already 
;                                       been loaded onto the CDS.
;                    vdswin.version   = integer giving the version number of the VDS calibration parameters
;                    vdswin.iefid     = CDHS ID of IEF master
;
;               The structure  {state_structure} has the tags :
;                  .mode    : character indicating CDHS mode
;                                   'B' = Ready BOTH
;                                   'G' = Ready GIS      
;                                   'N' = Ready NIS     
;                                   'X' = Unknown.    
;                  .solarx  : integer giving solar x position (arcsecs)
;                  .solary  : integer giving solar y position (arcsecs)
;                  .slitn   : integer giving slit number      
;                  .gsetid  : integer giving GSET database ID                       
;               Assumes for now that mode is READY BOTH.
;
;               The calculation of how long OPS actuator or slit number movements take
;               depends on constant delay and rate per step parameters which are kept 
;               in the CDHS state database (and possibly home position parameter). 
;               The OPS and slit number movements are commanded explicitly within the 
;               series table created for a study. Slit and mirror movements are implicit
;               in the raster table set up for each raster within the study.
;
;               CPT calculates the delay for any OPS or slit number movement within a
;               study and inserts an appropriate wait period in the study. 
;               The calculation of how long the raster or study takes is irrelevant to
;               CPT. It simply uses the start time of the study from the science plan
;               and the study duration in the case of a repeated study.
;    
;               CPT does not assume at the top level that studies use only one detector.
;               This is assumed in wr_series_file at present.
;               Flag studies can only have one raster and thus use only one detector.
;               CPT does not assume at the top level that the flag study uses the same
;               detector as the study that kicks it off.
;               This is assumed in wr_series_file at present.
;
;               The emergency study Id and varition are obtained from the state database.
;               It must have fixed pointing.
;
;               /STATE :
;
;               CPT accepts a parameter which tells it the current CDHS mode, solar x and y
;               positions, slit number and GIS parameters else it assumes unknown positions which it 
;               gets from the CDHS state database. 
;               This is passed as a structure {state_structure}.                        
;               The CDHS mode is only used at present to indicate whether or not the initial state
;               of the instrument is known.      
;
;               On detection of any errors within the software the IDL MESSAGE function is used 
;               to pinpoint the error. Since this application is non-widget based ON_ERROR=0 is
;               used to return control to the IDL command line.
;
; Use         :	<cpt> Prepares the tables needed for the studies for the next science
;                     plan period which unless otherwise specified starts from 0:0:0 UTC on 
;                     the following day and lasts for 24 hours. 
;                     With options set the usage is :
;                     <cpt, startofperiod='2000-1-1',endofperiod='2000-1-2',/new, STATE=state>
;
; Inputs      :	None.
;
; Opt. Inputs : None.
;
; Outputs     : Produces a TTC file and LTB file and the various CVT files needed for the
;               science plan.
;
; Opt. Outputs:	None.
;
; Keywords    : STARTOFPERIOD = start time of CDS science plan period;
;               ENDOFPERIOD   = stop  time of CDS science plan period;
;               NOW   : set time of CDS science plan period from now to end of today.
;               NEW=1 : initialize commprep database also.
;                  =2 ; initialize local series_id and raster_id databases ;
;               STATE : set current state of CDS.
;               EMERGENCY : add emergency study 
;               ADJUST_ALLOWED : allow adjustment of mirror and slit positions to avoid 
;                                OPS movement if possible.  If set to 1 then only mirror
;                                movements are allowed for NIS rasters but if ADJUST_ALLOWED=2 
;                                then explicit movement of the slit is allowed for NIS rasters.
;                                This latter case is not meant for general user use.  Ask 
;                                operations staff for advice.
;		MAX_SLIT_POS :	 Use the number passed through this keyword as the maximum
;				 allowed slit position.  This value is used to offset GIS rasters
;				 in the N/S direction in such a way that they do not exceed 
;				 this value.
;
; Calls       :	list_detail, init_cp_db, fini_cp_db, getnextperiod, 
;               emergency_study, op_ltb_file, cpt_details, cpt_flags,
;               get_home_pos, wr_ttc_file, get_utc, utc2tai, anytim2cal.
;                
; Common      :	None.
;
; Restrictions:	None.
;
; Side effects:	None.
;
; Category    :	Command preparation.
;
; Prev. Hist. :	None.
;
; Written     :	Version 0.0, Martin Carter, RAL, 14/10/94
;
; Modified    :	Version 0.1, Martin Carter, RAL, 28/11/94
;                 Added comments.
;               Version 0.2, Martin Carter, RAL, 2/6/95
;                 Changed startofperiod input to wr_ltb_file and wr_ttc_file
;                 to UTC string format.
;               Version 0.3, MKC, RAL, 16/2/95
;                 removed option of non time-tagged studies.  
;                 Changed so that outputs study ID to series file.                        
;               Version 0.4, MKC, RAL, 2/3/95
;                 Updated so that deals with new raster and study repeats.
;                 Moved some fundamental parameters into tableID database.
;                 Removed chk_fund_raster. Changed raster.ntimes tag to .repn.
;                 Removed DEXWIN and VDSWIN tables from tableID
;                 database and used planning database IDs for these internally.
;                 Removed tags from dexwin and vdswin structures.
;               Version 0.5, MKC, RAL, 6/3/95
;                 Added NOW keyword.
;                 Added exptm and expunits tags to raster info.
;                 Added STATE keyword.
;               Version 0.6, MKC, RAL, 14/3/95
;                 Used NINT rather than FIX to convert reals.
;               Version 0.7, MKC, RAL, 21/3/95
;                 Re-incorporated var_rasters code.
;                 Incorporated series repeat number : n_repeat_s.
;                 Removed indeces store for series and rasters.
;               Version 0.8, MKC, RAL, 27/3/95
;                 Incorporated changes to databases : removed var_rasters.
;               Version 0.9, MKC, RAL, 18/4/95
;                 Used details structure as well as details_list structure since 
;                 need pointings.
;                 Split tableID database into three different databases.
;                 Split get_table_info into four different routines.
;                 Changed series and raster structure tags.
;                 Changed state tags to solarx and solary.
;                 Added deferred pointing logic.
;                 Modified calls to get_raster_info, wr_raster_file, get_dexwin_info, wr_dexwin_file,
;                 get_vdswin_info, wr_vdswin_file, get_series_info, wr_series_file.
;                 Changed use of state structure.
;               Version 1.0, MKC, RAL, 17/5/95
;                 Added time tagged flag back in.  
;                 Changed chk_fund_series to procedure.    
;                 Added initial and final state structures to series structure.
;                 Added slit and mirror positions to raster structure.
;                 Added check that slit number is within valid range.
;                 Initialized slitn in series structure in cpt.
;               Version 1.1, MKC, 24/5/95
;                 Added explicit wait to reach initial position in case of non time
;                 tagged study.
;               Version 1.2, MKC, 1/6/95
;                 Corrected bug to do with passing empty lists to wr_ltb_file and wr_ttc_file.
;               Version 1.3, CDP, 17/6/95
;                 Replaced calls to NINT by ROUND to avoid ssw conflicts.
;               Version 1.4, MKC, 1/8/95
;                 Fixed bug due to generation of multiple series tables for study.
;               Version 1.5, MKC, 10/8/95
;                 Added rpt tag to series structure to use for emergency series.
;                 Added call to emergency_study.
;                 Added set_exposure.
;               Version 1.6, MKC, 14/8/95
;                 Added more information.
;                 Added routine get_home_pos
;                 Modified state structure.
;               Version 1.7, MKC, 25/8/95
;                 Added VDS window offset to dexwin_details.wins from state database.
;                 Added call to get vds_state variable.
;               Version 1.8, MKC, 4/9/95
;                 Wrote out some more study info.   
;               Version 1.9, MKC, 25/9/95
;                 Added explicit call to ON_ERROR=0.              
;                 Modified so that always calls init_cp_db. 
;                 Now always deletes previous CVT files.
;                 Added call to routine fini_cp_db.
;               Version 2.0, MKC, 28/9/95
;                 Modified way increments table lists.
;               Version 2.1, MKC, 29.9.95
;                 Split off part of code into cpt_details.pro.
;                 Used named structures for table lists.
;                 Added flag studies and cpt_flags.pro.
;                 Split wr_ltb_file into op_ltb_file.
;                 Added .repn tag to series.
;               Version 2.2, MKC, 31/10/95
;                 Added /emergency keyword
;               Version 2.3, MKC, 2/11/95
;                 Added logic for flag repointing and changed emergency study
;                 logic slightly.
;               Version 2.4, MKC, 3/11/95
;                 Changed argument list for cpt_flags and flag study logic.
;               Version 2.5, MKC, 7/11/95
;                 Add mechanism for clearing out macro stores prior to load.
;                 Added gset_id to state structure.
;                 Removed .dur tag from SERIES_STRUCTURE.
;                 Added emergency to wr_ttc_file.
;               Version 2.6, 21/11/95
;                 Modified so that VDS_STATE is part of vdswin structure and vdswin_id
;                 database.
;               Version 2.7, 23/11/95
;                 Removed state from argument list for cpt_details.
;                 Put initial state into SERIES_STRUCTURE.
;               Version 2.8, 1/12/95
;                 Added range to series table structure.
;               Version 2.9, 5/12/95
;                 Changed to slitspan and mirrorspan.
;                 Added dsolx and dsoly tags to series structure.        
;               Version 3.0, 14/12/95
;                 Removed tags nsfs and pcdhsx from series structure because of reverse 
;                 processing.         
;               Version 3.1, 2/1/96
;                 Checked which GIS detectors in use.
;                 Added flag study tag to series structure.
;               Version 3.2, MKC, 29/1/96
;                 Added adjust_allowed keyword.
;               Version 3.3, MKC, 19/2/96
;                 Changed dexwin and vdswin structures. 
;                 Removed vds_state. Added use of dexwin_id database.
;               Version 3.4, MKC, 23/2/96
;                 removed a vds_state comment.
;               Version 3.5, MKC, 11/3/96
;                 Changed argument list to cpt_details.
;                 State now assumed to be unknown = 'X' initially.
;               Version 3.6, MKC, 29/3/96
;                 Changed some comments.
;               Version 3.7, MKC, 5/9/96
;                 Modified adjust_allowed comment.
;               Version 3.8, MKC, 3/10/96
;                 Added time of last time tagged study.
;                 Added solx, soly to raster structure.
;                 Put back a tag giving following study cdhs id.
;               Version 3.9, MKC, 12/12/96
;                 Fixed bug with emergency study structure.
;               Version 4.0, MKC, 18/2/97
;                 Added gis tag to dexwin.
;               Version 4.1, MKC, 24/2/97
;                 Added type tag to series structure.
;               Version 4.2, MKC, 21/4/97
;                 Removed type tag to series structure.
;               Version 5.0, MKC, 20/4/98
;                 Added sci-alt database studies.
;		Version 5.1, REY, 08/05/03
;		  Added the MAX_SLIT_POS keyword.
;	        Version 5.2, REY, 02/12/04
;		  Made corrections to cpt_details to cater for GIS slit and s/c roll.
;
; Version     :	Version 5.2, 02/12/04

;-
;**********************************************************

PRO cpt, STARTOFPERIOD=startofperiod, ENDOFPERIOD=endofperiod, NOW=now, STATE=initial_state, NEW=new, $
         EMERGENCY=emergency, ADJUST_ALLOWED=adjust_allowed, MAX_SLIT_POS = max_slit_pos

  ; Force the keyword max_slit_pos to a value of 15, no matter what value was passed to the 
  ; program.  This should be removed once XCPT implements the MAX_SLIT_POS keyword.

  max_slit_pos = 15

  ; set up treatment of errors to "hard".

  ON_ERROR, 0  

  PRINT, ''

  ; check if need to initialize state structure

  IF N_ELEMENTS(initial_state) EQ 0 THEN BEGIN

    PRINT, 'Assuming instrument in unknown start position'
    PRINT, ''

    initial_state = { state_structure, mode:'X', solarx:0, solary:0, slitn:0, gsetid:0}

  ENDIF ELSE IF TAG_NAMES(initial_state,/STRUCTURE_NAME) NE 'STATE_STRUCTURE' THEN $
                MESSAGE, 'Invalid state structure'
    
  ; get range parameter from CDHS state database

  ss = cp_get_entry ( 'RANGE', [0] ) 
   
  range = FIX(ss(0).active)

  ; set up named structures for derived table info
  ; this ensures structure names are defined within cpt_flags, cpt_details and cpt_alts
  ; NB they still have to be initialized inside routines 

  series_st = { SERIES_STRUCTURE, $
                vs : '', id : 0, var : 0, cdhsx : 0, cdhsid : 0, time : 0.0D0, ok : 0, $
                reus : '', sft : '', istate : initial_state, fstate : initial_state, nsubs : 0, tt : 0, $
                rpt : '' , repn : 0, range : 0, dsolx : 0, dsoly : 0, flagst : '', nextst : 0 }

  raster_st = { RASTER_STRUCTURE, $
                vs : '', id : 0, var : 0, cdhsx : 0, cdhsid : 0, time : 0.0D0, ok : 0, $
                repn : 0, sft : '', slitn : 0, solx : 0, soly : 0, dexwid : 0, vdswid : 0,   $
                detector : ' ', expunits : 0, exptm : 0, mirrorspan : 0, slitspan : 0, $
                gis : [0, 0, 0, 0] }

  dexwin_st = { DEXWIN_STRUCTURE, $
                vs : '', id : 0, cdhsx : 0, cdhsid : 0, time : 0.0D0, ok : 0, $
                version : 0, gis : INTARR(4)}

  vdswin_st = { VDSWIN_STRUCTURE, $
                vs : '', id : 0, cdhsx : 0, cdhsid : 0, time : 0.0D0, ok : 0, $
                version : 0, iefid : 0 }

  ; initialize CVT directory and CPT databases

  init_cp_db, new

  ; get next CDS period

  timeof = getnextperiod( STARTOFPERIOD=startofperiod, ENDOFPERIOD=endofperiod, NOW=now)

  PRINT, 'PERIOD = ',timeof
  PRINT, ''

  ; Get current utc time in internal format

  get_utc, utc
  ; utc = anytim2utc(startofperiod) ; fudge for testing

  ; Convert to TAI format

  tai = utc2tai ( utc )

  ; set up cut off time

  cut_off_time = tai - 24.0*3600.0     ; default

  ; get detailed studies within last 24 hours

  list_detail, tai - 24.0*3600.0, tai, details_list, ndetails

  IF ndetails GT 0 THEN BEGIN

    ; find last time tagged study

    list = WHERE ( details_list.time_tagged, count)

    IF count GT 0 THEN cut_off_time = details_list(list(count-1)).date_obs

  ENDIF

  ; print cut off time

  PRINT, 'PREVIOUS TIME TAGGED STUDY = ', anytim2cal(cut_off_time)
  PRINT, ''

  ; get detailed studies within next period

  list_detail, timeof.startofperiod, timeof.endofperiod, details_list, ndetails

  PRINT, 'NO. OF DETAILS STUDIES = ', STRTRIM ( ndetails, 1)
  PRINT, ''

  ; get alternative studies within period of interest

  list_alt, timeof.startofperiod, timeof.endofperiod, altplan_details, nalts

  PRINT, 'NO. OF ALTERNATIVE STUDIES = ', STRTRIM ( nalts, 1)
  PRINT, ''

  ; check if any studies to process

  IF ndetails EQ 0 AND nalts EQ 0 THEN BEGIN
    PRINT, 'No studies exist for next period'
    RETURN
  ENDIF

  ; get flag studies within period of interest

  list_flag, timeof.startofperiod, timeof.endofperiod, flag_details, nflags

  PRINT, 'NO. OF FLAG STUDIES = ', STRTRIM ( nflags, 1)
  PRINT, ''

  ; open LTB file

  op_ltb_file, ltb_unit, timeof.startofperiod, new GE 1

  ; process alternative studies

  IF nalts GT 0 THEN BEGIN

    ; produce tables for sci_alt studies 
    ; and get corresponding CDHS IDs and indeces

    cpt_alts, ltb_unit, altplan_details, cut_off_time

  ENDIF

  ; process sciplan studies

  IF ndetails GT 0 THEN BEGIN

    ; set up list of flag study IDs corresponding to detailed studies
    ; NB use fact that ID=0 not a valid ID 

    detail_flags = REPLICATE ( {cdhsid:0, cdhsx:0, repoint:0, pointing:'', detector:''}, ndetails )

    ; add emergency study to details list and add dummy flag study entry

    IF KEYWORD_SET(emergency) THEN BEGIN

      details_list = [ details_list, emergency_study ( details_list(ndetails-1) ) ]
      detail_flags = [ detail_flags, detail_flags(0)]
    
    ENDIF

    IF nflags GT 0 THEN BEGIN

      ; set up structure array

      flag_list = REPLICATE ( detail_flags(0), nflags )

      ; produce tables for sci_flags studies 
      ; and get corresponding CDHS IDs and indeces

      cpt_flags, ltb_unit, flags_details, range, flag_list, cut_off_time

      ; find flag studies corresponding to detailed studies
      ; loop through detailed studies
      ; omit emergency study from loop

      FOR stdyno = 0, ndetails-1 DO BEGIN

        flag_study_index = WHERE ( ( details_list(stdyno).date_obs GE flags_details.rcvr_start ) $
                               AND ( details_list(stdyno).date_obs LT flags_details.rcvr_stop  ), count )

        ; if flag study exists which overlaps detailed study then set up cdhs id and
        ; index and repoint tag else leave cdhs id as 0

        IF count EQ 1 THEN detail_flags(stdyno) = flag_list(flag_study_index(0)) ELSE $
          IF count GT 1 THEN MESSAGE, 'Study has multiple flag studies associated'

      ENDFOR

    ENDIF

    ; get tables for sci_details studies

    cpt_details, ltb_unit, details_list, detail_flags, initial_state.gsetid, range, series_list, cut_off_time, $
                 EMERGENCY=emergency, ADJUST_ALLOWED=adjust_allowed, MAX_SLIT_POS = max_slit_pos

  ENDIF

  ; close LTB file

  FREE_LUN, ltb_unit
  
  ; write out TTC file
  ; NB potentially the series_list may be empty

  wr_ttc_file, details_list, series_list, timeof.startofperiod, initial_state, EMERGENCY=emergency

  ; copy databases back to official directory

  fini_cp_db

END
