;+
; NAME:
;       EIS_PLAN__DEFINE
;
; PURPOSE:
;       The eis_plan object is the general superclass for plan
;       class objects used by the Hansteen/Wikstøl QL/data analysis
;       SW. The plan object contains data that is aqcuired from 
;       an instruments planning tool. These data should be found 
;       in the main header unit (HDU) of the fits-files 
;
;       For a specific instrument, a new class must be defined
;       (i.e. eis_plan__define.pro for SOLAR-B EIS instrument). This class
;       inherits the eis_plan superclass. The plan class must
;       provide a read-routine for reading the specific plan
;       (i.e. eis_plan__read.pro).
;
;
; CATEGORY:
;       Hansteen/Wikstol Data analysis SW
;
; CALLING SEQUENCE:
;
;
; INPUTS:
;      None
;
; KEYWORD PARAMETERS:
;
;
; OUTPUTS:
;       Objects of class EIS_PLAN includes the following parameters:
;
; CALLS:
;
;      eis_get_sequence_details
;      eis_get_study_details
;      eis_get_line_list_details
;      eis_get_raster_details
;
; COMMON BLOCKS:
;
;
; PROCEDURE:
;       Defines the structure of plan class objects. If no filename 
;       is given as input, the FITS keywords are set by 
;       the init-procedure. If filename is given (plan or as-run
;       file), it is read from that file by eis_plan__read.pro
;
; RESTRICTIONS:
;
;
; MODIFICATION HISTORY:
;       28-Nov-2002: Oivind Wikstol  - First draft
;       13-Jan-2003: Oivind Wikstol  - Modifications to the init and
;                                      read methods. Add line_id to
;                                      the data structure
;       12-Apr-2005: Oivind Wikstol  - Added read method. 
;                                      Changed object definitions and almost 
;                                      completely re-written because of access
;                                      to planning tool data. 
;       August 2006: Oivind Wikstol  - Almost completely re-written to work with 
;                                      new planning tool
;       20-Nov-2006: Viggo H/        - Small clean up and last dry run test
;                    John Rainnie      at ISAS.                                      
;       23-Nov-2006: Viggo Hansteen  - Added method for reading/finding whether there 
;                                      is SAA or HLZ during the observation
;       10-Feb-2007: Viggo Hasnteen  - Added help methods.
;       15-Mar-2007: Viggo Hansteen/ - Bug fix in getsaa
;                    Matthew Whillock/
;                    John Rainnie    
;        4-Jul-2008: A. Gardini      - Added HELP and INIT_EIS_PLAN_METHODS.
;
; $Id: eis_plan__define.pro 4173 2014-09-17 15:31:24Z viggoh $
;-
;;; mcrw 20140808
pro eis_plan::debug_msg, msg, seq_id, rast_id
  !quiet=0
  message, msg + 'SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
  !quiet=1
end

function eis_plan::init, seq_id, rast_id
  self->init_eis_plan_methods ; initialization of the help method
  self.help=obj_new('hw_help')
  self.telescop = 'Hinode'
  self.instrume = 'EIS'
  ;; 20130220 mcrw
  self->debug_msg, '', seq_id, rast_id
;  !quiet=0
;  message, 'SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;  !quiet=1
  if n_params() lt 1 then begin
    ; no planning information found, using defaults
    self->default
  endif else begin
    self->default
    self->read, seq_id, rast_id
  endelse
  return,1
end

pro eis_plan::cleanup
  obj_destroy,self.help
end


pro eis_plan::display_all,init=init
  if n_elements(init) eq 1 then return
  self.help->display_all
  return
end

pro eis_plan::display_methods,init=init
  if n_elements(init) eq 1 then return
  self.help->display_methods
  return
end

pro eis_plan::read, seq_id, rast_id,init=init
  if n_elements(init) eq 1 then return
  if n_params() lt 2 then begin
    !quiet=0
    message,'SEQ_ID or RAST_ID missing. Using default planning values.',/info
    !quiet=1
    self-> default
    return
  endif

  ; 20130220 mcrw
;  message, 'read SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info

; make sure seq_id is long:
  seq_id = long(seq_id)

  zdbase = fix_zdbase(/USER) 

; get sequence structure based on seq_id
  if seq_id lt 5 then begin
;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
     self->debug_msg, 'HUNTER, ', seq_id, rast_id
;    !quiet=0
;    message, 'HUNTER, SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;    !quiet=1
    self.tl_id_hunter = self.tl_id
    seq = eis_get_science_entry(seq_id) ; should add response keyword
  endif else begin
;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
     self->debug_msg, 'NON-HUNTER1, ', seq_id, rast_id
;    !quiet=0
;    message, 'NON-HUNTER1, SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;    !quiet=1
    seq = eis_get_science_entry(seq_id)
;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
    self->debug_msg, 'NON-HUNTER2, ', seq_id, rast_id
;    !quiet=0
;    message, 'NON-HUNTER2, SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;    !quiet=1
  endelse

  if n_tags(seq) eq 0 then begin
    !quiet=0
    message,'Could not find sequence '+string(seq_id)+' in database.',/info
    message,'Using default planning values',/info
    !quiet=1
;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
    self->debug_msg, 'NO PLAN, ', seq_id, rast_id
;    message, 'NO PLAN, SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;    !quiet=1
    self-> default
    return
  endif

;;; mcrw 20140808 - if the planner does not make the target to be
;;;                 'Engineering' then the reformatter will crash 
;;;                 trying to fill the raster details
  if (strtrim(seq.target,2) EQ 'Engineering') THEN BEGIN
;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
     self->debug_msg, 'Target is ENG, ', seq_id, rast_id
;    !quiet=0
;    message, 'Target ENG, SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;    !quiet=1
    rast_id = 0
  ;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
    self->debug_msg, 'ENG, ', seq_id, rast_id
;    !quiet=0
;    message, 'ENG, SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;    !quiet=1
    self->default
  endif
  
;;; mcrw 20140808 - workaround to detect engineering rasters in case
;;;                 target has been changed in the plan
  change_raster_id = 0
  case rast_id of
     49271L : change_raster_id = 1 ; C077
     49266L : change_raster_id = 1 ; C072
     49265L : change_raster_id = 1 ; C071
     else :
  endcase
  if change_raster_id eq 1 then begin
     self->debug_msg, 'ENG (BAD TARGET), ', seq_id, rast_id
;     !quiet=0
;     message, 'ENG (BAD TARGET), SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;     !quiet=1
     rast_id = 0
  end

;;; mcrw 20130219 - 20130209 plan crash. Is seq_id out of range?
  self->debug_msg, 'Updating plan values: ', seq_id, rast_id
;  !quiet=0
;  message, 'Updating plan values: SEQ_ID is '+strtrim(string(seq_id),2)+', RAST_ID is '+strtrim(string(rast_id),2),/info
;  !quiet=1

  self.tl_id = seq_id
  self.observer = seq.observer
  self.planner = seq.planner 
  self.tohban = seq.tohbans[0]
  self.noaa_num = seq.target_id 
  self.sci_obj = seq.sci_obj
  self.obs_dec = seq.obs_dec
;  self.eis_sci = seq.eis_science
  self.solb_sci = seq.solarb_science
  self.obstitle = seq.obstitle
  self.join_sb = seq.join_sb
  self.obs_id = seq.obs_id
  self.jop_id = seq.jop_id
  zdbase = fix_zdbase(/EIS)

  ; get study ID and study details based on seq_id
  study_id = seq.study_id
  st = db_read_study_entry(study_id)
  self.study_id = study_id
  self.study_acr = st.acronym
  self.study_auth = st.author
  self.target = st.target
  self.datatype = st.category
  
  if (rast_id NE 0) then begin
;;; mcrw 20140806 - 20140726 plan crash. Is seq_id out of range?
;;; Also self.rast_id is not set if rast_id eq 0...
     self->debug_msg, 'Rast id ne 0, updating raster values: ', seq_id, rast_id
;     !quiet=0
;     message, 'Rast id ne 0, updating raster values', /info
;     !quiet=1
    ; get raster structure from rast_id:
      rast = db_read_raster_entry(rast_id)
      self.rast_id = rast_id
      self.rast_acr = rast.acronym
  ; of up to 8 exposures times, pick the first
      exposures = rast.exposures
      self.exptime = exposures[0]
      self.ll_id = rast.ll_id
      nlines = rast.nwindows

; get line list info:
;;; mcrw 20140806 - 20140726 plan crash. Is seq_id out of range?
      self->debug_msg, 'Getting linelist(s) for raster: ', seq_id, rast_id
;      !quiet=0
;      message, 'Getting linelist(s) for raster', /info
;      !quiet=1
      ll = db_read_linelist_entry(self.ll_id)
      self.ll_acr = ll.acronym
      for i = 0,nlines -1 do begin
          linfo = ll.lines[i]
          self.line_id[i] = strjoin([linfo.name, $
                                     strcompress(linfo.wavelength/100., /remove_all)], ' ', /single) 
          self.line_wvl = linfo.wavelength/100.
      endfor
  endif
end

pro eis_plan::default,init=init
  if n_elements(init) eq 1 then return
    nwin=n_elements(self.line_id)
    for i=0, nwin-1 do self.line_id[i] = 'Line '+strtrim(string(i),2)
    self.rast_acr = 'NA'
    self.study_acr = 'NA'
    self.study_auth = 'NA'
    self.obstitle = 'NA'
    self.obs_dec = 'NA'
    self.solb_sci = 'NA'
    self.eis_sci = 'NA'
    self.observer = 'NA'
    self.planner = 'NA'
    self.tohban = 'NA'
    self.target = 'NA'
    self.sci_obj = 'NA'
    self.obs_dec = 'NA'
    self.join_sb = 'NA'
    self.obs_id = -1
    self.jop_id = -1
    self.noaa_num = -1
    self.study_id = -1
    self.datatype = 'NA'
    self.ll_id = -1
    self.ll_acr = 'NA'        
    self.saa = 'NA'
    self.hlz = 'NA'
  return
end

pro eis_plan::getsaa,start_ut_str,end_ut_str,init=init
  if n_elements(init) eq 1 then return
  start_tai=anytim2tai(start_ut_str)
  end_tai=anytim2tai(end_ut_str)
  dur_hr=(end_tai-start_tai)/3600.  
  obev=eis_read_orbit_events(start_tai,dur_hr)
;
  if n_tags(obev) eq 0 then return
; saa
  saa_bool=max(start_tai lt obev[*].start_time and $
               end_tai gt obev[*].start_time and   $
               stregex(obev[*].name,/fold_case,'saa',/boolean))
  saa_bool=max(start_tai ge obev[*].start_time and $
               start_tai le obev[*].stop_time and  $
               stregex(obev[*].name,/fold_case,'saa',/boolean)) or saa_bool
  if saa_bool then self.saa='IN' else self.saa='OUT'
; hlz
  hlz_bool=max(start_tai lt obev[*].start_time and $
               end_tai gt obev[*].start_time and   $
               stregex(obev[*].name,/fold_case,'hla',/boolean))
  hzl_bool=max(start_tai ge obev[*].start_time and $
               start_tai le obev[*].stop_time and  $
               stregex(obev[*].name,/fold_case,'hla',/boolean)) or hlz_bool
  if hlz_bool then self.hlz='IN' else self.hlz='OUT'
end

function eis_plan::get_tl_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.tl_id
end

function eis_plan::get_tl_id_hunter,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.tl_id_hunter
end

function eis_plan::get_telescop,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.telescop
end

function eis_plan::get_instrume,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.instrume
end

function eis_plan::get_rast_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.rast_id
end

function eis_plan::get_rast_acr,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.rast_acr
end

function eis_plan::get_study_acr,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.study_acr
end

function eis_plan::get_study_auth,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.study_auth
end

function eis_plan::get_obstitle,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.obstitle
end

function eis_plan::get_solb_sci,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.solb_sci
end

function eis_plan::get_eis_sci,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.eis_sci
end

function eis_plan::get_planner,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.planner
end

function eis_plan::get_tohban,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.tohban
end

function eis_plan::get_observer,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.observer
end

function eis_plan::get_target,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.target
end

function eis_plan::get_sci_obj,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.sci_obj
end

function eis_plan::get_join_sb,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.join_sb
end

function eis_plan::get_obs_dec,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.obs_dec
end

function eis_plan::get_obs_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.obs_id
end

function eis_plan::get_jop_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.jop_id
end

function eis_plan::get_noaa_num,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.noaa_num
end

function eis_plan::get_study_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.study_id
end

function eis_plan::get_datatype,init=init
  if n_elements(init) eq 1 then return, -1
  return,self.datatype
end

function eis_plan::get_ll_acr,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.ll_acr
end

function eis_plan::get_ll_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.ll_id
end

function eis_plan::get_line_id,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.line_id
end

function eis_plan::get_exptime,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.exptime
end

function eis_plan::get_line_wvl,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.line_wvl
end

function eis_plan::getsaa,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.saa
end

function eis_plan::gethlz,init=init
  if n_elements(init) eq 1 then return, -1
  return, self.hlz
end

pro eis_plan::help
  help,self,/obj
  return
end

pro eis_plan::init_eis_plan_methods

  self->display_all,/init
  self->display_methods,/init
  self->read,/init
  self->default,/init
  self->getsaa,/init
  a=self->get_tl_id(/init)
  a=self->get_tl_id_hunter(/init)
  a=self->get_telescop(/init)
  a=self->get_instrume(/init)
  a=self->get_rast_id(/init)
  a=self->get_rast_acr(/init)
  a=self->get_study_acr(/init)
  a=self->get_study_auth(/init)
  a=self->get_obstitle(/init)
  a=self->get_solb_sci(/init)
  a=self->get_eis_sci(/init)
  a=self->get_planner(/init)
  a=self->get_tohban(/init)
  a=self->get_observer(/init)
  a=self->get_target(/init)
  a=self->get_sci_obj(/init)
  a=self->get_join_sb(/init)
  a=self->get_obs_dec(/init)
  a=self->get_obs_id(/init)
  a=self->get_jop_id(/init)
  a=self->get_noaa_num(/init)
  a=self->get_study_id(/init)
  a=self->get_datatype(/init)
  a=self->get_ll_acr(/init)
  a=self->get_ll_id(/init)
  a=self->get_line_id(/init)
  a=self->get_exptime(/init)
  a=self->get_line_wvl(/init)
  a=self->getsaa(/init)
  a=self->gethlz(/init)

  return
end

pro eis_plan__define
  nwin = 25
  struct={eis_plan, $
          help:obj_new(), $
          telescop:' ', $
          instrume:' ', $
          rast_acr:' ', $
          study_acr:' ', $
          study_auth:' ', $
          obstitle:' ', $
          obs_dec: ' ', $
          solb_sci:' ', $
          eis_sci:' ', $
          observer:' ', $
          planner:' ', $
          tohban:' ', $
          target:' ', $
          sci_obj:' ', $
          join_sb:' ', $
          obs_id:0L, $
          jop_id:0, $
          noaa_num:-1L, $
          study_id:0L, $
          datatype:' ', $
          ll_acr:' ', $          
          line_id:strarr(nwin), $
          line_wvl:fltarr(nwin), $
          exptime:0.0, $
          ll_id:0L, $
          rast_id:0L, $
          saa:' ', $
          hlz:' ', $
          tl_id:0L, $
          tl_id_hunter:0L}
end
