(function($){

    //add class of js to html tag
    $('html').addClass('js');

    //create cross-browser indexOf
    Array.prototype.indexOf = function (obj, start) {
        for (var i = (start || 0); i < this.length; i++) {
            if (this[i] == obj) {
                return i;
            }
        }
    }
    
    $.fn.sSelect = function(options) {
        return this.each(function(){
            
            var defaults = {
                defaultText: 'Please select',
                animationSpeed: 0, //set speed of dropdown
                ddMaxHeight: '', //set css max-height value of dropdown
                minListWidth: 150, //minimalna sirka zoznamu poloziek
                width: 0 //sirka selectu - ak nie je zadana, prisposobi sa podla original
            };

            //initial variables
            var opts = $.extend(defaults, options),
                $input = $(this),
                inputWidth = $(this).width() + 20,
                $containerDivText = $('<div class="text"></div>'),
                $containerDivTrigger = $('<div class="trigger"></div>'),
                $containerDiv = $('<div class="sselect-container"></div>'),
                $newUl = $('<ul class="sselect-list"></ul>'),
                itemIndex = -1,
                currentIndex = -1,
                keys = [],
                prevKey = false,
                newListItems = '',
                prevented = false;
            //prevezmeme sirku zo selectu
            if (jQuery.browser.msie) {
                inputWidth -= 20;
            }
            if (opts.width) {
                inputWidth = opts.width;
            }
            $containerDiv.width(inputWidth);
            if (inputWidth < opts.minListHeight) {
                $newUl.width(opts.minListHeight);
            } else {
                $newUl.width(inputWidth);
            }
            
            //build new list
            $containerDiv.insertAfter($input);
            $containerDiv
                .append($containerDivText)
                .append($containerDivTrigger);
            $('body').append($newUl);
            $newUl.keydown(keyPress);
            $input.hide();
            
            //optgroup - not supported
            if ($input.children('optgroup').length == 0){
                $input.children().each(function(i){
                    var option = $(this).text();
                    //add first letter of each word to array
                    keys.push(option.charAt(0).toLowerCase());
                    if ($(this).is(':selected')){
                        opts.defaultText = option;
                        currentIndex = i;
                    }
                    var li = $('<li>'+option+'</li>');
                    var optstyle = $(this).attr('style');
                    if (optstyle) {
                        li.attr('style',optstyle);
                    }
                    $newUl.append(li);
                });
                //cache list items object
                var $newLi = $newUl.children();
            }
            
            //get heights of new elements for use later
            var newUlHeight = $newUl.height(),
                containerHeight = $containerDiv.height(),
                newLiLength = $newLi.length;
                
            //check if a value is selected
            if (currentIndex != -1){
                navigateList(currentIndex, true);
            } else {
                //set placeholder text
                $containerDivText.text(opts.defaultText);
            }
            
            //decide if to place the new list above or below the drop-down
            function newUlPos(){
                var containerOffset = $containerDiv.offset();
                var containerPosY = containerOffset.top,
                    containerPosX = containerOffset.left,
                    docHeight = jQuery(window).height(),
                    scrollTop = jQuery(window).scrollTop(),
                    containerDivHeight = $containerDiv.height();
                    
                //if height of list is greater then max height, set list height to max height value
                if (newUlHeight > parseInt(opts.ddMaxHeight)) {
                    newUlHeight = parseInt(opts.ddMaxHeight);
                }
                
                //pozicia zhora
                if (containerPosY-scrollTop+newUlHeight+containerDivHeight > docHeight){
                    $newUl.css({
                        top: (containerPosY - newUlHeight)+'px'
                    });
                    $input.onTop = true;
                } else {
                    $newUl.css({
                        top: (containerPosY + containerDivHeight + 1)+'px'
                    });
                    $input.onTop = false;
                }
                //lava pozicia
                $newUl.css({
                    left: (containerPosX+jQuery(window).scrollLeft())+'px'
                }).height(newUlHeight);
            }
            
            //run function on page load
            window.setTimeout(newUlPos,500);
            
            //run function on browser window resize
            $(window).resize(function(){
                newUlPos();
            });
            
            $(window).scroll(function(){
                newUlPos();
            });
            
            function newListShow() {
                if ($newUl.is(':visible')){
					$newUl.hide();
					return false;
				}
				$('ul.sselect-list').hide();
				//show list
				$newUl.show();
				$newUl.focus();
				$('body').bind('click.sselect', function (event) {
                    if (!$(event.target).closest('div.sselect-container').length && !$(event.target).closest('div.sselect-list').length) {
                        $('ul.sselect-list').hide();
                        $('body').unbind('click.sselect');
                    }
                });
				//scroll list to selected item
				$newUl.scrollTop($input.liOffsetTop - 4);
            }
            
            $containerDivText.click(newListShow);
            $containerDivTrigger.click(newListShow);
            
            $newLi.hover(
              function (e) {
                var $hoveredLi = $(e.target);
                $hoveredLi.addClass('hover');
              },
              function (e) {
                var $hoveredLi = $(e.target);
                $hoveredLi.removeClass('hover');
              }
            );
            
            $newLi.click(function(e){
                var $clickedLi = $(e.target);
                //update counter
                currentIndex = $newLi.index($clickedLi);
                //remove all hilites, then add hilite to selected item
                prevented = true;
                navigateList(currentIndex);
                $newUl.hide();
            });

            function navigateList(currentIndex, init){
                //get offsets
                var containerOffsetTop = $containerDiv.offset().top,
                    liOffsetTop = $newLi.eq(currentIndex).offset().top,
                    ulScrollTop = $newUl.scrollTop();
                
                //get distance of current li from top of list                
                if ($input.onTop == true){
                    //if list is above select box, add max height value
                    $input.liOffsetTop = (((liOffsetTop-containerOffsetTop)-containerHeight)+ulScrollTop)+parseInt(opts.ddMaxHeight);
                } else {
                    $input.liOffsetTop = ((liOffsetTop-containerOffsetTop)-containerHeight)+ulScrollTop;
                }
                
                //scroll list to focus on current item
                $newUl.scrollTop($input.liOffsetTop);
                
                $newLi.removeClass('hiLite')
                      .eq(currentIndex).addClass('hiLite');
                var text = $newLi.eq(currentIndex).text();
                //page load
                if (init == true){
                    $input[0].selectedIndex = currentIndex;
                    $containerDivText.text(text);
                    return false;
                }
                $input[0].selectedIndex = currentIndex;
                $input.change();
                $containerDivText.text(text);
            };

            $input.change(function(event){
                var $targetInput = $(event.target);
                //stop change function from firing 
                if (prevented == true){
                    prevented = false;
                    return false;
                }
                $currentOpt = $targetInput.find(':selected');
                currentIndex = $targetInput.find('option').index($currentOpt);
                navigateList(currentIndex, true);
            });
            
            //handle up and down keys
            function keyPress(e) {
                var keycode = e.which;
                e.preventDefault();
                
                //prevent change function from firing
                prevented = true;
                
                switch(keycode) {
                    case 40: //down
                    case 39: //right
                        incrementList();
                        return false;
                        break;
                    case 38: //up
                    case 37: //left
                        decrementList();
                        return false;
                        break;
                    case 33: //page up
                    case 36: //home
                        gotoFirst();
                        return false;
                        break;
                    case 34: //page down
                    case 35: //end
                        gotoLast();
                        return false;
                        break;
                    case 13:
                    case 27:
                        $newUl.hide();
                        return false;
                        break;
                }
                //check for keyboard shortcuts
                keyPressed = String.fromCharCode(keycode).toLowerCase();
                var currentKeyIndex = keys.indexOf(keyPressed);
                if (typeof currentKeyIndex != 'undefined') { //if key code found in array
                    ++currentIndex;
                    currentIndex = keys.indexOf(keyPressed, currentIndex); //search array from current index
                    if (currentIndex == -1 || currentIndex == null || prevKey != keyPressed) currentIndex = keys.indexOf(keyPressed); //if no entry was found or new key pressed search from start of array
                    navigateList(currentIndex);
                    //store last key pressed
                    prevKey = keyPressed;
                    return false;
                }
            }
            
            function incrementList(){
                if (currentIndex < (newLiLength-1)) {
                    ++currentIndex;
                    navigateList(currentIndex);
                }
            }
            
            function decrementList(){
                if (currentIndex > 0) {
                    --currentIndex;
                    navigateList(currentIndex);
                }
            }
            
            function gotoFirst(){
                currentIndex = 0;
                navigateList(currentIndex);
            }
            
            function gotoLast(){
                currentIndex = newLiLength-1;
                navigateList(currentIndex);
            }
            
            $containerDiv.click(function(){
                $(this).keydown(keyPress);
            });
            
            $containerDiv.focus(function(e){
                $(this).addClass('sselect-container-focus');
                $(this).keydown(keyPress);
            });
            
            //reset left property and hide
            $newUl.hide();
            
        });
      
    };

})(jQuery);
