;+
; PROJECT
;           SolarB/Hinode EIS
;
; NAME
;           eis_response_obj__define
;
; PURPOSE
;           Class definition of response parameters
;
; CATEGORY
;           EIS Timeline Planning
;           Database
;
; NOTE
;           1.
;
; INPUTS
;           tlc      - timeline container of entries
;           triggers - list of trigger structures
;
; WRITTEN
;           John A Rainnie RAL 01-Feb-2010
;
; HISTORY
;           v0.1 JAR 25-Oct-2010
;                Updated to include eis_flare
;           v0.2 JAR 03-Dec-2014
;                Modified method "::eis_get_control", in line with XRTF
;
;-
;______________________________________________________________________________
FUNCTION eis_response_obj::Init , tlc , triggers

Self.tlc      = tlc
Self.triggers = PTR_NEW(triggers)

RETURN , 1

END
;______________________________________________________________________________
;
;______________________________________________________________________________
PRO eis_response_obj::setProperty , ll = ll

IF (N_ELEMENTS(ll)          GT 0) THEN Self.ll           = ll

END
;______________________________________________________________________________
;
;______________________________________________________________________________
PRO eis_response_obj::getProperty , ll = ll

stop
ll = Self.ll

END
;______________________________________________________________________________
; Cleanup
;______________________________________________________________________________
PRO eis_response_obj::Cleanup

PTR_FREE , Self.triggers

END
;______________________________________________________________________________
; Start here
;______________________________________________________________________________
FUNCTION eis_response_obj::get_eis_control

; Get eis_control structure
eis_control       = {eis_control_details}

; Divide trigger studies up into event type
eebp_list = WHERE(STRLOWCASE((*Self.triggers)[*].type) EQ 'eebp',eebp_count)
eisf_list = WHERE(STRLOWCASE((*Self.triggers)[*].type) EQ 'eisf',eisf_count)
xrtf_list = WHERE(STRLOWCASE((*Self.triggers)[*].type) EQ 'xrtf',xrtf_count)
aece_list = WHERE(STRLOWCASE((*Self.triggers)[*].type) EQ 'aece',aece_count)

; Now, if any of these event types are present, then update eis_control
; If more than 1 trigger type exists, just grab the first instance.
; EIS_EVENT
IF (eebp_count GE 1) THEN BEGIN

   trigger   = (*Self.triggers)[eebp_list[0]]
   struct    = eis_event_control_initialize(trigger , Self.tlc)
   eis_control.eis_event_control = struct

ENDIF
; EIS FLARE
IF (eisf_count GE 1) THEN BEGIN

   trigger   = (*Self.triggers)[eisf_list[0]]
   ; 03-Dec-2014 JAR
   ; Don't need to input "Self.tlc" anymore. Get all parameters from
   ; response DB. Genius!
   struct    = eis_flare_control_initialize(trigger) ; , Self.tlc)
   eis_control.eis_flare_control = struct

ENDIF
; XRT FLARE
IF (xrtf_count GE 1) THEN BEGIN

   trigger   = (*Self.triggers)[xrtf_list[0]]
   ; 26-Jun-2013 JAR
   ; Don't need to input "Self.tlc" anymore. Get all parameters from
   ; response DB. Genius!
   struct    = eis_xrt_flare_control_initialize(trigger) ; , Self.tlc)
   eis_control.xrt_flare_control = struct

ENDIF

RETURN , eis_control

END
;______________________________________________________________________________
; Start here
;______________________________________________________________________________
FUNCTION eis_response_obj::check_is_valid

valid = 1B
num_triggers = N_ELEMENTS(*Self.triggers)

print,'*************************************************'
print,STRJOIN(['Checking'                                            ,     $
               STRCOMPRESS(num_triggers,/REMOVE_ALL)                 ,     $
               'Trigger/Response Studies....'],' ',/SINGLE)
print,''

;Self.tlc->getProperty , eis_timeline_container = tlc

; OK, where do we start?
FOR i = 0 , num_triggers - 1 DO BEGIN
   trigger = (*Self.triggers)[i]
   valid   = Self->check_number_is_valid(trigger.seq_id,'seq_id',/NONZERO)
   IF (valid NE 1) THEN RETURN , 0
   temp = Self.tlc->get( position = trigger.tlc_position)
   tl   = temp->get()

   CASE STRLOWCASE(trigger.type) OF
       'eebp' : valid = Self->check_eebp_trigger(trigger , tl)
       'eisf' : valid = Self->check_eisf_trigger(trigger , tl)
       'xrtf' : valid = Self->check_xrtf_trigger(trigger , tl)
       ;'aece' : valid = Self->check_aece_trigger(trigger , tl)
       ELSE   : valid = 0
   ENDCASE
   line = STRJOIN(['  '                                              ,     $
                  STRCOMPRESS(i+1,/REMOVE_ALL)                       ,     $
                  '->'                                               ,     $
                  trigger.type                                       ,     $
                  'Trigger on TL seq_id'                             ,     $
                  STRCOMPRESS(trigger.seq_id,/REMOVE_ALL)            ,     $
                  'is '],' ',/SINGLE)
   IF (valid NE 1) THEN BEGIN
       status = 'NOT VALID'
       print,STRJOIN([line,status],/SINGLE)
       RETURN , 0
   ENDIF ELSE BEGIN
       status = 'OK'
       print,STRJOIN([line,status],/SINGLE)
   ENDELSE

ENDFOR

; Check for duplicates. If found, then check they are all the same
print,''
print,'   Checking for duplicate tables...'

; Check for more than 1 instance of a trigger type
trigger_type_list = (*Self.triggers)[*].type
unique_type_list  = trigger_type_list[UNIQ(trigger_type_list)]
FOR i = 0 , N_ELEMENTS(unique_type_list) -1 DO BEGIN
   list = WHERE(STRLOWCASE(trigger_type_list)    EQ                        $
                STRLOWCASE(unique_type_list[i]) , count)
   IF (count GT 1) THEN BEGIN
       ; OK, we have more than 1 table of this event type. Are they
       ; the same values - they must be since only 1 table is allowed.
       ; If not, complain and bail out!
       CASE STRLOWCASE(unique_type_list[i]) OF
           'eebp' : valid = Self->eis_event_props_same(list)
           'eisf' : valid = Self->eis_flare_props_same(list)
           'xrtf' : valid = Self->eis_xrt_flare_props_same(list)
           ELSE   : stop
       ENDCASE

       IF (valid EQ 1) THEN BEGIN
       ENDIF ELSE BEGIN
           print,'                                 ... bad news'
           RETURN , 0
       ENDELSE
   ENDIF
ENDFOR
print,'     ... confirm one instance of each table.'

RETURN , valid

END
;______________________________________________________________________________
; Non-zero
;______________________________________________________________________________
FUNCTION eis_response_obj::eis_event_props_same , list

triggers = (*Self.triggers)[list]
n_struct = REPLICATE({eis_event_component},N_ELEMENTS(list))
FOR i = 0 , N_ELEMENTS(list) -1 DO BEGIN
   trigger = triggers[i]
   temp    = Self.tlc->get( position = trigger.tlc_position)
   tl      = temp->get()
   ; Get sra_index
   st_id = tl.science_component.eis_event_response.response_study_id
   ra_id = tl.science_component.eis_event_response.repoint_raster_index

   ; Get studyRaster index
   status = eis_open_db(/STUDY)
   filter = STRJOIN(['ID=',STRCOMPRESS(st_id,/REMOVE_ALL)],/SINGLE)
   entry  = dbfind(filter , /SILENT , count = count)
   st     = db_read_study_entry(entry[0])
   sra_id = st.studyRasters[*].ra_id
   index  = WHERE(ra_id EQ sra_id , count)
   IF (count LE 0) THEN BEGIN
       print,"Error: Can't locate the selected studyRaster"
       RETURN , 0
   ENDIF
   n_struct[i] = Self.tlc->eis_event_component(tl , index[0])
ENDFOR

same = eis_event_props_same(n_struct)
IF (same[0].valid NE 1) THEN print,same[0].mText

RETURN , same[0].valid

END
;______________________________________________________________________________
; XRT Flare
;______________________________________________________________________________
FUNCTION eis_response_obj::eis_xrt_flare_props_same , list

; Get XRT Flare triggers
triggers = (*Self.triggers)[list]
; Now check all the values are identical
same = eis_xrt_flare_props_same(triggers)
IF (same[0].valid NE 1) THEN print,TRANSPOSE(same[0].mText)

RETURN , same[0].valid

END
;______________________________________________________________________________
; EIS Flare
;______________________________________________________________________________
FUNCTION eis_response_obj::eis_flare_props_same , list

; Get EIS Flare triggers
triggers = (*Self.triggers)[list]
; Now check all the values are identical
same = eis_flare_props_same(triggers)
IF (same[0].valid NE 1) THEN print,TRANSPOSE(same[0].mText)

RETURN , same[0].valid

END
;______________________________________________________________________________
; Non-zero
;______________________________________________________________________________
FUNCTION eis_response_obj::check_xrtf_trigger , trigger , tl

valid = 1

tc    = tl.time_component
sc    = tl.science_component
flag  = tc.respond_to_xrt_flare
; Check eis_event flag is TL is unity
valid = Self->check_number_is_valid(flag,'tc.respond_to_xrt_flare',/UNITY)
IF (valid NE 1) THEN RETURN , 0
; Check response study is non-zero, and actually exists
; Get values from response DB.
resp_id  = sc.xrt_flare_response.response_study_id
response = db_read_response_entry(id = resp_id)
st_id    = response.response_st_id
label    = 'response.response_st_id'
valid    = Self->check_response_study(st_id , label)
IF (valid NE 1) THEN RETURN , 0
; Actually, filler study ID is allowed to be zero!!!!!!
; Check filler study is non-zero, and actually exists
st_id = response.filler_st_id
label = 'sc.xrt_flare_response.follow_on_study_id'
IF (st_id NE 0) THEN BEGIN
   valid = Self->check_response_study(st_id , label , /FILLER)
   IF (valid NE 1) THEN RETURN , 0
ENDIF
; Check response raster is non-zero, and actually exists
ra_id = response.raster_identifier
label = 'response.raster_identifier'
valid = Self->check_response_raster(ra_id,label)
IF (valid NE 1) THEN RETURN , 0

; Check also - x0, y0, including limits (-4095 to 4095)
x0 = response.locate_x
label = 'response.locate_x'
valid = Self->check_number_is_valid(x0,label,/x0y0)
y0 = response.locate_y
label = 'response.locate_y'
valid = Self->check_number_is_valid(y0,label,/x0y0)

RETURN , valid

END
;______________________________________________________________________________
; Non-zero
;______________________________________________________________________________
FUNCTION eis_response_obj::check_eisf_trigger , trigger , tl

valid = 1

tc    = tl.time_component
sc    = tl.science_component
flag  = tc.respond_to_eis_flare
; Check eis_event flag is TL is unity
valid = Self->check_number_is_valid(flag,'tc.respond_to_eis_flare',/UNITY)
IF (valid NE 1) THEN RETURN , 0
; Check response study is non-zero, and actually exists
; Get values from response DB.
resp_id  = sc.eis_flare_response.response_study_id
response = db_read_response_entry(id = resp_id)
st_id    = response.response_st_id
label    = 'response.response_st_id'
valid    = Self->check_response_study(st_id , label)
IF (valid NE 1) THEN RETURN , 0
; Check response raster is non-zero, and actually exists
ra_id = response.raster_identifier
label = 'response.raster_identifier'
valid = Self->check_response_raster(ra_id,label)
IF (valid NE 1) THEN RETURN , 0

; X Threshold
x_threshold = response.x_threshold
label = 'response.x_threshold'
valid = Self->check_number_is_valid(x_threshold,label,/NONZERO)
IF (valid NE 1) THEN RETURN , 0
; Y Threshold
y_threshold = response.y_threshold
label = 'response.y_threshold'
valid = Self->check_number_is_valid(y_threshold,label,/NONZERO)
IF (valid NE 1) THEN RETURN , 0

; X/Y Min Limit - don't need checks - used widget sliders
; X/Y Locate    - don't need checks - binary flag

RETURN , valid

END
;______________________________________________________________________________
; Non-zero
;______________________________________________________________________________
FUNCTION eis_response_obj::check_eebp_trigger , trigger , tl

valid = 1

tc    = tl.time_component
sc    = tl.science_component
flag  = tc.respond_to_eis_event
; Check eis_event flag is TL is unity
valid = Self->check_number_is_valid(flag,'tc.respond_to_eis_event',/UNITY)
IF (valid NE 1) THEN RETURN , 0
; Check response study is non-zero, and actually exists
st_id = tl.science_component.eis_event_response.response_study_id
label = 'sc.eis_event_response.response_study_id'
valid = Self->check_response_study(st_id , label)
IF (valid NE 1) THEN RETURN , 0
; Check response raster is non-zero, and actually exists
ra_id = tl.science_component.eis_event_response.repoint_raster_index
label = 'sc.eis_event_response.repoint_raster_index'
valid = Self->check_response_raster(ra_id,label)
IF (valid NE 1) THEN RETURN , 0

; Now then, which studyRaster contains our response info? Huh?
index = WHERE(TOTAL(sc.studyRasters[*].eis_event_props.event_flag) EQ 1,count)
IF (count LE 0) THEN BEGIN
   print,"Error: Can't locate the selected studyRaster"
   RETURN , 0
ENDIF

; OK, now we have the appropriate studyRaster
sra = sc.studyRasters[index[0]]
; X Threshold
x_threshold = sra.eis_event_props.x_pixel_threshold
label = 'sra.eis_event_props.x_pixel_threshold'
valid = Self->check_number_is_valid(x_threshold,label,/NONZERO)
IF (valid NE 1) THEN RETURN , 0
; Y Threshold
y_threshold = sra.eis_event_props.y_pixel_threshold
label = 'sra.eis_event_props.y_pixel_threshold'
valid = Self->check_number_is_valid(y_threshold,label,/NONZERO)
IF (valid NE 1) THEN RETURN , 0

; X/Y Min Limit - don't need checks - used widget sliders

RETURN , valid

END
;______________________________________________________________________________
; Check Response Study
;______________________________________________________________________________
FUNCTION eis_response_obj::check_response_study , id , label , filler = filler

valid = 1
IF (KEYWORD_SET(filler) EQ 1) THEN type = 'Filler' ELSE type = 'Response'

; Check ID is nonzero
valid = Self->check_number_is_valid(id,label,/NONZERO)
IF (valid NE 1) THEN BEGIN
   print,STRJOIN(['Error: ',type,' Study ID is NOT valid'],/SINGLE)
   RETURN , 0
ENDIF

; OK, check it's in the study database
status = eis_open_db(/STUDY)
filter = STRJOIN(['ID=',STRCOMPRESS(id,/REMOVE_ALL)],/SINGLE)
entry  = dbfind(filter , /SILENT , count = count)
IF (count NE 1) THEN BEGIN
   print,STRJOIN(['Error: ',type,' Study ID not found'],/SINGLE)
   RETURN , 0
ENDIF

RETURN , valid

END
;______________________________________________________________________________
; Check Response Study
;______________________________________________________________________________
FUNCTION eis_response_obj::check_response_raster , id , label

valid = 1
valid = Self->check_number_is_valid(id,label,/NONZERO)
IF (valid NE 1) THEN BEGIN
   print,'Error: Response Raster ID is NOT valid'
   RETURN , 0
ENDIF

; OK, check it's in the study database
status = eis_open_db(/RASTER)
filter = STRJOIN(['ID=',STRCOMPRESS(id,/REMOVE)],/SINGLE)
entry  = dbfind(filter , /SILENT , count = count)
IF (count NE 1) THEN BEGIN
   print,'Error: Response Raster ID not found'
   RETURN , 0
ENDIF

RETURN , valid

END
;______________________________________________________________________________
; Non-zero
;______________________________________________________________________________
FUNCTION eis_response_obj::check_number_is_valid , number , label    ,     $
                                  nonzero = nonzero                  ,     $
                                  unity   = unity                    ,     $
                                  x0y0    = x0y0

valid = 1

IF KEYWORD_SET(x0y0) THEN BEGIN

   lower_limit = -4095
   upper_limit = 4095
   IF (number LT lower_limit) OR                                         $
      (number GT upper_limit) THEN BEGIN
       valid = 0
       print,STRJOIN(['Error: ',label,' is  out of range'],/SINGLE)
       RETURN , valid
   ENDIF
ENDIF
IF KEYWORD_SET(nonzero) THEN BEGIN
   IF (number LE 0) THEN BEGIN
       valid = 0
       print,STRJOIN(['Error: ',label,' is zero'],/SINGLE)
       RETURN , valid
   ENDIF
ENDIF
IF KEYWORD_SET(unity) THEN BEGIN
   IF (number NE 1) THEN BEGIN
       valid = 0
       print,STRJOIN(['Error: ',label,' is NOT unity'],/SINGLE)
       RETURN , valid
   ENDIF
ENDIF

RETURN , valid

END
;______________________________________________________________________________
PRO eis_response_obj__define
;______________________________________________________________________________

junk =  {eis_response_obj                                            ,     $
                   tlc                 : OBJ_NEW()                   ,     $
                   triggers            : PTR_NEW()                         $
        }

END
