function sqSelector(element) {
    this.selectorElement = $(element);
    this.selectedIndex = -1;
    this.enableHover = true;
    this.showGroups = true;
    this.itemsArray = [];
    this.groupsArray = [];
    this.onClickEvent = undefined;
    this.catchKeyEvents = false;

    this.selectorElement.addClass("sq-selector");

    var thisComponent = this;

    this.selectorElement.on("mouseover", function (e) {
        if (e.target.classList.contains("item")) {
            thisComponent.selectedIndex = e.target.dataset.index;
            $(thisComponent.selectorElement).find(".item").removeClass("active");
            $(e.target).addClass("active");
        }
    });

    this.selectorElement.on("mouseout", function (e) {
    });

    this.selectorElement.on("click", function (e) {
        if (e.target.classList.contains("item")) {
            thisComponent.selectedIndex = e.target.dataset.index;
            if (thisComponent.onClickEvent != undefined) {
                thisComponent.onClickEvent(thisComponent.itemsArray[e.target.dataset.index]);
            }
        }
    });

    $(document).on("keydown", function (e) {
        if (!thisComponent.catchKeyEvents) {
            return;
        }

        if (e.key == "Enter") {
            if (thisComponent.selectedIndex != -1) {
                if (thisComponent.onClickEvent != undefined) {
                    thisComponent.onClickEvent(thisComponent.itemsArray[thisComponent.selectedIndex]);
                }
            }
        }

        if (e.key == "ArrowUp") {
            if (thisComponent.selectedIndex == -1) {
                thisComponent.selectedIndex = 0;
            }
            if (thisComponent.selectedIndex > 0) {
                thisComponent.selectedIndex--;
            }

            thisComponent.markItemByIndex(thisComponent.selectedIndex);
            thisComponent.scrollToItemByIndex(thisComponent.selectedIndex);
            e.preventDefault();
        }

        if (e.key == "ArrowDown") {
            if (thisComponent.selectedIndex == -1) {
                thisComponent.selectedIndex = 0;
            }
            if (thisComponent.selectedIndex < thisComponent.itemsArray.length - 1) {
                thisComponent.selectedIndex++;
            }

            thisComponent.markItemByIndex(thisComponent.selectedIndex);
            thisComponent.scrollToItemByIndex(thisComponent.selectedIndex);
            e.preventDefault();
        }

        if (e.key == "Home") {
            thisComponent.selectedIndex = 0;

            thisComponent.markItemByIndex(thisComponent.selectedIndex);
            thisComponent.scrollToItemByIndex(thisComponent.selectedIndex);
            e.preventDefault();
        }

        if (e.key == "End") {
            thisComponent.selectedIndex = thisComponent.itemsArray.length - 1;

            thisComponent.markItemByIndex(thisComponent.selectedIndex);
            thisComponent.scrollToItemByIndex(thisComponent.selectedIndex);
            e.preventDefault();
        }

    });
}

sqSelector.fn = sqSelector.prototype;

sqSelector.fn.loadItems = function (items) {
    this.itemsArray = items;
    // format: {name: name, value: value, group: group}

    if (this.showGroups) {
        this.groupsArray = [];
        for (let i = 0; i < this.itemsArray.length; i++) {
            if ("group" in this.itemsArray[i] && this.groupsArray.indexOf(this.itemsArray[i].group) < 0) {
                this.groupsArray.push(this.itemsArray[i].group);
            }
        }
    }

    let newInnerHtml = "";

    if (this.showGroups && this.groupsArray.length > 0) {
        for (let i = 0; i < this.groupsArray.length; i++) {
            newInnerHtml += '<div class="group">' + this.groupsArray[i] + '</div>';
            for (let j = 0; j < this.itemsArray.length; j++) {
                if (this.itemsArray[j].group == this.groupsArray[i]) {
                    newInnerHtml += '<div class="item" data-index="' + j + '" data-value="' + this.itemsArray[j].value + '">' + this.itemsArray[j].name + '</div>';
                }
            }
        }
    }
    else {
        for (let i = 0; i < this.itemsArray.length; i++) {
            newInnerHtml += '<div class="item" data-index="' + i + '" data-value="' + this.itemsArray[i] + '">' + this.itemsArray[i] + '</div>';
        }
    }

    this.selectorElement.html(newInnerHtml);

    this.selectedIndex = 0;
}

sqSelector.fn.markItemByIndex = function (index) {
    this.selectedIndex = index;
    this.selectorElement.find(".item").removeClass("active");
    this.selectorElement.find(".item[data-index=" + index + "]").addClass("active");
}

sqSelector.fn.markItemByValue = function (newValue, scrollToo) {
    for (let i = 0; i < this.itemsArray.length; i++) {
        if (this.itemsArray[i].value == newValue) {
            this.markItemByIndex(i);
            if (scrollToo) {
                this.scrollToItemByIndex(i);
            }
            return;
        }
    }
}

sqSelector.fn.getSelectedItem = function () {
    if (this.selectedIndex != -1) {
        return this.itemsArray[this.selectedIndex];
    }
    else { return false; }
}

sqSelector.fn.scrollToItemByIndex = function (index) {
    let elementTop = this.selectorElement.find(".item[data-index=" + index + "]").position().top;
    if (elementTop < 0) {
        let scrollTo = (index == 0) ? 0 : (this.selectorElement.scrollTop() + this.selectorElement.find(".item[data-index=" + index + "]").position().top);
        this.selectorElement.scrollTop(scrollTo);
    }
    else if (elementTop > this.selectorElement.height() - this.selectorElement.find(".item[data-index=" + index + "]").height()) {
        let scrollTo = (index == 0) ? 0 : (this.selectorElement.scrollTop() + this.selectorElement.find(".item[data-index=" + index + "]").position().top - this.selectorElement.height() + this.selectorElement.find(".item[data-index=" + index + "]").height());
        this.selectorElement.scrollTop(scrollTo);
    }
    // console.error(this.selectorElement.scrollTop(), this.selectorElement.find(".item[data-index=" + index + "]").position().top);
    // 
    // 

    /*     this.selectorElement.stop().animate({
            scrollTop: posTop
        }, 0); */
}

