var tagStack = {

}

module.exports = function () {
    var hasClass = function (el, className) {
        return el && el.classList && el.classList.contains(className);
    };
    var removeElement = function (el) {
        el.parentNode.removeChild(el);
    };
    var getClosest = function (elem, selector) {

        // Element.matches() polyfill
        if (!Element.prototype.matches) {
            Element.prototype.matches =
                Element.prototype.matchesSelector ||
                Element.prototype.mozMatchesSelector ||
                Element.prototype.msMatchesSelector ||
                Element.prototype.oMatchesSelector ||
                Element.prototype.webkitMatchesSelector ||
                function (s) {
                    var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                        i = matches.length;
                    while (--i >= 0 && matches.item(i) !== this) { }
                    return i > -1;
                };
        }

        // Get the closest matching element
        for (; elem && elem !== document; elem = elem.parentNode) {
            if (elem.matches(selector)) return elem;
        }
        return null;

    };
    var setClassName = function (element, className) {
        element.className = className;
    };
    var setInnerHtml = function (element, html) {
        element.innerHTML = html;
    };
    var createElement = function (tag, parent) {
        var element = document.createElement(tag);
        if (parent)
            parent.appendChild(element);
        return element;
    };
    var createTag = function (obj) {
        var element = document.createElement(obj.name);
        if (obj.className)
            element.className = obj.className;
        if (obj.id)
            element.id = obj.id;
        if (obj.styles)
            element.setAttribute("style", obj.styles);
        else
            element.setAttribute("style", "");
        if (obj.text)
            element.innerText = obj.text;
        if (obj.html)
            element.innerHTML = obj.html;
        if (obj.value)
            element.value = obj.value;
        if (obj.attributes)
            setAttributes(element, obj.attributes);
        if (obj.attach !== false) {
            if (obj.addBefore)
                obj.parent.prepend(element);
            else
                obj.parent.appendChild(element);
        }
        if (obj.onclick)
            element.onclick = obj.onclick;
        if (obj.ondblclick)
            element.ondblclick = obj.ondblclick;


        if (obj.children) {
            for (var i = 0; i < obj.children.length; i++) {
                obj.children[i].parent = element;
                createTag(obj.children[i]);
            }
        }



        return element;
    }
    var cloneTag = function (obj) {
        var element;
        if (tagStack[obj.className])
            element = tagStack[obj.className].cloneNode();
        else
            element = document.createElement(obj.name);
        if (obj.className)
            element.className = obj.className;
        if (obj.styles)
            element.setAttribute("style", obj.styles);
        if (obj.text)
            element.innerText = obj.text;
        element.value = obj.value;
        if (obj.attributes)
            setAttributes(element, obj.attributes);
        obj.parent.appendChild(element);
        if (!tagStack[obj.className])
            tagStack[obj.className] = element;
        return element;
    }
    var setAttributes = function (el, args) {
        for (var k in args) {
            if (args.hasOwnProperty(k)) {
                var val = args[k];
                el.setAttribute(k, val);
            }
        }
    };
    return {
        hasClass: hasClass,
        removeElement: removeElement,
        getClosest: getClosest,
        setClassName: setClassName,
        setInnerHtml: setInnerHtml,
        createElement: createElement,
        cloneTag: cloneTag,
        createTag: createTag,
        setAttributes: setAttributes
    };
}();

Array.prototype.remove = function (val) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] === val) {
            this.splice(i, 1);
            i--;
        }
    }
    return this;
}