/**
 * @class Voyeur.Tool.CorpusSummary
 * @description A panel that provides an overview of the current corpus, intended to suggest preliminary aspects to study.
 * @extends Ext.grid.Panel
 * @extends Voyeur.Tool
 * @author Stéfan Sinclair
 * @since 0.1.1
 */
Voyeur.Tool.CorpusSummary = Ext.extend(Ext.Panel, {
	
	/**
	 * Defines the number of documents for which distinctive words should be fetched.
	 */
	numberOfDocumentsForDistinctiveWords: 5
	,stopList : null
	
	,constructor : function(config) {
		
		Ext.apply(this, new Voyeur.Tool(config, Voyeur.Tool.CorpusSummary.prototype.i18n));

		this.setQueryValues('stopList','numberOfDocumentsForDistinctiveWords');

		Ext.applyIf(config, {
			bodyStyle: {'background-color': 'white', padding: '1em'},
			frame: true,
			border: false
			,autoScroll: true
		})
		Voyeur.Tool.CorpusSummary.superclass.constructor.call(this, config);
		
		this.addListener('CorpusSummaryResultLoaded', function(src, data) {
			this.body.update(""); // clear page
			this.showCorpusDocsAndWordsCount()
		}, this);
		this.addListener('CorpusSummaryBootstrap', function(src, params) {
			this.update({params : params, tool : 'CorpusSummary'});
		}, this)
		
		this.addListener('render', function(panel) {
			panel.body.addListener('click', function(e) {
				var target = e.getTarget(null,null,true);
				if (target && target.dom.tagName=='A') {
					var app = panel.getApplication();
					params = {};
					if (target.hasClass('corpus-documents')) {
						if (target.hasClass('corpus-documents-length')) {
							params.sortBy =  'totalWordTokens';
						}
						else if (target.hasClass('corpus-documents-density')) {
							params.sortBy =  'wordDensity';
						}
						params.direction='DESC';
						app.dispatchEvent.call(app, 'CorpusGridBootstrap', this, params)
					}
					else if (target.hasClass('document-id')) {
						if (target.hasClass('document-id-distinctive')) {
							Ext.apply(params, {sortBy: 'rawZscoreCorpusDelta', direction: 'DESC'});
						}
						if (target.hasClass('document-id-density')) {
							Ext.apply(params, {sortBy: 'wordDensity', direction: 'DESC'});
						}
						params.docId = target.getAttributeNS('voyeur', 'val');
						app.dispatchEvent.call(app, 'corpusDocumentSelected', this, params)
					}
					else if (target.hasClass('corpus-type')) {
						app.dispatchEvent.call(app, 'corpusTypeSelected', this, {type: target.dom.innerHTML})
					}
					else if (target.hasClass('corpus-types')) {
						if (target.hasClass('corpus-types-peaks')) {
							Ext.apply(params, {sortBy: 'relativeKurtosis', direction: 'DESC'});
						}
						app.dispatchEvent.call(app, 'CorpusTypeFrequenciesGridBootstrap', this, params)
					}
					else if (target.hasClass('document-type')) {
						app.dispatchEvent.call(app, 'documentTypeSelected', this, {docIdType: target.getAttributeNS('voyeur', 'val')})
					}
				}
			})
		}, this)
	}

	,showCorpusDocsAndWordsCount: function() {
		var corpus = this.getCorpus();
		new Ext.XTemplate(this.localize('corpusDocsAndWordsCount')).append(this.body, {
			docsCount: Ext.util.Format.number(corpus.get('docsCount'),'0,000')
			,totalWordTokens: Ext.util.Format.number(corpus.get('totalWordTokens'),'0,000')
			,totalWordTypes: Ext.util.Format.number(corpus.get('totalWordTypes'),'0,000')
		});
		this.showDocLengthsAndDensity();
	}
	
	,showDocLengthsAndDensity : function() {

		var docs = this.getCorpus().getDocuments().clone();
		var count = docs.getCount();
		if (count>1) {
			
			var lengths = [];
			var densities = [];
			docs.each(function(item) {
				lengths.push(item.get('totalWordTokens'))
				densities.push(item.get('wordDensity'))
			})

			// sort items
			docs.sort(null, function(a,b) {
				return a.get('totalWordTokens') >  b.get('totalWordTokens') ? -1 : 1;
			});
			
			var data = {};
			var data = count>5 ? {shortest: docs.getRange(count-2).reverse(), longest: docs.getRange(0,1)} : {all: docs.getRange()}
			var obj;
			for (var k in data) {
				if (k) {
					var items = data[k];
					for (var i=0;i<items.length;i++) {
						data[k][i] = {
							title: items[i].getShortTitle(),
							id: items[i].get('id'),
							totalWordTokens: Ext.util.Format.number(items[i].get('totalWordTokens'),'0,000'),
							docsLen: items.length
						}
					}
				}
			}
			
			var tpl = new Ext.XTemplate(this.localize('docsLength'));
			var out = '';
			if (count>5) {
				out += new Ext.Template(this.localize('docsLengthLongest')).applyTemplate([this.getSparkLine(lengths)]) + this.localize('colon', 'app') + tpl.apply({docs: data.longest})+'. ';
				out += this.localize('docsLengthShortest') + this.localize('colon', 'app') + tpl.apply({docs: data.shortest})+'. ';
				out += "<a href='#' onclick='return false' class='corpus-documents corpus-documents-length'>"+this.localize('seeAll')+'</a>'
			}
			else {
				out += new Ext.Template(this.localize('docsLengthAll')).applyTemplate([this.getSparkLine(lengths)]) + this.localize('colon', 'app') + tpl.apply({docs: data.all});
			}
			
			Ext.DomHelper.append(this.body, {tag: 'div', cls: 'corpus-summary-item', html: out});

			// sort items
			docs.sort(null, function(a,b) {
				return a.get('wordDensity') >  b.get('wordDensity') ? -1 : 1;
			});
			
			var data = {};
			var data = count>5 ? {lowest: docs.getRange(count-2).reverse(), highest: docs.getRange(0,1)} : {all: docs.getRange()}
			var obj;
			
			for (var k in data) {
				if (k) {
					var items = data[k];
					for (var i=0;i<items.length;i++) {
						data[k][i] = {
							title: items[i].getShortTitle(),
							id: items[i].get('id'),
							wordDensity: Ext.util.Format.number(items[i].get('wordDensity'),'0,000.0'),
							docsLen: items.length
						}
					}
				}
			}
			var tpl = new Ext.XTemplate(this.localize('docsDensity'));
			var out = '';
			if (count>5) {
				out += new Ext.Template(this.localize('docsDensityHighest')).applyTemplate([this.getSparkLine(densities)]) + this.localize('colon', 'app') + tpl.apply({docs: data.highest})+'. ';
				out += this.localize('docsDensityLowest') + this.localize('colon', 'app') + tpl.apply({docs: data.lowest})+'. '
				out += "<a href='#' onclick='return false' class='corpus-documents corpus-documents-density'>"+this.localize('seeAll')+'</a>'
			}
			else {
				out += new Ext.Template(this.localize('docsDensityAll')).applyTemplate([this.getSparkLine(densities)])  + this.localize('colon', 'app') + tpl.apply({docs: data.all}) +'.';
			}

			Ext.DomHelper.append(this.body, {tag: 'div', cls: 'corpus-summary-item', html: out})
		}
		
		this.showCorpusTypesTop();
	}
	
	,showCorpusTypesTop: function() {
		var el = Ext.DomHelper.append(this.body, {tag: 'div', cls: 'corpus-summary-item', html: this.localize('corpusTypesTop')}, true);
		var mask = new Ext.LoadMask(el, {msg: this.localize('loading'), removeMask: true});
		mask.show();
		Ext.Ajax.request({
			url: this.getTromboneUrl()
			,params: {tool: 'CorpusTypeFrequencies', limit: 5, corpus: this.getCorpus().get('id'), stopList: this.stopList}
			,callback: function(options, success, response) {
				if (success) {
					var json = Ext.decode(response.responseText);
					var store = new Ext.data.JsonStore({
						fields: Voyeur.data.CorpusTypes.fields
						,data: json.corpusTypes.types
					})
					var data = [];
					var len = store.getCount();
					store.each(function(item) {
						data.push({
							type: item.get('type'),
							val: Ext.util.Format.number(item.get('rawFreq'),'000,0'),
							len: len});
					})
					mask.hide();
					new Ext.DomHelper.overwrite(el, {
						tag: 'p'
						,html: this.localize('corpusTypesTop')+this.localize('colon','app')+
							new Ext.XTemplate(this.localize('corpusType')).applyTemplate({types: data})+
							'. <a href="#" onclick="return false;" class="corpus-types corpus-types-freqs">'+this.localize('more')+'</a>'
					})
				}
				this.showCorpusTypesPeaks();
			}
			,scope: this
		})
		
	}
	
	,showCorpusTypesPeaks: function() {
		if (this.getCorpus().getSize()>1) {
			var el = Ext.DomHelper.append(this.body, {tag: 'div', cls: 'corpus-summary-item',  html: this.localize('corpusTypesPeaks')}, true);
			var mask = new Ext.LoadMask(el, {msg: this.localize('loading'), removeMask: true});
			mask.show();
			Ext.Ajax.request({
				url: this.getTromboneUrl()
				,params: {tool: 'CorpusTypeFrequencies', limit: 5, corpus: this.getCorpus().get('id'), sortBy: 'relativeKurtosis', extendedSortZscoreMinimum: 1}
				,callback: function(options, success, response) {
					if (success) {
						var json = Ext.decode(response.responseText);
						var store = new Ext.data.JsonStore({
							fields: Voyeur.data.CorpusTypes.fields
							,data: json.corpusTypes.types
						})
						var data = [];
						var len = store.getCount();
						store.each(function(record) {
							var val = record.get('relativeFreqs');
							data.push({
								type: record.get('type'),
								val: this.getSparkLine(val, 20),
								len: len
							});
						}, this)
						mask.hide();
						new Ext.DomHelper.overwrite(el, {
							tag: 'p'
							,html: this.localize('corpusTypesPeaks')+this.localize('colon','app')+
								new Ext.XTemplate(this.localize('corpusType')).applyTemplate({types: data}) +
								'. <a href="#" onclick="return false;" class="corpus-types corpus-types-peaks">'+this.localize('more')+'</a>'
						})
					}
					this.showDocumentDistinctiveWords();
				}
				,scope: this
			})
		}
		else {
			this.showDocumentDistinctiveWords();
		}
	}
	
	/**
	 * Show the distinctive words in the document.
	 */
	,showDocumentDistinctiveWords : function() {
		if (this.getCorpus().getSize()>1) {
			var docs = this.getCorpus().getDocuments();
			if (docs.getCount()>1) {
				Ext.DomHelper.append(this.body, {tag: 'div', cls: 'corpus-summary-item',  html: this.localize('distinctiveWords')});
				var list = Ext.DomHelper.append(this.body, {tag: 'ol', cls: 'normal-list', html: ''}, true);
				var item;
				var len = this.numberOfDocumentsForDistinctiveWords;
				docs.each(function(item,index,length) {
					Ext.DomHelper.append(list, {tag: 'li', 'voyeur:index': String(index), cls: (index>len-1 ? 'x-hidden' : ''), html: '<a href="#" onclick="return false" class="document-id document-id-distinctive" voyeur:val="'+item.get('id')+'">'+item.getShortTitle()+'</a>'});
				});
				if (docs.getCount()>len) {
					var tpl = new Ext.Template(this.localize('moreDistinctiveWords'));
					var remaining = docs.getCount()-len;
					var more = Ext.DomHelper.append(this.body, {tag: 'div', style: 'display: block; margin-left: 40px;', html: tpl.apply([len>remaining ? remaining : len,remaining])}, true);
					more.addListener('click', function() {
						var hidden = list.select("li[@class=x-hidden]");
						var item;
						for (i=0;i<hidden.getCount();i++) {
							if (i==len) {break;}
							item = hidden.item(i).removeClass('x-hidden');
						}
						this.showDocumentDistinctiveWordsStep(hidden.item(0));
						var remaining = hidden.getCount()-len;
						if (remaining>0) {
							more.update(tpl.apply([len>remaining ? remaining : len,remaining]))
						}
						else {more.remove();}
					}, this);
				}
	//			docs.each(function(item,index,length) {
	//				Ext.DomHelper.append(list, {tag: 'li', html: '<a href="#" onclick="return false" class="document-id document-id-distinctive" voyeur:val="'+item.get('id')+'">'+item.getShortLabel()+'</a>'});
	//			});
				this.showDocumentDistinctiveWordsStep(list.first());
			}
		}
	}
	
	,showDocumentDistinctiveWordsStep : function(el) {
		var mask = new Ext.LoadMask(el, {msg: this.localize('loading'), removeMask: true});
		mask.show();
		var index = Number(el.getAttributeNS('voyeur','index'));
		Ext.Ajax.request({
			url: this.getTromboneUrl()
			,params: {tool: 'DocumentTypeFrequencies', docIndex: String(index), limit: 5, corpus: this.getCorpus().getId(), sortBy: 'rawZscoreCorpusDelta', direction: 'DESC'}
			,callback: function(options, success, response) {
				if (success) {
					var data = Ext.decode(response.responseText);
					var store = new Ext.data.JsonStore({
						fields: Voyeur.data.DocumentTypes.fields
						,data: data.documentTypes.types
					})
					var data = [];
					var len = store.getCount();
					store.each(function(item) {
						data.push({
							type: item.get('type'),
							val: Ext.util.Format.number(item.get('rawFreq'),'000,0'),
							docId: item.get('docId'),
							len: len})
					})
					mask.hide();
					new Ext.DomHelper.append(el,
							this.localize('colon','app')+new Ext.XTemplate(this.localize('documentType')).applyTemplate({types: data})+
							'. <a href="#" onclick="return false;" class="document-id document-id-distinctive" voyeur:val="'+this.getCorpus().getDocument(index).get('id')+'">'+this.localize('more')+'</a>'
					)
					var nextel = el.next();
					if (nextel && !nextel.hasClass('x-hidden')) {
						this.showDocumentDistinctiveWordsStep(nextel, index+1)
					}
				}
			}
			,scope: this
		})
	}
	
	// private localization variables
	,i18n : {
		title : {en: "Summary"}
		,corpusDocsAndWordsCount: {en: '<div class="corpus-summary-item">There <tpl if="docsCount == 1">is <a href="#" onclick="return false" class="corpus-documents" ext:qtip="Click to see a table of documents">1 document</a></tpl><tpl if="docsCount &gt; 1">are <a href="#" onclick="return false" class="corpus-documents" ext:qtip="Click to see a table of documents">{docsCount} documents</a></tpl> in this corpus with a total of <b>{totalWordTokens} words</b> and <b>{totalWordTypes} unique words</b>.</div>'}
		,docsLength: {en: '<tpl for="docs"><a href="#" onclick="return false" class="document-id" voyeur:val="{id}">{title}</a> ({totalWordTokens})<tpl if="xindex &lt; docsLen">, </tpl></tpl>'}
		,docsLengthLongest: {en: '<b>Longest documents</b> (by words {0})'}
		,docsLengthShortest: {en: 'Shortest documents'}
		,docsLengthAll: {en: 'Documents ordered by number of words ({0})'}
		,docsDensity: {en: '<tpl for="docs"><a href="#" onclick="return false" class="document-id" voyeur:val="{id}">{title}</a> ({wordDensity})<tpl if="xindex &lt; docsLen">, </tpl></tpl>'}
		,docsDensityHighest: {en: 'Highest <b>vocabulary density</b> ({0})'}
		,docsDensityLowest: {en: 'Lowest density'}
		,docsDensityAll: {en: 'Documents ordered by vocabulary density ({0})'}
		,help : {en : "<p>This tool shows an overview of the corpus and tries to suggest characteristics worthy of further exploration.</p>"}
		,corpusTypesTop: {en: 'Most <b>frequent words</b> in the corpus'}
		,corpusTypesPeaks: {en: 'Words with <b>notable peaks in frequency</b> across the corpus'}
		,corpusType: {en: '<tpl for="types"><a href="#" onclick="return false" class="corpus-type keyword">{type}</a> ({val})<tpl if="xindex &lt; len">, </tpl></tpl>'}
		,documentType: {en: '<tpl for="types"><a href="#" onclick="return false" class="document-type keyword" voyeur:val="{docId}:{type}">{type}</a> ({val})<tpl if="xindex &lt; len">, </tpl></tpl>'}
		,distinctiveWords: {en: '<b>Distinctive words</b> (compared to the rest of the corpus)'}
		,moreDistinctiveWords: {en: '<a href="#" onclick="return false">Next {0} of {1} remaining</a>'}
		,loading: {en: 'Loading&hellip;'}
		,seeAll: {en: 'All&hellip;'}
		,more: {en: 'More&hellip;'}
	}
});

Ext.reg('voyeurCorpusSummary', Voyeur.Tool.CorpusSummary);

