/**
 * @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, {
	
	constructor : function(config) {
		
		Ext.apply(this, new Voyeur.Tool(config, this));

		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) {
			if (this.rendered) {this.fireEvent('afterrender', this);}
		}, this);
		
		this.addListener('afterrender', function(panel) {
			this.body.update(""); // clear page
			if (this.getCorpus().getSize()==0) {return;}
			this.showCorpusDocsAndWordsCount();
			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.getApiParamValue('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.getApiParamValue('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
		})
	}
	
	,showOptions : function() {
		this.showOptionsWindow({
			items : [{
				xtype : 'form',
				labelWidth : 150,
				labelAlign : 'right',
				border : false,
				items : [{
					xtype : 'combo',
					id : 'stopList',
					value : this.stopList,
					fieldLabel : '<span ext:qtip="'
							+ this.localize('stopListTip','tool') + '">'
							+ this.localize('stopList','tool') + '</span>',
					loadingText : this.localize('loading', 'tool'),
					width : 300,
					store : this.getApplication().getStopListsStore()
				    ,selectOnFocus : true
				    ,displayField: 'label'
				    ,triggerAction: 'all'
				    ,valueField: 'id'
				    ,mode: 'local'
				    ,emptyText: this.localize('none','tool')
				}],
				buttons : [{
					text : this.localize('ok', 'tool'),
					iconCls : 'icon-accept',
					listeners : {
						click : {
							fn : function(btn) {
								var formPanel = btn.findParentByType('form');
								var form = formPanel.getForm();
								var stopList = form.findField('stopList');
								
								// make sure we don't have any queries
								if (stopList.getValue() && !stopList.getRawValue()) {stopList.setValue('');}
								this.setApiParams({stopList: stopList.getValue()});
								
								this.initialized = false;
								this.initCirrus({});
						    	this.reupdate({stopList: stopList.getValue()});
						    	
								formPanel.findParentByType('window').destroy();
							},
							scope : this
						}
					}
				}, {
					text : this.localize('cancel', 'tool'),
					handler : function(btn) {
						btn.findParentByType('window').destroy();
					}
				}, {
					text : this.localize('restore', 'tool'),
					listeners : {
						click : {
							fn : function(btn) {
								var form = btn.findParentByType('form').getForm();
								form.findField('stopList').setValue(this.stopList);
							},
							scope : this
						}
					}
	
				}]
			}]
		})

	}
	
	,api: {
		'stopList': {
			'default': null
			,'choices': ['stop.en.taporware.txt', 'stop.en.glasgow.txt']
		}
		,'numberOfDocumentsForDistinctiveWords': {
			'default': 5
		}
	}
	
	// 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);

