(function(w){
	var Framework=function(el){
		return Framework.fn.init(el);
	}
	Framework.__proto__ = Framework.prototype = {};
	Framework.v={};
	Framework.f={};
	Framework.f.init=function(el){

	};
	Framework.fn.extend=function(name,func){
		if((typeof name) == "string"){
			Framework.extend(Framework.fn,{name:func});
		}else if((typeof name) == "object"){
			for (var n in name){
				Framework.fn.extend(n,name[n]);
			}
		}
		return Framework.fn;
	};
	Framework.extend=function(name,func){
		if((typeof name) == "string"){
			Framework[name] = func;
		}else if(typeof name === typeof func === "object"){
			$keys=Object.keys(func);
			for(var i=0; i<$keys.length; i++){
				var n=$keys[i];
				var v=func[n];
				name[n] = v;
			}
		}
		return Framework;
	};
	Framework.extend(Framework.fn,{
		ready: function(callback){
			this[0].addEventListener('readystatechange', e => {
				if(this[0].readyState === "complete"){
					callback();
					return true;
				}
			  });
		},
		each: function(callback) {
			if (callback && typeof(callback) == 'function') {
				for (let i = 0; i < this.length; i++) {
					callback(this[i], i);
				}
				return this;
			} 
		},
		siblings: function(){
			return  [...this[0].parentNode.children].filter(c=>c!=this[0])
		},
		addClass: function(className) {
			this.each(function(el) {
				el.classList.add(className);
			})
			return this;
		},
		removeClass: function(className) {
			this.each(function(el) {
				el.classList.remove(className);
			})
			return this;
		},
		hasClass: function(className) {
			return this[0].classList.contains(className);
		},
		css: function(propertyObject) {
			this.each(function(el) {
				Object.assign(el.style,propertyObject);
			 })
			 return this;
		},
		attr: function(attr, value = null) {
			let getattr = this;
			if (value){
				this.each(function(el) {
					el.setAttribute(attr, value);
		
				});
			} else {
					getattr = this[0].getAttribute(attr);
			}
			return getattr;
		},
		html: function(data) {
			if (data) {
				this.each(function(el) {
					el.innerHTML = data;
				})
			} else {
				return this[0].innerHTML;
			}
			return this;
		},
		prepend: function(el){
			this[0].prepend(el);
			return this;
		},
		append: function(el){
			this[0].append(el);
			return this;
		},
		hide: function() {
			this.each(function(el) {
				el.style.display = "none";
			});
			return this;
		},
		show: function() {
			this.each(function(el) {
				el.style.display = "block";
			});
			return this;
		},
		on: function(event, child, callback = null) {
			if (callback != null) {
				let selector = child;
				this.each(function(element) {
					element.addEventListener(event, function(event) {
						if (event.target.matches(selector + ', ' + selector + ' *')) {
							callback.apply(event.target.closest(selector), arguments);
						}
					})
				})
			} else {
			//if the callback argument is not present then assume  the child argument is being use as callback
				callback = child;
				this.each(function(element) {
					element.addEventListener(event, callback);
				})
			}
		
			return this;
		}
	});
	Framework.ajax=function(args) {
        let url = args["url"];
        let type = "get";
        let success =function(){};
        let fail = function(){};
        if(args['success']){
            success=args['success'];
        }
        if(args['fail']){
            fail=args['fail'];
        }
        let xhttp = new XMLHttpRequest();
        xhttp.onerror = function(error){
        //return fial callback with error 
            return fail(error);
        }
        xhttp.onload = function() {
            let response;
            if (this.readyState == 4 && this.status == 200) {
                let response="";
                try {
                //check if the response in json 
                //if json the parse it
                    response=JSON.parse(this.responseText)
                } catch (e) {
                //if not json the simple reurn the response
                    response = this.responseText;
                    }
                 // give a success callback
                return success(response);
            } else {
            //give a fail callback with the error status 
                return fail(this.status);
            }
        };
        let parameters="";
        if (args) {
            type = args["type"];
            if ('data' in args) {
            //converting object to url URLSearchParams
                parameters = new URLSearchParams(args['data']).toString();
            }

        }
        if (type && type.toUpperCase()=='POST') {
            xhttp.open("POST", url, true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send(parameters);
        } else if (!type || type.toUpperCase()=='GET'){
            xhttp.open("GET", url + "?" + parameters, true);
            xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhttp.send();
        }
    }
	window.Framework &= Framework;
})(window);