/**
 * Project  : AMDA-NG
 * Name	 : EpnTapModule.js
 * @class   amdaDesktop.EpnTapModule
 * @extends amdaDesktop.AmdaModule
 * @brief   EpnTap Module controller definition
 * @author  Nathanael Jourdane
 */

// Load text with Ajax synchronously: takes path to file and optional MIME type
function loadTextFileAjaxSync(filePath, mimeType) {
	var xmlhttp=new XMLHttpRequest();
	xmlhttp.open("GET", filePath, false);
	if (mimeType != null) {
		if (xmlhttp.overrideMimeType) {
			xmlhttp.overrideMimeType(mimeType);
		}
	}
	xmlhttp.send();
	if (xmlhttp.status == 200) {
		return xmlhttp.responseText;
	} else {
		return null;
	}
}

function prettify(name) {
	return name.charAt(0).toUpperCase() + name.replace(/_/g, ' ').substr(1).toLowerCase();
}

function allPrettify(name) {
	return 'All ' + (name[name.length-1] == 's' ? name : name + 's').replace(/_/g, ' ').toLowerCase();
}

function isLatest(newStrDate, oldStrDate) {
	if (newStrDate === null) {
		return false;
	}
	if (oldStrDate === null) {
		return true;
	}

	var newDate = newStrDate.split('/');
	var oldDate = oldStrDate.split('/');

	if(newDate[2]>oldDate[2]) {
		return true;
	} else if(newDate[2]<oldDate[2]) {
		return false;
	}
	if(newDate[1]>oldDate[1]) {
		return true;
	} else if(newDate[1]<oldDate[1]) {
		return false;
	}
	if(newDate[0]>oldDate[0]) {
		return true;
	} else {
		return false;
	}
}

Ext.define('amdaDesktop.EpnTapModule', {

	extend: 'amdaDesktop.AmdaModule',

	// requires: ['amdaUI.EpnTapUI', 'amdaReader.EpnTapReader'],
	requires: ['amdaUI.EpnTapUI'],
	contentId : 'EpnTapUI',

	/** The alias name of the module view. */
	uiType: 'panelEpnTap',

	/** The text displayed on the *help button* tooltip. */
	helpTitle: 'Help on EPN-TAP Module',

	/** The name of the documentation file related to the module. */
	helpFile : 'epnTapHelp',

	/** Window dimentions. */
	width : 1000,
	height: 550,

	/** @class Module initialisation. */
	init: function() {
		this.metadata = JSON.parse(loadTextFileAjaxSync('../../generic_data/EpnTapData/metadata.json', 'application/json'));
		this.services = JSON.parse(loadTextFileAjaxSync('../../generic_data/EpnTapData/services.json', 'application/json'));
		this.productTypeDict = JSON.parse(loadTextFileAjaxSync('../../generic_data/EpnTapData/dataproduct_types.json', 'application/json'));
		this.mimetypeDict = JSON.parse(loadTextFileAjaxSync('../../generic_data/EpnTapData/mimetypes.json', 'application/json'));

		this.select = Array();
		this.filter = Array();

		this.selectedServiceId = null;

		this.launcher = {
			text: this.title,
			iconCls: this.icon,
			handler: this.createWindow,
			scope: this
		};
	},

	onWindowLoaded: function() {
		// UI elements
		this.dataProdutTypeCB = Ext.getCmp('productTypeCB');
		this.targetClassCB = Ext.getCmp('targetClassCB');
		this.targetNameCB = Ext.getCmp('targetNameCB');
		this.startTimeDF = Ext.getCmp('startTimeDF');
		this.stopTimeDF = Ext.getCmp('stopTimeDF');

		this.servicesGrid = Ext.getCmp('servicesGrid');
		this.granulesGrid = Ext.getCmp('granulesGrid');

		this.rowsPerPageNf = Ext.getCmp('rowsPerPageNf');
		this.currentPageLb = Ext.getCmp('currentPageLb');
		this.totalPagesLb = Ext.getCmp('totalPagesLb');

		this.previousBtn = Ext.getCmp('previousPageBtn');
		this.nextBtn = Ext.getCmp('nextPageBtn');
		this.firstBtn = Ext.getCmp('firstPageBtn');
		this.lastBtn = Ext.getCmp('lastPageBtn');

		this.dataProdutTypeCB.getStore().removeAll();
		this.dataProdutTypeCB.getStore().add({'id': 'all', 'name': 'All data product types'});
		for (var productTypeId in this.metadata) {
			if (productTypeId in this.productTypeDict) {
				this.dataProdutTypeCB.getStore().add({'id': productTypeId, 'name': prettify(this.productTypeDict[productTypeId])});
			} else {
				console.log('Unknown data product type "' + productTypeId + '"');
			}
		}
		this.dataProdutTypeCB.select('all');

		this.targetClassCB.getStore().removeAll();
		this.targetClassCB.getStore().add({'id': 'all', 'name': 'All target names'});
		this.targetClassCB.select('all');
		this.targetClassCB.disable();

		this.targetNameCB.getStore().removeAll();
		this.targetNameCB.getStore().add({'id': 'all', 'name': 'All target classes'});
		this.targetNameCB.select('all');
		this.targetNameCB.disable();

		this.updateServices();
	},

	// *** form events ***

	onProductTypeCBChanged: function() {
		this.targetClassCB.getStore().removeAll();
		this.targetNameCB.getStore().removeAll();
		this.targetNameCB.disable();

		if (this.dataProdutTypeCB.value == 'all') {
			this.targetClassCB.disable();
		} else {
			var targetClasses = this.metadata[this.dataProdutTypeCB.value];

			if (Object.keys(targetClasses).length == 1) {
				this.targetClassCB.getStore().add({'id': Object.keys(targetClasses)[0], 'name': prettify(Object.keys(targetClasses)[0])});
				this.targetClassCB.disable();
				this.targetClassCB.select(this.targetClassCB.getStore().getAt(0)['internalId']);
			} else {
				this.targetClassCB.getStore().add({'id': 'all', 'name': allPrettify(this.productTypeDict[this.dataProdutTypeCB.value])});
				for (var targetClassId in targetClasses) {
					this.targetClassCB.getStore().add({'id': targetClassId, 'name': prettify(targetClassId)});
				}
				this.targetClassCB.select('all');
				this.targetClassCB.enable();
			}
		}
		this.targetNameCB.getStore().add({'id': 'all', 'name': 'All target names'});
		this.targetNameCB.select('all');
		this.updateServices();
	},

	onTargetClassCBChanged: function() {
		this.targetNameCB.getStore().removeAll();

		if (this.targetClassCB.value == 'all') {
			this.targetNameCB.getStore().add({'id': 'all', 'name': 'All target names'});
			this.targetNameCB.select('all');
			this.targetNameCB.disable();
		} else {
			var targetNames = this.metadata[this.dataProdutTypeCB.value][this.targetClassCB.value];

			if (Object.keys(targetNames).length == 1) {
				this.targetNameCB.getStore().add({'id': Object.keys(targetNames)[0], 'name': prettify(Object.keys(targetNames)[0])});
				this.targetNameCB.select(this.targetNameCB.getStore().getAt(0)['internalId']);
				this.targetNameCB.disable();
			} else {
				this.targetNameCB.getStore().add({'id': 'all', 'name': allPrettify(this.targetClassCB.value)});
				for (var targetNameId in targetNames) {
					this.targetNameCB.getStore().add({'id': targetNameId, 'name': prettify(targetNameId)});
				}
				this.targetNameCB.select('all');
				this.targetNameCB.enable();
			}
		}
		this.updateServices();
	},

	onTargetNameCBChanged: function() {
		this.updateServices();
	},

	onRowsPerPageChanged: function() {
		console.log("rows per page: " + this.rowsPerPageNf.value);
	},

	// *** Buttons events ***

	onFirstPageBtnClicked: function() {
		this.currentPageLb.setText('1');

		this.nextBtn.setDisabled(false);
		this.lastBtn.setDisabled(false);
		this.firstBtn.setDisabled(true);
		this.previousBtn.setDisabled(true);

		var selectedServiceURL = this.services[this.selectedServiceId]['accessurl'];
		var limit = this.rowsPerPageNf.value;
		var offset = '0';

		AmdaAction.epnTapGetGranules(this.selectedServiceId, selectedServiceURL, this.filter, this.select, limit, offset, this.fillGranules);
	},

	onPreviousPageBtnClicked: function() {
		var newPageNumber = Number(this.currentPageLb.text) - 1;
		this.currentPageLb.setText('' + newPageNumber);

		this.nextBtn.setDisabled(false);
		this.lastBtn.setDisabled(false);
		if (this.currentPageLb.text === '1') {
			this.previousBtn.setDisabled(true);
			this.firstBtn.setDisabled(true);
		}

		var selectedServiceURL = this.services[this.selectedServiceId]['accessurl'];
		var limit = this.rowsPerPageNf.value;
		var offset = '' + (newPageNumber-1) * Number(this.rowsPerPageNf.value);

		AmdaAction.epnTapGetGranules(this.selectedServiceId, selectedServiceURL, this.filter, this.select, limit, offset, this.fillGranules);
	},

	onNextPageBtnClicked: function() {
		var newPageNumber = Number(this.currentPageLb.text) + 1;
		this.currentPageLb.setText('' + newPageNumber);

		this.previousBtn.setDisabled(false);
		this.firstBtn.setDisabled(false);
		if (this.currentPageLb.text === this.totalPagesLb.text) {
			this.nextBtn.setDisabled(true);
			this.lastBtn.setDisabled(true);
		}

		var selectedServiceURL = this.services[this.selectedServiceId]['accessurl'];
		var limit = this.rowsPerPageNf.value;
		var offset = '' + (newPageNumber-1) * Number(this.rowsPerPageNf.value);

		AmdaAction.epnTapGetGranules(this.selectedServiceId, selectedServiceURL, this.filter, this.select, limit, offset, this.fillGranules);
	},

	onLastPageBtnClicked: function() {
		var newPageNumber = this.totalPagesLb.text;
		this.currentPageLb.setText('' + newPageNumber);

		this.previousBtn.setDisabled(false);
		this.firstBtn.setDisabled(false);
		this.nextBtn.setDisabled(true);
		this.lastBtn.setDisabled(true);

		var selectedServiceURL = this.services[this.selectedServiceId]['accessurl'];
		var limit = this.rowsPerPageNf.value;
		var offset = '' + (newPageNumber-1) * Number(this.rowsPerPageNf.value);

		AmdaAction.epnTapGetGranules(this.selectedServiceId, selectedServiceURL, this.filter, this.select, limit, offset, this.fillGranules);
	},

	// *** Grid click events ***

	onServiceSelected: function(selectedServiceId) {
		this.selectedServiceId = selectedServiceId;
		var selectedServiceURL = this.services[selectedServiceId]['accessurl'];

		this.select = Array();
		if (! selectedServiceId in this.services) {
			throw this.selectedServiceId + ' not found in the list of services.';
			return;
		}

		var columns = this.services[selectedServiceId]['columns'].split(',');
		for (var ic=0 ; ic<this.granulesGrid.columns.length ; ic++) {
			if (columns.indexOf(this.granulesGrid.columns[ic].dataIndex) != -1) {
				this.select.push(this.granulesGrid.columns[ic].dataIndex);
			}
		}
		this.filter = Array(
			this.dataProdutTypeCB.value !== 'all' ? this.dataProdutTypeCB.value : null, // product type
			this.targetNameCB.value !== 'all' ? this.targetNameCB.value : null, // target name
			Ext.getCmp('startTimeDF').getRawValue() !== '' ? Ext.getCmp('startTimeDF').getRawValue() : null, // start time
			Ext.getCmp('stopTimeDF').getRawValue() !== '' ? Ext.getCmp('stopTimeDF').getRawValue() : null // stop time
		);

		var limit = this.rowsPerPageNf.value;
		AmdaAction.epnTapGetNbRows(selectedServiceId, selectedServiceURL, this.filter, this.updateNbRows);
		AmdaAction.epnTapGetGranules(selectedServiceId, selectedServiceURL, this.filter, this.select, limit, 0, this.fillGranules);
	},

	onGranuleSelected: function() {
		// console.log('selected granule: ' + granule.targetName);
	},

	// *** Other functions ***

	updateNbRows: function(nb_results) {
		/* /!\ Can not get `this`. */
		var totalPages = '' + Math.ceil(Number(nb_results) / Ext.getCmp('rowsPerPageNf').value);

		Ext.getCmp('currentPageLb').setText('1');
		Ext.getCmp('totalPagesLb').setText(totalPages);
		Ext.getCmp('previousPageBtn').setDisabled(true);
		Ext.getCmp('firstPageBtn').setDisabled(true);
		if (totalPages === '1') {
			Ext.getCmp('nextPageBtn').setDisabled(true);
			Ext.getCmp('lastPageBtn').setDisabled(true);
		} else {
			Ext.getCmp('nextPageBtn').setDisabled(false);
			Ext.getCmp('lastPageBtn').setDisabled(false);
		}
	},

	fillGranules: function(granules) {
		/* /!\ Can not get `this`. */

		if (granules == null) {
			console.log("There is no granules to add.");
		} else {
			try {
				// console.log('Added granules:', granules);
				Ext.getCmp('granulesGrid').getStore().removeAll();
				Ext.getCmp('granulesGrid').getStore().add(granules);
			} catch( e ) {
				console.log('Can not add granules: ' + e);
			}
		}
	},

	updateServices: function() {
		this.servicesGrid.getStore().removeAll();
		this.granulesGrid.getStore().removeAll();

		var service = null;
		var timeMinArr = null;
		var timeMaxArr = null;
		var timeMin = null;
		var timeMax = null;

		var filterDict = new Array();
		if(this.dataProdutTypeCB.value === 'all') {
			for (var dpt in this.metadata) {
				for (var tc in this.metadata[dpt]) {
					for (tn in this.metadata[dpt][tc]) {
						for (serv in this.metadata[dpt][tc][tn]) {
							service = this.metadata[dpt][tc][tn][serv];
							timeMinArr = service[1].split('/');
							filterDict[serv] = service[0] + (serv in filterDict ? filterDict[serv] : 0);
							if (isLatest(service[1], timeMin)) {
								timeMin = service[1];
							}
							if (isLatest(service[2], timeMax)) {
								timeMax = service[2];
							}
						}
					}
				}
			}
		} else if (this.targetClassCB.value === 'all') {
			for (var tc in this.metadata[this.dataProdutTypeCB.value]) {
				for (tn in this.metadata[this.dataProdutTypeCB.value][tc]) {
					for (serv in this.metadata[this.dataProdutTypeCB.value][tc][tn]) {
						service = this.metadata[this.dataProdutTypeCB.value][tc][tn][serv];
						filterDict[serv] = service[0] + (serv in filterDict ? filterDict[serv] : 0);
						if (isLatest(service[1], timeMin)) {
							timeMin = service[1];
						}
						if (isLatest(service[2], timeMax)) {
							timeMax = service[2];
						}
					}
				}
			}
		} else if (this.targetNameCB.value === 'all') {
			for (tn in this.metadata[this.dataProdutTypeCB.value][this.targetClassCB.value]) {
				for (serv in this.metadata[this.dataProdutTypeCB.value][this.targetClassCB.value][tn]) {
					service = this.metadata[this.dataProdutTypeCB.value][this.targetClassCB.value][tn][serv];
					filterDict[serv] = service[0] + (serv in filterDict ? filterDict[serv] : 0);
					if (isLatest(service[1], timeMin)) {
						timeMin = service[1];
					}
					if (isLatest(service[2], timeMax)) {
						timeMax = service[2];
					}
				}
			}
		} else {
			for (serv in this.metadata[this.dataProdutTypeCB.value][this.targetClassCB.value][this.targetNameCB.value]) {
				service = this.metadata[this.dataProdutTypeCB.value][this.targetClassCB.value][this.targetNameCB.value][serv];
				filterDict[serv] = service[0] + (serv in filterDict ? filterDict[serv] : 0);
				if (isLatest(service[1], timeMin)) {
					timeMin = service[1];
				}
				if (isLatest(service[2], timeMax)) {
					timeMax = service[2];
				}
			}
		}

		console.log('times min/max: [' + timeMin + ' ; ' + timeMax + ']');
		// TODO: charger times min/max dans formulaire
		// TODO: dans formulaire, mettre à jour duration avec times min/max

		var filter = Object.keys(filterDict).map(function(key) {
			return [key, filterDict[key]];
		});
		filter.sort(function(first, second) {
			return second[1] - first[1];
		});
		for (var s = 0; s < filter.length; s++) {
			var service = this.services[filter[s][0]];
			this.servicesGrid.getStore().add({'id': filter[s][0], 'nbResults': filter[s][1], 'shortName': service['shortname'], 'title': service['title'], 'accessURL': service['accessurl']});
		}
	}

});