/**
     * Validations Facade. All the validation rules go here.
     */
    Y.ValidationFacade = Y.Base.create("ValidationFacade", Y.Base, [], {

        validations: {
            trim: function(key, val, attrs) {
                if (!val) {
                    val = "";
                }
                return val.trim();
            },
            required: function(key, val, attrs) {
                if (typeof val === "undefined" || !val) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> can not be empty", {
                            s: this.titlize(key)
                        })
                    };

                }
                return val;
            },
            max: function(key, val, attrs, a) {
                var args = a.replace("(", "").replace(")", "").split(",");
                if (parseInt(args[0], 10) < val.length) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> can not be longer than {L} chars", {
                            s: this.titlize(key),
                            L: args[0]
                        })
                    };
                }
                return val;
            },
            min: function(key, val, attrs, a) {
                var args = a.replace("(", "").replace(")", "").split(",");
                
                if (parseInt(args[0], 10) > val.length) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> can not be shorter than {L} chars", {
                            s: this.titlize(key),
                            L: args[0]
                        })
                    };
                }
                return val;
            },
            email: function(key, val, attrs) {
                var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
                if (!reg.test(val)) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> is not a valid email address", {
                            s: this.titlize(key)
                        })
                    };
                }
                return val.toLowerCase();
            },
            match: function(key, val, attrs, a) {
                var args = a.replace("(", "").replace(")", "").split(",");
                if (!attrs[args[0]] || attrs[args[0]] !== val) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> does not match with {L}", {
                            s: this.titlize(key),
                            L: this.titlize(args[0])
                        })
                    };
                }
            },
            numeric: function(key, val, attrs) {
                var reg = /^([0-9])$/;
                if (!reg.test(val)) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> is not a number", {
                            s: this.titlize(key)
                        })
                    };
                }
                return val;
            },
            string: function(key, val, attrs) {
                var reg = /^([A-Za-z])$/;
                if (!reg.test(val)) {
                    throw {
                        target: key,
                        val: val,
                        message: Y.Lang.sub("<strong>{s}</strong> is not a string", {
                            s: this.titlize(key)
                        })
                    };
                }
                return val;
            },
            /**
             * Uniqueness is a server only valdiation though it is transparently to the user.
             * @param a: "DocumentType,key"
             */
            unique: function(key, val, attrs) {
                var output;
                output = Y.api.invoke("/user/is_taken", {
                    key: key,
                    val: val
                });
               
                if (typeof output !== "undefined" && output !== false) {
                    if (output.taken === true) {
                        throw {
                            target: key,
                            val: val,
                            message: Y.Lang.sub("<strong>{s}</strong> is taken", {
                                s: this.titlize(key)
                            })
                        };
                    }
                }
                return val;
            }


        },
        titlize: function(str) {
            str = str.replace(/_/g, " ");
            return str.replace(/\w\S*/g, function(txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            });

        },
        checkValidity:function(){ 
        	var errors = this.validate(this.getAttrs());
        	if(typeof errors ==="undefined" || errors===null){
        		return;
        	}
        	else{
        		return errors;
        	}
        	
        }
        

    });

/*
     * The CommonModel class represents the base Model for our application which supports our customized validation framework as well
     * @class  CommonModel
     * @extends AshleshaBaseModel
     * @uses
     * @constructor
     * @cfg {attrs:{
     *         attr_name:{
     *         value:'default value',
     *         validation_rules:'trim|required|numeric',
     *         hash:[true|false]
     *         save:[true,false]
     * }
     * }} configuration attributes
     *
     */
    Y.CommonModel = Y.Base.create("CommonModel", Y.AshleshaBaseModel, [Y.ValidationFacade], {
        initializer: function(config) {
            var attrs = this.get("attrs") || (config && config.attrs);

            if (attrs) //We supply attributes as initialization parameters along with
            {
                this.set("attrs", Y.clone(attrs));
                this.addAttrs(attrs);

            }

        },
        validate: function(attrs,callback) {
        	var attrConfig = this.get("attrs"),
                errors = [];
            if (attrConfig) {

                Y.Object.each(attrConfig, function(val, key) {
                    var v = val.validation_rules,
                        rules;

                    //If the validation rule chain is specified
                    if (v) {
                        rules = v.split("|");

                        try {

                            Y.Array.each(rules, function(item, index) {
                                var args = item.match(/\(.*\)/),
                                    f;
                                if (!args) {
                                    val = this.validations[item].apply(this, [key, attrs[key], attrs]);
                                }
                                else {
                                    f = item.match(/^(.*)(:?\(.*)/);

                                    //Teh function name max where the item = max(10)
                                    val = this.validations[f[1]].apply(this, [key, attrs[key], attrs, f[2]]);
                                }

                            }, this);

                        } catch (ex) {

                            errors.push({
                                field: key,
                                error: ex
                            });
                        }

                    }
                }, this);
            }
            if (errors.length > 0) {
                callback && callback(errors);
                return errors;
            }
            else
            {
            	callback && callback();
            }
        }
        
    	
    });






//EXAMPLE MODEL

Y.WREntryModel = Y.Base.create("WREntryModel", Y.CommonModel, [], {
        initializer: function() {
            Y.PostModel.superclass.initializer.apply(this, [{
                attrs: {

                    posttext: {
                        value: '',
                        validation_rules: "trim|required|min(8)"
                    },
                    image: {
                        value: ''
                    },
                    comments_count: {
                        value: 0
                    },
                    comments: {
                        value: []
                    },
                    likes: {
                        value: []
                    },
                    shares: {
                        value: []
                    },
                    tType: { //tType refers to the category of the post.
                        value: ''
                    },
                    section:{ //Each entry belongs to a section. For example "Mobile Phones" is a section
                    	value:''
                    	validation_rules: "trim|required"
                    },
                    brand_name:{ //Each product may be associated with a brand_name
                    	value:'',
                    	validation_rules: "trim|required"
                    },
                    section_id:{	//For future sake we also store the section_id if present
                    	value:''
                    },
                    brand_id:{ //For futures sake
                    	value:''
                    },
                    purchased_at:{ //location_id
                    	value:''
                    }
                    
                    

                }}]);
        }
    });