;+
; Project     : SOLAR-B - EIS
;
; Name        : EIS_CPT_orl_class__define
;
; Purpose     : Generates object EIS_CPT_orl_class.
;
; Explanation : EIS_CPT_orl_class
;
;               Tags are :-
;                   seqexec   : OBJECT of type EIS_CPT_seqexec
;                   op        : OBJECT of type EIS_CPT_commands
;                   og        : OBJECT of type EIS_CPT_og
;                   real      : OBJECT of type EIS_CPT_commands
;
;               Methods are :-
;                   init         : Initializes Objects.
;                        Use         : <res = self->init()>
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                   cleanup      : Destroys contained Objects.
;                        Use         : <self->cleanup>
;                   add          : Adds OP/OG/SEQEXEC/REAL sequence to the respective sequence store.
;                        Use         : <res = self->add(onboard_flag, time, command, int_parameter, str_parameter, description)>
;                        Inputs      : onboard_flag  : INT flag indicating whether sequence onboard or not.
;                                      time          : DOUBLE TAI time of sequence
;                                      command       : STRING sequence mnemonic.
;                                      int_parameter : INT parameter for sequence.
;                                      str_parameter : STRING parameter for sequence.
;                                      description   : STRING description of sequence.
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                        Keywords    : POINT         : STRING replacing time.
;                   seq_add      : Adds OP/OG/SEQEXEC/REAL sequence text to the respective sequence store.
;                        Use         : <res = self->seq_add(time, seq_name, description, sequence_text, $
;                                                       OP=op, OG=og, REAL=real, SEQEXEC=seqexec, POINT=point)>
;                        Inputs      : time          : DOUBLE TAI time of sequence
;                                      seq_name      : STRING sequence name.
;                                      description   : STRING description of sequence.
;                                      sequence_text : STRARR[] sequence commands.
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                        Keywords    : OP            : INT flag indicating OP sequence.
;                                      OG            : INT flag indicating OG sequence.
;                                      REAL          : INT flag indicating REAL sequence.
;                                      SEQEXEC       : INT flag indicating SEQEXEC sequence.
;                                      POINT         : STRING replacing time.
;                   manual      : Adds OP/OG/REAL manual mode command text.
;                        Use         : <res = self->manual(sequence_text, OP=op, OG=og, REAL=real)>
;                        Inputs      : sequence_text : STRARR[] sequence commands.
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                        Keywords    : OP            : INT flag indicating OP sequence.
;                                      OG            : INT flag indicating OG sequence.
;                                      REAL          : INT flag indicating REAL sequence.
;                   check        : Checks items in store valid.
;                                  Reorders SEQEXEC into time order.
;                        Use         : <res = self->check()>
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                   process      : Outputs items as text array.
;                        Use         : <res = self->process(text)>
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                                      text          : STRARR[] text from sequences.
;                        Keywords    : TEST          : INT flag indicating TEST output.
;                   output       : Outputs to ORL file.
;                        Use         : <res = self->output(STAMP=stamp)>
;                        Outputs     : res           : INT 1 or 0 indicating success or failure.
;                        Keywords    : STAMP         : STRING stamp for file.
;                                      TEST          : INT flag indicating TEST output.
;                                      LATEST        : INT flag indicating output to 'latest' directory.
;                   getTimes     : Gets times of sequences.
;                        Use         : <times = self->getTimes(OP=op, OG=og, REAL=real, SEQEXEC=seqexec)>
;                        Outputs     : times         : DBLARR[] TAI times or [-1] if no sequences.
;                        Keywords    : OP            : INT flag indicating OP sequence.
;                                      OG            : INT flag indicating OG sequence.
;                                      REAL          : INT flag indicating REAL sequence.
;                                      SEQEXEC       : INT flag indicating SEQEXEC sequence.
;                   getNames    : Gets names of sequences.
;                        Use         : <name = self->getNames( OP=op, OG=og, REAL=real, SEQEXEC=seqexec)>
;                        Outputs     : names         : STRARR[] sequence names.
;                        Keywords    : OP            : INT flag indicating OP sequence.
;                                      OG            : INT flag indicating OG sequence.
;                                      REAL          : INT flag indicating REAL sequence.
;                                      SEQEXEC       : INT flag indicating SEQEXEC sequence.
;                   getNumber   : Gets number of sequences.
;                        Use         : <num = self->getNumber( OP=op, OG=og, REAL=real, SEQEXEC=seqexec)>
;                        Outputs     : num           : LONG no. of sequences.
;                        Keywords    : OP            : INT flag indicating OP sequence.
;                                      OG            : INT flag indicating OG sequence.
;                                      REAL          : INT flag indicating REAL sequence.
;                                      SEQEXEC       : INT flag indicating SEQEXEC sequence.
;
; Use         : <dummy = {EIS_CPT_orl_class}>
;
; Inputs      : None.
;
; Opt. Inputs : None.
;
; Outputs     : Sets up class structure.
;
; Opt. Outputs: None.
;
; Keywords    : None,
;
; Calls       : None.
;
; Common      : None.
;
; Restrictions: None.
;
; Side effects: None.
;
; Category    : EIS_CPT.
;
; Prev. Hist. : None.
;
; Written     : Martin Carter RAL 08/03/05
;
; Modified    : Version 0.0, 08/03/05, MKC
;               Version 0.1, 24/03/05, MKC
;                 Added onboard tag.
;                 Renamed from eis cpt jside command define.
;               Version 0.2, 01/10/05, MKC
;                 Added OG number for command and exists tags.
;                 Added additional string parameter.
;               Version 0.3, 27/04/07, MKC
;                 Switched to OO version of command store.
;               Version 0.4, 15/05/07, MKC
;                 Changed eis sib cmd function.
;                 Removed individual indentation of commands.
;                 Added TEST keyword.
;               Version 0.5, 20/09/07, JAR
;                 Changed some of the output formatting.
;               Version 0.6, 27/02/08, MKC
;                 Added new EIS TBL upload procedure.
;                 Added POINT keyword to add method.
;               Version 0.7, 07/07/08, MKC
;                 Changed so that if orl file name blank then does not output.
;               Version 0.8, 01/10/08, MKC
;                 Added LATEST keyword to output method.
;               Version 0.9, 22/04/14, MKC
;                 Changed how fixed OG number specified.
;                 Removed keyword number from seq add method.
;                 Replaced with keyword FIXED in method og add.
;                 Keyword controlling fixed OG no longer accessible from external method call.
;                 Added extra commands to MANUAL sequence in REAL.
;
; Version     : 0.9, 22/04/14
;-
;**********************************************************

FUNCTION eis_cpt_orl_class::init

  self.seqexec = OBJ_NEW('eis_cpt_seqexec_class')

  self.op      = OBJ_NEW('eis_cpt_commands_class')

  self.og      = OBJ_NEW('eis_cpt_og_class')

  self.real    = OBJ_NEW('eis_cpt_commands_class')

  RETURN, 1

END

PRO eis_cpt_orl_class::cleanup

  ; clean up objects

  OBJ_DESTROY, self.seqexec

  OBJ_DESTROY, self.op

  OBJ_DESTROY, self.og

  OBJ_DESTROY, self.real

END

FUNCTION eis_cpt_orl_class::seq_add, time, seq_name, description, sequence_text, OP=op, OG=og, REAL=real, SEQEXEC=seqexec, POINT=point

  ; check which type of sequence

  IF KEYWORD_SET(seqexec) THEN BEGIN

    ; add to SEQEXEC store

    IF NOT self.seqexec->add( time, seq_name, description, POINT=point) THEN GOTO, error

  ENDIF ELSE IF KEYWORD_SET(op) THEN BEGIN

    ; add to OP store

    IF NOT self.op->add( time, seq_name, description, sequence_text, 'OP') THEN GOTO, error

  ENDIF ELSE IF KEYWORD_SET(og) THEN BEGIN

    ; add to OG store

    IF NOT self.og->add( time, seq_name, description, sequence_text) THEN GOTO, error

  ENDIF ELSE IF KEYWORD_SET(real) THEN BEGIN

    ; prepend comment to operator

    IF KEYWORD_SET(description) THEN eis_cpt_add, sequence_text, 'C.:"' + description + '";', /PRE

    ; add to REAL store

    IF NOT self.real->add( time, seq_name, description, sequence_text, 'REAL') THEN GOTO, error

  ENDIF ELSE BEGIN

    MESSAGE, 'IMPLEMENTATION ERROR'

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END


FUNCTION eis_cpt_orl_class::manual, sequence_text, OP=op, OG=og, REAL=real

  ; check which type of sequence

  IF KEYWORD_SET(op) THEN BEGIN

    ; add MANUAL MODE command to OP sequence

    eis_cpt_add, sequence_text, 'OG:' + 'EIS_FIXED_OG;'

    eis_cpt_add, sequence_text, 'INTERVAL:10;'

  ENDIF ELSE IF KEYWORD_SET(og) THEN BEGIN

    ; add FIXED manual OG
    ; will not be added if already present

    ; get SIB commands for OG

    IF NOT eis_cpt_jside_commands('FIXED', dummy, dummy, seq_name, command_text, dummy, /ONBOARD) THEN GOTO, error

    ; add fixed OG to store (whether or not used)
 
    IF NOT self.og->add( 0.0d0, seq_name+'_OG', 'FIXED MANUAL COMMAND', command_text, /FIXED) THEN GOTO, error

  ENDIF ELSE IF KEYWORD_SET(real) THEN BEGIN

    ;add manual command to REAL sequence

    ; prepend comment

    eis_cpt_add, sequence_text, 'C.:"Verify EIS in MANUAL mode";', /PRE

    ; generate MANUAL mode command

    IF NOT eis_cpt_sib('EIS_MODE_MANU',SIBCMD=sibcmd) THEN GOTO, error

    ; prepend command text for MANUAL mode command

    eis_cpt_add, sequence_text, sibcmd, /PRE

    ; prepend comment

    eis_cpt_add, sequence_text, 'C.:"Verify EIS_MODE_CHG_FLG is ENA";', /PRE

    ; generate mode change enable command

    IF NOT eis_cpt_sib('EIS_MODE_CHG_ENA',SIBCMD=sibcmd) THEN GOTO, error

    ; prepend command text for mode change enable command

    eis_cpt_add, sequence_text, sibcmd, /PRE

  ENDIF ELSE BEGIN

    MESSAGE, 'IMPLEMENTATION ERROR'

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::add, onboard_flag, time, command, int_parameter, str_parameter, description, POINT=point

  ; get SIB commands (OG or REAL)
  ; NB onboard_flag needed for MANUAL command

  IF NOT eis_cpt_jside_commands(command, int_parameter, str_parameter, seq_name, command_text, manual_flag, ONBOARD=onboard_flag) THEN GOTO, error

  ; check if onboard or not

  IF KEYWORD_SET(onboard_flag) THEN type = '_OP' ELSE type = '_REAL'

  ; add to SEQEXEC store

  IF NOT self->seq_add( time, seq_name+type, description, /SEQEXEC, POINT=point) THEN GOTO, error

  ; check if OP or REAL

  IF KEYWORD_SET(onboard_flag) THEN BEGIN

    ; generate OP sequence

    ; check if MANUAL MODE command required

    IF KEYWORD_SET(manual_flag) THEN BEGIN

      ; add lines to OP sequence

      IF NOT self->manual(op_text, /OP) THEN GOTO, error

      ; add FIXED manual OG if needed
      ; will not be added if already present

      IF NOT self->manual(dummy, /OG) THEN GOTO, error

    ENDIF

    eis_cpt_add, op_text, 'OG:' + seq_name + '_OG;'

    ; add to OP store

    IF NOT self->seq_add( time, seq_name+'_OP', description, op_text, /OP ) THEN GOTO, error

    ; add to OG store

    IF NOT self->seq_add( time, seq_name+'_OG', description, command_text, /OG ) THEN GOTO, error

  ENDIF ELSE BEGIN

    ; add manual commands

    IF KEYWORD_SET(manual_flag) THEN IF NOT self->manual(command_text, /REAL) THEN GOTO, error

    ; add to REAL store

    IF NOT self->seq_add( time, seq_name+'_REAL', description, command_text, /REAL) THEN GOTO, error

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::check

  ; check number of time tagged sequences

  IF self.seqexec->getNumber() GT 0 THEN BEGIN

    ; check SEQEXEC store

    IF NOT self.seqexec->check() THEN GOTO, error

    ; get seqexec names

    seq_names = self.seqexec->getNames()

    ; remove any duplicates

    seq_names = seq_names[SORT(seq_names)]

    seq_names = seq_names[UNIQ(seq_names)]

    ; check all sequences present in OP or REAL

    FOR k = 0, N_ELEMENTS(seq_names)-1 DO BEGIN

      IF self.op->chkName(seq_names[k])+self.real->chkName(seq_names[k]) NE 1 THEN BEGIN

        eis_cpt_message, 'ERROR, SEQEXEC NAME NOT IN OP OR REAL :'+seq_names[k], /INFORMATIONAL

        GOTO, error

      ENDIF

    ENDFOR

    ; check all OP/REAL sequences used

    IF N_ELEMENTS(seq_names) NE self.op->getNumber()+self.real->getNumber() THEN BEGIN

      eis_cpt_message, 'ERROR, UNUSED OP OR REAL SEQUENCES', /INFORMATIONAL

      GOTO, error

    ENDIF

    ; check OGs for OP and REAL sequences are present

    ; get text for OP and REAL sequences

    IF NOT self.real->process( text ) THEN GOTO, error

    IF NOT self.op->process( text ) THEN GOTO, error

    ; get list of OGs

    list = WHERE (STRCMP(text,'  OG:',5) NE 0, count)

    IF count GT 0 THEN BEGIN

      ; extract OG sequence names

      og_names = text[list]

      ; remove any duplicates

      og_names = og_names[SORT(og_names)]

      og_names = og_names[UNIQ(og_names)]

      lens = STRPOS(og_names,';')

      ; remove ';'

      FOR k= 0, N_ELEMENTS(og_names)-1 DO og_names[k] = STRMID(og_names[k], 5, lens[k]-5)

      ; check all sequences present in OG

      FOR k = 0, N_ELEMENTS(og_names)-1 DO BEGIN

        IF NOT self.og->chkName(og_names[k]) THEN BEGIN

          eis_cpt_message, 'ERROR, OG SEQUENCE NAME NOT IN OG :'+og_names[k], /INFORMATIONAL

          GOTO, error

        ENDIF

      ENDFOR

      ; check all OG sequences used

      IF N_ELEMENTS(og_names) NE self.og->getNumber() THEN BEGIN

        eis_cpt_message, 'ERROR, UNUSED OG SEQUENCES', /INFORMATIONAL

        GOTO, error

      ENDIF

    ENDIF ELSE BEGIN

      ; check no og sequences

      IF self.og->getNumber() GT 0 THEN BEGIN

        eis_cpt_message, 'ERROR, ORPHANED OG SEQUENCES', /INFORMATIONAL

        GOTO, error

      ENDIF

    ENDELSE

  ENDIF ELSE BEGIN

    ; check no other sequences

    IF self.op->getNumber() GT 0 OR self.real->getNumber() GT 0 OR self.og->getNumber() GT 0 THEN BEGIN

      eis_cpt_message, 'ERROR, ORPHANED REAL/OP/OG SEQUENCES', /INFORMATIONAL

      GOTO, error

    ENDIF

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::process, text, TEST=test

  ; initialize text

  text = ''

  ; add EIS start comment for operator

  eis_cpt_add, text, '/***********************************/'

  eis_cpt_add, text, '/*   EIS START                     */'

  eis_cpt_add, text, '/*   EIS_CPT version ' + eis_cpt_version() +' */'

  eis_cpt_add, text, '/***********************************/'

  eis_cpt_add, text, ''

  ; check if any sequences

  IF self.seqexec->getNumber() EQ 0 AND self.op->getNumber() EQ 0 AND self.og->getNumber() EQ 0 AND self.real->getNumber() EQ 0 THEN BEGIN

    ; no commands

    eis_cpt_add, text, '/* NO COMMANDS FOR THIS PLAN */'

  ENDIF ELSE BEGIN

    ; set up preset POINTs

    eis_cpt_add, text, '/* POINT definitions */'
    eis_cpt_add, text, ''

    eis_cpt_add, text, 'POINT-AT OP_START ~- 30 { POINT:TI_MODE_MANU_POINT ;}'

    eis_cpt_add, text, 'POINT-AT OP_START ~- 20 { POINT:TI_CHG_DIS_POINT ;}'

    eis_cpt_add, text, 'POINT-AT OP_START ~- 10 { POINT:TI_CHG_ENA_POINT ;}'

    eis_cpt_add, text, ''

    ; initialize SEQEXEC text

    eis_cpt_add, text, '/* Execution definitions */'
    eis_cpt_add, text, ''

    ; add SEQEXEC sequences
    ; doesn't need reordering since already done in check

    IF NOT self.seqexec->process( text) THEN GOTO, error

    ; check if test flag set

    IF KEYWORD_SET(test) THEN BEGIN

      ; comment out any EIS_LOAD_OBSTBL_REAL commands for test output
      ; START:2008/12/25.23:50:00 { SEQ:EIS_LOAD_OBSTBL_REAL ;}

      list = WHERE (STRPOS(text,'SEQ:EIS_LOAD_OBSTBL_REAL') GE 0, count)

      IF count GT 0 THEN text[list] = '/*'+text[list]+'*/'

    ENDIF

    ; initialize REAL text

    eis_cpt_add, text, '/*------------------------------------------*/'
    eis_cpt_add, text, '/* Real sequences */'
    eis_cpt_add, text, ''

    ; add REAL sequences

    IF NOT self.real->process( text, /REORDER) THEN GOTO, error

    ; initialize OP text

    eis_cpt_add, text, '/*------------------------------------------*/'
    eis_cpt_add, text, '/* OP sequences */'
    eis_cpt_add, text, ''

    ; add OP sequences

    IF NOT self.op->process( text, /REORDER) THEN GOTO, error

    ; initialize OG text

    eis_cpt_add, text, '/*------------------------------------------*/'
    eis_cpt_add, text, '/* OG sequences */'
    eis_cpt_add, text, ''

    ; add OG sequences

    IF NOT self.og->process( text, /REORDER) THEN GOTO, error

  ENDELSE

  ; add EIS stop comment for operator

  eis_cpt_add, text, ''

  eis_cpt_add, text, '/***********************************/'

  eis_cpt_add, text, '/*   EIS STOP                      */'

  eis_cpt_add, text, '/***********************************/'

  eis_cpt_add, text, ''

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::output, STAMP=stamp, TEST=test, LATEST=latest

  ; produce text for output

  IF NOT self->process( text, TEST=test) THEN GOTO, error

  ; get file for output

  IF KEYWORD_SET(latest) THEN $
    file = eis_cpt_file_name('ORL', STAMP=stamp, /LATEST) $
  ELSE $
    file = eis_cpt_file_name('ORL', STAMP=stamp)

  ; check file defined

  IF KEYWORD_SET(file) THEN BEGIN

    ; print info

    eis_cpt_message, 'ORL Commands file       : ' + file, /INFORMATIONAL

    ; write output data to ASCII file

    IF NOT KEYWORD_SET(eis_cpt_write_ascii(file, text)) THEN GOTO, error

  ENDIF

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::getTimes, OP=op, OG=og, REAL=real, SEQEXEC=seqexec

  ; check which type of sequence

  IF KEYWORD_SET(seqexec) THEN BEGIN

    ; return SEQEXEC store times

    RETURN, self.seqexec->getTimes()

  ENDIF ELSE IF KEYWORD_SET(op) THEN BEGIN

    ; return OP store times

    RETURN, self.op->getTimes()

  ENDIF ELSE IF KEYWORD_SET(og) THEN BEGIN

    ; return OG store times

    RETURN, self.og->getTimes()

  ENDIF ELSE IF KEYWORD_SET(real) THEN BEGIN

    ; return REAL store times

    RETURN, self.real->getTimes()

  ENDIF ELSE BEGIN

    MESSAGE, 'IMPLEMENTATION ERROR'

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::getNames, OP=op, OG=og, REAL=real, SEQEXEC=seqexec

  ; check which type of sequence

  IF KEYWORD_SET(seqexec) THEN BEGIN

    ; return SEQEXEC store times

    RETURN, self.seqexec->getNames()

  ENDIF ELSE IF KEYWORD_SET(op) THEN BEGIN

    ; return OP store times

    RETURN, self.op->getNames()

  ENDIF ELSE IF KEYWORD_SET(og) THEN BEGIN

    ; return OG store times

    RETURN, self.og->getNames()

  ENDIF ELSE IF KEYWORD_SET(real) THEN BEGIN

    ; return REAL store times

    RETURN, self.real->getNames()

  ENDIF ELSE BEGIN

    MESSAGE, 'IMPLEMENTATION ERROR'

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

FUNCTION eis_cpt_orl_class::getNumber, OP=op, OG=og, REAL=real, SEQEXEC=seqexec

  ; check which type of sequence

  IF KEYWORD_SET(seqexec) THEN BEGIN

    ; return SEQEXEC store times

    RETURN, self.seqexec->getNumber()

  ENDIF ELSE IF KEYWORD_SET(op) THEN BEGIN

    ; return OP store times

    RETURN, self.op->getNumber()

  ENDIF ELSE IF KEYWORD_SET(og) THEN BEGIN

    ; return OG store times

    RETURN, self.og->getNumber()

  ENDIF ELSE IF KEYWORD_SET(real) THEN BEGIN

    ; return REAL store times

    RETURN, self.real->getNumber()

  ENDIF ELSE BEGIN

    MESSAGE, 'IMPLEMENTATION ERROR'

  ENDELSE

  ; return finished OK flag

  RETURN, 1

error :

  ; issue routine name

  MESSAGE, 'ERROR', /INFORMATIONAL

  ; return error flag

  RETURN, 0

END

PRO eis_cpt_orl_class__define

  dummy = {eis_cpt_orl_class, seqexec:OBJ_NEW(), op:OBJ_NEW(), og:OBJ_NEW(), real:OBJ_NEW() }

END




