;+
; NAME:
;	MAKE_SMEI_ARG
;
;
; PURPOSE:
;	Generate a SMEI_ARGUMENT from a sequence, image or number and
;	descriptors. 
;
;
; CATEGORY:
;	OPS
;
;
; CALLING SEQUENCE:
;	argref = make_smei_arg(descriptor)
;
;
; INPUTS:
;	descriptor	str/num	A descriptor or a number (or array).
;
;
; KEYWORD_PARAMETERS:
;	get_level	int	The calling level from which to get
;				the object being argumentified
;				(usually only used by the
;	/transient		If set, then any new argument object
;				is generated with the transient flag.
;
; OUTPUTS:
;	argref	objref	The argument object reference
;
;
; NOTES:
;	When the argument is expressed as a string, then the object
;	referred must exist in the caller or at the top ($MAIN$) level
;	in SSWIDL. The
;	format is "name{plane}[start:stop:step]", if no plane is given
;	then the "processed" plane is assumed, if no range specifier
;	is given for a sequence then the whole sequence is assumed.
;
;
; MODIFICATION HISTORY:
;	Original: 28/10/03; SJT
;	Get from caller or specified level: 30/10/03
;	Tidy up level handling: 4/11/03; SJT
;	Added transient flag: 5/11/03; SJT
;-

function make_smei_arg, descriptor, get_level = get_level, transient = $
                        transient 

dtype = size(descriptor, /type)

numeric = [1, 2, 3, 4, 5, 6, 9, 12, 13, 14, 15]
templ = $
  '([a-zA-Z][a-zA-Z0-9_$]*)(\{(-?[0-9]+)\})?' + $
  '(\[([0-9]*)(:(-?[0-9]*))?(:([0-9]*))?\])?'

case dtype of
    11: begin                   ; A object reference
        cls = obj_class(descriptor)
        case cls of
            'SMEI_OPERATOR_ARGUMENT': begin
                smei_msg, /warn, "Argument is already a SMEI_ARGUMENT"
                return, descriptor
            end
            'SMEI_SEQUENCE': return, $
              obj_new('SMEI_OPERATOR_ARGUMENT', descriptor, transient $
                      = transient)
            'SMEI_IMAGE': return, $
              obj_new('SMEI_OPERATOR_ARGUMENT', descriptor, transient $
                      = transient)
            'SMEI_OPERATOR': return, $
              obj_new('SMEI_OPERATOR_ARGUMENT', descriptor, transient $
                      = transient)
            else: begin
                smei_msg, /alert, 'Invalid object class for value: '+cls
                return, 0
            end
        endcase
    end
    7: begin                    ; A string descriptor
        d = strcompress(descriptor, /remove)
        psd = stregex(d, templ, /subexpr, /extract)

        iname = 1
        iplane = 3
        irange = 4
        istart = 5
        istop = 7
        istep = 9
        if psd[iname] eq '' then begin
            smei_msg, /alert, ["No object named in descriptor"]
            return, 0
        endif else begin
            if keyword_set(get_level) then llist = [get_level, -1, 1] $
            else llist = [-1, 1]
            for jl = 0, n_elements(llist)-1 do begin
                nlist = scope_varname(level = llist[jl])
                junk = where(nlist eq strupcase(psd[iname]), nn)
                if nn ne 0 then begin
                    obref = scope_varfetch(psd[iname], level = llist[jl])
                    if n_elements(obref) gt 0 then break
;                 if (n_elements(routine_names(psd[iname], fetch = $
;                                              llist[jl])) gt 0) then begin
;                     obref = routine_names(psd[iname], fetch = llist[jl])
;                     break
                endif
            endfor
            if n_elements(obref) eq 0 then  begin
                smei_msg, /alert, ['Variable '+psd[iname]+' not ' + $
                                   'found', $
                                   'at requested levels']
                return, 0
            endif
        endelse

        ocls = size(obref, /type)
        if ocls eq 11 then begin
            case obj_class(obref) of
                'SMEI_SEQUENCE': begin
                    if psd[iplane] ne '' then plane = fix(psd[iplane]) $
                    else plane = 0
                    range = intarr(3)
                    if psd[istart] ne '' then range[0] = $
                      fix(psd[istart]) $
                    else range[0] = 0
                    if psd[istop] ne '' then range[1] = $
                      fix(psd[istop]) $
                    else range[1] = obref -> get_count()-1
                    if psd[istep] ne '' then range[2] = $
                      fix(psd[istep]) $
                    else range[2] = 1

                    return, obj_new('SMEI_OPERATOR_ARGUMENT', obref, $
                                    plane, range, transient = transient)
                end
                'SMEI_IMAGE': begin
                    if psd[iplane] ne '' then plane = fix(psd[iplane]) $
                    else plane = 0
                    return, obj_new('SMEI_OPERATOR_ARGUMENT', obref, $
                                    plane, transient = transient)
                end
                'SMEI_OPERATOR': return, $
                  obj_new('SMEI_OPERATOR_ARGUMENT', obref, transient = $
                          transient)
                'SMEI_OPERATOR_ARGUMENT': return, obref
                
                else: begin
                    smei_msg, /alert, ["Invalid object class for an " + $
                                       "argument", cls]
                    return, 0
                end
            endcase
        endif else begin
            locs = where(ocls eq numeric, nn)
            if nn eq 0 then begin
                smei_msg, /alert, ["Core of an argument must be an ", $
                                   "object or a numeric type"]
                return, 0
            endif
            return, obj_new('SMEI_OPERATOR_ARGUMENT', obref, transient $
                            = transient)
        endelse
    end
    else: begin
        locs = where(dtype eq numeric, nn)
        if nn eq 0 then begin
            smei_msg, /alert, ['An argument descriptor must be one ' + $
                               'of', $
                               'a SMEI_* object, a string descriptor ' + $
                               'or', $
                               'a numerical value']
            return, 0
        endif
        return, obj_new('SMEI_OPERATOR_ARGUMENT', descriptor, $
                        transient = transient)
    end
endcase

end

