;+
; Project     : SOLAR-B - EIS
;
; Name        : EIS_CPT_OBSTBL
;
; Purpose     : Performs various processing options with the OBSTBL.
;
; Explanation : Finds best location to put table in OBSTBL and inserts table into OBSTBL.
;               For SEQUENCE tables allows links between sequences to be inserted and terminate command
;               parameter to be set. Calculates checksum to complete sequence table.
;
; Use         : < result = eis_cpt_obstbl ( table, table_index, time_for_reuse, description, $
;                            SEQUENCE=sequence, LINELIST=linelist, AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
;                            XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, STAMP=stamp, $
;                            EIS_EVENT=eis_event, PLACE=place, EXTRACT=extract, OUTPUT=output, $
;                            MSSL=mssl, INTEL=intel, LINK=link) >
;
; Inputs      : None.
;
; Opt. Inputs : table          : BYTARR[] for processing
;               table_index    : INT table index. May be undefined on input.
;               time_for_reuse : DOUBLE TAI time after which linelists may be reused.
;               description    : STRING description of table
;
; Outputs     : result      : INT flag :
;                              1 : processed science plan OK.
;                              0 : processing failed.
;               table_index : INT index table placed at.
;                              Undefined if no place found for table.
;
; Opt. Outputs: None.
;
; Keywords    : GET               : FLAG indicating should read in OBSTBL or return individual OBSTBL table
;               REFRESH           : FLAG indicating should refresh OBSTBL
;               EXTRACT           : FLAG indicating should extract table from OBSTBL.
;               CHECK             : FLAG indicating should check table.
;               PLACE             : FLAG indicating that should find location for table in OBSTBL
;               EXACT             : FLAG indicating that should check if there is an exact table match in OBSTBL
;                                   If defined on input table_index specifies a single table that should be checked.
;                                   On output table_index gives the table index if an exact match found else -1.
;               USED              : INT indicating should look in 'inuse = used' tables also.
;               SET               : FLAG indicating that should write table to OBSTBL.
;               RESPONSE          : FLAG indicating that table is used in response study.
;               TERMINATE         : FLAG indicating that table defined by table_index terminates
;               LINK              : INT containing table index which links to this sequence.
;               FIRST             : INT flag indicating sequence table first in study (for use with LINK).
;               LAST              : INT flag indicating sequence table last  in study (for use with LINK).
;               OUTPUT            : FLAG indicating should output OBSTBL
;               SEQUENCE          : FLAG indicating that processing a sequence or LONARR[] list of sequences
;               LINELIST          : FLAG indicating that processing a linelist or LONARR[] list of linelists
;               AEC_EXPOSURE      : FLAG indicating that processing an AEC exposure table
;               AEC_TABLE         : FLAG indicating that processing an AEC control table
;               XRT_FLARE         : FLAG indicating that processing an XRT flare trigger  control table
;               EIS_FLARE         : FLAG indicating that processing an EIS flare trigger  control table
;               EIS_EVENT         : FLAG indicating that processing an EIS event trigger  control table
;               STAMP             : STRING stamp indicating should stamp file names.
;               INTERNAL          : FLAG indicating that outputting to INTERNAL directory.
;               LATEST            : FLAG indicating that outputting to LATEST directory.
;               RESET             : FLAG for use with get.
;               UPLOAD            : STRUCTURE of type EIS_upload.
;               ULBA              : UINT extended linear base address for OBSTBL (only used with EXTRACT)
;               TEXT              : STRARR[] returns decoded table in MSSL command mnemonic form.
;                                   Used with CHECK.
;               RASTERS           : INTARR[] indexes of raster commands returned
;                                   Used with CHECK (sequence table only).
;               MSSL              : INT Flag indicating should produce individual ASCII files for each sequence table
;                                   and line list table in MSSL command mnemonic form.
;                                        0 : no output
;                                        1 : outputs new tables
;                                        2 : outputs all tables
;               INTEL             : INT Flag indicating should produce individual Intel hex files for each sequence table
;                                   and line list table.
;                                        0 : no output
;                                        1 : outputs new tables
;                                        2 : outputs all tables;
;               DIFFERENCE        : FLAG indicating should calculate difference of OBSTBL with previous OBSTBL.
;
; Calls       : None.
;
; Common      : EIS_CPT_obstbl_block
;
; Restrictions: None.
;
; Side effects: May output ASCII files.
;
; Category    : EIS_CPT.
;
; Prev. Hist. : None.
;
; Written     : Martin Carter RAL 01/02/05
;
; Modified    : Version 0.1, 07/02/05
;                 Renamed eis cpt get obstbl, eis cpt refresh obstbl, eis cpt output obstbl.
;                 Added AEC exposure table etc.
;               Version 0.2, 01/03/05, MKC
;                 Renamed the AEC and event tags.
;                 Added PLACE keyword back in.
;                 Changed TIMESTAMP flag to string containing time.
;                 Moved indexes to !EIS_CPT_CONSTANTS.
;               Version 0.3, 02/04/05, MKC
;                 Added EXTRACT keyword.
;                 Used eis cpt obstbl place.
;               Version 0.4, 28/04/05, MKC
;                 Added ULBA keyword.
;                 Rearranged order of processing keywords.
;                 Changed use of !EIS_CPT_CONSTANTS.
;               Version 0.5, 12/05/05, MKC
;                 Rearranged processing order.
;                 Changed INDEX keyword to LINK.
;                 Added CHECK, TEXT, RASTERS keywords.
;                 Changed error message if get fails.
;               Version 0.6, 14/07/05, MKC
;                 Added INTEL and MSSL and ALL keywords to print out tables as intel hex.
;               Version 0.7, 16/09/05, MKC
;                 Changed sense of LINK keyword so that refers to previous table rather than following table.
;                 Added EXACT keyword.
;                 Added SET keyword.
;                 Added USED keyword.
;               Version 0.8, 04/10/05, MKC
;                 Added UPLOAD_TIME keyword.
;                 Changed so that if no place found then sets table_index to -1.
;               Version 0.9, 14/06/06, MKC
;                 Used EIS_upload structure.
;               Version 1.0, 16/06/06, MKC
;                 Changed so that if no place found then table_index is undefined.
;                 Changed so that table_index is undefined or valid on input.
;               Version 1.1, 14/07/06, MKC
;                 Updated OBSTL_MAP link info.
;                 Added FIRST and LAST keywords.
;                 Added TERMINATE keyword.
;               Version 1.2, 21/08/06, MKC
;                 Changed error message.
;               Version 1.3, 23/09/06, MKC
;                 Keep copy of previous obstbl in common block.
;                 Added keyword DIFFERENCE.
;                 Removed keyword ALL.
;               Version 1.4, 03/10/06, MKC
;                 Changed TIMESTAMP keyword to STAMP.
;               Version 1.5, 01/07/08, MKC
;                 Added INTERNAL keyword.
;               Version 1.6, 01/10/08, MKC
;                 Added LATEST keyword.
;               Version 1.7, 05/05/11, MKC
;                 Added STAMP keyword to eis cpt obstbl ascii.
;
; Version     : 1.7, 05/05/11
;-
;**********************************************************

FUNCTION eis_cpt_obstbl, table, table_index, time_for_reuse, description, $
                         GET=get, REFRESH=refresh, EXTRACT=extract, CHECK=check, $
                         PLACE=place, USED=used, EXACT=exact, SET=set, RESPONSE=response, $
                         LINK=link, FIRST=first, LAST=last, TERMINATE=terminate, $
                         OUTPUT=output, SEQUENCE=sequence, LINELIST=linelist, $
                         AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
                         XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, $
                         EIS_EVENT=eis_event, $
                         STAMP=stamp, INTERNAL=internal, LATEST=latest, RESET=reset, DIFFERENCE=difference, $
                         UPLOAD=upload, ULBA=ulba, TEXT=text, RASTERS=rasters, MSSL=mssl, INTEL=intel

  ; common block used for storing the EIS_CPT obstbl data
  ;   obstbl     : STRUCTURE of type EIS_CPT_OBSTBL.

  COMMON EIS_CPT_obstbl_block, obstbl, previous_obstbl

  ; check if get obstbl table required

  IF KEYWORD_SET(get) THEN BEGIN

    ; read in current OBSTBL

    IF NOT eis_cpt_obstbl_get(obstbl, RESET=reset) THEN BEGIN

      eis_cpt_message, 'UNABLE TO RETRIEVE OBSTBL map or OBSTBL - to initialize use RESET'

      GOTO, error

    ENDIF

    ; get copy of previous obstbl

    previous_obstbl = obstbl

  ENDIF

  ; check if refresh required
  ; after get

  IF KEYWORD_SET(refresh) THEN BEGIN

    ; NB upload need not be defined

    eis_cpt_obstbl_refresh, obstbl, upload

  ENDIF

  ; check if extract required
  ; before check

  IF KEYWORD_SET(extract) THEN BEGIN

    ; check table index set

    IF N_ELEMENTS(table_index) EQ 0 THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; set up ULBA

    ulba = obstbl.ulba

    IF NOT eis_cpt_obstbl_extract(obstbl, table_index, table, time_for_reuse, description, $
                         SEQUENCE=sequence, LINELIST=linelist, $
                         AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
                         XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, $
                         EIS_EVENT=eis_event ) THEN GOTO, error

  ENDIF

  ; check table
  ; table may be passed as argument for checking or extracted from OBSTBL
  ; table may be generated within eis_cpt or read from Intel Hex file
  ; table may be 0 if no valid table in extract
  ; [0] is not a valid table anyway but keyword_set([0])=0 under 6.2

  IF KEYWORD_SET(check) AND KEYWORD_SET(table) THEN BEGIN

    ; table index may be undefined if table is read from Intel hex file

    ; set up some preliminary info for output

    IF KEYWORD_SET(description) THEN $
      text = '# ' + description $
    ELSE $
      text = '# NO DESCRIPTION'

    ; add time for reuse

    IF KEYWORD_SET(time_for_reuse) THEN $
      eis_cpt_add, text, '# EXPIRY TIME : '+ anytim2cal(time_for_reuse) $
    ELSE $
      eis_cpt_add, text, '# NO EXPIRY TIME'

    eis_cpt_add, text, ''

    IF NOT eis_cpt_check_table( table, table_index, SEQUENCE=sequence, LINELIST=linelist, $
                         AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
                         XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, $
                         EIS_EVENT=eis_event, TEXT=text, RASTERS=rasters) THEN BEGIN

      eis_cpt_message, 'WARNING, CHECK FAILURE FOR TABLE'

      IF N_ELEMENTS(table_index) GT 0 THEN eis_cpt_message, '   TABLE INDEX : '+eis_cpt_strtrim(FIX(table_index))

      GOTO, error

    ENDIF

  ENDIF

  ; check if place table required
  ; after CHECK

  IF KEYWORD_SET(place) THEN BEGIN

    IF NOT eis_cpt_obstbl_place ( obstbl, table, table_index, $
                                  SEQUENCE=sequence, LINELIST=linelist, $
                                  AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
                                  XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, $
                                  EIS_EVENT=eis_event, USED=used, EXACT=exact) THEN GOTO, error

  ENDIF

  ; check if set table required
  ; after PLACE

  IF KEYWORD_SET(set) THEN BEGIN

    ; check table index set

    IF N_ELEMENTS(table_index) EQ 0 THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; set table

    IF NOT eis_cpt_obstbl_set ( obstbl, table_index, table, time_for_reuse, description, $
                         SEQUENCE=sequence, LINELIST=linelist, $
                         AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
                         XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, $
                         EIS_EVENT=eis_event, RESPONSE=response) THEN GOTO, error

  ENDIF

  ; finish off a previous sequence table by adding terminate to this table

  IF KEYWORD_SET(terminate) THEN BEGIN

    ; check that is sequence table

    IF NOT KEYWORD_SET(sequence) THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; check table index set

    IF N_ELEMENTS(table_index) EQ 0 THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; set up position in obstbl of the current sequence table

    IF NOT eis_cpt_obstbl_index(table_index, index, max_length, number, /SEQUENCE) THEN GOTO, error

    ; insert this table index and checksum into current sequence table

    st = index

    en = st + obstbl.data[st]

    obstbl.data[en-2] = BYTE(table_index)

    obstbl.data[en-1] = eis_cpt_checksum(obstbl.data[st:en-2],/XXOR)

    ; update obstbl map link info

    obstbl.map.sequences[table_index].link = -1

    ; update first and last flags

    obstbl.map.sequences[table_index].first = first

    obstbl.map.sequences[table_index].last  = last

  ENDIF

  ; finish off a previous sequence table by adding link to this table
  ; NB link can be zero
  ; NB LINK must be performed after PLACE so that table index is defined.
  ; NB link gives the table which links to the table defined by table_index
  ; if link = table_index then table links to itself

  IF N_ELEMENTS(link) NE 0 THEN BEGIN

    ; check that is sequence table

    IF NOT KEYWORD_SET(sequence) THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; check table index set

    IF N_ELEMENTS(table_index) EQ 0 THEN MESSAGE, 'IMPLEMENTATION ERROR'

    ; set up position in obstbl of the previous sequence table

    IF NOT eis_cpt_obstbl_index(link, index, max_length, number, /SEQUENCE) THEN GOTO, error

    ; insert this table index and checksum into previous sequence table

    st = index

    en = st + obstbl.data[st]

    obstbl.data[en-2] = BYTE(table_index)

    obstbl.data[en-1] = eis_cpt_checksum(obstbl.data[st:en-2],/XXOR)

    ; update obstbl map link info
    ; NB table_index = link for infinite repeat

    obstbl.map.sequences[link].link = table_index

    ; update first and last flags

    obstbl.map.sequences[link].first = first

    obstbl.map.sequences[link].last  = last

  ENDIF

  ; check if OBSTBL hex OUTPUT required
  ; NB perform after GET

  IF KEYWORD_SET(output) THEN BEGIN

    IF NOT KEYWORD_SET(eis_cpt_obstbl_output(obstbl, STAMP=stamp, INTERNAL=internal, LATEST=latest)) THEN GOTO, error

  ENDIF

  ; check if INTEL or MSSL output required

  IF KEYWORD_SET(intel) OR KEYWORD_SET(mssl) THEN BEGIN

    IF NOT eis_cpt_obstbl_ascii( MSSL=mssl, INTEL=intel, STAMP=stamp, SEQUENCE=sequence, LINELIST=linelist, $
                                 AEC_EXPOSURE=aec_exposure, AEC_TABLE=aec_table, $
                                 XRT_FLARE=xrt_flare, EIS_FLARE=eis_flare, EIS_EVENT=eis_event) THEN GOTO, error

  ENDIF

  ; check if OBSTBL differences required

  IF KEYWORD_SET(difference) THEN BEGIN

    IF NOT KEYWORD_SET(previous_obstbl) THEN GOTO, error

    difference = eis_cpt_table_difference(obstbl.data,previous_obstbl.data)

  ENDIF

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END





