(function($) {
	var Watajax = function(element, options) {

		var defaults = {
		   page: 1,
		   per_page: 30,
                   letter_sort: "",
		   pager_max_buttons: 5,
		   ajax_connector: '/ajax.php',
		   table_id: 1,
		   sort_order: "DESC",
		   search: "",
		   search_timeout: 300,
		   tools_position: "under",
		   table_class: "watajax_table",
                   use_cookies: true,
                   cookie_life: 12, // Days
		   filters: {},
                   lang: {
                       could_not_load_settings : "Kunde inte ladda WATAJAX",
                       all: "Alla",
                       no_rows_found: "Inga produkter hittades",
                       rows: "rader",
                       page: "Sida",
                       search: "Sök",
                       export_csv: "Exportera till fil",
                       more_rows: "Visa flera rader.."
                   },
                   enable_export: false,
                   enable_keyboard: true,
                   enable_more_rows_button: true,
                   jump_on_pagechange: "table_top", // "page_top", "none"
                   zebra: "odd"
		};       
		var options = $.extend(defaults, options);
		var table = $(element);
		var dataOptions = {};
		var searchTimeout = null;
		
		
		/**
		 * Methods
		 */
                this.changePage = function(page) {
			options.page = page;
		}

		this.changeConnector = function(connector) {
			options.ajax_connector = connector;
			this.loadFromConnector('head');
			this.loadFromConnector('body');
			this.loadSettingsFromConnector();
		}
		
		this.loadFromConnector = function(section, args) {
			var _this = this;
			var args = (args == undefined) ? "" : args;
			$('#'+table.attr('id')+"_table_loading").show();
			
			if (section == "body" || section == "csv") {
				args += "watajax_page="+options.page+"&";
				args += "watajax_per_page="+options.per_page+"&";	
				args += "watajax_letter_sort="+options.letter_sort+"&";
				
				if (options.sortBy) {
					args += "watajax_sortBy="+options.sortBy+"&";	
					args += "watajax_sortOrder="+options.sort_order+"&";	    					
				}
				if (options.search != "") {
					args += "watajax_search="+options.search+"&";
				}
				var filters = this.objectToQuery(options.filters);
				if (filters != '') {
					args += "watajax_filter="+filters+"&";
				}
			}
			var q = (options.ajax_connector.charAt(options.ajax_connector.length-1) == "?" || options.ajax_connector.charAt(options.ajax_connector.length-1) == "&") ? "" : "?";
                        var url = options.ajax_connector+q+"action=watajax_load_"+section+"&watajax_table="+options.table_id+"&"+args
                        if (section == "csv") {
                            document.location = url;
                            $('#'+table.attr('id')+"_table_loading").hide();
                            return true;
                        }
			$.ajax({
  			      url: url,
  			      dataType: "html",
  			      success: function(msg, stat){
    				if (stat == "success") {
    					$('#'+table.attr('id')+"_table_loading").hide();
                                        if(msg != 'no_rows_found') {
                                            $('#'+table.attr('id')+"_table_"+section).html(msg);
                                        } else {
                                            $('#'+table.attr('id')+"_table_"+section).html(options.lang.no_rows_found);
                                        }
                                        if (section == "head") {
    						_this.activateHeader();
    						_this.loadSettingsFromConnector();
    					} else if (section == "body") {
                                                /* Adding markings to the sorted column */
       						$('#'+table.attr('id')+"_table_head tr th").removeClass('header_sorting');
                                                $('#'+table.attr('id')+"_table_head tr th").removeClass('sort_asc');
                                                $('#'+table.attr('id')+"_table_head tr th").removeClass('sort_desc');

						$('#'+table.attr('id')+"_table_head tr th#"+options.sortBy).addClass('header_sorting');
                                                $('#'+table.attr('id')+"_table_head tr th#"+options.sortBy).addClass('sort_'+options.sort_order);

    						$('#'+table.attr('id')+"_table_body tr:"+options.zebra).addClass('zebra');
    						$('#'+table.attr('id')+"_table_body tr").hover(
    								   function() {$(this).addClass("highlight")},
    								   function() {$(this).removeClass("highlight")}
    						)}
    				}
    			  }
  			   }
  			);
		}
		
		this.loadSettingsFromConnector = function (args, create) {
			var _this = this;
			var create = (create == undefined) ? "all" : create;

			$('#'+table.attr('id')+"_table_loading").show();
			if (args == undefined) {args = new String();} else {args += "&";}
			args += "watajax_page="+options.page+"&";
			args += "watajax_per_page="+options.per_page+"&";
			args += "watajax_letter_sort="+options.letter_sort+"&";
			if (options.sortBy) {
				args += "watajax_sortBy="+options.sortBy+"&";
				args += "watajax_sortOrder="+options.sort_order+"&";
			}
			var filters = this.objectToQuery(options.filters);
			if (filters != '') {
				args += "watajax_filter="+filters+"&";
			}			
			if (options.search != '') {
				args += "watajax_search="+options.search+"&";
			}			
			
			var q = (options.ajax_connector.charAt(options.ajax_connector.length-1) == "?" || options.ajax_connector.charAt(options.ajax_connector.length-1) == "&") ? "" : "?";
			$.ajax({
  			      url:	options.ajax_connector+q+"action=watajax_load_settings&watajax_table="+options.table_id+"&"+args,
  			      dataType: "json",
  			      cache: false,
  			      success: function(msg, stat){
    				if (stat == "success") {
    					$('#'+table.attr('id')+"_table_loading").hide();
    					dataOptions = msg;
    					if(create == "all" || create == "pager") {
    						_this.createPager();
    					}
    					if(options.tools_position != "none" && (create == "all" || create == "search")) {
    						_this.createSearch();
    					}
    					if(create == "all" || create == "filter") {
    						_this.createFilter();
    					}
    				} else {
    					alert(options.lang.could_not_load_settings);
    			    }
    			  }
  			   }
  			) 			
		}
		
		this.activateHeader = function () {
			var _this = this;
			$('#'+table.attr('id')+"_table_head tr th").each(function () {
				if (!$(this).hasClass('virtual')) {
					$(this).click(function () {
						_this.sortBy($(this).attr('id'));
					})
				}
			})
		}
		
		this.sortBy = function (column, order) {
                        if (order == undefined) {
                            options.sort_order = (options.sort_order == "ASC") ? "DESC" : "ASC";
                        } else {
                            options.sort_order = order;
                        }
			options.sortBy = column;
			this.loadFromConnector('body');
                        this.saveSettings();
			this.loadSettingsFromConnector();
		}

                this.gotoNextPage = function() {
                    if(options.page < dataOptions.pages) {
                        this.gotoPage((options.page*1)+1);
                        return false;
                    } else {
                        return false;
                    }
                }

                this.gotoPreviousPage = function() {
                    if (options.page == 1) {
                        return false;
                    } else {
                        this.gotoPage(options.page-1);
                        return false;
                    }
                }

		this.gotoPage = function (page) {
			options.page = page;
			this.createPager();
			this.loadFromConnector('body');
                        this.saveSettings();
                        if(options.jump_on_pagechange == "table_top") {
                            document.location = "#"+options.table_id+"_scroll_top";
                        } else if(options.jump_on_pagechange == "page_top") {
                            window.scrollTo(0,0);
                        }
		}
		
		this.refresh = function() {
			this.init();
		}
		
		this.refreshTableBody = function() {
			this.loadFromConnector('body');
		}
		
		this.search = function (string) {
			options.page = 1;
			options.search = string;
			this.loadSettingsFromConnector('', 'pager');
			this.loadFromConnector('body');
                        this.saveSettings();
		}
		
		this.searchKeyUp = function (string) {
			var _this = this;
			clearTimeout(searchTimeout);
			searchTimeout = setTimeout(function () {
				_this.search(string);
			}, options.search_timeout);
		}
		
		this.setPerPage = function(num) {
			options.per_page = num;
			this.loadFromConnector('body');
			this.loadSettingsFromConnector();
                        this.saveSettings();
		}

		this.setLetterSort = function(str) {
			options.letter_sort = str;
			this.loadFromConnector('body');
			this.loadSettingsFromConnector();
                        this.saveSettings();
		}

                this.resetFilter = function () {
			options.filters = {};
		}
		
		this.objectToQuery = function (obj) {
			var query = '';
			for (var i in obj) {
				query += i+':'+obj[i]+'|';
			}
			return query.substr(0, (query.length-1));
		}
		
		this.applyFilter = function (column, filter_value) {
			if (filter_value == '') {
				delete options.filters[column];
			} else {
				options.filters[column] = filter_value;	
			}
			
			options.page = 1;
			this.loadSettingsFromConnector();
			this.loadFromConnector('body');
                        this.saveSettings();
		}

		this.createFilter = function () {
			var _this = this;
			if (dataOptions.filters != undefined && dataOptions.filters.watajax_has_filters == true) {
				// First create filter row in thead (if not there)
				if ($('#'+table.attr('id')+"_table_filter").html() == null) {
					var filter = document.createElement('tr');
					filter.id = table.attr('id')+"_table_filter";
					filter.className = 'filter';
					$('#'+table.attr('id')+"_table_head").append(filter);
				} else {
					$('#'+table.attr('id')+"_table_filter").html(''); // Empty filters
				}
				
				$('#'+table.attr('id')+"_table_head tr th").each(function() {
					var column = $(this).attr('id');
					
					var filter_html = $('<td>');
					var filter_obj = dataOptions.filters[column];

					if (filter_obj == undefined) {
						filter_html.html('&nbsp;');						
					} else if(filter_obj.type == "select") {
						var select_contents = '';
						var select_box = $('<select>');
						select_box.attr('id', column+'_filter');
						select_contents = '<option value="">- '+options.lang.all+'</option>';
						for(var i in filter_obj.contents) {
							if (filter_obj.contents[i] != "") {
                                                                if(filter_obj.contents_override == true) {
                                                                    var selected = (options.filters[column] != undefined && options.filters[column] == i) ? ' selected="selected"' : '';
                                                                    select_contents += '<option'+selected+' value="'+i+'">'+filter_obj.contents[i]+'</option>';
                                                                } else {
                                                                    var selected = (options.filters[column] != undefined && options.filters[column] == filter_obj.contents[i]) ? ' selected="selected"' : '';
                                                                    select_contents += '<option'+selected+' value="'+filter_obj.contents[i]+'">'+filter_obj.contents[i]+'</option>';
                                                                }

							}
						}
						select_box.html(select_contents);
						select_box.change(function () {
							_this.applyFilter($(this).attr('id').replace('_filter', ''), $(this).val());
						});
						filter_html.append(select_box);
					} else if (filter_obj.type == "text") {
						filter_html.html('- text not implemented -');
					}
					$('#'+table.attr('id')+"_table_filter").append(filter_html);
				})

			}
		}

		this.createSearch = function () {
			var _this = this;
			var search_title = document.createElement('div');
			search_title.className = "search_title";
			search_title.innerHTML = options.lang.search+":";
			
			var search_input = document.createElement('input');
			search_input.value = options.search;
			search_input.type = "text";
			search_input.id = "search_input";
			$(search_input).keyup(function () {
				_this.searchKeyUp($(this).val());
			});
			$('#'+table.attr('id')+"_table_search").html(''); 
			$('#'+table.attr('id')+"_table_search").append(search_title); 
			$('#'+table.attr('id')+"_table_search").append(search_input); 
		}
		
		this.createPager = function () {
			var _this = this;
			$('#'+table.attr('id')+"_table_pager").html(''); // Empty pager first			
			if (dataOptions.pages > 1) {
				var pager_title = document.createElement('div');
				pager_title.innerHTML = options.lang.page+' ';
				pager_title.className = 'pager_title';
				$('#'+table.attr('id')+"_table_pager").append(pager_title);    				

				/**
				 * Check if we need to show the first page button
				 */
				if (options.page > ((options.pager_max_buttons-1)/2)+1) { 
					var pager_button = document.createElement('div');
					pager_button.className = "page_button";
					pager_button.innerHTML = 1;
					$(pager_button).click(function () {_this.gotoPage(1);});
					$('#'+table.attr('id')+"_table_pager").append(pager_button);
					var pager_button = document.createElement('div');
					pager_button.className = "page_button page_dots";
					pager_button.innerHTML = "...";
					$('#'+table.attr('id')+"_table_pager").append(pager_button);    					
				}
				
				/**
				 * Render page buttons
				 */					
				var i_start = (options.page - ((options.pager_max_buttons-1)/2))-1;
				var i_end = i_start + options.pager_max_buttons;
				i_end = (i_end > dataOptions.pages) ? dataOptions.pages : i_end;
				i_start = (i_start < 0) ? 0 : i_start;
				
				for(var i=i_start; i<i_end; i++) {
					var pager_button = document.createElement('div');
					pager_button.className = "page_button";
					pager_button.innerHTML = (i+1);
					if (options.page == (i+1)) {
						pager_button.className = "page_button current_page";
					}
					$(pager_button).click(function () {
    					var page_ref = $(this).html();
						_this.gotoPage(page_ref);
					});
					$('#'+table.attr('id')+"_table_pager").append(pager_button);
				}

				/**
				 * Check if we need to show the last page button
				 */
				if (options.page < (dataOptions.pages-(((options.pager_max_buttons-1)/2)))) { 
					var pager_button = document.createElement('div');
					pager_button.className = "page_button page_dots";
					pager_button.innerHTML = "...";
					$('#'+table.attr('id')+"_table_pager").append(pager_button);    											
					var pager_button = document.createElement('div');
					pager_button.className = "page_button";
					pager_button.innerHTML = dataOptions.pages;
					$(pager_button).click(function () {_this.gotoPage(dataOptions.pages);});
					$('#'+table.attr('id')+"_table_pager").append(pager_button);
				}
				$('#'+table.attr('id')+"_table_pager").append("<span id='number_items'>"+dataOptions.items+" "+options.lang.rows+"</span>");
			}
		}

                /**
                 * Cookie settings handling
                 */
                this.createCookie = function(name,value,days) {
                        if (days) {
                                var date = new Date();
                                date.setTime(date.getTime()+(days*24*60*60*1000));
                                var expires = "; expires="+date.toGMTString();
                        } else {var expires = "";}
                        document.cookie = name+"="+value+expires+"; path=/";
                }

                this.readCookie = function(name) {
                        var nameEQ = name + "=";
                        var ca = document.cookie.split(';');
                        for(var i=0;i < ca.length;i++) {
                                var c = ca[i];
                                while (c.charAt(0)==' ') c = c.substring(1,c.length);
                                if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
                        }
                        return null;
                }

                this.eraseCookie = function(name) {
                        this.createCookie(name,"",-1);
                }

                this.saveSettings = function () {
                    if (options.use_cookies == false) {return false;}
                    /* Saving settings */
                    this.createCookie('watajax_'+table.attr('id')+'_page',              options.page, options.cookie_life);
                    this.createCookie('watajax_'+table.attr('id')+'_per_page',          options.per_page, options.cookie_life);
                    this.createCookie('watajax_'+table.attr('id')+'_letter_sort',          options.letter_sort, options.cookie_life);
                    //this.createCookie('watajax_'+table.attr('id')+'_ajax_connector',    options.ajax_connector, options.cookie_life);
                    this.createCookie('watajax_'+table.attr('id')+'_sort_order',        options.sort_order, options.cookie_life);
                    if (options.search != undefined && options.search != "") {
                        this.createCookie('watajax_'+table.attr('id')+'_search',        options.search, options.cookie_life);
                    } else {
                        this.eraseCookie('watajax_'+table.attr('id')+'_search');
                    }
                    if (options.sortBy != undefined) {
                        this.createCookie('watajax_'+table.attr('id')+'_sortBy',            options.sortBy, options.cookie_life);
                    } else {
                        this.eraseCookie('watajax_'+table.attr('id')+'_sortBy');
                    }
                    // Saving filters
                    var added_filters = 0;
                    var save_filters = "";
                    for (var i in options.filters) {
                        added_filters++;
                        save_filters += i+":"+options.filters[i]+"&";
                    }
                    if (added_filters <= 0) {
                        this.eraseCookie('watajax_'+table.attr('id')+'_filters');
                    } else {
                        this.createCookie('watajax_'+table.attr('id')+'_filters', save_filters.slice(0, -1), options.cookie_life);
                    }
                }

                this.clearSettings = function () {
                    this.eraseCookie('watajax_'+table.attr('id')+"_page");
                    this.eraseCookie('watajax_'+table.attr('id')+"_per_page");
                    this.eraseCookie('watajax_'+table.attr('id')+"_letter_sort");
                    this.eraseCookie('watajax_'+table.attr('id')+"_ajax_connector");
                    this.eraseCookie('watajax_'+table.attr('id')+"_sort_order");
                    this.eraseCookie('watajax_'+table.attr('id')+"_search");
                    this.eraseCookie('watajax_'+table.attr('id')+"_sortBy");
                    this.eraseCookie('watajax_'+table.attr('id')+"_filters");
                }

                this.loadSettings = function () {
                    if (options.use_cookies == false) {return false;}
                    var cookie_page = this.readCookie('watajax_'+table.attr('id')+'_page');
                    var cookie_per_page = this.readCookie('watajax_'+table.attr('id')+'_per_page');
                    var cookie_letter_sort = this.readCookie('watajax_'+table.attr('id')+'_letter_sort');
                    var cookie_ajax_connector = this.readCookie('watajax_'+table.attr('id')+'_ajax_connector');
                    var cookie_sort_order = this.readCookie('watajax_'+table.attr('id')+'_sort_order');
                    var cookie_search = this.readCookie('watajax_'+table.attr('id')+'_search');
                    var cookie_sortBy = this.readCookie('watajax_'+table.attr('id')+'_sortBy');
                    var cookie_filters = this.readCookie('watajax_'+table.attr('id')+'_filters');

                    if (cookie_page != undefined) {options.page = cookie_page;}
                    if (cookie_per_page != undefined) {options.per_page = cookie_per_page;}
                    if (cookie_letter_sort != undefined) {options.letter_sort = cookie_letter_sort;}
                    if (cookie_ajax_connector != undefined) {options.ajax_connector = cookie_ajax_connector;}
                    if (cookie_sort_order != undefined) {options.sort_order = cookie_sort_order;}
                    if (cookie_search != undefined && cookie_search != null) {options.search = cookie_search;}
                    if (cookie_sortBy != undefined) {options.sortBy = cookie_sortBy;}

                    // Read filters
                    if (cookie_filters != undefined) {
                        var cookie_filters_array = cookie_filters.split("&");
                        for(var i in cookie_filters_array) {
                            var column = cookie_filters_array[i].split(":");
                            options.filters[column[0]] = column[1];
                        }
                    }

                }

                /**
                 * Init
                 */
		this.init = function() {
                        var Ref = this;
                        this.loadSettings();
			table.html(
                                        "<a name='"+options.table_id+"_scroll_top"+"'></a>" +
					"<table class='"+options.table_class+"' cellspacing='0' id='"+table.attr('id')+"_table'>" +
					"<thead id='"+table.attr('id')+"_table_head'></thead>" +
					"<tbody id='"+table.attr('id')+"_table_body'></tbody>" +
					"</table>");
			
			var tools = "<div id='"+table.attr('id')+"_table_pager' class='table_pager'></div>" +
			"<div id='"+table.attr('id')+"_table_search' class='table_search'></div>" +
			"<div id='"+table.attr('id')+"_table_loading' class='ajax_loading'></div>";

                        if (options.tools_position == "both") { // TODO: Not done yet
                            table.html(tools+table.html()+tools)
                        } else if (options.tools_position == "above") {
                            table.html(tools+table.html())
                        } else {
                            table.html(table.html()+tools)
                        }

                        if (options.enable_more_rows_button == true) {
                            table.html(table.html()+'<div id="'+table.attr('id')+'_more_rows_button" class="more_rows_button" title="'+options.lang.more_rows+'"><span>'+options.lang.more_rows+'</span></div>');
                            $("#"+table.attr('id')+"_more_rows_button").click(function() {
                                options.per_page = (options.per_page*1) + 10;
                                Ref.loadFromConnector('head');
                                Ref.loadFromConnector('body');
                            });
                        }
                        
                        if (options.enable_export == true) {
                            table.html(table.html()+'<div id="'+table.attr('id')+'_export_file" class="export_file" title="'+options.lang.export_csv+'"><span>'+options.lang.export_csv+'</span></div>');
                            $("#"+table.attr('id')+"_export_file").click(function() {
                                Ref.loadFromConnector('csv');
                            });
                        }

			$('#'+table.attr('id')+"_table_loading").hide();

			this.loadFromConnector('head');
			this.loadFromConnector('body');

                        if (options.enable_keyboard) {
                            $(document).keydown(function(e){
                                if (e.keyCode == 37) { 
                                   Ref.gotoPreviousPage();
                                   return false;
                                } else if (e.keyCode == 39) {
                                   Ref.gotoNextPage();
                                   return false;
                                }
                            });
                        }
		}
		
		this.init();   

    }
	/* Wrapper */
	$.fn.watajax = function(options) {
       return this.each(function() {
           var element = $(this);
          
           // Return early if this element already has a plugin instance
           if (element.data('watajax')) return;

           // pass options to plugin constructor
           var watajax = new Watajax(this, options);

           // Store plugin object in this element's data
           element.data('watajax', watajax);
       });
   };

	
})(jQuery);

