/**
 * Basic CWIS functions for Javascript.
 *
 * Part of the Collection Workflow Integration System (CWIS)
 * Copyright 2011 Internet Scout Project
 * http://scout.wisc.edu
 */

var cw = {};
/**
 * Log a warning and optional information to the console.
 * @param message:string warning message
 * @param ...:mixed optional information to log
 */
cw.warning = function(message) {
    var info;

    if (arguments.length > 1) {
        info = Array.prototype.slice.call(arguments);

        // remove the message from the info. it's logged separately
        info.shift();

        console.warn(message, info);
    } else {
        console.warn(message);
    }
};

/**
 * Log an error and optional information to the console. Throws an exception.
 * @param message:string error message
 * @param ...:mixed optional information to log
 */
cw.error = function(message) {
    var info;

    if (arguments.length > 1) {
        info = Array.prototype.slice.call(arguments);

        // remove the message from the info. it's logged separately
        info.shift();

        console.error("Error Details:", info);
    }

    throw message;
};

/**
 * Extend a subclass to inherit another class' private methods, privileged
 * methods and data members.
 * http://blog.reinpetersen.com/2008/12/work-around-for-common-inheritance.html
 * @param subclass:Object_reference subclass class
 * @param base:Object_reference parent class
 */
cw.extend = function(subclass, base) {
    function Closure(){}
    Closure.prototype = base.prototype;
    subclass.prototype = new Closure();
    subclass.prototype.constructor = subclass;
    subclass.base = base;
};

/**
 * Construct a callback referring the method of a instantiated object.
 * Additional arguments to this function will be used as arguments to the
 * callback. The additional arguments will come before any arguments passed to
 * the callback when executed. For example, if passing the integer "1" as an
 * additional argument, the callback this function returns will pass in the
 * integer "1" as the first argument and then any other arguments passed in at
 * the time it was called.
 * @param object object an instantiated object
 * @param function method a method (function) of the object
 * @param ... additional arguments
 * @return a callback for the method of the object
 */
cw.bindObjectMethodCallback = function(object, method) {
  var parameters = Array.prototype.slice.call(arguments).slice(2);

  return function(){
    return method.apply(
      object,
      parameters.concat(Array.prototype.slice.call(arguments).slice(0)));
  };
};

/**
* Get the base URL for the page.
* @return Returns the base URL for the page.
*/
cw.getBaseUrl = function() {
  var url;

  // if the base URL global is set
  if (typeof CWIS_BASE_URL != "undefined") {
    return CWIS_BASE_URL;
  }

  // otherwise try to get the base URL from the current URL
  url = window.location.pathname;
  url = url.substring(0, url.lastIndexOf("/")+1);

  return url;
};

/**
* Get the URL for the CWIS router page.
* @return Returns the URL for the CWIS router page.
*/
cw.getRouterUrl = function() {
  return cw.getBaseUrl() + "index.php";
};

(function(cw){

var Modules = {};

/**
 * Provide a named module for CWIS.
 * @param name:string module name
 * @param module:function module
 */
cw.provide = function(name, module) {
    if (typeof module != "function") {
        cw.error("Module isn't a function", {"name": name, "module": module});
    }

    Modules[name] = module;
};

/**
 * Retrieve a provided module.
 * @param name:string module name
 * @return reference reference to the module
 */
cw.require = function(name) {
    if (!Modules[name]) {
        cw.error("Module is unavailable.", {"name": name});
    }

    return new Modules[name];
};

}(cw));
