Ext.namespace('Voyeur.Tool');


/**
 * @class Voyeur.Tool
 * @extends Ext.util.Observable
 * @param {Object} config configuration object
 * @constructor
 */
Voyeur.Tool = Ext.extend(Ext.util.Observable, {
	constructor : function(config, i18n) {
		Voyeur.Tool.superclass.constructor.call(this);
		
		this.xtype = config.xtype;
		this.events = [];

		// make sure the application knows about us
		this.addListener('render', function(cmp) {
			Voyeur.application.addTool(cmp)
		})

		this.loadLocalization(i18n, this.xtype);


		this.exporters = config.exporters ? config.exporters : {};
		Ext.applyIf(this.exporters, {
			url: this.localize('exportUrl','tool'),
			button: this.localize('exportButton','tool'),
			iframe: this.localize('exportIframe','tool'),
			citation: this.localize('exportCitation','tool')
			//html: this.localize('exportHtml','tool')
		});
		
		if (this.getColumnModel) {
			Ext.applyIf(this.exporters, {
				htmlTable: this.localize('exportHtmlTable','tool'),
				textTable: this.localize('exportTextTable','tool'),
				csvTable: this.localize('exportCsvTable','tool'),
				tabTable: this.localize('exportTabTable','tool'),
				xmlTable: this.localize('exportXmlTable','tool')
			})
		}
		
		
				
		// build the default toolset
		Ext.applyIf(config, {
			title : this.localize('title') +
				'<span  class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rfr_id=info%3Asid%2Focoins.info%3Agenerator&amp;rft.genre=book&amp;rft.btitle=Voyeur+Tools&amp;rft.title='+this.getApplication().localize('app.title')+' :: '+this.localize('title')+'&amp;rft.aulast=Sinclair&amp;rft.aufirst=St%C3%A9fan&amp;rft.au=St%C3%A9fan+Sinclair&amp;rft.au=Geoffrey+Rockwell&amp;rft.date=2009&amp;rft_id=http://voyeurtools.org/"></span>',
			toolNames : [ 'help' ],
			tools : [
					{
						id : 'gear',
						qtip : '<h3>' + this.localize('options', 'tool')
						+ this.localize('colon', 'app')
						+ this.localize('title') + '</h3>'
						+ this.localize('optionsTip','tool'),
						handler : this.onOptions,
						scope : this
					},
					{
						id : 'save',
						qtip : '<h3>' + this.localize('export', 'tool')
						+ this.localize('colon', 'app')
						+ this.localize('title') + '</h3>'
						+ this.localize('exportTip','tool'),
						handler : this.onExport
						,scope : this
					},
					{
						id : 'help',
						qtip : '<h3>' + this.localize('help', 'tool')
								+ this.localize('colon', 'app')
								+ this.localize('title') + '</h3>'
								+ this.localize('help')
						,handler : this.onHelp
						,scope : this
					} ]
		})
	}
	
	,onExport : function(ev, tool, panel) {
		/*
							Ext.applyIf(this.exporters, {
								url: this.localize('exportUrl','tool'),
								button: this.localize('exportButton','tool'),
								iframe: this.localize('exportIframe','tool'),
								citation: this.localize('exportCitation','tool')
								//html: this.localize('exportHtml','tool')
							});
							
							if (panel.getColumnModel) {
								Ext.applyIf(this.exporters, {
									htmlTable: this.localize('exportHtmlTable','tool'),
									textTable: this.localize('exportTextTable','tool'),
									csvTable: this.localize('exportCsvTable','tool'),
									tabTable: this.localize('exportTabTable','tool'),
									xmlTable: this.localize('exportXmlTable','tool')
								})
							}
		*/
							var items = [];
							for (var k in panel.exporters) {
								if (panel.exporters[k]) {
									items.push({
										inputValue: k,
										boxLabel: panel.exporters[k],
										name: 'exp',
										checked: k=='url' ? true : false
									})
								}
							}
							new Ext.Window({
								title: 'Export',
								modal: true,
								items: 
								{
									xtype: 'form',
									labelAlign: 'top',
									bodyStyle: 'padding:0 10px 0;',
									width: 350,
									items: {
										xtype: 'radiogroup'
										,fieldLabel: 'Export Format'
										,hideLabel: true
										,items: items
										,columns: 1
									}
									,buttons: [
									{
										text: this.localize('ok','tool'),
										listeners: {
											click: {
												fn: function(btn) {
													var exp = btn.findParentByType('form').getForm().getValues(false).exp;
													this.fireEvent('export', exp);
													var content = '';
													var isGrid = this.getView && this.getColumnModel;
													msg = ''; // if this is empty at the end nothing will be displayed
													var url = panel.getApplication().getBaseUrl();
													var params = {};
													if (panel.xtype!='voyeurDocumentInputAdd') {url+='tool/'+panel.xtype.replace(/^voyeur/,'')+'/';}
													
													if (exp=='url' || exp=='iframe' || exp=='button') {
														msg += '<p>'+this.localize('apiWarn','tool')+'</p>';
														if (exp=='iframe' || exp=='button') {
															content+="<!--\tExported from Voyeur (http://voyeur.hermeneuti.ca/).\n\t"+this.localize('apiWarn','tool').replace(/<.+?>/g,'')+" -->\n"
														}
														if (exp=='iframe') {
															var size = this.getSize();
															content+='<iframe width="'+size.width+'" height="'+size.height+'" src="';
														}
														else if (exp=='button') {
															content+="<form action='"+url+"' method='get' target='_blank'>\n";
														}
														if (panel.xtype!='voyeurDocumentInputAdd') {
															url += '?';
															params.corpus = this.getCorpus().getId()
															if (this.store) {
																var sortState = this.store.getSortState();
																if (sortState) {
																	params.sortBy = sortState.field;
																	params.direction = sortState.direction;
																}
																if (this.store.lastOptions) {Ext.apply(params,this.store.lastOptions.params);}
																else if (this.store.baseParams) {Ext.apply(params,this.store.baseParams);}
															}
															Ext.applyIf(params, this.getAdditionalExportParams());
															url+=Ext.urlEncode(params);
														}
														if (exp=='iframe' || exp=='url') {content+=url;}
														if (exp=='iframe') {content+='"></iframe>';}
														else if (exp=='button') {
															for (var k in params) {

																if (typeof params[k] == 'string') {
																	content+="<input type='hidden' name='"+k+"' value=\""+params[k]+"\" />\n"
																}
																else if (params[k] && params[k].length) {
																	for (var i=0;i<params[k].length;i++) {
																		content+="<input type='hidden' name='"+k+"' value=\""+params[k][i]+"\" />\n"
																	}
																}
															}
															content+='<input type="submit" value="'+new Ext.Template(this.localize('viewResults','tool')).apply([this.localize('title')])+'" />\n</form>';
														}
														else if (exp=='url') {
															msg += '<p>'+ new Ext.Template(this.localize('clickUrl','tool')).apply([url])+'</p>';
														}
													}
													else if (exp=='htmlTable' || exp=='textTable' || exp=='csvTable' || exp=='tabTable' || exp=='xmlTable') {
														if (isGrid) {
															var columnModel = this.getColumnModel();
															var columnCount = columnModel.getColumnCount();
															var view = this.getView();
															var rowCount = view.getRows().length
															var cols = [];
															var rows = []
															var val;
															for (var i=0;i<columnCount;i++) {
																val = columnModel.getColumnHeader(i);
																if (val.indexOf('-checker')==-1) {
																	cols.push(val);
																}
															}
															rows.push(cols);
															for (var i=0;i<rowCount;i++) {
																cols = [];
																for (var j=0;j<columnCount;j++) {
																	val = view.getCell(i,j).innerHTML;
																	if (val.indexOf('-checker')==-1) {
																		cols.push(val);
																	}
																}
																rows.push(cols);
															}
															var table = "";
															if (exp=='textTable') {
																longest = new Array(rows[0].length);
																for (var i=0;i<rows.length;i++) {
																	for (var j=0;j<rows[i].length;j++) {
																		val = rows[i][j].replace(/&nbsp;/g,' ').replace(/<\/?\w+.*?>/g,'');
																		rows[i][j] = val;
																		if (!longest[j] || longest[j]<val.length) {longest[j]=val.length;}
																	}
																}
																for (var i=0;i<rows.length;i++) {
																	for (var j=0;j<rows[i].length;j++) {
																		rows[i][j] = String.leftPad(rows[i][j],longest[j],' ');
																	}
																}
															}
															for (var i=0;i<rows.length;i++) {
																if (exp=='htmlTable') {
																	if (i==0) {table+="\t<thead>\n";}
																	if (i==1) {table+="\t<tbody>\n";}
																	table+="\t\t<tr>\n\t\t\t<td>"+rows[i].join("</td>\n\t\t\t<td>")+"</td>\n\t\t</tr>\n";
																	if (i==0) {table+="\t</thead>\n";}
																	if (i==rows.length-1) {table+="\t</tbody>\n";}
																}
																else if (exp=='csvTable') {table+=rows[i].join(',')+"\n";}
																else if (exp=='tabTable' || exp=='textTable') {table+=rows[i].join("\t")+"\n";}
																else if (exp=='xmlTable') {
																	if (i==0) {continue;}
																	table+="\t<row>\n";
																	for (var j=0;j<rows[0].length;j++) {
																		table+="\t\t<field name='"+rows[0][j]+"'>"+rows[i][j].replace(/<\/?\w+.*?>/g,'')+"</field>\n";
																	}
																	table+="\t</row>\n";
																}
															}
															table = table.replace(/&nbsp;/g,' ').replace(/<\/?div.*?>/g,'');
															
															if (exp=='htmlTable') {
																if (exp=='html') {
																	content+='<html><body><'
																}
																content+="<table cellpadding='0' cellspacing='0' border='1'>\n<caption style='caption-side: bottom; text-align: left;'><p><strong>"+this.localize('title')+"</strong>. "+this.localize('help')+'</p><p>'+this.getFooterText()+"</p></caption>"+table+"</table>\n";
															}
															else if (exp=='xmlTable') {
																content+="<?xml version='1.0'>\n<rows>\n"+table+"</rows>\n";
															}
															else if (exp=='tabTable' || exp=='csvTable') {content+=table.replace(/<\/?\w+.*?>/g,'');}
															else {content+=table;}
														}
													}
													else if (exp=='citation') {
														msg+='<br clear="all" />'
														var cite = '<p>Sinclair, Stéfan and Geoffrey Rockwell. &ldquo;' +this.localize('title')+'.&rdquo; '+
															'<u>'+this.localize('title','app')+'</u>. '+
															new Date().format("j M. Y") +
															' &lt;'+url+'&gt;</p>'
														msg+=cite;
														content+=cite;
														cite = '<p>Sinclair, S. and G. Rockwell ('+new Date().format("Y")+'). '+
															this.localize('title')+'. <i>'+this.localize('title','app')+'</i>. '+
															'Retrieved '+new Date().format("F j, Y")+' from '+url+'</p>'
														msg+=cite;
														content+="\n\n"+cite;
													}
													
													btn.findParentByType('window').destroy();
													
													if (msg) {
														
														// before we start, change the text area to monospace, nowrapping
														var textarea = Ext.DomQuery.selectNode('textarea',Ext.Msg.getDialog().body.dom);
														textarea.originalFontFamily=textarea.style.fontFamily;
														textarea.originalWrap=textarea.originalWrap;
														textarea.style.fontFamily='monospace';
														textarea.setAttribute('wrap','off');
	
														var msgBox = Ext.Msg.show({
														   title: this.localize('export','tool'),
														   msg:  '<p>'+this.localize('export','tool')+' '+this.exporters[exp]+'.</p>'+msg+"\n",
														   value: content,
														   width: Ext.getBody().getWidth()-50,
														   buttons: Ext.MessageBox.OK,
														   multiline: true,
														   icon: Ext.MessageBox.INFO,
														   fn: function() {
														   		textarea.style.fontFamily=textarea.originalFontFamily;
														   		textarea.setAttribute('wrap',textarea.originalWrap ? textarea.originalWrap : '');
														   }
														})
													}
												}
												,scope: panel
											}
										}
									},
									{
										text: this.localize('cancel','tool')
										,handler: function(btn) {
											btn.findParentByType('window').destroy();
										}
									}
									]
								}}).show();
	}
	,onOptions : function(ev, tool, panel) {
		if (panel.showOptions) {
			panel.showOptions.apply(panel, arguments)
		} else {
			this.alertInfo( {
				msg : this.localize('noOptions', 'tool')
			})
		}
	}
	
	,onHelp : function(ev, tool, panel) {
			var msgBox = Ext.Msg.show( {
				title : this.localize('help', 'tool')
						+ this.localize('colon', 'app')
						+ this.localize('title'),
				msg : this.localize('help'),
				buttons : Ext.Msg.OK,
				icon : Ext.Msg.INFO
			});
	}

	/*
	 * { id : 'save', qtip : '<h3>'+Voyeur.localization.get('voyeurTool.export')+'</h3>'+
	 * Voyeur.localization.get(xtypePrefix+'help'), handler: function(ev, tool,
	 * panel){ Ext.Msg.alert('Exporting is not yet fully implemented.') } ]},
	 */

	,
	showOptionsWindow : function(config) {
		Ext.applyIf(config, {
			renderTo : document.body
			,modal : true
			,title : this.localize('options', 'tool')
			,items: []
		})
		config.items.unshift({
				border: false,
				html : '<div style="text-align: center; margin: .75em;">'+this.localize('hoverLabel','tool')+'</div>'
			})
		this.optionsWindow = new Ext.Window(config);
		this.optionsWindow.show();
	},
	
	hideOptionsWindow : function() {
		if (this.optionsWindow) {this.optionsWindow.destroy();}
	}
	,getGridSearch : function(config) {
		Ext.applyIf(config,
				{
					iconCls : 'icon-zoom',
					// minChars:2,
					searchText : Voyeur.localization
							.get('voyeurTool.searchText'),
					searchTipText : Voyeur.localization
							.get('voyeurTool.searchTextTip'),
					selectAllText : Voyeur.localization
							.get('voyeurTool.selectAll')
				// minCharsTipText:Voyeur.localization.get('voyeurTool.minCharsTipText'),
				})
		return new Ext.ux.grid.Search(config);
	}
	
	// this is meant to be overridden
	,getAdditionalExportParams: function() {
		return {};
	}
	
	,setQueryValues : function() {
		var query = this.getApplication().query;
		var key;
		for (var i=0;i<arguments.length;i++) {
			key = arguments[i];
			if (key instanceof Array) {
				for (var j=0;j<key.length;j++) {this.setQueryValues(key[j]);}
			}
			else if (key instanceof Object) {
				for (var k in key) {this.setQueryValues(k);}
			}
			else {
				if (key && query[key]) {this[key]=query[key];}
			}
		}
	}

	,getCorpus : function() {
		return this.getApplication().getCorpus();
	}

	,
	getLocalization : function() {
		return this.getApplication().getLocalization();
	}

	,
	loadLocalization : function(loc) {
		this.getApplication().loadLocalization(loc, this.xtype + '.');
	}

	,
	localize : function(key, prefix) {
		return this.getLocalization().get(
				(prefix ? prefix : this.xtype) + '.' + key);
	}

	,
	getApplication : function() {
		return Voyeur.application;
	}

	,
	alertError : function(config) {
		Ext.applyIf(config, {
			title : this.localize('error', 'app'),
			buttons : Ext.Msg.OK,
			icon : Ext.Msg.ERROR
		})
		return Ext.MessageBox.show(config);
	}

	,handleAjaxError: function(response, options) {
		this.alertError({msg: response.responseText})
	}
	
	,
	alertInfo : function(config) {
		Ext.applyIf(config, {
			title : this.localize('info', 'app'),
			buttons : Ext.Msg.OK,
			icon : Ext.Msg.INFO
		})
		return Ext.MessageBox.show(config);
	}

	,
	update : function(config) {
		this.getApplication().update(config);
	}

	,
	getTromboneUrl : function() {
		return this.getApplication().getTromboneUrl();
	}
	
	,getToolDirectoryUrl: function() {
		return this.getApplication().getBaseUrl()+'resources/tools/'+this.xtype.replace(/^voyeur/,'')+'/';
	}
	
	,getFooterText : function() {
		return this.localize('appLink','tool') + 
    		" (&copy;"+ new Date().getFullYear() +") "+
    		"<a href='http://stefansinclair.name/'>St&eacute;fan Sinclair</a> &amp; <a href='http://geoffreyrockwell.com'>Geoffrey Rockwell</a>, "+
    		"v. "+this.getApplication().getVersion() + " ("+this.getApplication().getBuild()+")<span>"
	}
	
	,getSparkLine : function(values, stretch) {
		if (values.length<2) {return ''}
		var min = Number.MAX_VALUE;
		var max = Number.MIN_VALUE;
		var hasDecimal = false;
		for (var i=0;i<values.length;i++) {
			if (values[i]<min) {min=values[i];}
			if (values[i]>max) {max=values[i];}
			if (!hasDecimal && values[i].toString().indexOf('.')>-1) {hasDecimal=true;}
		}
		var dif = (max-min).toString();
		var multiplier = 1;
		var divider = 1;
		if (hasDecimal) {
			var multiplier = 100;
			var ind = dif.indexOf(".")+1;
			for (var i=ind;i<dif.length;i++) {
				if (dif.charAt(i)=='0') {multiplier*=10;}
				else {break;}
			}
			for (var i=0;i<values.length;i++) {
				values[i]=parseInt(values[i]*multiplier);
			}
			max = parseInt(max*multiplier);
			min = parseInt(min*multiplier);
			
		}
		else {
			var divider = 1;
			for (var i=dif.length-1;i>-1;i--) {
				if (dif.charAt(i)=='0') {divider*=10;}
				else {break;}
			}
			if (divider!=1) {
				for (var i=0;i<values.length;i++) {
					values[i]/=divider;
				}
				max /= divider;
				min /= divider;
			}
		}
		
		var valLen = (max.toString().length > min.toString().length ? max.toString().length : min.toString().length)+1;
		var valuesPerImage = Math.floor(1800/valLen);
		var baseUrl = 'http://chart.apis.google.com/chart?cht=ls&amp;chco=0077CC&amp;chls=1,0,0&amp;chds='+min+','+max
		var images = Math.ceil(values.length/valuesPerImage);
		var counter=0;
		var response = '';
		var wid;
		if (values.length<5) {wid=5;}
		else if (values.length<10) {wid=4;}
		else if (values.length<20) {wid=3;}
		else if (values.length<50) {wid=2;}
		else {wid=1;}
		/*
		if (stretch) {
			if (wid)
			wid = Math.ceil(stretch/values.length);
			if (wid>5) {wid=5;}
		}
		*/
		for (var i=0;i<images;i++) {
			var vals = values.slice(counter,counter+=valuesPerImage);
			response += "<img style='margin: 0; padding: 0;' border='0' src='"+baseUrl+'&amp;chs='+(wid*vals.length)+'x15&amp;chd=t:'+vals.join(',')+"' alt='' class='chart-";
			if (images==1) {response+='full';}
			else {
				if (i>0 && i+1<images) {response+'middle';}
				else if (i==0) {response+='left';}
				else {response+='right';}
			}
			response += "' />";
		}
		return response;
	}

});

Voyeur.localization.load( {
	'tool.help' : {
		en : 'Help'
	},
	'tool.helpTip' : {
		en : 'Click here for help with this tool.'
	},
	'tool.viewResults' : {
		en : 'View {0} in Voyeur.'
	},
	'tool.noResults' : {
		en : 'No results.'
	},
	'tool.noOptions' : {
		en : 'This tool does not define any user-controlled options.'
	},
	'tool.options' : {
		en : 'Options'
	},
	'tool.optionsTip' : {
		en : 'Click here to modify options for this tool.'
	},
	'tool.export' : {
		en : 'Export'
	},
	'tool.exportTip' : {
		en : 'Click here to export data from this tool.'
	},
	'tool.noExport' : {
		en : 'This tool does not provide any export options.'
	},
	'tool.hoverLabel' : {
		en: 'Tip: Hover over the labels to see more information about each item.'
	},
	'tool.ok' : {
		en : 'OK'
	},
	'tool.cancel' : {
		en : 'Cancel'
	},
	'tool.restore' : {
		en : 'Defaults'
	},
	'tool.exportUrl' : {
		en: 'a URL for this tool and current data'
	},
	'tool.clickUrl' : {
		en: 'Open this <a href="{0}" target="_blank">URL</a> in a new window.'
	},
	'tool.exportIframe' : {
		en: 'an HTML snippet to embed this tool and current data'
	},
	'tool.exportButton' : {
		en: 'an HTML button for this tool and current data'
	},
//	'tool.exportHtml' : {
//		en: 'a simple HTML page with static tabular data'
//	},
	'tool.exportHtmlTable' : {
		en: 'an HTML snippet with static tabular data'
	},
	'tool.exportTextTable' : {
		en: 'tabular data as plain text'
	},
	'tool.exportCsvTable' : {
		en: 'current data as comma-separated values'
	},
	'tool.exportTabTable' : {
		en: 'current data as tab-separated values'
	},
	'tool.exportXmlTable' : {
		en: 'current data as XML'
	},
	'tool.exportCitation' : {
		en: 'a bibliographic citation for this tool'
	},
	'tool.apiWarn' : {
		en: 'Please note that this is an early version and the API may change.\n\tSend an email to <a href="mailto:sgsinclair@gmail.com">sgsinclair@gmail.com</a> to be notified of API changes.'
	},
	'tool.appLink' : {
		en: "<a href='http://hermeneuti.ca/voyeur/' target='_blank'>Voyeur Tools</a>"
	},
	'tool.extendedSortZscoreMinimum' : {
			en : 'Minimum Z-Score'
	},
	'tool.extendedSortZscoreMinimumTip' : {
			en : 'This defines the minimum z-score (up to two decimals) for a corpus type. The default value of 1 helps to ensure that only higher frequency terms are kept.'
	},
	'tool.stopList' : {
		en: 'Stop Words List'
	},
	'tool.stopListTip' : {
		en: 'Stop words are usually high frequency words that carry little meaning, such as articles (the, a, etc.) and prepositions (of, to, etc.). You can select a pre-existing list from the menu, specify a URL for a list of stop words in plain text format (one per line), or provide a custom list with words separated by commas.'
	},
	'tool.filtersInEffect' : {
		en: 'Filters in Effect (see options):'
	},
	'tool.none' : {
		en : 'none'
	}
})
