// borrowed from John Resig's blog post: http://ejohn.org/blog/simple-javascript-inheritance/
// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();


var divvy = divvy || {};
divvy.global = this;
divvy.DEBUG = false;
divvy.console = {
    _getConsole: function(){
        if (divvy.DEBUG && typeof(console) !== 'undefined' && console != null){
            return divvy.global.console;
        }
        return null;
    },

    log: function(){
        var console = divvy.console._getConsole();
        if (console){
            try{
                console.log.apply(window, arguments);
            } catch (e){
                var s = '';
                for (var i=0; i < arguments.length; i++){
                    s += " "+arguments[i];
                }
                console.log(s);
            }
        }
    },
    getLogger: function(name){
        return {
            log: function(){
                var newArgs = [name+":"];
                for (var i=0; i<arguments.length; i++){
                    newArgs.push(arguments[i]);
                }
                try{
                    divvy.console.log.apply(window, newArgs);
                } catch (e){
                    divvy.console.log(newArgs.join(" "));
                }
            }
        };
    }
};

divvy.alertAutoHideTimeout = null;
divvy.alert = function(message, autoHideTime){
    var alertBox = jQuery("#divvy-alert-box");
    if (alertBox.length === 0){
        alertBox = jQuery(
            '<div id="divvy-alert-box">'
            + '<span class="message"></span>'
            + '<button class="small_button">Dismiss</button>'
            + '</div>').prependTo("body");
    };
    alertBox.hide().find(".message").html(message).end().slideDown();
    alertBox.find("button")
        .unbind("click")
        .click(
            function(){
                jQuery("#divvy-alert-box").slideUp();
                return false;
            });
    if (divvy.alertAutoHideTimeout){
        window.clearTimeout(divvy.alertAutoHideTimeout);
        divvy.alertAutoHideTimeout = null;
    }
    if (autoHideTime){
        divvy.alertAutoHideTimeout = window.setTimeout(
            function(){ jQuery("#divvy-alert-box").slideUp(); }, autoHideTime);
    }
};
divvy.alert.quiet = function(message){
    divvy.console.log(message);
};

divvy.caller = function(func, scope){
    var memoArgs = [];
    for (var i=2; i < arguments.length; i++){
        memoArgs.push(arguments[i]);
    }
    return function(){
        return func.apply(scope, $.merge(memoArgs, arguments));
    };
};
