imx = {
  version:'0.1.3',
  /**
   * @param {mixed} expression
   * @return fluent interface
   * @type imx
   */
  log: function(expression) {
    if(typeof(console) == 'object' && typeof(console.log) == 'function') {
      console.log(expression);
    }
    return this;
  },
  /**
   * @param {mixed} expression
   * @return fluent interface
   * @type imx
   */
  warn: function(expression) {
    if(typeof(console) == 'object' && typeof(console.warn) == 'function') {
      console.warn(expression);
    } else {
      imx.log(expression);
    }
    return this;
  },
  /**
   * @param {mixed} expression
   * @return fluent interface
   * @type imx
   */
  error: function(expression) {
    if(typeof(console) == 'object' && typeof(console.error) == 'function') {
      console.error(expression);
    } else {
      imx.warn(expression);
    }
    return this;
  },
  /**
   * @param {String} expected the expected type as string
   * @param {Object} subject the object to test
   * @param {bool} showLog switch wether to show log messages or not
   * @return True if the type matches the expected
   * @type bool
   */
  isTypeOf: function(expected, subject, showLog) {
    if(showLog) imx.log('isTypeOf: type of subject: ' + typeof(subject) + ' expected: ' + expected);
    return (typeof(subject) == expected);
  },
  includedScripts: new Array(),
  /**
   * Includes a javascript by appending a script tag with the given source to the body
   * @param {string} source the path of the including script
   * @return fluent interface
   * @type imx
   */
  include: function(source) {
    imx.log('include: including script ' + source);
    var script = jQuery(document.createElement('script'));
    script.attr('type', 'text/javascript');
    script.attr('language', 'javascript');
    script.attr('src', source);
    jQuery('body').append(script);
    return this;
  },
  /**
   * Includes a javascript by appending a script tag with the given source to the body only if is not yet included
   * @param {string} source the path of the including script
   * @return fluent interface
   * @type imx
   */
  include_once: function(source) {
    imx.log('include_once: checking for included script ' + source);
    if (!this.in_array(source, this.includedScripts)) {
      imx.log('include_once: script not yet included');
      this.includedScripts[this.includedScripts.length] = source;
      this.include(source);
    }else {
      imx.log('include_once: script already included');
    }

  },
  /**
   * aquvivalent to php's in_array, searches an array for the given needle
   * @return the search result
   * @type bool
   */
  in_array: function (needle, haystack) {
    for (var i = 0; i < haystack.length; i++) {
      if (haystack[i] == needle) {
        return true;
      }
    }
    return false;
  },

  /**
  * Simple thread-safe implementation. If checkFunction returns true, the callback is executed. If not, a recursion is executed after the given timeout
  * @param {function} checkFunction
  * @param {function} callback
  * @param {int} timeout Timeout in milliseconds, defaults to 500
  * @todo handle callback arguments
  */
  waitUntil: function (checkFunction,callback,timeout) {
    if (checkFunction()) {
      return callback();
    }
    var args = imx.collectionToArray(imx.waitUntil.arguments).join();
    setTimeout("imx.waitUntil("+args+")",timeout || 500);
    return null;
  },

  /**
 * turns a collection into a proper array
 * @param {idk?} collection
 * @return Array
 */
  collectionToArray: function (collection) {
    var entries = collection.length;
    var result = new Array(entries);
    for (var entry= 0; entry < entries; entry++) result[entry] = collection[entry];
    return result;
  }

};

/**
 * Check for dependend jQuery
 */
if(!imx.isTypeOf('function',jQuery)) alert('GNAAAAAAH! MISSING jQuery!!!');

