-- Written by Moritz Hoffmann 2006, part of the orx-irc project
-- Released under the BSD license

::CLASS ClientEvent PUBLIC SUBCLASS SuperClientEvent
::METHOD Unknown
    use arg methodname, methodargs
    methodname = methodname~translate
    call debug "[ClientEvent: Unknown method called:" methodname, 1
    if .LOCAL[methodname] \= .nil then do i = 1 to .local[methodname]~items
--	call debug "[ClientEvent: Unknown: Searching" .local[methodname][i],8
	if self~EventhasMethod(.local[methodname][i]~translate) then do
	    call debug "[ClientEvent: Unknown: Found" .local[methodname][i],8
            self~run(self~EventGetMethod(.local[methodname][i]~translate),"A",methodargs)
	    return 1
	end
    end
    call debug "[ClientEvent: Unknown: No method found",8
    return 0

::CLASS SuperClientEvent
::METHOD Init
    expose methods
    -- the directory to hold the methods and their names
    -- the directory will later hold stacks, either with more than one element
    -- or just one
    methods = .directory~new()
    -- modus can either be stack or flat
    -- in stack mode it will remember old methods defined and will invoke them
    -- if the current method for a name has been removed.
    -- in flat mode only the current method is stored, after removing it
    -- ~hasmethod() will return .false
    self~EventSetMode("Stack")
    call debug "[SuperClientEvent: Init: Instance initialized",1
    
::METHOD EventSetMode
    expose modus methods
    parse upper arg NewModus
    -- save only the first non whithspace character
    NewModus = NewModus~strip~left(1)
    call debug "[SuperClientEvent: EventSetMode: Mode set to" NewModus,1
    -- Don't do anything if the mode remains unchanged
    if Modus = NewModus then return
    -- Look for mode S and F, raise an error in case it's something else
    SELECT
	-- Modus was changed to stack mode
	When NewModus = "S" then do
	    Modus = "S"
	end
	-- Modus was changed to flat
	When NewModus = "F" then do method over methods
	    -- get the method stack for the current method name
	    methodstack = methods[method]
	    -- recreate it only transferring the currently active method
	    methods[method] = .queue~new~~push(methodstack~pull)
	    -- explicitly drop the old stack
	    drop methodstack
	end
	Otherwise
	    nop
	    -- RAISE NEEDS TO BE INCORRPORTAED HERE ---
    End

::METHOD EventGetMode
    expose modus;return modus

::METHOD EventSetMethod
    expose Methods
    use arg methodname, source
    call debug "[SuperClientEvent: EventSetMethod: defining method" methodname,1
    methodname = methodname~translate
    call debug "[SuperClientEvent: EventsetMethod: source is of type" source~class,8
    if source = .nil then return
    if source~class \= .method then do
        method = .method~new(methodname~translate, source)
    end
    else method = source
    if self~EventGetMode = "S" then do
        if Methods~HasIndex(methodname) then
	    Methods[methodname]~push(method)
	else
	    Methods[methodname] = .queue~new~~push(method)
    end
    else Methods[methodname] = .queue~new~~push(method)

::METHOD EventSetMethods
    use arg methods
    do name over methods
	self~EventSetMethod(name,methods[name])
    end

::METHOD EventGetMethod
    expose methods
    if methods~HasIndex(arg(1)) then return methods[arg(1)]~peek
    else return .nil

::METHOD EventRemoveMethod
    expose methods
    parse upper arg methodname
    call debug "[SuperClientEvent: EventRemoveMethod: trying to remove" methodname,3
    if methods~HasIndex(methodname) then do
	ret =  methods[methodname]~pull
	if methods[methodname]~items = 0 then methods~remove(methodname)
	call debug "[SuperClientEvent: EventRemoveMethod: remove succesful!",4
    end
    else ret = .nil
    return ret
    
::METHOD EventHasMethod
    expose methods
    parse arg methodname
    return methods~hasIndex(methodname)