/**
 * Main Profile class
 * Every profile information extends this class
 * Handles editing, viewing, and validating a profile as well as common helper functions
 * This constructor is never called. The only thing we're extending are the functions
 * @class Profile
 * @requires JQuery
 * @param {String} id: 'new' or integeger
 * @param {String} name: 'Brokerage', 'Institution', 'Investment', 'Investor', 'Plant', 'Series', 'Representative', 'Task', 'User'
 * @param {boolean} edit
 */
function Profile(id, name, edit){
	this.id = id;
	this.name = name;
	this.edit = edit;
}
Profile.prototype = {
	id:null,
	auditId: null,
	name: null,
	edit: null,

	/**
	 * returns an element with this specific id: #ProfileName[id][elementName]
	 * ex. Brokerage[10][company_name]
	 * @param {String} name
	 * @return {JQuery} DOM element
	 */
	getElt: function(name) {
		return $('#' + this.name + '\\[' + this.id + '\\]\\[' + name + '\\]');
	},
	
	/**
	 * helper function to get the ID
	 * @return {String} name + id
	 */
	getId: function() {
		return this.name + this.id;
	},
	
	/**
	 * sets the audit id
	 * @return instance of self
	 */
	setAuditId: function(id) {
		this.auditId = id;
		return this;
	},
	
	/**
	 * ajax call to listByAction in Ecm_Controller_Action
	 * gets a specific list based on this profile id
	 * ex. if an investor profile wants to list all its investments
	 * @param {String} profile
	 */
	getList: function(profile){
		var self = this;
		ajax(HTMLPATH + '/' + profile + '/listBy/ajax/true/profile/' + this.name + 'Id/id/' + this.id, null, function(response) {
			self.listDisplay(response.html);
		});
	},
	
	/**
	 * getList callback
	 * displays the list
	 * @param {String} html
	 */
	listDisplay: function(html){
		$('#' + this.getId() + ' div.stats').empty();
		$('#' + this.getId() + ' div.stats').html(html);
		$('#' + this.getId() + ' div.stats').show('normal');
	},
	
	/**
	 * changes profile title
	 */
	changeTitle: function() {
		var titleElt = $('#' + this.getId() + '.profile span.' + this.getId() + 'title');
		var title = '';
		$('#' + this.getId() + '.profile div.section.name :input').each(function() {
			title += jQuery.trim(this.value) + ' ';
		});
		titleElt.html(title);
	},
	
	/**
	 * ajax call to readonly view
	 * @param {Boolean} cancel
	 */
	view: function(cancel) {
		var self = this;
		
		if (this.auditId) {
			var idName = 'auditId';
			var id = this.auditId;
		}
		else {
			var idName = 'id';
			var id = this.id;
		}

		if (!cancel)
			url = '/' + this.name + '/profile/ajax/true/' + idName + '/' + id;
		// if cancel is passed clear errors
		else url = '/' + this.name + '/profile/ajax/true/' + idName + '/' + id + '/status/reset/';
		
		$('#' + this.getId()).html('<div class="loading">Loading...</div>');
		ajax(url, null, function(obj) {
			self.display(obj.html);
		});
	},
	
	/**
	 * cancel edit view
	 */
	cancel: function() {
		this.view(true);
	},
	
	/** 
	 * ajax call to edit view
	 */
	editView: function() {
		var self = this;
		$('#' + this.getId()).html('<div class="loading">Loading...</div>');
		
		if (this.auditId) {
			var idName = 'auditId';
			var id = this.auditId;
		}
		else {
			var idName = 'id';
			var id = this.id;
		}
			
		ajax('/' + this.name + '/profile/ajax/true/edit/true/' + idName + '/' + id, null, function(obj) {
			self.display(obj.html);
		});
	},

	/**
	 * view or editView callback
	 * displays views (edit/readonly)
	 * @param {String} html
	 */
	display: function(html) {
		try {
			var container = $('#' + this.getId()).parent();
			container.html(html);
			container.show('normal');
		}
		catch (e) {
			alert('Profile.view error: ' + e.message)
		}
	},

	/**
	 * serializes all input elements in the profile div (DOESN'T REQUIRE FORMS)
	 * ajax call to validateAction in Ecm_Controller_Action
	 */
	validate: function() {
		var self = this;
		var form = $('#' + this.getId() + ' :input').serialize();

		$('#' + this.getId() + ' div#' + this.getId() + 'report').addClass('report');
		$('#' + this.getId() + ' div#' + this.getId() + 'report').removeClass('reportError');
		$('#' + this.getId() + ' div#' + this.getId() + 'report').html('validating...');
		$('#' + this.getId() + ' div#' + this.getId() + 'report').show();

		ajax('/' + self.name + '/validate/ajax/true/id/' + self.id, form, function(obj) {
			self.validation(obj);
		});
	},
	
	/**
	 * validate callback
	 * dipslays profile if errors or calls 'update' function
	 * @param {JSON} obj
	 */
	validation: function(obj){
		try {
			if (obj.errors)
				this.display(obj.html);
			else {
				this.update(obj.json);
			}
		}
		catch (e) {
			alert('Profile.validation error: ' + e.message);
		}
	},
	
	/**
	 * reloads page after a new profile
	 * updates any element with corresponding form element name in the form of #ProfileName[id][elementName] (ex. Brokerage[10][company_name])
	 * this keeps information consistent without reloading the page
	 * @param {Object} data
	 */
	update: function(data){
		var self = this;
		try {
			if (this.updateFunction)
				this.updateFunction(data);
			else if (this.id == 'new') {
				window.location.reload();
			}
			else {
				this.view();
				jQuery.each(data, function(name, value){
					$('.' + self.name + '\\[' + self.id + '\\]\\[' + name + '\\]:not(:input)').html(value);
				});
			}
		}
		catch (e) {
			alert('Profile.update error: ' + e.message);
		}
	},

	/**
	 * sets the updateFunction for NEW profiles
	 * in certain cases we don't want to reload the page (ex. adding a new plant while creating a new series)
	 * this will override the 'update' function after a new profile is created
	 * @param {Function} name
	 */
	setUpdate: function(name){
		if (typeof(name) == 'function')
			this.updateFunction = name;
	},
	
	/**
	 * confirms delete if yes:
	 * ajax call to deleteAction in Ecm_Controller_Action
	 * @param {String} name: the name associated to the profile
	 */
	deleteCheck: function(name){
		var deleteCheck = confirm(name + ': ' + this.name + '\nAre you sure you want to delete this profile?');
		var self = this;
		if (deleteCheck) {
			ajax(HTMLPATH + '/' + this.name + '/delete/ajax/true/id/' + this.id, null, function(response){
				self.deleteResponse(response);
			});
		}
	},
	
	/**
	 * displays error message a link to the conflict if any otherwise reloads the page only if
	 * the profile was created from an ajax call (Profiles.list[this.getId()] exists)
	 * @param {JSON} obj
	 */
	deleteResponse: function(obj){
		if (obj.html == 'DELETED') {
			if (Profiles.list[this.getId()]) {
			window.location.reload();
			}
			else alert('This profile has been deleted');
		}
		else {
			$('#deleteMessage').html(obj.html);
			$('#deleteError').show('normal');
		}
	},
	
	/**
	 * finds and selects the open tab with name + id as data
	 * @return {Boolean}: true if sound, false if not
	 */
	selectTab: function(){
		var tabs = TABS.getTabs();
		for (var i = 0; i < tabs.length; i++) {
			if (tabs[i].getData() == this.getId()) {
				tabs[i].select();
				return true;
			}
		}
		return false;
	}
};

/**
 * creates a profile of type 'name' and maintains a list of profiles in Profiles.list.['ProfileName' + 'ProfileId']
 * If a profile exists the user will be alerted. The only exception is when a profile exists but its container is no longer linked to the document.
 * @class Profiles
 * @requires JQuery
 * @param {Interger|new} id: use 'new' for a new object otherwise the id of the element
 * @param {String} name: 'Brokerage', 'Institution', 'Investment', 'Investor', 'Plant', 'Series', 'Representative', 'Task', 'User'
 */
Profiles = function(id, name) {
	this.id = id;
	this.name = name;
	
	// if profile is already open, search for it in tabs and select it
	if (Profiles.list[name + id]) {
		var tabs = TABS.getTabs();
		for (var i = 0; i < tabs.length; i++) {
			if (tabs[i].getData() == this.name + this.id) {
				tabs[i].select();
				this.profileOpen = true;
				return this;
			}
		}
	}
	else {
		this.profileOpen = false;
		Profiles.list[name + id] = this;
		this._onComplete = null;
	}
}
Profiles.prototype = {
	id: null,
	auditId: null,
	name:null,
	open:null,
	
	_onComplete:null,
	
	/**
	 * sets the audit id
	 * @return instance of self
	 */
	setAuditId: function(id) {
		this.auditId = id;
		return this;
	},
	
	/**
	 * ajax call to profile action in the controller defined by this.name
	 * sets parameters edit to true when id = 'new'
	 * sets parameters name to 'name' if argument exists
	 * otherwise displays the readonly version of the profile
	 * @param {String} name: name for creation of new profile
	 * @param {Function} onComplete: function executed at the end of the callback function (getResponse function)
	 * @param {String} additionalParams: a key-value pair string for additional url paramaters
	 * @return {Profiles}: returns instance of this
	 */
	get: function(name, onComplete, additionalParams){
		if (INTRIGO.isFunction(onComplete)) {
			this._onComplete = onComplete;
		}
		
		if (!additionalParams)
			additionalParams = '';
		
		//if profile is already open do nothing
		if (this.profileOpen == true) {
			this.profileOpen = false;
			return this;
		}
		var self = this;
		
		if (this.id == 'new') {
			if (name)
				var url = '/profile/ajax/true/edit/true/name/' + name;
			else var url = '/profile/ajax/true/edit/true';
			ajax('/' + this.name + url + additionalParams, null, function(obj){
				self.getResponse(obj);
			});
		}
		else {
			if (this.auditId) {
			var idName = 'edit/true/auditId';
				var id = this.auditId;
			}
			else {
				var idName = 'id';
				var id = this.id;
			}
			ajax('/' + this.name + '/profile/' + idName + '/' + id + '/ajax/true' + additionalParams, null, function(obj){
				self.getResponse(obj);
			});
		}
		return this;
	},
	
	/**
	 * get callback
	 * adds a tab to TABS object with the profile info as the content
	 * @param {JSON} obj
	 */
	getResponse: function(obj){
        var self = this;
		try {
			var tmpDiv = document.createElement('div');
			tmpDiv.innerHTML = obj.html;
			$('#body').append(tmpDiv);
			var tab = TABS.addTab(obj.label, tmpDiv, this.name + this.id).setRemoveFunc(function() {
				self.close();
			}).select();
			
			if (this._onComplete)
				this._onComplete(this.id, this.name, tab);
        }
        catch (e) {
            alert('Profiles.getResponse error: ' + e);
        }
	},
	
	/**
	 * this closes and destroys any information associated with this profile
	 * @param {Function} onComplete: called when the slider animation is complete
	 */
	close: function(onComplete) {
		var self = this;
		Profiles.list[self.name + self.id] = null;
		Profiles[self.name + self.id] = null;
		if (typeof(onComplete) == 'function')
			onComplete();
	}
};
Profiles.list = {};
Profiles.filter = {};
