(function() {

var _reHtmlEscape = new RegExp('[&<>"]', 'gim');

var _reTime = new RegExp('^((?:[0-1]{0,1}[0-9]{1,1})|(?:2[0-3]))(?::?:([0-5]\\d)(?::?:([0-5]\\d))?)?$', 'i');
var _reDate = new RegExp('^((?:[0-2]?[0-9])|(?:3[0-1]))/((?:0{0,1}[1-9])|(?:1[0-2]))/([0-9]*)$', 'i');


/* The base Whispercast namespace */
Whispercast = (typeof(Whispercast) != 'undefined') ? Whispercast : {
  htmlEscape: function(s) {
    if (s) {
      return (''+s).replace(
        _reHtmlEscape,
        function(c) {
          switch (c) {
            case '&':
              return '&amp;';
            case '<':
              return '&lt;';
            case '>':
              return '&gt;';
            case '"':
              return '&quot;';
          }
          return c;
        }
      );
    }
    return s;
  },
  htmlUnescape: function(s) {
  },

  closure: function(scope, callback) {
    var bound = [];
    for (var i = 2; i < arguments.length; i++) {
      bound.push(arguments[i]);
    }
    return function() {
      var args = bound.slice(0);
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      return callback.apply(scope, args);
    }
  },
  overload: function(o, method, overload) {
    var previous = o[method];
    o[method] = function() {
      var args = [previous];
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      return overload.apply(o, args);
    }
  },

  clone: function(o) {
    if (!o || (typeof(o) != 'object')) {
      return o;
    }

    if (typeof(o.clone) == 'function') {
      return o.clone();
    }

    if (o.constructor == Array) {
      return [].concat(o);
    }
    if (o.constructor == Object) {
      var r = {};
      for (var i in o) {
        r[i] = Whispercast.clone(o[i]);
      }
      return r;
    }
    return o;
  },

  parseTime: function(s) {
    var r = _reTime.exec(s);
    if (r != null) {
      return {hour:r[1],minute:(r[2] ? r[2] : 0),second:(r[3] ? r[3] : 0)};
    }
    return null;
  },
  parseDate: function(s) {
    var r = _reDate.exec(s);
    if (r != null) {
      var d = new Date(r[3], r[2]-1, r[1]);
      if (d.getFullYear() == r[3] &&
          d.getMonth() == (r[2]-1) &&
          d.getDate() == r[1]) {
        return {year:r[3],month:r[2],day:r[1]};
      }
    }
    return null;
  },

  formatTime: function(d) {
    var m = d.getMinutes();
    m = ((m < 10) ? '0':'')+m;
    var s = d.getSeconds();
    s = ((s < 10) ? '0':'')+s;
    return d.getHours()+':'+m+':'+s;
  },
  formatDate: function(d) {
    return d.getDate()+'/'+(d.getMonth()+1)+'/'+d.getFullYear();
  },

  log: function(message) {
    if (typeof(console) != 'undefined') {
      if (typeof(console.log) != 'undefined') {
        console.log(message);
      }
    }
  },

  global: {
  }
};

}());
