;+
; Project     : SOLAR-B - EIS
;
; Name        : EIS_CPT_TABLE_PLACE
;
; Purpose     : Finds best place to put a table in OBSTBL.
;
; Explanation : Goes through all of the available locations in OBSTBL using the
;               minimum number of byte differences with the table to be placed as the criterion
;               for determining the best place to put it.
;               For sequence tables, it is difficult to determine the TERM_SEQ or CALL_SEQ argument
;               before the table indexes are known. This argument and the checksum are omitted from
;               the byte difference comparison. This means that exact matches cannot be verified
;               for sequence tables.
;
;               Ensures that uses used table in preference to unused table if looking for exact match.
;
;               If table index defined on entry then checks whether that table gives an exact match.
;
; Use         : <  result = eis_cpt_table_place (obstbl, indexes, used, table, table_index, SEQUENCE=sequence) >
;
; Inputs      : obstbl  : BYTARR[] OBSTBL data
;               indexes : LONARR[n] indexes of tables to be searched in OBSTBL data
;               inuse   : INTARR[n] flag indicating whether table in use
;               table   : BYTARR[] table data
;
; Opt. Inputs : table_index : INT index into indexes of table specifying one table to search
;                             If undefined then does full search of tables.
;
; Outputs     : result      : INT flag :
;                               1 : processed science plan OK.
;                               0 : processing failed.
;               table_index : INT index into indexes of table
;                             Not defined if no place found for table
;
; Opt. Outputs: None.
;
; Keywords    : SEQUENCE          : FLAG indicating table is a sequence table.
;               LINELIST          : FLAG indicating that processing a linelist
;               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
;               EXACT             : FLAG indicating should look for exact match when doing full search in unused tables
;                                   NB with proviso about last two bytes in sequence table
;               USED              : INT indicating should look in 'inuse = used' tables also.
;
; Calls       : None.
;
; Common      : None.
;
; Restrictions: None.
;
; Side effects: May output ASCII files.
;
; Category    : EIS_CPT.
;
; Prev. Hist. : None.
;
; Written     : Martin Carter RAL 11/11/04
;
; Modified    : Version 0.1, 15/11/04, MKC
;                 Changed so that can reuse tables.
;               Version 0.2, 25/01/05, MKC
;                 Added SEQUENCE keyword.
;                 Corrected logic.
;                 Tightened up use of WHERE.
;               Version 0.3, 22/03/05, MKC
;                 Added table type to error messages.
;               Version 0.4, 17/09/05
;                 Removed restriction that only looks for exact matches for linelist tables.
;                 Use routine eis cpt table difference.
;                 Added EXACT and USED keywords.
;                 Changed so that returns table index as an argument.
;                 Changed so that if table index defined on input then only
;                 looks at specified table.
;                 Renamed from eis cpt place table
;                 Split into two routines.
;               Version 0.5, 04/10/05, MKC
;                 Added control table keywords.
;                 Changed so that if no place found then sets table_index to -1.
;                 Allowed table_index = -1 on input.
;               Version 0.6, 16/06/06, MKC
;                 Changed so that table_index is undefined if no match found.
;                 Simplified behaviour if table index set on entry.
;               Version 0.7, 07/10/11, MKC
;                 Changed warning messages when OBSTBL table already in use.
;
; Version     : 0.7, 07/10/11
;-
;**********************************************************

FUNCTION eis_cpt_table_place, obstbl, indexes, inuse, 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

  ; set up STRING type for use in error messages

  IF KEYWORD_SET(sequence) THEN type = 'SEQUENCE' ELSE $
  IF KEYWORD_SET(linelist) THEN type = 'LINELIST' ELSE $
  IF KEYWORD_SET(aec_exposure) THEN type = 'AEC EXPOSURE' ELSE $
  IF KEYWORD_SET(aec_table) THEN type = 'AEC_TABLE' ELSE $
  IF KEYWORD_SET(xrt_flare) THEN type = 'XRT FLARE' ELSE $
  IF KEYWORD_SET(eis_flare) THEN type = 'EIS FLARE' ELSE $
  IF KEYWORD_SET(eis_event) THEN type = 'EIS EVENT' ELSE $
    MESSAGE, 'IMPLEMENTATION ERROR'

  ; get length of table

  IF KEYWORD_SET(sequence) OR KEYWORD_SET(linelist) THEN BEGIN

    ; variable length tables

    length = table[0]

    IF length EQ 0 THEN BEGIN

      eis_cpt_message, 'INVALID '+ type + ' TABLE'

      GOTO, error

    ENDIF

    ; if sequence table then do not use the last two bytes in comparison
    ; i.e checksum and linked sequence index or sequence index

    IF KEYWORD_SET(sequence) THEN length = length - 2

  ENDIF ELSE BEGIN

    ; fixed length tables

    length = N_ELEMENTS(table)

  ENDELSE

  ; check if table_index specified
  ; if table index is specified then want to know if there is an exact match or not
  ; regardless of whether the table is used or not
  ; if no exact match found then returns table index as undefined but no error set

  IF N_ELEMENTS(table_index) NE 0 THEN BEGIN

    index = eis_cpt_table_search (obstbl, indexes, [table_index], table[0:length-1], /EXACT)

    ; if match found then set table_index else undefine table_index

    IF index GE 0 THEN table_index = index ELSE eis_cpt_undefine, table_index

    ; in the case where the table index is specified, if no match is found then return value is
    ; still OK (in contrast to when full search of tables is performed when return value is NOT OK).

    RETURN, 1

  ENDIF

  ; do full search

  ; check if used table exists which is exact match to current table

  IF KEYWORD_SET(used) THEN BEGIN

    ; get list of used (and available) tables

    list = WHERE(inuse EQ used)

    ; check if any exact matches

    index = eis_cpt_table_search (obstbl, indexes, list, table[0:length-1], /EXACT)

    ; if match found then set table_index and return

    IF index GE 0 THEN BEGIN

      table_index = index

      RETURN, 1

    ENDIF

  ENDIF

  ; get list of unused tables
  ; if only one table to check and in use then must be used by previous plan
  ; since cannot plan cannot contain two control tables of same type

  list = WHERE(inuse EQ 0, count)

  IF count EQ 0 THEN BEGIN

    IF N_ELEMENTS(inuse) GT 1 THEN BEGIN

      eis_cpt_message, 'ALL '+ type + ' TABLES IN USE BY CURRENT OR PREVIOUS PLAN'

      eis_cpt_message, 'TRY RECONFIGURING CURRENT PLAN WITH FEWER STUDIES OR RASTERS'

    ENDIF ELSE BEGIN

      eis_cpt_message, type + ' TABLE STILL IN USE BY PREVIOUS PLAN'

      eis_cpt_message, 'USE CONTROL TABLE RESET IF CERTAIN THAT TABLE CAN BE SAFELY OVERWRITTEN'

    ENDELSE

    ; put this message at end so that sensible message returned in !ERROR_STATE.MSG

    eis_cpt_message, 'ERROR, INSUFFICIENT SPACE IN OBSTBL FOR TABLE OF TYPE : '+ type

    GOTO, error

  ENDIF

  ; check if any matches

  index = eis_cpt_table_search (obstbl, indexes, list, table[0:length-1], EXACT=exact)

  ; if match found then set table_index

  IF index GE 0 THEN table_index = index

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END





