/**
 * JIM-Framework: JavaScript in medienPARK
 *
 * Das Jim-Framework bietet Grundfunktionalitäten zum Arbeiten mit
 * Objektbasierten Modulen und Funktionen. Und gliedert die Module
 * in eine einheitliche Form.
 *
 * Momentan sind folgende Funktionalitäten implementiert:
 *
 * Objekte:
 * - Jim.Version        : Versionskontroller des Jim.Frameworks
 * - Jim.Paths          : Pfadspeicher
 * - Jim.Events         : Eventhandling
 * - Jim.Class          : Grundlegende Klassenerstellung
 *
 * Funktionen:
 * - Jim.raise()        : Exceptionhandling
 * - Jim.byId()         : HTML-Objekte finden über die ID
 * - Jim.byTag()        : HTML-Objekte finden über den Tagnamen
 * - Jim.typeOfWindow() : Prüft ob das Element vom Typ Window ist
 *
 * @category Core
 * @author Matthias Göbels <goebels@medienpark.net>
 * @copyright Copyright by medienPARK 2006
 * @version 01.08.06
 * @todo byId und byTag verbessern siehe auch Dojo
 * @todo Jim.Events um globales Eventhandling erweitern
 * @access public
 **/
var Jim = {

//////////////////////////////////////////////////////////////////////////////////////
// JIM STATIC CLASSES
//////////////////////////////////////////////////////////////////////////////////////

  /**
   * Jim.Version Objekt
   *
   * Definiert die aktuelle Version des Jim.Frameworks und bietet
   * eine Versionsüberprüfung und -ausgabe.
   *
   * @category Core
   * @access public
   **/
  Version:
  {
    /**
     * Speicher in dem die Majorreleases gespeichert werden
     *
     * @var integer
     */
    major: 0,
    
    /**
     * Speicher in dem die Minorreleases gespeichert werden
     *
     * @var integer
     */
    minor: 4,
    
    /**
     * Speicher in dem die Patchreleases gespeichert werden
     *
     * @var integer
     */
    patch: 0,
    
    /**
     * Speicher in dem die Flagreleases gespeichert werden
     *
     * @var string alpha|beta|stable
     */
    flag: "alpha",
    
    /**
     * Speicher in dem die Revisionsnummer gespeichert wird
     *
     * @var integer
     */
    revision: 171,
    
    /**
     * Setzt den Versionsstring zusammen und gibt diesen zurück
     *
     * @return string Versionsstring
     * @access public
     **/
    toString: function()
    {
      with(Jim.Version)
      {
        return "Jim.Framework " + major + "." + minor + "." + patch + flag + " (Revision " + revision + ")";
      }
    },

    /**
     * Überprüft ob die übergebene Minimalanforderung erfüllt ist.
     *
     * @return boolean gibt true zurück wenn die Anforderungen erfüllt sind und wirft eine Exception, wenn dem nicht so ist.
     * @access public
     **/
    check: function(major, minor, patch, moduleName)
    {
      if(this.major >= major)
      {
        if(this.major == major)
        {
          if(this.minor >= minor)
          {
            if(this.minor == minor)
            {
              if(this.patch >= patch)
              {
                return true;
              }
              else
              {
                Jim.raise('Version', 'check', 'The ' + moduleName + ' Module needs minimum this Version: Jim.Framework ' + major+ '.' + minor + '.' + patch + '. You are using this Version: ' + Jim.Version.toString());
                return false;
              }
            }
          }
          else
          {
            Jim.raise('Version', 'check', 'The ' + moduleName + ' Module needs minimum this Version: Jim.Framework ' + major+ '.' + minor + '.' + patch + '. You are using this Version: ' + Jim.Version.toString());
            return false;
          }
        }
      }
      else
      {
        Jim.raise('Version', 'check', 'The ' + moduleName + ' Module needs minimum this Version: Jim.Framework ' + major+ '.' + minor + '.' + patch + '. You are using this Version: ' + Jim.Version.toString());
        return false;
      }
    }
  },
  
//////////////////////////////////////////////////////////////////////////////////////

  /**
   * Jim.Paths Objekt
   *
   * Speicher in dem die Pfade des Framworks hinterlegt sind.
   *
   * @category Core
   * @access public
   **/
  Paths :
  {
    /**
     * Speicher in dem der Pfad zum Jim.Framework hinterlegt ist.
     *
     * @var string
     */
    framework: null,

    /**
     * Speicher in dem der Host hinterlegt ist, auf dem das Jim.Framework genuzt wird.
     *
     * @var string
     */    
    host: null,
    
    /**
     * Generiert die Pfade des Frameworks
     *
     * @access public
     **/
    init: function()
    {
      scripts = Jim.byTag("script");
      
      var script = null;
      for(i = 0; i < scripts.length; i++)
      {
        if(scripts[i].src.match(/Jim\.js(\?.*)?$/))
        {
          script = scripts[i];
        }
      }
      
      this.host = document.location.host;
      eval('pattern = /http:\\/\\/' + this.host + '/')
      this.framework = (script.src.replace(/Jim\.js(\?.*)?$/,'')).replace(pattern, '');
    }
  },
   
//////////////////////////////////////////////////////////////////////////////////////

  /**
   * Jim.Events Objekt
   *
   * Verwaltet die Events der Seite
   *
   * @category Core
   * @access public
   **/
  Events: 
  {
    /**
     * Speicher in dem die, beim onload Event, auszuführenden Funktionen
     * hinterlegt werden.
     *
     * @var array
     */
    onLoadEvents: new Array(),

    /**
     * Speicher in dem die, beim onunload Event, auszuführenden Funktionen
     * hinterlegt werden.
     *
     * @var array
     */
    onUnloadEvents: new Array(),
    
    /**
     * Fügt dem onload Event eine neue auszuführende Funktion hinzu.
     *
     * @param function Die hinzuzufügende Funktion.
     * @access public
     **/
    addOnLoad: function(func)
    {
      if((typeof func == 'function' || typeof func == 'object'))
      {
        this.onLoadEvents.push(func);
      }
      else
      {
        Jim.raise('Events', 'addOnLoad', 'You can only add functions!');
      }
    },

    /**
     * Fügt dem onunload Event eine neue auszuführende Funktion hinzu.
     *
     * @param function Die hinzuzufügende Funktion.
     * @access public
     **/    
    addOnUnload: function(func)
    {
      if((typeof func == 'function' || typeof func == 'object'))
      {
        this.onUnloadEvents.push(func);
      }
      else
      {
        Jim.raise('Events', 'addOnUnload', 'You can only add functions!');
      }
    },
    
    /**
     * Führt alle Funktionen aus, die für das onload Event vorgesehen sind.
     *
     * @access public
     **/
    doOnLoad: function()
    {
      for(i = 0; i < this.onLoadEvents.length; i++)
      {
        (this.onLoadEvents[i])();
      }
    },
     
    /**
     * Führt alle Funktionen aus, die für das onunload Event vorgesehen sind.
     *
     * @access public
     **/
    doOnUnload: function()
    {
      for(i = 0; i < this.onUnloadEvents.length; i++)
      {
        (this.onUnloadEvents[i])();
      }
    },

    /**
     * Weißt dem onload un unload Event die auszuführenden Funktionen zu.
     *
     * @access public
     **/    
    init: function()
    {
      window.onload = (function(){ Jim.Events.doOnLoad(); });
      window.onunload = (function(){ Jim.Events.doOnUnload(); });
    }
  },
 
//////////////////////////////////////////////////////////////////////////////////////

  /**
   * Jim.Class Objekt
   *
   * Liefert die grundfunktionalitäten zum erstellen von JavaScript-Objekten
   *
   * @category Core
   * @access public
   **/
  Class: 
  {
    /**
     * Erstellt ein JavaScript Objekt
     *
     * @access public
     **/  
    create: function()
    {
      return function()
      {
        if(this.__construct)
        {
          this.__construct.apply(this, arguments);
        }
      }
    },

    /**
     * Erweitert ein Objekt um ein zweites. Achtung es kann so nur jeweils ein
     * Objekt erweitert werden.
     *
     * @param destination_object Das Objekt welches erweitert werden soll.
     * @param source Das Object welches die Erweiterungen enthält.
     * @access public
     **/  
    extend: function(destination_object, source)
    {
      destination = destination_object.prototype;
      for (property in source) {
        destination[property] = source[property];
      }
      return destination;
    }
  },
  
//////////////////////////////////////////////////////////////////////////////////////
// JIM FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////

  /**
   * Dient zur Exceptionbehandlung
   *
   * @param string klasse Klassenname des Exceptionwerfenden Objektes oder null
   * @param string method Methodenname der Exceptionwerfenden Methode oder null
   * @param string message Fehlermeldung die geworfen werden soll
   * @param string optional Exception die abgefangen wurde und weitergeworfen werden soll
   * @access public
   **/  
  raise: function(klasse, method, message, exception)
  {
    var text = "Jim.";
    
    if(klasse !== null)
    {
      text = text + klasse + '.';
    }
    
    if(method !== null)
    {
      text = text + method;
    }
    
    text = text + ': ';
    
    if(exception)
    {
      text = text + message + " > " + exception.message;
    }
    else
    {
      text = text + message;
    }
    
    throw Error(text);
  },  

  /**
   * Liefert ein Objekt des Knotens mit der ID 'id'
   *
   * @param string id ID-Des zu referenzierenden HTML-Elements
   * @return HTML-Element Objekt
   * @access public
   **/ 
  byId: function (id)
  {
    return document.getElementById(id);
  },

  /**
   * Liefert eine HTML-Collection mit den Objekt, welche vom Tagtyp 'name'
   * sind.
   *
   * @param string name Name des HTML-Tags welches gesucht wird
   * @return HTML-Collection Object
   * @access public
   **/ 
  byTag: function (name)
  {
    return document.getElementsByTagName(name);
  },
  
  /**
   * Überprüft ob ein Objekt vom Typ Window ist.
   * Diese Überprüfung wurde im wesentlichen für das Popup Modul erstellt
   * und ist keine 'echte' Überprüfung
   *
   * @param Window object Objekt welches als Window-Objekt verifiziert werden soll.
   * @return boolean
   * @access public
   **/ 
  typeOfWindow: function(object)
  {
    try
    {
      if(object != null)
      {
        if(typeof object != 'undefined' && typeof object == 'object')
        {
          if((typeof object.close == 'function' || typeof object.close == 'object'))
          {
            return true;
          }
          else
          {
            return false;
          }
        }
        else
        {
          return false;
        }
      }
      else
      {
        return false;
      }
    }
    catch(e)
    {
      return false;
    }
  }
}

//////////////////////////////////////////////////////////////////////////////////////
// JIM DYNAMIC CLASSES
//////////////////////////////////////////////////////////////////////////////////////

// Zur Zeit keine geschrieben

//////////////////////////////////////////////////////////////////////////////////////
// JIM INITIALISATION
//////////////////////////////////////////////////////////////////////////////////////

/**
 * Liest die Framwork Pfade aus und speichert diese
 **/ 
Jim.Paths.init();

/**
 * Aktiviert die onload und onunload Events
 **/ 
Jim.Events.init();
