(function() {
/*
 * Class: Javascript Baseclass. Inspired by Underscore.js and Backbone.js
 *
 * NOTE: Hard dependency on Underscore.js
 *
 */

  // Safely import underscore
  var _ = this._;
  if (!_ && (typeof require !== 'undefined')) _ = require('underscore');

  // The base class
  var Class = function() {};

  // Extend function for sub-classing
  Class.extend = function(protoProps, classProps) {
    var child,
        parent = this;

    // Use constructor of extend object as constructor. Use parent otherwise.
    if (protoProps && protoProps.hasOwnProperty('constructor')) {
      child = protoProps.constructor;
    } else {
      child = function() { parent.apply(this, arguments); };
    }

    // Inherit static properties from parent
    _.extend(child, parent);

    child.prototype = new parent();

    // Copy prototype properties if supplied
    if (protoProps) _.extend(child.prototype, protoProps);

    // Copy class properties if supplied
    if (classProps) _.extend(child, classProps);

    // Set child's prototype constructor
    child.prototype.constructor = child;

    // Set parent's prototype to child's super
    child.__super__ = parent.prototype;

    // Set child's extend to parent.extend
    child.extend = parent.extend;

    return child;
  };

  // Make class available
  this.Class = Class;

})();

// Sample usage
var Person = Class.extend({
  firstName: "",
  lastName: "",
  hello: function() {
    return "Hello, " + this.firstName + " " + this.lastName + "!";
  }
});

var Me = Person.extend({
  firstName: "Jesse",
  lastName: "Panganiban"
});

// Call hello
console.log(new Me().hello());  // Hello, Jesse Panganiban!