(function($) {
    var classfinder_animate = false;
    $.widget('ui.classfinder',
    {
        _context:{
            includes: [],
            excludes: []
        },

        options: {
            title: 'Classes',
            baseUrl: '',
            filterhandlerurl: '/widget/allclasses',
            filterDefaultActiveButton: 'all_classes',
            defaultbehaviour: true,
            width: 735,
            height: $(window).height()-150,
            subscribe: '',
            autoopen :false
        },
        page:2,
        selectedLetter:null,
        scrollingEnd:false,
        elementtext:"",
        selectedMenu:null,
        animate:false,
        dialogcontent:'',
        dialogId:'',
        ajaxloader:$('<span class="loading2"></span>'),
        _init: function(){
            var self=this;

           if(self.options.autoopen == false){
               self.element.bind('click',function(event){
                    event.preventDefault();
                    self. elementtext = $(this).text();
                    self.init=self.element
                    self.dialogcontent.dialog('open');
                    self.loadpagebody();

                });
             }else{
               self.elementtext = $(this).text();
                    self.init=self.element
                    self.dialogcontent.dialog('open');
                    self.loadpagebody();
           }


            self.resetPagination();
            self.dialogcontent.bind('scroll', $.proxy(self.classlistscrolled, self));
            self.setContext(self.options.includes,self.options.excludes);
            $('.ui-icon-closethick').html('×');
        },
        _create:function(){
            var self=this;
            var tempId = new Date().getTime();
            var id = self.element.attr('id') ? self.element.attr('id') : 'tempId_' + tempId++;
            self.dialogId = 'classlistContainer-'+id;
            self.addsearchbar();
            self.addalphapager();
            self.dialogcontent.on("click", 'a.classfinderwiget-classes', $.proxy(self.classSelected, self));
            self.dialogcontent.on("click", 'a.classadd', $.proxy(self.addclassfilter, self));
            $.ui.classfinder.instances.push(this.element);
        },

       getContainer:function(){
           var self=this;
           return self.dialogId;
       },

        _displayFailure: function(jqXHR,textStatus, errorThrown) {
            var serverMsg,
            self = this;
            if (jqXHR.status == 0) {
                serverMsg = 'You are offline!!\n Please Check Your Network.';
            }else if (jqXHR.status == 404) {
                serverMsg = 'Requested URL not found.';
            }else if (jqXHR.status == 500) {
                serverMsg = 'Internal Server Error. ' + jqXHR.responseText;
            }else if (errorThrown == 'parsererror') {
                serverMsg = 'Error.\nParsing JSON Request failed.';
            }else if (errorThrown == 'timeout') {
                serverMsg = 'Request Time out.';
            }else {
                serverMsg = 'Unknow Error.\n' + jqXHR.responseText;
            }
            self.dialogcontent.html("<div class='ui-state-error' style='padding: 1em;width:90%'><p><span style='float: left; margin-right: 0.3em;' class='ui-icon ui-icon-alert'></span>" + ' ' + serverMsg + '</p></div>');
            //self.element.text(self.elementtext);
            self.revertTitle();
        },

        addsearchbar:function(){

            var self = this;
            self.dialogcontent = self.dialogContainer();
            self.dialogcontent.dialog({
                height: self.options.height,
                width: self.options.width,
                autoOpen: false,
                modal: true
            });
            // modal hide fade in custom-size
            self.dialogcontent.parent().addClass('modal customdlg classfinder').removeClass('ui-widget-content');

            self.titlebar = self.dialogcontent.siblings('div.ui-dialog-titlebar');
            //self.titlebar.addClass('modal-header').css('z-index', '6000');
            self.filter = $('<ul>');
            self.filter.attr('id', 'cfinderfilter').addClass('classfilters').appendTo(self.dialogcontent.parent());

            self.searchbar=$('<form id="classfindersearch" class="form-inline"><input type="text" class="input-large" autocomplete="off" name="search" value="Search by class (context)" title="Regx supported"/><a href="#" class="searchsubmit btn" role="button"><i class="icon-search"></i>&nbsp;</a></form>');

            self.titlebar.append(self.ajaxloader);
            self.titlebar.append(self.searchbar).on("submit", 'form',{
                ui: self
            },function(event) {
                event.preventDefault();
            });
            self.searchbar.on("click", 'input[type="text"]', function() {
                $(this).focus().select();
            });
            self.searchbar.on("focusin", 'input[type="text"]',$.proxy(self.searchboxevent,self));
            self.searchbar.on("focusout", 'input[type="text"]',$.proxy(self.searchboxevent,self));
            self.searchbar.find('input[type="text"]').data('default',self.searchbar.find('input[type="text"]').val());
            self.searchbar.on("keyup", 'input[type="text"]',$.proxy(self.searchclassinlist,self));
            self.searchbar.on("click", 'a.searchsubmit', $.proxy(self.searchclassinlist,self));

        },


        menuitemclicked:function(event){
            var self=this;
            var sender=$(event.target);

            var search_text = $.trim(sender.text().toLowerCase());

            self.selectedLetter = null; // reset the letter selection
            self.resetPagination();
            self.resetScrollPosition();
            self.searchbar.find('input[type="text"]').val('Search on ' + search_text).data('default', 'Search on ' + search_text);
            self.dialogcontent.html(self.ajaxloader);

            self.selectedMenu = search_text;

            var params = {
                'url': self.options.baseUrl + self.options.filterhandlerurl,
                'data': {
                    filter: search_text.split(' ')[0]
                },
                'success': function(data) {
                    self.loadDataInContainer(data);
                }
            };
            self.sendRequest(params);


            self.searchbar.find('input[type="text"]').trigger('blur');
            self.resetSelectedLetter();
        },

        classlistscrolled:function(event) {

            var listpane=event.currentTarget;
            var self=this;

            if (self.scrollingEnd == true || $(listpane).scrollTop()==0 || classfinder_animate==true) return;
            // only do scrolling event when no menu option are selected or all classes is selected.
            if (self.selectedMenu == null) {
                self.selectedMenu = 'all classes';
            }
            var filter = self.selectedMenu.toLowerCase().split(' ')[0];
            if ($(listpane)[0].scrollHeight - ($(listpane).scrollTop()) <= ($(listpane).outerHeight(false) + 400)) {
                classfinder_animate = true;


                var url = self.options.baseUrl + self.options.filterhandlerurl + '/' + self.page;
                if (self.selectedLetter != null) {
                    url = url + '/' + self.selectedLetter;
                }
                self.changeTitle('Loading');


                var params = {
                    'url': url,
                    'data': {
                        filter: filter
                    },
                    'success': function(data) {
                        classfinder_animate = false;
                        self.loadDataInContainer(data, true);
                    }
                };
                self.sendRequest(params);

                self.page++;
            }

        },

        addclassfilter: function(event)
        {
            event.preventDefault();
            var self = this,
            sender = $(event.target),
            selectedclass = $(sender).attr('title');
            var li = $('<li>');
            li.text(selectedclass).data('filter', selectedclass).appendTo(self.filter);
            $('<a>').text('X').appendTo(li);
            self.filter.find('li').on("click", 'a', $.proxy(self.removeclassfilter, self));
            self.gethostbtn.show();
        },

        removeclassfilter: function(event)
        {
            event.preventDefault();
            var self = this;
            $(event.target).parent().remove();
            if (self.filter.find('li').length == 0)
            {
                self.gethostbtn.hide();
            }
        },

        loadpagebody: function() {
            var self = this;

            self.changeTitle('Loading');
            var params = {
                'url': self.options.baseUrl + '/widget/allclasses',
                'success': function(data) {
                    self.loadDataInContainer(data, false);
                }
            };
            self.sendRequest(params);
        },

        loadDataInContainer: function(data,append) {
            var self = this;
            var previousListElement = $('#'+self.dialogId).find('ul.classList');
            var previousList = null;
            if (previousListElement != null && previousListElement.html() != '') {
                previousList = previousListElement.html();
            }

            var list = [];
            var length = data.length;

            // To end the scrolling so that no further request is sent
            if (data.length == 0) {
                self.scrollingEnd = true;
            }

            for (var i = 0; i < length; i++) {
                list.push('<li>');
                var val = data[i];
                var viewHostLink = '';
                var addClassLink = '';
                var textLink = '<a class="name classfinderwiget-classes" target="_blank" title="' + val + '" href="' + self.options.baseUrl + '/search/index/host/All/report/contexts/from/0/to/0/name/'+ val + '">' + val + '</a>';
                list.push(textLink);
                list.push(viewHostLink);
                list.push(addClassLink);
                list.push('</li>');
            }

            var ul = '';
            // check for empty list and give a message
            if (list.length == 0 && !append) {
                list.push('<li style="border:0"><p class="info">No classes found</p></li>');
            }

            // unstyled - added class for tw bootstrap support
            if (append) {
                ul = '<ul class="classList unstyled">' + previousList + list.join('') + '</ul>';
            } else {
                ul = '<ul class="classList unstyled">' + list.join('') + '</ul>';
            }
            document.getElementById(self.dialogId).innerHTML = ul;

            self.revertTitle();
        },

        classSelected: function(event) {
            var self = this,
            sender = $(event.target);
            var selectedClass = sender.text();

            if (!self.options.defaultbehaviour)
            {
                event.preventDefault();
                self.dialogcontent.dialog('close');
                self._trigger("complete",null,{
                    'selectedclass': selectedClass
                });
            }
        },

        dialogContainer: function() {
            var self = this;

            var existing = $('#'+self.dialogId);
            if (existing.length > 0) {
                return existing.first();
            }
            else {
                //single shared element for modal dialogs
                var requestDialog = $('<div id="'+self.dialogId+'" style="display:none" class="finderwidget  result" title="'+ self.options.title +'"><ul class="classList"></ul></div>').appendTo('body').
                dialog({
                    autoOpen: false,
                    zIndex: 9000,
                    beforeClose: function(event, ui) {
                        self.destroy();
                    }
                });
                self.originalTitle = requestDialog.dialog('option', 'title');
                return requestDialog;
            }

        },

        searchboxevent: function(event)
        {
            var self = this;
            var searchbox = event.target;
            if ((searchbox.value == $(searchbox).data('default') || searchbox.value == '') && event.type == 'focusin')
            {
                searchbox.value = '';
            }
            if (searchbox.value == '' && event.type == 'focusout')
            {
                searchbox.value = $(searchbox).data('default');
            }
        },

        searchclassinlist: function(event)
        {
            var self=this,
                searchbox = self.searchbar.find('input');


            var searchWord = encodeURIComponent(searchbox.val());

            if (event.keyCode == 13 || event.type =='click') {
                var url = self.options.baseUrl + self.options.filterhandlerurl + '/1/' + searchWord;
                self.resetSelectedLetter();
                self.resetPagination();
                self.resetScrollPosition();
                var params = {
                    'url': url,
                    'success': function (data) {
                        self.loadDataInContainer(data,false);
                    }
                };
                self.sendRequest(params);
            }
        },

        addalphapager: function()
        {
            var self = this;
            var alphabets = 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
            var alphaarr = alphabets.split(',');
            self.alphasearch = $('<ul>').attr('class', 'alphasearch');
            $.each(alphaarr, function(i,val) {
                var li = $('<li>');
                $('<a>').text(val).attr({
                    title: val,
                    href: '#'
                }).appendTo(li);
                li.appendTo(self.alphasearch);
            });
            self.alphasearch.appendTo(self.dialogcontent.parent());
            self.alphasearch.on("click", 'a', $.proxy(self.sorton, self));
        },

        sorton: function(event) {
            event.preventDefault();
            var self = this;
            var sender = $(event.target).parent();
            sender.addClass('selected').siblings().removeClass('selected');

            var clickedLetter = sender.text().toLowerCase();
            self.selectedLetter = encodeURIComponent('^[' + clickedLetter + '|' + sender.text() + ']');

            self.resetPagination();
            self.resetScrollPosition();
            var url = self.options.baseUrl + self.options.filterhandlerurl + '/1/' + self.selectedLetter;
            self.changeTitle('Loading');

            var params = {
                'url': url,
                'success': function (data) {
                    self.loadDataInContainer(data,false);
                }
            };
            self.sendRequest(params);
        },

        resetPagination: function() {
            var self = this;
            self.page = 2;
            self.scrollingEnd = false;
        },

        resetSelectedLetter: function() {
            var self = this;
            self.selectedLetter = null,
            self.alphasearch.find('li').removeClass('selected');
        },

        resetScrollPosition: function() {
            var self = this;
            self.dialogcontent.scrollTop(0);
        },

        changeTitle: function(text) {
            var self = this;
            self.dialogcontent.dialog('option', 'title', text);
            self.ajaxloader.show();
        },

        revertTitle: function() {
            var self = this;
            self.dialogcontent.dialog('option', 'title', self.originalTitle);
            self.ajaxloader.hide();
        },

        destroy: function() {
            // remove the dialog list content before closing
            var self = this;
            document.getElementById(self.dialogId).innerHTML = '';

            self.resetPagination();
            self.resetSelectedLetter();
            // remove this instance from $.ui.mywidget.instances
            var element = this.element,
            position = $.inArray(element, $.ui.classfinder.instances);
            // if this instance was found, splice it off
            if (position > -1) {
                $.ui.classfinder.instances.splice(position, 1);
            }
            // call the original destroy method since we overwrote it
            $.Widget.prototype.destroy.call(this);
        },
        beforeRequest: function(params) {
            var self = this;
        },

        setContext: function(includes, excludes) {
            var self = this;
            self._context.includes = includes;
            self._context.excludes = excludes;
        },
        sendRequest: function(params) {
            var self = this;

            if (self.options.subscribe) {
                var par = self.options.subscribe.getContext();
                self.setContext(par.includes, par.excludes);
            }

            var senddata = $.extend(params.data, self._context);
            $.ajax({
                type: params.type ? params.type : 'post' ,
                url: params.url,
                data: senddata,
                dataType: params.dataType ? params.dataType : 'json',
                success: function(data) {
                    if ($.isFunction(params.success)) {
                        return $.call(params.success(data));
                    }
                    return data;
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    if ($.isFunction(params.error)) {
                        return $.call(params.error());
                    }
                    self._displayFailure(jqXHR,textStatus, errorThrown);
                }
            });
        }

    });

    $.extend($.ui.classfinder, {
        instances: []
    });

})(jQuery);
