-- Main generic routines for comparing and other things are in here --
-- Written by Moritz Hoffmann 2006, part of the orx-irc project
-- Released under the BSD license

::CLASS routines_init
::METHOD init CLASS
signal on syntax name err
numeric digits 10
--the timestamps used by IRC are 10 chars long 
return
err: .debug~error(condition('O'))

::ROUTINE IRCIsChannel PUBLIC
  return (pos(left(strip(arg(1)),1),'#!+&')>0) & (length(strip(arg(1)))<= 50)

::ROUTINE IRCUpper PUBLIC
  parse arg string
  return string~translate~translate('{}|^','[]\~')
-- Use this routine to convert an IRC name to compare it

::ROUTINE IRCCompare PUBLIC
  return IRCUpper(arg(1)) = IRCUpper(arg(2))

::ROUTINE NowToTS PUBLIC
  Numeric Digits 11
  return (date('B')-719162)*86400+time('S')
-- 719162 are the days until 19700101 starting from 00010101
-- 86400 are the seconds per day 

::ROUTINE TStoStr PUBLIC
  if \ datatype(arg(1),'N') then return arg(1)
  return date('N',719162+arg(1)%86400,'B') time('N',arg(1)//86400,'S')

-- This method removes all occurances of key in string
::ROUTINE RemoveStr
    use arg string, key
    keylength = key~length
    position = 1
    do until position = 0
        position = string~pos(key)
        string = string~left(position-keylength)||string~right(string~length-position)
    end
    return string
					

::ROUTINE debug PUBLIC
  .local["DEBUG"]~debug(arg(1),arg(2)) -- pass messages on to the debug class

::CLASS Debug PUBLIC
::METHOD Init CLASS
  expose monitor
  monitor = .monitor~new  -- create a new monitor object to receive unknown messages

::METHOD UnInit CLASS
    self~lineout("-- Debug log ended" date() time() "--")

::METHOD Initialize CLASS
  expose monitor level
  use arg outputstream, alevel
  -- level is a char string
  if arg() < 2 then raise syntax 93.901 ARRAY (2)
  if arg() > 2 then raise syntax 93.902 ARRAY (2)
  if alevel~class = .string then
    SELECT
      WHEN alevel~datatype('NUM') then level=alevel~d2c -- convert to correct type
      WHEN alevel~length>0 then level=alevel
      OTHERWISE raise syntax 93.914 array ("level","NUM, STRING",alevel)
    END
  else raise syntax 93.914 array ("level","NUM, STRING",alevel)
  if outputstream~open("WRITE REPLACE NOBUFFER") \= "READY:" then
    monitor~destination(.output) -- use stdout: if the output stream fails to open
  else
    monitor~destination(outputstream) -- set the monitor's destination to the stream specified
  parse source rxsource -- create some initial output of the debug log
  parse version rxversion
  self~debug("Debug Log started" date() "-" time(),31)
  self~debug(rxsource "-" rxversion,31)
-- level bits:
-- 1   = method/routine calls
-- 2   = argument input
-- 4   = returning values
-- 8   = intermediates
-- 16  = errors

  .local["DEBUG"] = self

::METHOD Unknown CLASS
  expose monitor
  forward to (monitor)


::METHOD debug CLASS
  expose level
  use arg string, aLevel
  if alevel = "" then self~lineout(">>" string)
  else if level~bitand(aLevel~d2c,"0"b) > "0"b then -- at least one bit is set...
    self~lineout(string)

::METHOD error CLASS
  use arg errobj
  -- error object are usually directories
  if errobj~class \= .directory then
    errobj = condition('O') -- no object passed, try to get a new one
  if errobj = .nil then do
    self~lineout("Error catched but no object received!")
    return
  end
  .local["IRC.DEBUG.LASTERROR"] = errobj
  self~lineout("[Debug: Error --- ERROR CATCHED! ---")
  do entry over errobj
    SELECT
      WHEN entry = "ADDITIONAL" then if errobj[entry] \= "" then if errobj[entry]~class = .array then do item over errobj[entry]
        self~lineout("> ADDITIONAL:" item)
      end
      WHEN entry = "TRACEBACK"  then if errobj[entry] \= "" then if errobj[entry]~class = .list then do item over errobj[entry]
        self~lineout("> TRACEBACK:" item)
      end
      WHEN length(errobj[entry]) = ""   then iterate
      WHEN errobj[entry] = .nil then iterate
      OTHERWISE self~lineout(">" entry":" errobj[entry])
    END
  end