// # VNLS 
// Singleton providing helper functions
// VNLS is the one namespace object which contains
// all references to used objects.
// The goal is to leave all standard javascript intact and
// not to interfere nor extend 'basic' global javascript
// or any other library.
// It acts as a small independend Framework
// 
// Food for Thoughts 
// In a nodejs environment there are multiple users, needing 'personal' objects
// On the client site only one user needs refrences to single objects (most of the time)
// 
// I think its best to Load Class definitions and create objects from there
// The framework itself could kept clean
// So lets make a way to load class definitions
// Extend Classes, and extend objects created form this classes.


var VNLS = new function(){
    // Private object containing all references to models
	var MODELS = {};
	var CONTROLLERS = {};
	var CLASSES = {};
	var SELF = this;
	
	function _VnlsFrameWork(){
	
	}
	
	// ---------------------
	// ## Public methods
	// ---------------------
	//
	// ### VNLS.extend(object,object)
	// Extend child with parent
	// returns a 'better' child object
	// But we need to refactor this
    _VnlsFrameWork.prototype.extend = function(child, parent) {
        for (var key in parent) {
            if (Object.hasOwnProperty.call(parent, key)) {
                child[key] = parent[key];
            }
        }
        function ctor() {
            this.constructor = child;
        }
        ctor.prototype = parent.prototype;
        child.prototype = new ctor;
        child.__super__ = parent.prototype;
        return child;
    };
    
    _VnlsFrameWork.prototype.addClass = function(class_name,fn){
        if(CLASSES.hasOwnProperty(class_name)){
            throw "Class allready registerd: "+class_name;
        }
        CLASSES[class_name] = fn();
    }
    // ## VNLS.getObject(string class_name,[arguments ...])
    // Get a Class definition and create an new object with it
    // If this class has a method 'init', init is called
    // applying the arguments.
    _VnlsFrameWork.prototype.getObject = function(class_name){
        // Need to slice the arguments and chop of the first,
        // pass the rest to the INIT declaration ?
        // Unsure about the local var ob
        // Does is get carbage collected as it holds a reference
        var pass_prams = [];
        for(var i = 0, len = arguments.length; i < len; i++){
            if(i>0){
                pass_prams.push(arguments[i]);
            }
        }
        if(CLASSES.hasOwnProperty(class_name)){
             var ob = new CLASSES[class_name]();
             if(typeof(ob.init)=='function'){
                    ob.init.apply(ob, pass_prams);
              }
              return ob;
        }else{
            throw "Class not found:"+class_name;
        }
    }
    
	_VnlsFrameWork.prototype.createModel = function (model_structure,ext_ob){
	    if(MODELS.hasOwnProperty(model_structure.name)){
	       throw "Model allready registerd";
	    }
	    MODELS[model_structure.name] = VNLS.getObject("Model",model_structure);
	    if(ext_ob){
	       VNLS.extend(MODELS[model_structure.name],new ext_ob);
	    }
        return this.getModel(model_structure.name);
    };
    // ### VNLS.getModel(string modenlame)
    // Get a reference to the model by name
    // throws an error when the model doen't exsist
    _VnlsFrameWork.prototype.getModel = function(model_name){
        if(MODELS.hasOwnProperty(model_name)){
            return MODELS[model_name];
        }else{
            throw "Model not found:"+model_name;
        }
    };
    
    _VnlsFrameWork.prototype.addController = function(controller_name,fn){
        if(CONTROLLERS.hasOwnProperty(controller_name)){
            throw "Controller allready registerd: "+controller_name;
        }
        CONTROLLERS[controller_name] = fn();
    }
    
    _VnlsFrameWork.prototype.getController = function(controller_name){
        // Need to slice the arguments and chop of the first,
        // pass the rest to the INIT declaration ?
        // Unsure about the local var ob
        // Does is get carbage collected as it holds a reference
        var pass_prams = [];
        for(var i = 0, len = arguments.length; i < len; i++){
            if(i>0){
                pass_prams.push(arguments[i]);
            }
        }
        if(CONTROLLERS.hasOwnProperty(controller_name)){
             var ob = new CONTROLLERS[controller_name]();
             if(typeof(ob.init)=='function'){
                    ob.init.apply(ob, pass_prams);
              }
              return ob;
        }else{
            throw "Controller not found:"+controller_name;
        }
    }
    
    // Chop OF spaces before and after chars
    _VnlsFrameWork.prototype.trim = function(str){
          return str.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
        
    }
    
    _VnlsFrameWork.prototype.checkEmail = function(str){
        var regx = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;
        return regx.test(str);
    }
    
    
    return  new _VnlsFrameWork();
}

