/**
 * Scalar
 * Copyright 2013 The Alliance for Networking Visual Culture.
 * http://scalar.usc.edu/scalar
 * Alliance4NVC@gmail.com
 *
 * Licensed under the Educational Community License, Version 2.0
 * (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.osedu.org/licenses /ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

;(function( $, window, document, undefined ) {

	var pluginName = "scalarindex",
		defaults = {
			root_url: ''
		};

	/**
	 * Manages the index dialog.
	 */
	function ScalarIndex( element, options ) {

		this.element = $(element);
		this.options = $.extend( {}, defaults, options );
		this._defaults = defaults;
		this._name = pluginName;

		this.DisplayMode = {
			Path: 'Path',
			Page: 'Page',
			Media: 'Media',
			Tag: 'Tag',
			Annotation: 'Annotation',
			Comment: 'Reply'
		};

		this.init();

	}

	ScalarIndex.prototype.bodyContent = null;			// body content container
	ScalarIndex.prototype.currentMode = null;			// Current display mode
	ScalarIndex.prototype.currentPage = null;			// Current page of results being displayed
	ScalarIndex.prototype.resultsTable = null;			// Table for the results
	ScalarIndex.prototype.pagination = null;			// Pagination interface
	ScalarIndex.prototype.resultsPerPage = null;		// Results to show per page
	ScalarIndex.prototype.controlBar = null;			// Index controls
	ScalarIndex.prototype.firstRun = null;				// First time the plug-in has run?
	ScalarIndex.prototype.maxPages = null;				// Maximum number of pages with known results in the current tab

	ScalarIndex.prototype.init = function () {
		var me = this;

		this.currentPage = 1;
		this.maxPages = 1;
		this.resultsPerPage = 10;
		this.firstRun = true;

		this.element.addClass( 'modal fade' );
		this.element.attr( {
			'tabindex': '-1',
			'role': 'dialog',
			'aria-labelledby': 'index-modal-title'
		} );
		this.element.append( '<div class="modal-dialog modal-lg"><div class="modal-content index_modal"></div></div>' );
		var modalContent = this.element.find( '.modal-content' );
		var header = $( '<header class="modal-header"><h2 id="index-modal-title" class="modal-title heading_font heading_weight">Index</h2><button type="button" title="Close" class="close" data-dismiss="modal"><span>Close</span></button></header>' ).appendTo( modalContent );
		this.bodyContent = $( '<div class="modal-body"></div>' ).appendTo( modalContent );

		this.controlBar = $( '<ul class="nav nav-tabs"></ul>' ).appendTo( this.bodyContent );
		var pathBtn = $( '<li id="pathBtn" class="active caption_font"><a href="#Path">Paths</a></li>' ).appendTo( this.controlBar );
		var pageBtn = $( '<li id="pageBtn" class="caption_font"><a href="#Page">Pages</a></li>' ).appendTo( this.controlBar );
		var mediaBtn = $( '<li id="mediaBtn" class="caption_font"><a href="#Media">Media</a></li>' ).appendTo( this.controlBar );
		var tagBtn = $( '<li id="tagBtn" class="caption_font"><a href="#Tag">Tags</a></li>' ).appendTo( this.controlBar );
		var annotationBtn = $( '<li id="annotationBtn" class="caption_font"><a href="#Annotation">Annotations</a></li>' ).appendTo( this.controlBar );
		var commentBtn = $( '<li id="replyBtn" class="caption_font"><a href="#Comment">Comments</a></li>' ).appendTo( this.controlBar );

		var showTab = function(event) {
			event.preventDefault();
			var mode = $(this).attr('href').substr(1);
			me.setDisplayMode( me.DisplayMode[mode] );
		}

		this.controlBar.find('li>a').on('click', showTab);

		var resultsDiv = $( '<div class="results_list caption_font"></div>' ).appendTo( this.bodyContent );
		this.resultsTable = $( '<table summary="" class="table table-striped table-hover table-responsive small"></table>' ).appendTo( resultsDiv );
		this.loading = $('<div class="loading"><p>Loading...</p></div>').hide().insertAfter(this.resultsTable);

		this.pagination = $( '<ul class="pagination caption_font"></ul>' ).appendTo( this.bodyContent );
	}

	ScalarIndex.prototype.showIndex = function() {

		var me = this;
		var modal = this.element.modal();
		modal.on('shown.bs.modal', function() {
			modal.find( '.modal-body a' )[ 0 ].focus();
			var firstFocusable = modal.find('.close');
			var lastFocusable = modal.find('.modal-body a').last();
			setupFocusTrap(firstFocusable, lastFocusable)
		});

		modal.on('hidden.bs.modal', function (e) {
			$( 'body' ).css( 'overflowY', 'auto' );
			removeFocusTrap();
		});

		var mode = this.currentMode || this.DisplayMode.Path;

		if ( this.firstRun ) {
			this.setDisplayMode(this.DisplayMode.Path);
			this.firstRun = false;
		}
		setState( ViewState.Modal );
	}

	ScalarIndex.prototype.hideIndex = function() {

		this.element.modal( 'hide' );
		restoreState();
	}

	ScalarIndex.prototype.setDisplayMode = function( mode ) {

		var me = this;

		if ( me.currentMode != mode ) {
			this.currentPage = 1;
			this.currentMode = mode;
			this.maxPages = 0;
			mode = mode.toLowerCase();
			this.controlBar.find('li').removeClass('active');
			$('#'+mode+'Btn').addClass('active');
			me.pagination.empty();
			me.getResults();
		}

	}

	ScalarIndex.prototype.showLoading = function() {
		var h = this.resultsTable.height();
		var $p = this.loading.find('p');
		this.loading.width(this.resultsTable.width()).height(h);
		$p.css('top', (((h-$p.height())/2)-5)+'px');
		this.loading.show();
	}

	ScalarIndex.prototype.getResults = function(callback) {
		var me = this;
		this.showLoading();
		scalarapi.loadNodesByType(
			this.currentMode.toLowerCase(), true,
			function( data ) {
				me.loading.hide();
				me.handleResults( data );
				if (callback) callback();
			},
			null, 0, false, null, ( me.currentPage - 1 ) * me.resultsPerPage, me.resultsPerPage
		);
	}

	ScalarIndex.prototype.handleResults = function( data ) {

		var i, node, description, row, prev, next, prevx10, nextx10,
			nodes = [],
			me = this;

		for ( i in data ) {
			node = scalarapi.getNode( i );
			if ( node !== undefined ) {
				if(me.maxPages == 0){
					//We have not yet calculated the number of pages - use the citation property to determine maxPages
					var citationProp = node.properties['http://scalar.usc.edu/2012/01/scalar-ns#citation'][0].value;
					var p = new RegExp('.*?(methodNumNodes=)(\\d+)',["i"]);
					var m = p.exec(citationProp);
					me.maxPages = Math.ceil(parseInt(m[2])/me.resultsPerPage);
				}
				nodes.push( node );
			}
		}

		this.resultsTable.parent().scrollTop( 0 );
		this.resultsTable.empty();
		var $a = this.controlBar.find('li.active a');
		if ($a.length) {
			this.resultsTable.attr('summary', 'Results for '+$a.html().toLowerCase());
		}

		for ( i in nodes ) {
			node = nodes[i];
			description = node.current.description;
			if (description == null) {
				description = '(No description)';
			} else {
				description = description.replace(/<\/?[^>]+>/gi, '');
			}
			var thumb = '';
			if (node.thumbnail) {
				thumb = '<img src="'+node.getAbsoluteThumbnailURL()+'" alt="'+node.current.getAltTextWithFallback('Thumbnail for ' + node.getDisplayTitle())+'" />';
			}
			row = $( '<tr><td class="title"><a href="javascript:;">'+node.getDisplayTitle()+'</a></td><td class="desc">'+description+'</td><td class="thumb">'+thumb+'</td></tr>' ).appendTo( this.resultsTable );
			row.data( 'node', node );
			row.on('click',  function() { document.location = addTemplateToURL($(this).data('node').url, 'cantaloupe'); } );
		}

		if ( nodes.length == 0 ) {
			row = $( '<tr><td style="width:30%">No results found.</td><td></td></tr>' ).appendTo( this.resultsTable );
		}
		if ( this.currentPage > 1 ) {
			this.pagination.find('.prevPage,.prevPagex10').removeClass('disabled');
		}else{
			this.pagination.find('.prevPage,.prevPagex10').addClass('disabled');
		}

		if(this.currentPage < me.maxPages){
			this.pagination.find('.nextPage,.nextPagex10').removeClass('disabled');
		}else{
			this.pagination.find('.nextPage,.nextPagex10').addClass('disabled');
		}

		if(me.maxPages > 1 && this.pagination.html() == ""){
			if (me.maxPages > 15) {
				prevx10 = $('<li class="disabled prevPagex10"><a aria-label="Jump back 10 pages" href="javascript:;">&laquo;</a></li>').appendTo( this.pagination );
				prevx10.find('a').on('click',  function() { if(!$(this).parent().hasClass('disabled')){me.goToPage(Math.max(1,me.currentPage-10));} } );
			}
			if(me.maxPages > 1){
				prev = $('<li class="disabled prevPage"><a aria-label="Previous results page" href="javascript:;">&lsaquo;</a></li>').appendTo( this.pagination );
				prev.find('a').on('click',  function() { if(!$(this).parent().hasClass('disabled')){me.previousPage();} } );
			}
			this.pagination.append('<li class="disabled"><a href="#">Page <span class="current-page">' + this.currentPage + '</span> of ' + me.maxPages + '</a></li>');
			if(me.maxPages > 1){
				next = $( '<li class="nextPage"><a aria-label="Next results page" href="javascript:;">&rsaquo;</a></li>' ).appendTo( this.pagination );
				next.find('a').on('click',  function() { if(!$(this).parent().hasClass('disabled')){me.nextPage();} } );
			}
			if(me.maxPages > 15){
				nextx10 = $( '<li class="nextPagex10"><a aria-label="Jump ahead 10 pages" href="javascript:;">&raquo;</a></li>' ).appendTo( this.pagination );
				nextx10.find('a').on('click',  function() { if(!$(this).parent().hasClass('disabled')){me.goToPage(Math.min(me.maxPages,me.currentPage+10));} } );
			}
		}

	}

	ScalarIndex.prototype.updateCurrentPageNumber = function() {
		this.pagination.find('.current-page').text(this.currentPage);
	}

	ScalarIndex.prototype.previousPage = function() {
		this.currentPage--;
		this.updateCurrentPageNumber();
		var self = this;
		this.getResults(function(){ self.focusOnCurrentPage(); });
	}

	ScalarIndex.prototype.nextPage = function() {
		this.currentPage++;
		this.updateCurrentPageNumber();
		var self = this;
		this.getResults(function() { self.focusOnCurrentPage(); });
	}

	ScalarIndex.prototype.goToPage = function( pageNum ) {
		this.currentPage = pageNum;
		this.updateCurrentPageNumber();
		var self = this;
		this.getResults(function() { self.focusOnCurrentPage(); });
	}

	ScalarIndex.prototype.focusOnCurrentPage = function() {
		this.pagination.find('a[data-page="'+this.currentPage+'"]').trigger('focus');
	}

    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if ( !$.data(this, "plugin_" + pluginName )) {
                $.data( this, "plugin_" + pluginName,
                new ScalarIndex( this, options ));
            }
        });
    }

})( jQuery, window, document );
