/*
lib.js 0.1
(c) 2011 TORRES Frederic
lib.js is freely distributable under the MIT license.
*/
function print(s) {
    if (console !== undefined)
        console.log(s);
}
function isNodeJs() {
    return (typeof require === "function" && typeof Buffer === "function" && typeof Buffer.byteLength === "function" && typeof Buffer.prototype !== "undefined" && typeof Buffer.prototype.write === "function");
}
function isBrowser() {
    return (typeof window !== undefined);
}
lib = (function () {

    var _lib      = {};
    _lib.Version  = "1.0";
    _lib.debug    = true;

    _lib._log = function (message) {

        if (isBrowser()||isNodeJs()) {
            console.log(message);
        }
    }
    _lib.TRACE = function (message) {

        var now         = new Date();
        var callerName  = "";

        try{ callerName = arguments.callee.caller.name } catch(ex){}

        var msg = "["+now+"]["+callerName+"]"+(message===undefined ? "":message);

        if (this.debug) {
            this._log(msg);
        }
    }
    _lib.isNodeJs = function () {
        return (typeof require === "function" && typeof Buffer === "function" && typeof Buffer.byteLength === "function" && typeof Buffer.prototype !== "undefined" && typeof Buffer.prototype.write === "function");
    }
    _lib.isBrowserMode = function (){
        try{
            return (window!=null);
        }
        catch(ex){
            return false;
        }
    }
    return _lib; // Return the lib object
})();

///////////////////////////////////////////////////////////////////////////////
/// Date
///////////////////////////////////////////////////////////////////////////////
Date.isDate = function (d){
    try{
        if((d===null) || (d===undefined) || (typeof d === "number") || (typeof d === "boolean")) return false;
        var s  = new Date(d);
        var ss = s.toString();
        return !(ss== "NaN" || ss == "Invalid Date");
    }
    catch(ex){
        return false;
    }
}
///////////////////////////////////////////////////////////////////////////////
/// ARRAY
///////////////////////////////////////////////////////////////////////////////

Array.range = function(max, inc) {

    if (inc===undefined)
        inc=1;
    a = [];
    for (i=0; i<max; i++)
        a.push(i);
    return a;
}
// http://snook.ca/archives/javascript/testing_for_a_v
Array.list = function(a) {

    if(Array.isArray(a)){
        var o = {};
        for(var i=0;i<a.length;i++)
            o[a[i]] = null;
        return o;
    }
    else{
        var argumentsArray = [];
    	for(var i=0; i<arguments.length; i++)
            argumentsArray.push(arguments[i]);
        return Array.list(argumentsArray);
    }
}
///////////////////////////////////////////////////////////////////////////////
///
Array.build = function(a,v){

    if((a===undefined)||(a===null))
        return [v];
    else {
        a.push(v);
        return a;
    }
}
///////////////////////////////////////////////////////////////////////////////
///
Array.prototype.findFirst = function (f){

    for(var i=0; i<this.length; i++)
        if(f(this[i]))
            return true;
    return false;
}
///////////////////////////////////////////////////////////////////////////////
///
if (typeof Array.contains !== 'function') {
    Array.prototype.contains=function(v){
        if (v===undefined)
            throw "parameter v must be defined"
        for (i=0; i<this.length; i++)
            if (this[i]===v)
                return true;
        return false;
    }
}
///////////////////////////////////////////////////////////////////////////////
///
Array.prototype.format = function (fmt){

    if(fmt===undefined){
        return "[ " + this.join(", ") + " ]";
    }
    else{
        var s = "";
        for(var i=0; i<this.length; i++)
            s += fmt.format(this[i]);
        return s;
    }
}

///////////////////////////////////////////////////////////////////////////////
/// OBJECT
///////////////////////////////////////////////////////////////////////////////
/*
if (typeof Object.prototype.In !== 'function') {
    Object.prototype.In=function(a){
        if(a===undefined)
            throw "parameter a must be defined"
        for (i=0; i<a.length; i++)
            if (a[i]==this)
                return true;
        return false;
    }
}
if (typeof Object.keys !== 'function') {
    Object.keys = function (o) {
        var array = [], key;
        for (key in o)
            if (Object.prototype.hasOwnProperty.call(o, key))
                array.push(key);
        return array;
    };
}
*/
///////////////////////////////////////////////////////////////////////////////
///
if (typeof Object.FunctionName !== 'function') {

    Object.FunctionName = function (fn) {

        var name=/\W*function\s+([\w\$]+)\(/.exec(fn);
        if(!name)return 'No name';
        return name[1];
    }
}

///////////////////////////////////////////////////////////////////////////////
/// the word class and super are reserved and cannot be used as parameter name
if (typeof Object.Inherit !== 'function') {

    Object.Inherit = function (Super, Class, printMethod) {

        printMethod = (typeof printMethod === "boolean") ? printMethod : false;
        if(printMethod)
            print("Inherit "+Object.FunctionName(Class)+" : "+Object.FunctionName(Super));

        for (var method in Super.prototype) {
            if(printMethod)
                print("  "+method);
            Class.prototype[method] = Super.prototype[method];
        }
    }
}



///////////////////////////////////////////////////////////////////////////////
/// String Extensions
///////////////////////////////////////////////////////////////////////////////
String.prototype.LeftPad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = padString + str;
    return str;
}
String.prototype.RightPad = function(padString, length) {
    var str = this;
    while (str.length < length)
        str = str + padString;
    return str;
}
String.prototype.Trim       = function()    { return this.replace(/^\s+|\s+$/g,""); }
String.prototype.LeftTrim   = function()    { return this.replace(/^\s+/,"");       }
String.prototype.RightTrim  = function()    { return this.replace(/\s+$/,"");       }



///////////////////////////////////////////////////////////////////////////////
//
String.prototype.startsWith = function(str){ return (this.indexOf(str) === 0); }
String.prototype.endsWith   = function(str){
    var lastIndex = this.lastIndexOf(str);
    return (lastIndex != -1) && (lastIndex + str.length == this.length);
}

///////////////////////////////////////////////////////////////////////////////
// format()
//
// Usage:
//      "LastName:{lastName}, Age:{Age}".format({ lastName:"TORRES", Age:45 });
//
//      "LastName:{0}, Age:{1}".format("TORRES", 45);
//
String.prototype.format = function ()
{
    var txt = this;

    // Pass one instance
    if((arguments.length===1)&&(typeof arguments[0] === "object")&&(!Array.isArray(arguments[0]))){

        for(var i=0;i<arguments.length;i++) {
            var instance = arguments[i];
            for(var p in instance){
                txt = txt.replace(new RegExp('{'+p+'}','g'), instance[p]);
            }
        }
    }
    else{
        for(var i=0;i<arguments.length;i++){

            var v = arguments[i];
            if(Array.isArray(v))
                v = v.format(); // format the array to a string
            txt = txt.replace(new RegExp('\\{' + (i) + '\\}','gm'), v);
        }
    }
    return txt;
}
///////////////////////////////////////////////////////////////////////////////
/// isArray as a static method
if (typeof Array.isArray !== 'function') {
    Array.IsArray = function (o) {
        return Object.prototype.toString.apply(o) === '[object Array]';
    };
}
///////////////////////////////////////////////////////////////////////////////
// String.format()
//
// Usage:
//      String.format("LastName:{0}, Age:{1}", "TORRES", 45);
//
String.format = function ()
{
    for(var i=1;i<arguments.length;i++)
    	arguments[0] = arguments[0].replace(new RegExp('\\{' + (i-1) + '\\}','gm'),arguments[i]);
    return arguments[0];
}


