
function struct4event, feat_code, infil_params=infil_params, $
  buff=buff, list_features=list_features, help_struct=help_struct, $
  dbase=dbase

;+
;   Name:
;	struct4event
;   Purpose:
;	Create an empty IDL structure for a VOEvent.
;   Input Parameters:
;	feat_code - code of feature/event (feature name or feature code).  Currently recognized:
;
;       Feature Name      Feature Code
;       -----------       ------------
;       ActiveRegion      AR
;       BrightPoint       BP
;       CME               CE
;       CoronalDimming    CD
;       CoronalHole       CH
;       CoronalWave       CW
;       FilamentEruption  FE
;       Filament          FI
;       Flare             FL
;       Loop              LP
;       Oscillation       OS
;       SunSpot           SS
;	EmergingFlux	  EF
;
;   Keyword Parameters:
;	list_features - List all features and associated feature codes
;   Output:
;	IDL structure template for specified event type
;   Calling Examples:
;	evstruct = struct4event(/list)
;	evstruct = struct4event('SS')
;	evstruct = struct4event('SunSpot',infil='VOEvent_Spec.txt')
;	evstruct = struct4event('SunSpot',infil='VOEvent_Spec.txt',/help)
;       evstruct = struct4event('fl',/DBASE) use dbase for structures
;                                            (default for RUNTIME & VM)
;   Procedure:
;
;   History:
;	2007-03-06 (GLS)
;       2007-03-08 Karel Schrijver
;	2007-03-14 Mark Cheung
;       2007-03-15 S.L.Freeland - sswify w/environmentals, add /GET_LUN
;       2007-04-16 Mark Cheung - Removed hardcoding of feature/event
;                                types
;       2008-03-14 Mark Cheung - Added Reference_Names and
;                                Reference_Links (strarr) to structure
;       2008-03-18 Mark Cheung - Added Description field
;       2009-02-05 S.L.Freeland - add /DBASE option (for run-time/VM use)
;       2009-02-06 S.L.Freeland - auto-set DBASE if runtime or VM
;       2009-10-03 Mark Cheung  - Added Citations to structure
;       2010-05-10 S.L.Freeland - protect against undefined environmental
;
;   Restrictions:                                                                     
;       Requires Solarsoft to operate
;-       

usedbase=keyword_set(dbase) or get_logenv('ssw_noexecute') or $
   lmgr(/runtime) or lmgr(/vm)

if get_logenv('SSW_ONTOLOGY_DATA') eq '' then $
   set_logenv,'SSW_ONTOLOGY_DATA',concat_dir('$SSW_ONTOLOGY','data')
if usedbase then begin 
   dbname='struct4event_dbase.save'
   dbf=file_search(concat_dir(['HOME','SSW_ONTOLOGY_DATA'],dbname))
   retval=''
   box_message,'Using STRUCT4EVENT database'
   if n_elements(feat_code) eq 0 then feat_code="No event code supplied"
   if dbf(0) eq '' then box_message,'No struct4event dbase found...' else begin
      restore,file=last_nelem(dbf)
      sse=where(tag_names(struct4event_dbase) eq strupcase(feat_code(0)),fcnt)
      if fcnt gt 0 then retval=struct4event_dbase.(sse) else $
         box_message,'No matching event code found in dbase' 
 
   endelse
   return,retval ; !!! Early Exit for /DBASE use (no execute statement)
endif

type_vec = ['string' ,'byte','integer','long' ,'float'  ,'double' ,'undefined']
val_vec  = ['"blank"','0b'  ,'-9999'  ,'-999999l','!VALUES.F_Infinity','!VALUES.D_Infinity','"-"'      ]

defevent='VOEvent_Spec.txt'
local=concat_dir(curdir(),defevent)
sswdef=concat_dir('$SSW_ONTOLOGY_DATA',defevent)

case 1 of
   data_chk(infil_params,/string):   ; user supplied
   file_exist(local): infil_params = local
   file_exist(sswdef): infil_params = sswdef
   else: begin 
      box_message,'Cannot find event file> ' + sswdef
      return,-1
   endcase
endcase


; Read in Spec table
lines = strarr(file_lines(infil_params))
lines = strarr(file_lines(infil_params))
openr, lun,/get_lun, infil_params
readf, lun, lines
free_lun, lun 
lines = lines[2:*]
ncols = n_elements(strsplit(lines[0],',',/extract))
buff0 = strarr(ncols, n_elements(lines))
FOR I=0,N_ELEMENTS(lines)-1 DO buff0[*,I] = strsplit(lines[i],',',/extract)

buff1 = buff0[*,2:*]
feat_code_vec = strtrim(buff0[*,0],2)
feat_code_arr = feat_code_vec
feat_name_arr = strtrim(buff0[*,1],2)


if keyword_set(list_features) then begin
  print, '        Feature     Feature Code'
  print, '        -------     ------------'
  correct_code = where(strlen(feat_code_arr) EQ 2)
  for i=0,n_elements(feat_name_arr[correct_code])-1 do $
    print, string(feat_name_arr[correct_code[i]], format='$(a20)'), '     ', feat_code_arr[correct_code[i]]
    print, "e.g. evstruct = struct4event('ActiveRegion')"
    print, "e.g. evstruct = struct4event('CH')"
  return, feat_code_arr
endif
IF N_ELEMENTS(feat_code) EQ 0 THEN BEGIN
   print, "INSTRUCTIONS: evstruct = struct4event(/list)"
   print, "FOR A LIST OF FEATURES AND EVENTS"
   print, "e.g. evstruct = struct4event('ActiveRegion')"
   print, "For complete list, go to http://www.lmsal.com/helio-informatics/hpkb/VOEvent_Spec.html"
   return, -1
ENDIF
if strlen(feat_code) gt 2 then begin
  index=where(strupcase(feat_name_arr) eq strupcase(feat_code(0))) 
  if index ge 0 then begin
    feat_code=feat_code_arr(index(0))
  endif else begin
    print, 'Passed feature name does not match catalog list.'
    return,'Invalid feature name'
  endelse
endif else feat_code=strupcase(feat_code)  ; to allow case errors


ss_code_match = where(feat_code_vec eq feat_code,count_match)
if count_match gt 0 then begin
  feat_flags         = strtrim(buff1(ss_code_match,*),2)
  VOParamType_flags  = strtrim(buff1(where(feat_code_vec EQ 'VOParamType'),*),2)
  ss_required = where(feat_flags eq '9',                         count_required)
  ss_optional = where((feat_flags gt '0') and (feat_flags lt '9'),count_optional)
endif else begin
  print, 'Passed feature name does not match catalog list.'
  print, 'Returning default required structure tags.'
; Arbitrarily use first feature column as template for required tags:
  ss_required = where(strcompress(buff1(2,*),/remove_all) eq '9',count_required)
  ss_optional = where(strcompress(buff1(2,*),/remove_all) eq '9',count_optional)
endelse
if count_required gt 0 then begin
  ntags_required = count_required
  tagnames_required = strtrim(reform(buff1(0,ss_required)),2)
  tagtypes_required = strtrim(reform(buff1(1,ss_required)),2)
  tagvals_required = strarr(ntags_required)
  for i=0,ntags_required-1 do tagvals_required(i) = val_vec(where(type_vec eq tagtypes_required(i)))
endif

if count_optional gt 0 then begin
  ntags_optional = count_optional
  tagnames_optional = strtrim(reform(buff1(0,ss_optional)),2)
  tagtypes_optional = strtrim(reform(buff1(1,ss_optional)),2)
  tagvals_optional = strarr(ntags_optional)
  for i=0,ntags_optional-1 do tagvals_optional(i) = val_vec(where(type_vec eq tagtypes_optional(i)))
endif

; Construct structure definition command:
cmd = 'evstruct = { '
if ntags_required gt 0 then begin
  cmd = cmd + 'required:{ '
  for i=0,ntags_required-1 do begin
     cmd = cmd + tagnames_required(i) + ':' + tagvals_required(i) + ', '
  endfor
  cmd = strmid(cmd,0,strlen(cmd)-2)
  cmd = cmd + ' }, '
endif

if ntags_optional gt 0 then begin
  cmd = cmd + 'optional:{ '
  for i=0,ntags_optional-1 do begin
    cmd = cmd + tagnames_optional(i) + ':' + tagvals_optional(i) + ', '
  endfor
  cmd = strmid(cmd,0,strlen(cmd)-2)
  cmd = cmd + '} '
endif else begin
  cmd = strmid(cmd,0,strlen(cmd)-2)
endelse

cmd = cmd + ', SpecFile:"'+infil_params+ '" '
cmd = cmd + ', Reference_names:strarr(20), Reference_links:strarr(20), ' + $
      'Reference_types:strarr(20), Description:"", '+$
      'Citations:replicate({EventIVORN:"",Action:"Accepted values:followup, supercedes, retraction",Description:""},20)'+$
      '}'

; Execute command to create structure:
result = execute(cmd(0))

; KlugeStart:
index=where(feat_code eq feat_code_arr)
evstruct.required.Event_Type      = feat_code_arr(index)+": "+feat_name_arr(index)
evstruct.required.KB_ARCHIVID     = 'Reserved for KB archivist: KB entry identifier'
evstruct.required.KB_ARCHIVIST    = 'Reserved for KB archivist: KB entry made by'
evstruct.required.KB_ARCHIVDATE   = 'Reserved for KB archivist: KB entry date'
evstruct.required.KB_ARCHIVURL    = 'Reserved for KB archivist: URL to suppl. info.'
evstruct.required.Event_StartTime = '1492-10-12 00:00:00'
evstruct.required.Event_EndTime   = '1492-10-12 00:00:00'
evstruct.optional.Event_Expires   = '1492-10-12 00:00:00'

case strlowcase(feat_code) of
   'ce' : evstruct.required.Event_CoordSys ="UTC-HRC-TOPO"
   else : evstruct.required.Event_CoordSys ="UTC-HPC-TOPO"
endcase
; KlugeEnd

if keyword_set(help_struct) then begin
  print,'Required attributes: '
  help,/str,evstruct.required
  print,'Optional attributes: '
  help,/str,evstruct.optional
  print, 'For further info, go to http://www.lmsal.com/helio-informatics/hpkb/VOEvent_Spec.html'
endif

return, evstruct

end
