(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
	typeof define === 'function' && define.amd ? define(['exports'], factory) :
	(factory((global.PureDropdown = global.PureDropdown || {})));
}(this, (function (exports) {
    'use strict';
    /**
     * Questa libreria gestisce agilmente e senza requisiti iniziali dei menu a tendina custom.
     * Pensata per essere flessibile, ha delle classi sue di default e uno stile minimale per permettere 
     * di coprire una vasta varietà di casi.
     * @param  {...any} elements HTML Collection o Array di nodi
     */
    exports.PureDropdown = function PureDropdown(...elements) {
        let self = this;
        if(elements.length === 0) {
            elements = document.getElementsByClassName("pure-dropdown");
        };
        self.elements = elements;
        self.backdropHtml = `<div class="pure-dropdown-backdrop"></div>`;
        self.backdrop = undefined;
        self.originalContainerPosition = undefined;
        self.currentOpenDropdownTarget = undefined;
        self.currentActiveDropdown = undefined;
        self.activeClassName = undefined; //default: pure-dropdown-active
        self.openDropdownClassName = undefined; //default: pure-dropdown-open
        self.setElements = function(searchArea, ...elements) {
            if(elements.length === 0) {
                searchArea = searchArea ? searchArea : document.body;
                elements = searchArea.getElementsByClassName("pure-dropdown");
            };
            self.elements = elements;
        };
        /**
         * funzione che ritorna il parent che matcha il selettore (classe e id supportati) o il primo parent
         * se non trova nulla risale al body
         * @param {*} element 
         * @param {*} toMatch 
         * @returns 
         */
        self.getParentNode = function(element, toMatch=undefined) {
            if(!toMatch) {
                return element.nodeName === "BODY" ? element:  element.parentNode;
            } else {
                if(element.nodeName === "BODY") {
                    return element;
                }
                let parent = element.parentNode;
                if(toMatch[0] === ".") {
                    if(element.classList.contains(toMatch.substr(1))) {
                        return element;
                    }
                    while(!parent.classList.contains(toMatch.substr(1)) && parent.nodeName !== "BODY") {
                        parent = parent.parentNode;
                    }
                    return parent;
                } else if(toMatch[0] === "#") {
                    if(element.id === toMatch.substr(1)) {
                        return element;
                    }
                    while(!parent.id === toMatch.substr(1) && parent.nodeName !== "BODY") {
                        parent = parent.parentNode;
                    };
                    return parent;
                };
                return parent;
            };
        };
        /**
         * 
         * @param {*} selector un selettore css, al momento funzione limitata a id, classe e name passato come "[name=nome]"
         * @returns una HTMLCollection con gli elementi che matchano il selettore
         */
        self.getDropdownTargetElement = function(selector) {
            if(selector[0] === "#") {
                return document.getElementById(selector.substr(1));
            } else if(selector[0] === ".") {
                let collection = document.getElementsByClassName(selector.substr(1));
                return collection.length > 0 ? collection[0] : undefined; //per ora
            } else if(selector.indexOf("[") >= 0) {
                //console.log("SELECTOR BY NAME");
                //console.log(selector);
                selector = selector.replace("[", "").replace("]", "").split("=");
                //console.log(selector);
                if(selector[0] === "name") {
                    return document.getElementsByName(selector[1]);
                } 
            } 
            return document.getElementsByClassName(selector.substr(1));
        };
        /**
         * 
         * @param {*} zindexLevel un intero da passare che verrà assegnato allo z-index del backdrop, opzionale
         * crea il backdrop e gli attacca l'evento di chiusura del dropdown
         */
        self.applyCustomDropdownBackdrop = function(zindexLevel=undefined) {
            document.body.append(self.backdropHtml);
            self.backdrop = document.getElementsByClassName("pure-dropdown-backdrop");
            if(zindexLevel) {
                self.backdrop.style.zIndex = parseInt(zindexLevel, 10);
            }
            self.backdrop.addEventListener("click", self.closeDropdown.bind(self));
        };
        /**
         * rimuove il backdrop staccando da esso l'event listener
         */
        self.removeCustomDropdownBackdrop = function() {
            if(self.backdrop) {
                self.backdrop.removeEventListener("click", self.permanentlySelfBindedCloseDropdown);
                self.backdrop.remove();
                self.backdrop = undefined;
            };
        };
        /**
         * chiude il dropdown
         * @param {*} event 
         */
        self.closeDropdown = function(event) {
            let self = this;
            event.stopPropagation();
            let target = event.target;
            /*console.log(" === closeDropdown === ");
            console.log(event);
            console.log(self);*/
            if(event.type === 'pure-dd-close') {
                self.unsetCurrentActiveDropdown();
            } else {
                let closed = false;
                for(let f = 0; f<self.elements.length; f++) {
                    //console.log(self.elements[f]);
                    //console.log(self.elements[f] === target);
                    if(self.elements[f] === target) {
                        self.unsetCurrentActiveDropdown();
                        closed = true;
                        break;
                    }
                }
                if(!closed) {
                    let findParent = self.getParentNode(target, "." + self.openDropdownClassName);
                    /*console.log(findParent);
                    console.log(findParent.classList);
                    console.log(findParent.classList.contains(self.openDropdownClassName));
                    console.log(self.openDropdownClassName);*/
                    if(!findParent.classList.contains(self.openDropdownClassName)) {
                        self.unsetCurrentActiveDropdown();
                    };
                }
            };
        };
        /**
         * funzione chiamata dall' evento per aprire il dropdown
         * @param {*} event 
         */
        self.openDropdown = function(event) {
            event.stopPropagation();
            let target = event.target;
            if(!target.classList.contains(self.activeClassName)) {
                self.unsetCurrentActiveDropdown();
                self.setCurrentActiveDropdown(target);
            };
        };
        // bind crea nuove istanze della funzione, questo serve per ottimizzare gli eventi aggiunti da questa libreria
        self.permanentlySelfBindedCloseDropdown = self.closeDropdown.bind(self);
        self.permamentlyBindedOpenDropdown = self.openDropdown.bind(self);
        /**
         * imposta gli eventi di chiusura del menu a tendina.
         * pure-dd-close è un evento custom da emettere all' occorrenza per forzare la chiusura (pensato per quando si seleziona il menuitem)
         */
        self.setCloseEvents = function() {
            let self = this;
            if(!self.currentActiveDropdown.dataset.preventcloseonbodyclick) {
                document.body.addEventListener("click", self.permanentlySelfBindedCloseDropdown);
            };
            self.currentActiveDropdown.addEventListener("click", self.permanentlySelfBindedCloseDropdown);
            document.body.addEventListener("pure-dd-close", self.permanentlySelfBindedCloseDropdown);
        };
        /**
         * apre il menu a tendina impostando le referenze necessarie per ottimizzare le cose
         * e setta gli eventi di chiusura
         * @param {*} target DOM Element
         */
        self.setCurrentActiveDropdown = function(target) {
            let dropdownTarget = target.dataset.dropdownTarget;
            if(dropdownTarget) {
                self.activeClassName = target.dataset.dropdownActiveClass ? target.dataset.dropdownActiveClass : "pure-dropdown-active";
                self.openDropdownClassName = target.dataset.openDropdownClass ? target.dataset.openDropdownClass : "pure-dropdown-open";
                // absolute è default
                let dropdownBackdrop = target.dataset.dropdownBackdrop === "true" ? true : false;
                let dropdownTransition = target.dataset.dropdownTransition === "true" ? true : false;

                /*let targetParent = target.parentNode;
                let targetParentComputedStyle = targetParent.getComputedStyle();
                if(targetParentComputedStyle.getPropertyValue("position") === "static" || targetParent.style.position === "static") {
                    self.originalContainerPosition = "static";
                    targetParent.style.position = "relative";
                }*/
                self.currentOpenDropdownTarget = self.getDropdownTargetElement(dropdownTarget);
                console.log(self.currentOpenDropdownTarget);
                self.currentActiveDropdown = target;
                if(dropdownBackdrop) {
                    let zindexlevel = target.dataset.zindex ? target.dataset.zindex : undefined;
                    self.applyCustomDropdownBackdrop(zindexlevel);
                };
                self.currentOpenDropdownTarget.classList.add(self.openDropdownClassName);
                self.currentActiveDropdown.classList.add(self.activeClassName);
                self.setCloseEvents();
            } else {
                console.warn("No data-dropdown-target set on element");
            };
        };
        /**
         * chiude il dropdown e imposta allo stato iniziale le referenze, resettando eventualmente gli event listener
         */
        self.unsetCurrentActiveDropdown = function() {
            if(self.currentOpenDropdownTarget) {
                self.currentOpenDropdownTarget.classList.remove(self.openDropdownClassName);
                self.currentOpenDropdownTarget = undefined;
            };
            if(self.currentActiveDropdown) {
                self.currentActiveDropdown.classList.remove(self.activeClassName);
                self.currentActiveDropdown.removeEventListener("click", self.permanentlySelfBindedCloseDropdown);
                self.currentActiveDropdown = undefined;
            };
            self.removeCustomDropdownBackdrop();
            document.body.removeEventListener("click", self.permanentlySelfBindedCloseDropdown);
            document.body.removeEventListener("pure-dd-close", self.permanentlySelfBindedCloseDropdown);
            self.activeClassName = undefined;
            self.openDropdownClassName = undefined;
        };
        self.detachEvents = function() {
            Array.prototype.forEach.call(self.elements, (el) => {
                el.removeEventListener(el.dataset.customDropdownEvent || "click", self.permamentlyBindedOpenDropdown);
            });
        }
        // attacca gli handlers con l'evento specificato sugli elementi passati al costruttore
        // N.B. è possibile agganciare un evento diverso per ogni elemento tramite data-custom-dropdown-event="nome_evento";
        self.attachEvents = function() {
            Array.prototype.forEach.call(self.elements, (el) => {
                el.addEventListener(el.dataset.customDropdownEvent || "click", self.permamentlyBindedOpenDropdown);
            });
        };
        self.reset = function() {
            self.unsetCurrentActiveDropdown();
            if(self.elements) {
                self.detachEvents();
                self.elements = undefined;
            }
            self.backdropHtml = `<div class="pure-dropdown-backdrop"></div>`;
            self.backdrop = undefined;
            self.originalContainerPosition = undefined;
            self.currentOpenDropdownTarget = undefined;
            self.currentActiveDropdown = undefined;
            self.activeClassName = undefined; //default: pure-dropdown-active
            self.openDropdownClassName = undefined; //default: pure-dropdown-open
        }
    };
})))