define([
    'Global',
    'dataTables',
	'Text!../html/templates/pagination-controls.html',
],
    function (Global, dataTables, paginationControlsTemplate) {
        'use strict';
        var thisView;
        return Backbone.View.extend({
            tagName: 'div',
            initialize: function (options) {
                this.options = options || {};
                this.$dataTable = null;
                this.tableConfiguration = options.tableConfiguration || {};
				this.serverPaginate = this.tableConfiguration.serverPaginate;
	            this.dataCollection = options.dataCollection;

	            var container = this.tableConfiguration.container;
                this.$container = container ? $(container) : $('#' + this.tableConfiguration.id + '> div').eq(0);

                this.id = this.tableConfiguration.id + "-table";
                this.$el.data('details', options.rowSelected);
	            this.language = {
		            "sSearch": "",
		            "sZeroRecords": "There are no matching records."
	            };

	            this.maxPerPage = 20;
	            this.sortOn = "";
	            this.filterOn = "";
	            this.refreshData = true;
	            this.goToPage = 1;

                thisView = this;

	            this.paginationTemplate = _.template(paginationControlsTemplate);
            },

            render: function () {
                this.$container.empty().append(this.$el);
                this.buildDatatable();
                this.getData();
                this.addToolTips();
                this.fixedHeaderShimResize();

                return this;
            },

            events: {
                'tap tbody tr': 'tapRow',
                'tap tbody tr a': 'preventDefault',
                'keydown tbody tr a': 'tapRow508',
	            'click thead th': 'sortByColumn',
				'click .server-paginate .first:not(.paginate_button_disabled)': 'goToFirstPage',
	            'click .server-paginate .previous:not(.paginate_button_disabled)': 'goToPreviousPage',
	            'click .server-paginate .next:not(.paginate_button_disabled)': 'goToNextPage',
	            'click .server-paginate .last:not(.paginate_button_disabled)': 'goToLastPage'
            },

	        sortByColumn: function (e) {
		        if (this.serverPaginate) {
			        e.preventDefault();

			        this.$dataTable.fnClearTable();

			        var $target = $(e.currentTarget),
				        sortProp = $target.attr('sort-prop'),
				        ascending = $target.attr('aria-sort') === "ascending";

			        this.sortOn = sortProp + "," + ascending + ";";

			        this.goToPage = 1;

					this.getData();
		        }
	        },

	        goToFirstPage: function () {
				this.goToPage = 1;

		        this.getData();
	        },

	        goToPreviousPage: function () {
				var currentPage = this.dataCollection.currentPage,
					goToPage = currentPage - 1;

		        this.goToPage = goToPage > 0 ? goToPage : 1;

		        this.getData();
	        },

	        goToNextPage: function () {
		        var currentPage = this.dataCollection.currentPage,
			        goToPage = currentPage + 1,
			        pageCount = this.dataCollection.pageCount;

		        this.goToPage = goToPage <= pageCount ? goToPage : pageCount;

		        this.getData();
	        },

	        goToLastPage: function () {
				this.goToPage = this.dataCollection.pageCount;

		        this.getData();
	        },

            fixedHeaderShimResize: function() {
                $(window).on('resize', function(){
                    var tables = $('.ui-collapsible-inset').not('.ui-collapsible-collapsed').find('.dataTable'),
                        $cells = $(tables[1]).find('tr:first-child td'),
                        $headers = $(tables[0]).find('th');

                    for (var i = 0, len = $cells.length; i < len; i++) {
                        $headers.eq(i).width($cells.eq(i).width());
                    }
                });
            },

            addToolTips: function () {
                var toolTips = this.tableConfiguration.columns,
                    $headers = this.$container.find('thead:first-child th');

                for(var i = 0, len = toolTips.length; i < len; i++) {
                    $headers.eq(i).attr('title', toolTips[i].sToolTip);
                }
            },

            tapRow508: function (e) {
                if (e.which === 13) {
                    e.preventDefault();
                    $(e.currentTarget).parent().parent().trigger('tap');
                }
            },

            tapRow: function (e) {
                var $this = $(e.currentTarget),
                    requestHref = $this.jqmData('requestHref'),
	                detailsId = $this.jqmData('detailsId');

                $this.addClass('selected-active').prop({'title': 'Currently viewed.'})
                    .siblings().removeClass('selected-active').prop({'title': 'Tap to see details'});

	            if (detailsId !== undefined) {
		            $(document).jqmData('details-id', detailsId);
	            }

                if (requestHref !== undefined) {
                    $(document).jqmData('requestHref-for-detail-viewing', requestHref);
                    this.$el.data().details(e);
                }
            },

            preventDefault: function (e) {
                e.preventDefault();
            },

            addCustomSorting: function () {
                $.fn.dataTableExt.oSort['text-as-int-asc'] = function (a, b) {
                    var value1 = parseInt($(a).text()),
                        value2 = parseInt($(b).text());
                    return ((value1 < value2) ? -1 : ((value1 > value2) ? 1 : 0));
                };

                $.fn.dataTableExt.oSort['text-as-int-desc'] = function (a, b) {
                    var value1 = parseInt($(a).text()),
                        value2 = parseInt($(b).text());
                    return ((value1 < value2) ? 1 : ((value1 > value2) ? -1 : 0));
                };
            },

            buildDatatable: function () {
                var tableSorting = this.serverPaginate ? this.createDataTableSort() : this.tableConfiguration.sorting || [],
                    dom = this.tableConfiguration.dom || '<"top"f<"clear">>t<"bottom"l<"clear">>',
	                rowCallback = $.isFunction(this.options.rowCallback) ? this.options.rowCallback : this.rowCallBack,
	                drawCallback = $.isFunction(this.options.drawCallback) ? this.options.drawCallback : function () {},
                    options = {
	                    oLanguage: this.tableConfiguration.oLanguage || this.language,
                        bLengthChange: this.tableConfiguration.lengthChange,
                        bFilter: this.tableConfiguration.filter,
                        bInfo: this.tableConfiguration.info,
                        bAutoWidth: this.tableConfiguration.autoWidth,
                        bScrollCollapse: this.tableConfiguration.scrollCollapse,
                        bJQueryUI: this.tableConfiguration.jQueryUI,
                        bProcessing: this.tableConfiguration.processing,
                        bPaginate: this.tableConfiguration.paginate,
	                    sPaginationType: this.tableConfiguration.paginationType,
                        bDestroy: this.tableConfiguration.destroy,
                        sDom: dom,
	                    aaSorting: tableSorting,
                        aoColumns: this.tableConfiguration.columns,
                        fnRowCallback: rowCallback,
	                    fnDrawCallback: drawCallback
                    };

                $.fn.dataTableExt.oStdClasses.sStripeOdd =
                $.fn.dataTableExt.oStdClasses.sStripeEven = "ui-btn ui-btn-icon-right ui-li-has-arrow ui-li ui-btn-up-c";
                $.fn.dataTableExt.oStdClasses.sSortable =
                $.fn.dataTableExt.oStdClasses.sSortDesc =
                $.fn.dataTableExt.oStdClasses.sSortAsc = "ui-bar ui-bar-d";

                this.addCustomSorting();

                this.$dataTable = this.$el
	                                .empty()
                                    .append("<table><thead></thead><tbody></tbody></table>")
                                    .find("table")
                                    .attr('id', this.id)
                                    .dataTable(options);

	            this.$dataTable.setRefreshFlag = this.setRefreshFlag;
	            this.$dataTable.clearTable = this.clearTable;
	            this.$dataTable.refreshTable = this.refreshTable;
				this.$dataTable.filterTable = this.filterTable;
	            this.$dataTable.clearFilter = this.clearFilter;

	            if (this.serverPaginate) {
		            this.addSortingAttributesToHeaders();
	            }
            },

	        createDataTableSort: function () {
		        var defaultSort = this.tableConfiguration.defaultSort,
			        columns = this.tableConfiguration.columns,
			        sortOn = "",
			        dataTableSort = [],
			        counter = 0;

				if (defaultSort) {
					sortOn = defaultSort;
				} else {
			        _.each(columns, function(column) {
						var sortProp = column.sortProp || column.mDataProp,
							ascending = column.sortAscending;

				        if (ascending !== undefined) {
					        sortOn += sortProp + "," + ascending + ";";
				            dataTableSort.push([counter, ascending ? "asc" : "desc"]);
				        }

				        counter++;
			        });
				}

		        this.sortOn = sortOn;

		        return dataTableSort;
	        },

	        addSortingAttributesToHeaders: function () {
		        var columns = this.tableConfiguration.columns,
			        $columnHeaders = this.$el.find('th'),
			        counter = 0;

		        _.each(columns, function(column) {
			        var $columnHeader = $columnHeaders.eq(counter),
				        sortProp = column.sortProp || column.mDataProp;

			        $columnHeader.attr({
				        "sort-prop": sortProp
			        });

			        counter++;
		        });
	        },

	        getParams: function (url) {
		        var paramChar = url && url.indexOf("?") === -1 ? "?" : "&",
			        refresh = this.refreshData,
			        maxPerPage = this.maxPerPage,
			        goToPage = this.goToPage,
			        sortOn = this.sortOn,
			        filter = this.filterOn,
			        params = paramChar
				        + "refresh=" + refresh
				        + "&max-per-page=" + maxPerPage
				        + "&go-to-page=" + goToPage
			            + "&sort-on=" + sortOn
			            + "&filter=" + filter;

		        this.refreshData = false;

		        return params;
	        },

            getData: function() {
                var noFetch = this.options.noFetch,
					that = this;

	            if (noFetch) {
					this.loadData(this.dataCollection.toJSON());
				} else {
					var params = this.serverPaginate ? this.getParams(this.options.tableDataURL) : "",
						tableDataURL = this.options.tableDataURL + params;

					this.dataCollection.fetch({
						url: tableDataURL,
						cache: false,
						success: function () {
							if ($.isFunction(that.options.fetchSuccess)) {
								that.options.fetchSuccess();
							}
							that.loadData(that.dataCollection.toJSON());

							if (that.serverPaginate) {
								that.buildControls();
							}
						}
					});
				}
            },

			loadData: function(data) {
				if (this.$dataTable.fnSettings() !== null) {
					var defaultState = this.tableConfiguration.default;

					this.$dataTable.fnClearTable();

					this.$dataTable.fnAddData(data);

					this.getDataTableHeader(this.$dataTable);

					var rows = $("#" + this.$el.attr("id") + " tbody tr")
						.removeClass('selected-active');

					if (defaultState && defaultState === "first") {
						rows.eq(0).trigger("tap");
					}
				}
			},

			buildControls: function () {
				var recordCount = this.dataCollection.recordCount,
					stopRecord = this.dataCollection.stopRecord,
					paginationInfo = {
						currentPage: this.dataCollection.currentPage,
						recordCount: recordCount,
						startRecord: this.dataCollection.startRecord
					};

					paginationInfo.stopRecord = stopRecord > recordCount ? recordCount : stopRecord;

				this.$el
					.find('.pagination-controls')
					.remove();

				this.$el.append(this.paginationTemplate(paginationInfo));

				this.enableFirstButton();
				this.enablePreviousButton();
				this.enableNextButton();
				this.enableLastButton();
			},

	        enableFirstButton: function () {
		        var $firstButton = this.$el.find('.first');

		        if (this.dataCollection.currentPage > 1) {
			        $firstButton.removeClass('paginate_button_disabled');
		        } else {
			        $firstButton.addClass('paginate_button_disabled');
		        }
	        },

	        enablePreviousButton: function () {
		        var $previousButton = this.$el.find('.previous');

		        if (this.dataCollection.currentPage > 1) {
			        $previousButton.removeClass('paginate_button_disabled');
		        } else {
			        $previousButton.addClass('paginate_button_disabled');
		        }
	        },

	        enableNextButton: function () {
		        var $nextButton = this.$el.find('.next'),
			        pageCount = this.dataCollection.pageCount;

		        if (pageCount > 1 && this.dataCollection.currentPage < pageCount) {
			        $nextButton.removeClass('paginate_button_disabled');
		        } else {
			        $nextButton.addClass('paginate_button_disabled');
		        }
	        },

	        enableLastButton: function () {
		        var $lastButton = this.$el.find('.last'),
			        pageCount = this.dataCollection.pageCount;

		        if (pageCount > 1 && this.dataCollection.currentPage < pageCount) {
			        $lastButton.removeClass('paginate_button_disabled');
		        } else {
			        $lastButton.addClass('paginate_button_disabled');
		        }
	        },

            getDataTable: function() {
                return this.$dataTable;
            },

			getDataTableHeader: function($this) {
				var containerId = $this.attr('id'),
					rowCount = this.serverPaginate ? this.dataCollection.recordCount : $this.fnSettings().asDataSearch.length;

				containerId = containerId.slice(0, containerId.length - 6);

				return $('#' + containerId).find('.ctn-count').eq(0).text(rowCount);
			},

            rowCallBack: function(nRow, aData) {
                var $nRow = $(nRow),
                    firstCellText = $nRow.find('td:nth-child(1)').text();

                //data going to need to be configurable...
                $nRow
                    .data({
                        'requestHref': aData.detailsLink,
                        'detail': aData.detail,
		                'detailsId': aData.detailsId
                    })
                    .attr({
                        'data-theme': 'c',
                        'data-role': 'button'
                    })
                    .find('td:nth-child(1)').html('<a href="#">' + firstCellText + '</a>');

                //highlight row if currently viewed appointment.
                //if not current let screen readers know tap/click triggers appointment request details
                if (aData.detailsLink && aData.detailsLink === $(document).jqmData('requestHref-for-detail-viewing')) {
                    $nRow
                        .prop({'title': 'Currently viewed.'})
                        .addClass('selected-active');
                } else {
                    $nRow.prop({'title': 'Tap to see details.'});
                }
            },

	        setRefreshFlag: function (refreshFlag) {
		        thisView.refreshData = refreshFlag;
	        },

	        clearTable: function () {
		        thisView.$dataTable.fnClearTable();

		        thisView.sortOn = "";
		        thisView.filterOn = "";
		        thisView.refreshData = true;
		        thisView.goToPage = 1;
	        },

	        refreshTable: function () {
		        thisView.refreshData = true;

		        thisView.getData();
	        },

	        filterTable: function (filterString) {
		        thisView.filterOn = filterString;
		        thisView.goToPage = 1;

		        thisView.getData();
	        },

	        clearFilter: function () {
		        thisView.filterOn = "";
		        thisView.goToPage = 1;

		        thisView.refreshTable();
	        }
        });
    }
);

