;+
;PROCEDURE:  store_data,name,DATA=data,LIMITS=limits,DLIMITS=dlimits,
;     NEWNAME=newname,DELETE=delete
;PURPOSE:
;   Store time series structures in static memory for later retrieval
;   by the tplot routine.  Three structures can be associated with the
;   string 'name':  a data structure (DATA) that typically contains the x and
;   y data. A default limits structure (DLIMITS) and a user limits structure
;   (LIMITS) that will typically contain user defined limits and options
;   (typically plot and oplot keywords).  The data structure and the default
;   limits structure will be
;   over written each time a new data set is loaded.  The limit structure
;   is not over-written.
;INPUT:
;   name:   string name to be associated with the data structure and/or
;     the limits structure.  Also, can enter tplot index as name.
;     The name should not contain spaces or the characters '*' and '?'
;KEYWORDS:
;    DATA:  variable that contains the data structure.
;    LIMITS; variable that contains the limit structure.
;    DLIMITS; variable that contains the default limits structure.
;    NEWNAME: new tplot handle.  Use to rename tplot names.
;    DELETE: array of tplot handles or indices to delete from common block.
;    MIN: if set, data values less than this value will be made NaN.               (obsolete)
;    MAX: if set, data values greater than this value will be made NaN.            (obsolete)
;    NOSTRSW: if set, do not transpose multidimensional data arrays in
;         structures.  The default is to transpose.
;    ERROR: if set returns error code for store_data, values are:
;    0=NO ERROR
;    1=INVALID HANDLE ERROR
;    2=OTHER ERROR
;
;SEE ALSO:    "GET_DATA", "TPLOT_NAMES",  "TPLOT", "OPTIONS"
;
;CREATED BY:    Davin Larson
; $LastChangedBy: jwl $
; $LastChangedDate: 2011-02-15 15:51:48 -0800 (Tue, 15 Feb 2011) $
; $LastChangedRevision: 8221 $
; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/ssl_general/trunk/tplot/store_data.pro $
;-
pro store_data,name, time,ydata,values, $
   data = data, $
   limits= limits, $
   dlimits = dlimits, $
   newname = newname, $
   min=min, max=max, $
   delete = delete, $
   verbose = verbose, $
   nostrsw = nostrsw,$
   except_ptrs = except_ptrs, $
   error=error

@tplot_com.pro

error = 0

if n_params() ge 3 then begin
   if keyword_set(data) then message,/info,'Warning! Data keyword ignored!'
   data = {x:time, y:ydata}
   if keyword_set(values) then data = create_struct(data,'v',values)
endif

str_element,tplot_vars,'options.verbose',verbose   ; get default value if it exists

if keyword_set(delete) then begin
   if n_elements(name) ne 0 then delete = name
   delnames = tnames(delete,cnt)
   if cnt ne 0 then begin
         au = array_union(data_quants.name,delnames)
         savevars = where(au eq -1)
         delevars = where(au ne -1)
         saveptrs = ptr_extract(except_ptrs)
         saveptrs = [saveptrs,ptr_extract(data_quants[savevars])]
         delptrs = ptr_extract(data_quants[delevars],except=saveptrs)
         data_quants=data_quants[savevars]
         ptr_free,delptrs
   endif else dprint,dlevel=1,verbose=verbose,'No matching variables to delete'
   return
endif


dt = size(name,/type)
if size(name,/n_dimen) ne 0 then begin
   dprint,verbose=verbose,'Input name must be scalar!'
   error=1
   return
endif

if dt eq 7 then begin
  if total( array_union(byte(name),byte(' *?[]\'))  ge 0) then begin
       dprint,verbose=verbose,'Invalid name: "'+name+'"; Name may not contain spaces, or the characters: "* ? [ ] \"'
       error=1
       return
  endif
  if n_elements(data_quants) eq 0 then index = 0 else $
    index = find_handle(name)
endif else if (dt ge 1) and (dt le 3) then begin
       index = name
       name = data_quants(index).name
    endif else if not keyword_set(delete) then begin
         dprint,verbose=verbose,'Invalid handle name or index'
         error=1
         return
    endif

dq = {tplot_quant}

if n_elements(data_quants) eq 0 then data_quants = [dq]


if index eq 0 then begin        ; new variable
  orig_name = name+'x'          ; required due to compile bug in early versions of IDL
  dq.name = strmid(orig_name,0,strlen(name))
;  if keyword_set(verbose) then print,'Creating new tplot variable: ',dq.name
  verb = 'Creating'
  dq.dh = ptr_new(0)  ;/allocate)
  dq.lh = ptr_new(0)  ;/allocate)
  dq.dl = ptr_new(0)  ;/allocate)
  data_quants = [data_quants,dq]
  index = n_elements(data_quants) - 1
  dq.create_time = systime(1)
endif else begin
  dq = data_quants(index)
;  if keyword_set(verbose) then print,'Replacing tplot variable: ',dq.name
  verb = 'Altering'
endelse


if keyword_set(min) then begin
   bad = where(data.y lt min,c)
   if c ne 0 then data.y(bad) = !values.f_nan
endif

if keyword_set(max) then begin
   bad = where(data.y gt max,c)
   if c ne 0 then data.y(bad) = !values.f_nan
endif


; set values:
if n_elements(newname) ne 0 then begin
    if total( array_union(byte(newname),byte(' *?[]\'))  ge 0) then begin
       dprint,verbose=verbose,dlevel=0,'Invalid name: "'+name+'"; Name may not contain spaces, or the characters: "* ? [ ] \"'
       error=2
       return
    endif
    nindex = where(data_quants.name eq newname, count)
    if count gt 0 then begin
       dprint,verbose=verbose,dlevel=0,'New name must not already be in use!
       error=2
       return
    endif else dq.name = newname
endif

if n_elements(limits) ne 0 then *dq.lh = limits
if n_elements(dlimits) ne 0 then *dq.dl = dlimits
if n_elements(data) ne 0 then begin
    save_ptrs = ptr_extract(except_ptrs)
    save_ptrs = [save_ptrs, ptr_extract(limits) ]
    save_ptrs = [save_ptrs, ptr_extract(dlimits)]
    save_ptrs = [save_ptrs, ptr_extract(data)]
    save_ptrs = [save_ptrs, ptr_extract( data_quants[where(data_quants.name ne dq.name)])]
    dprint,verbose=verbose,dlevel=1,verb+' tplot variable: ',strtrim(index,2),' ',dq.name
    dq.create_time = systime(1)
  if size(/type,data) eq 8 then begin
    mytags = tag_names(data)
    myptrstr = 0
    for i = 0, n_elements(mytags) - 1 do begin
       newv = data.(i)    ;  faster than:   str_element,data,mytags(i),foo
       oldp = ptr_new()
       str_element,*dq.dh,mytags[i],oldp
       if size(/type,newv) ne 10 then begin       ; newv is not a pointer
          ptr_free,ptr_extract(oldp,except=save_ptrs)       ;  free old stuff (if any exist)
          newv = ptr_new(newv,/no_copy)
       endif else begin                           ; newv is a pointer
          if oldp ne newv then  ptr_free,ptr_extract(oldp,except=save_ptrs)
       endelse
       str_element,/add_replace,myptrstr,mytags[i],newv
    endfor
    *dq.dh = myptrstr
  endif else *dq.dh = data
endif

;if n_elements(data) ne 0 then if data_type(data) eq 10 then $
;   dq.dh = data else *dq.dh = data

extract_tags,dstr,data
extract_tags,dstr,dlimits
extract_tags,dstr,limits


str_element,dstr,'x',value=x
str_element,dstr,'y',value=y
if size(/type,x) eq 10 then if ptr_valid(x) then x=*x
if size(/type,y) eq 10 then if ptr_valid(y) then y=*y
if n_elements(x) ne 0 and n_elements(y) ne 0 then begin
    dq.dtype = 1
    dq.trange = minmax(x)
endif
str_element,dstr,'time',value=time0
if size(/type,time0) eq 10 then time0=*time0
if n_elements(time0) ne 0 then begin                ; obsolete format of passing in an array of structures
    dq.dtype = 2
    message,/info,'Obsolete storage method.  type .cont to continue'
;    stop
;   report
    dq.trange = minmax(time0)
        dqtags = tag_names(*dq.dh)
    data_quants(index) = dq
        for i=0,n_elements(dqtags)-1 do if dqtags(i) ne 'TIME' then begin
            subname = dq.name+'.'+dqtags(i)
            str_element,*dq.dh,dqtags(i),foo
            if ndimen(*foo) ne 1 then $
              if dimen((*foo)[0]) ne n_elements(time0) then $
                if keyword_set(nostrsw) eq 0 then $
                  *foo = transpose(*foo)
          store_data,subname,data={x: time0, y:foo}, $
           dlimits=*dq.dl, limits=*dq.lh
        endif
endif

if size(/type,data) eq 7 then begin
    dq.dtype = 3
    names = tnames(data,trange=tr)
    dprint,verbose=verbose,dlevel=1,'Multi-'+' tplot variable: ',strtrim(index,2),' ',dq.name,' : ' ,names
    dq.trange = minmax(tr)
endif

data_quants[index] = dq

;pos = strpos(name,'.')
;if (pos gt 0) then begin
;   names = strarr(2)
;        names(0) = strmid(name,0,pos)
;        names(1) = strmid(name,pos+1,100)
;   superind = find_handle(names(0))
;   dq.trange = data_quants(superind).trange
;endif

end
