/*
,,
`""*3b..											Saeven|CRM :: http://crm.saeven.net
     ""*3o.					  						saeven@saeven.net
         "33o.			                  			S. Alexandre M. Lemaire
           "*33o.                                 	(c) saeven.net consulting inc
              "333o.								Redistribution, re-engineering or copying of this content in part or in whole is illegal.
                "3333bo...       ..o:               This copyright notice may not be removed.
                  "33333333booocS333    ..    ,.	Violators will be prosecuted to the fullest extent of the law.
               ".    "*3333SP     V3o..o33. .333b
                "33o. .33333o. ...A33333333333333b
          ""bo.   "*33333333333333333333P*33333333:
             "33.    V333333333P"**""*"'   VP  * "l
               "333o.433333333X
                "*3333333333333AoA3o..oooooo..           .b
                       .X33333333333P""     ""*oo,,     ,3P
                      33P""V3333333:    .        ""*****"
                    .*"    A33333333o.4;      .
                         .oP""   "333333b.  .3;
                                  A3333333333P
                                  "  "33333P"
                                      33P*"
		                              .3"
                                     "
                                     "
*/

var proxyURL			= new String( "themeproxy.php" )
var xmlrpcURL			= new String( "xmlrpcproxy.php" );
var waitImage			= new String(  "<img src='templates/" + theme + "/visual/images/wait.gif'>" );

var rememberCheckbox	= null;
var lastScreenAction	= null;
var mainToolbar			= null;
var openTickets 		= new Object();
var ticketContainers	= new Object();



function processScreenCallback(){
	if( !lastScreenAction )
		return;	
	
	switch( lastScreenAction.t ){
		case 'ticket':
			submitTicket( lastScreenAction.c );		
		break;		
		
		case 'kb':
			viewKnowledgebase( lastScreenAction.c, lastScreenAction.i );
		break;
		
		case 'tr':
			viewTroubleshooter( lastScreenAction.c, lastScreenAction.i );
		break;
		
		default: 
			alert( "no idea what :" + lastScreenAction.t );
		break;
	}	
	
	lastScreenAction = null;
}

/**
 * Fetch a form radio select value
 */
function getRadioValue( controlName, formObj ){	

	if( formObj )		
		for( var i = 0 ; i < formObj[controlName].length ; i++ )
			if( formObj[controlName][i].checked )
				return formObj[controlName][i].value;
		
	return null;
}


/**
 * Fetch a form select value
 */
function getSelectValue( selectObj ){
	for( var i = 0 ; i < selectObj.options.length ; i++ )
		if( selectObj.options[i].selected )
			return selectObj.options[i].value;
			
	return null;
}
	

function moveCursor( obj, pos ){
	if( obj.createTextRange ){ 
        var range = obj.createTextRange(); 
        range.move("character", pos); 
        range.select(); 
    } else if( obj.selectionStart ){ 
        obj.focus(); 
        obj.setSelectionRange(pos, pos); 
    } 
}


function insertcode( id, tag ){
	var textarea = Ext.get( "topic_" + id + "_message" ).dom;
	var open_tag = "[" + tag + "]";
	var close_tag = "[/" + tag + "]";

	if( textarea.setSelectionRange ){
		var pretext = textarea.value.substring( 0, textarea.selectionStart );
		var codetext = open_tag + textarea.value.substring( textarea.selectionStart, textarea.selectionEnd ) + close_tag;
		var posttext = textarea.value.substring(textarea.selectionEnd, textarea.value.length);
		textarea.value = pretext + codetext + posttext;
	}
	
	// set the focus on the text field
	textarea.focus();
}
	
/**
 * Insert a string myValue into myField
 */
function insertString( extField, myValue ){
	
	var myField = extField.dom;
	
	if( document.selection ){
		extField.focus();
		var sel 	= document.selection.createRange();
		sel.text 	= myValue;
		extField.focus();
	}
	else if ( myField.selectionStart || myField.selectionStart == '0' ){
		var startPos 	= myField.selectionStart;
		var endPos 		= myField.selectionEnd;
		myField.value 	= myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length);
		extField.focus();
		myField.selectionStart = startPos + myValue.length;
		myField.selectionEnd = startPos + myValue.length;
	} else {
		myField.value += myValue;
		extField.focus();
	}
}

function showValidated(){
	Ext.MessageBox.alert( jsl.validation_confirmed, jsl.validation_thanks );
}


// update the navigation table, perhaps after login
function updateNavTable(){
	var c = new Ext.data.Connection();
	c.request({
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'navarea' },
		callback: function( options, success, transport ){
			if( success ){
				Ext.get( 'nav_area' ).update( transport.responseText );	
			}
			else{
				updateNavTable();
			}
		}				  
	});
}

function getLanguageSelect(){	
	var lStore = new Ext.data.JsonStore({
			url: proxyURL,
			root: 'languages',
			fields: [ 'name', 'id' ],
			baseParams: { action: 'language_list' }
	});

	var s = new Ext.form.ComboBox({
		typeAhead: false,
		width:135,
		readOnly: true,
		editable: false,
		triggerAction:'all',
		displayField: 'name',
		valueField: 'id',
		store: lStore,
		value: selected_language_id
	});
	
	s.on( 'select', function( combo, record, index ){ 
		window.location.href="index.php?language=" + record.data.id;
	});
	return s;
}



/**
 *
 *
 * AUTHENTICATION BLOCK
 *
 *
 */ 
var usernameField;
var passwordField;


function login(){
	Ext.MessageBox.getDialog().on( 'show', executeLoginRequest );
	Ext.MessageBox.show({
	   title: jsl.authenticating,
	   msg: jsl.wait_authenticating,
	   progress: false,
	   closable: false,
	   animEl: 'root-menu'
	});			
}


function executeLoginRequest(){
	var c = new Ext.data.Connection();
	c.timeout = 8000;
	c.request({
		url: xmlrpcURL,
		method: 'post',
		params: { action: 'login', username: usernameField.getValue(), password: passwordField.getValue(), json: 1 },
		callback: function( options, success, transport ){
			Ext.MessageBox.getDialog().un( 'show', executeLoginRequest );
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
				
				// if login was not successful
				if( !json.success ){
					Ext.MessageBox.alert( jsl.login_failed, jsl.login_failed_verbose );		
				}
				// login was successful
				else{
					// remember login?
					if( rememberCheckbox.getValue() ){
						var cp = new Ext.ux.CleanCookieProvider({
						   expires: new Date(new Date().getTime()+(1000*60*60*24*30)), //30 days
						   domain: cookieDomain
						});
						
						cp.set( 'auracleuser', json.cookie );
					}
									
					firstName	= json.first_name;
					admin		= json.admin;
					while( mainToolbar.items.getCount() > 0 ){
						var i = mainToolbar.items.itemAt(0);
						mainToolbar.items.removeAt(0);
						i.destroy();
					}						
					
					addLogoutButton();
					updateNavTable();
					processScreenCallback();
					Ext.MessageBox.hide();
					
				}
			}
			else{
				executeLoginRequest();				
			}
		}				  
	});		
	
}

var passwordPending;
function sendPassword( button, text ){
	if( button == 'cancel' )
		return;
	
	if( !passwordPending ){
		passwordPending = true;
		Ext.MessageBox.show({
		   title: jsl.wait,
		   msg: jsl.wait_server,
		   width:240,
		   progress:false,
		   closable:false
		});		
	}
	
	
	var c = new Ext.data.Connection();
	c.request({
		url: xmlrpcURL,
		method: 'post',
		params: { action: 'passwordRequest', email: text, json: 1 },
		callback: function( options, success, transport ){
			if( success ){
				var json 		= Ext.util.JSON.decode( transport.responseText );
				passwordPending = false;
				// if login was not successful
				if( !json.success ){
					Ext.MessageBox.alert( jsl.password_fetch_failed, json.message );		
				}
				// login was successful
				else{
					Ext.MessageBox.alert( jsl.success, json.message );					
				}
			}
		}				  
	});	
}

var validationPending;
function sendValidation( button, text ){
	if( button == 'cancel' )
		return;
	
	if( !validationPending ){
		validationPending = true;
		Ext.MessageBox.show({
		   title: jsl.wait,
		   msg: jsl.wait_server,
		   width:240,
		   progress:false,
		   closable:false
		});	
	}
	
	var c = new Ext.data.Connection();
	c.request({
		url: xmlrpcURL,
		method: 'post',
		params: { action: 'validationRequest', email: text, json: 1 },
		callback: function( options, success, transport ){
			if( success ){
				validationPending = false;
				var json = Ext.util.JSON.decode( transport.responseText );			
				Ext.MessageBox.alert( json.validation_request, json.message );
			}
		}				  
	});	
}

function addLogoutButton(){
	var langSelect = getLanguageSelect();
	mainToolbar.add( "language ", langSelect, "->" );
	mainToolbar.add( jsl.welcome_back + " " + firstName + "!" );
	mainToolbar.addSeparator();
	var logoutButton = new Ext.Toolbar.Button({
		text: jsl.logout,
		handler: function( btn, e ){
			window.location.href="?logout=1";									
		}
	});								
	mainToolbar.add( logoutButton );
}


/**
 *
 *
 * REGISTRATION BLOCK
 *
 *
 */
var tab_registration;
function showRegistrationForm(){
	
	if( tab_registration == null ){
		var simple = new Ext.FormPanel({
			labelWidth: 75, // label settings here cascade unless overridden
			url: proxyURL,
			frame: true,
			height: menuHeight,
			title: 'Registration Form',
			bodyStyle: 'padding:10px;',
			method: 'post',
			buttonAlign: 'center',
			closable: true,
			baseParams: {
				action: 'register'
			},
			errorReader: new Ext.data.JsonReader({
				successProperty: 'success',
				root: 'errors'
			}, [ 'id', 'msg'] )
		});
		
		// REGISTRATION FORM FIELDS
		simple.add(
			new Ext.form.TextField({
				fieldLabel: jsl.first_name,
				name: 'first',
				width: 300,
				allowBlank:false
			}),
	
			new Ext.form.TextField({
				fieldLabel: jsl.last_name,
				name: 'last',
				width: 300,
				allowBlank:false
			}),
	
			new Ext.form.TextField({
				fieldLabel: jsl.company,
				name: 'company',
				width: 300
			}),
	
			new Ext.form.TextField({
				fieldLabel: jsl.email,
				name: 'email',
				vtype:'email',
				width: 300,
				allowBlank:false
			})
		);
	
		simple.addButton( jsl.register, 
			function(){ 
				simple.form.submit({
					waitMsg: jsl.one_moment, 
					reset: false 
				});	
			}
		);
		
		simple.on({ 
			actioncomplete: function( form, action ) { 
				// show the navtable if no validation is required, show the validation confirmation otherwise
				var json = Ext.util.JSON.decode( action.response.responseText );		
							
				if( json.validate ){
					Ext.MessageBox.alert( jsl.validation_required, json.validate_msg, Ext.get( 'nav_area' ) );				
				}
				else{
					updateNavTable();	
				}		
			}
		});	
		
		tab_registration = tabs.add( simple );
		tab_registration.on( 'destroy', function(){ 
			tab_registration = null;											 
		});
	}
	tab_registration.show();
}

/**
 *
 * TICKET SUBMITTAL BLOCK
 *
 *
 */
var tab_ts;
var ticketPanel;
var suggestionTimer;
var suggestionCache;
var suggestionsShown	= 0;
var	suggestionsClicked	= 0;
var ticket_category		= 'C0';
function submitTicket( chosenCategory ){
	
	if( tab_ts == null ){		
				
		ticketPanel = new Ext.Panel({
			title: 'Submit a Ticket',
			closable: true,
			collapsible: false,
			defaults: { autoHeight: true },			
			autoWidth:true
		});
		
		tab_ts = tabs.add( ticketPanel );
		
		tab_ts.on( 'destroy', function(){ 
			tab_ts 				= null; 
			ticketPanel			= null;
					
			if( suggestionTimer ){
				clearTimeout( suggestionTimer );			
				suggestionTimer		= null;
			}
		});	
	}
	
	tab_ts.show();
	loadTicketPanel( chosenCategory );
} 

function loadTicketPanel( category ){
	if( !category )
		category = 'C0';
	
	ticket_category = category;	
	
	if( ticket_category == 'C0' && suggestionTimer ){
		clearTimeout( suggestionTimer );			
		suggestionTimer		= null;	
	}
		
	
	ticketPanel.body.load({
		timeout: 5000,
		url: 'index.php',
		method: 'post',
		scripts: true,
		params: { tsrc: 'ticket_send', 'category': category },
		callback: function( oElement, bSuccess ){
			if( bSuccess ){
				if( ticket_category != 'C0' ){
					suggestionTimer = setTimeout( ticketSuggestionEngine, 3000 );	
				}
			}		
			else{
				loadTicketPanel( category );	
			}
		}
	});
}

function ticketSuggestionEngine(){
	var mField		= Ext.get( 'message' );
	
	if( !mField ){
		suggestionTimer = setTimeout( ticketSuggestionEngine, 3000 );
		return;		
	}
		
	var mText 	= mField.getValue();
	
	if( mText && mText != suggestionCache ){
		suggestionCache = mText;
		ticketSuggestionRequest( suggestionCache );	
	}
	else{
		suggestionTimer = setTimeout( ticketSuggestionEngine, 3000 );
	}
}


function ticketSuggestionRequest( text ){
	var c = new Ext.data.Connection();
	c.timeout = 8000;
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'ticket_suggestion_list', "text": text },
		headers: { 'Accept' : 'application/json' },
		callback: function( options, success, transport ){
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
				if( json.result ){					
					if( json.result == 'noresult' ){
						Ext.get( 'suggestion_area' ).update( "" );
					}
					else if( json.result != "nochange" ){		
						suggestionsShown = json.total;
						Ext.get( 'suggestion_area' ).update( json.text );											
					}
				}
				suggestionTimer = setTimeout( ticketSuggestionEngine, 3000 );
			}
			else{
				ticketSuggestionRequest( text )	
			}
		}				  
	});	
}


/**
 * The user has clicked on the 'submit' button
 */
var interceptWindow;
function fireTicketFormSubmittal(){
	if( suggestionTimer ){
		clearTimeout( suggestionTimer );			
		suggestionTimer = null;
	}
			
	if( suggestionsShown && !suggestionsClicked ){
		interceptWindow = new Ext.Window({
			title: jsl.suggestions_ignore,
			html: "<div style='padding:5px'>" + jsl.suggestions_ignore_body + "</div>",
			buttons: [{ 
				text: "Submit anyway", 
				handler: function(){ 
					interceptWindow.close(); 
					submitTicketForm();
				}					
			},{
				text: "Review suggested articles!",
				handler: function(){
					interceptWindow.close();
				}
			}],
			buttonAlign: 'center',
			modal: true,
			width: 450,
			height: 150
		});		
		interceptWindow.show();
	}
	else{
		submitTicketForm();	
	}
}

var ticketPending = false;
function submitTicketForm(){
	suggestionsClicked = 1;
	var errors = "";
	for( value in required ){
		if( !Ext.get( value ) )
			continue;
			
		var type  = required[value];			
		var regex = /^e_(\d*?)_(.*?)$/i
		var	list  = regex.exec( value );
		var name  = list[2];
		
		switch( type ){			
			case 'radio':
				if( !getRadioValue( value, Ext.get( 'ticket_form' ).dom ) )
					errors += '\n- ' + jsl.validate_select + ' \'' + name + '\'.';					
			break;
			
			case 'checkbox':
				if( !Ext.get( value ).dom.checked )
					errors += '\n- ' + jsl.validate_check + ' \'' + name + '\' checkbox.';			
			break;
			
			case 'select':
				if( !getSelectValue( Ext.get( value ).dom ) )
					errors += '\n- ' + jsl.validate_select + ' \'' + name + '\'.';			
			break;
			
			default:
				if( Ext.get( value ).dom.value.length == 0 )
					errors += '\n- ' + jsl.validate_field_1 + ' \'' + name + '\' ' + jsl.validate_field_2;
			break;
		}
	}
	
	if( Ext.get('subject').getValue().length == 0 || Ext.get('message').getValue().length == 0 )
		errors += '\n- ' + jsl.validate_subject_message;

	if( errors.length > 0 ){
		alert( jsl.validate_errors + "\n\n" + errors );
		return false;
	}
	
	
	if( !ticketPending ){
		ticketPending = true;
		Ext.MessageBox.getDialog().on( 'show', submitTicketExecute );
		Ext.MessageBox.show({
		   title: jsl.wait,
		   msg: jsl.wait_submit,
		   width:240,
		   progress:false,
		   closable:false,
		   animEl: Ext.get( 'ticket_submit' )
		});		
	}
}


function submitTicketExecute(){
	var c = new Ext.data.Connection();
	c.timeout = 60000;
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'ticket_submit', category : ticket_category },
		form: 'ticket_form',
		headers: { 'Accept' : 'application/json' },
		callback: function( options, success, transport ){
			if( success ){
				ticketPending = false;
				Ext.MessageBox.getDialog().un( 'show', submitTicketExecute );
				Ext.MessageBox.hide();
				var json = Ext.util.JSON.decode( transport.responseText );				
				
				if( json.ticketID ){
					// if the address is not validated, and validation is required
					if( json.validate ){
						showValidationWarning( json.ticketID );
					}
					// if the user submitted for a valid profile
					else {
						showTicketConfirmation( json.ticketID, json.temporary ? json.authkey : '' );
					}									
				}
				else{
					Ext.MessageBox.alert( jsl.ticket_submit_failed, json.error );	
				}				
			}
			else{
				submitTicketExecute();
			}
		}				  
	});		
}


/**
 *
 *
 * TICKET LIST BLOCK
 *
 *
 */ 
var tab_ticket_list;
var ticket_tab_panel;
var ticket_list_grid;
var Ticket = Ext.data.Record.create([
	{name: 'id' },
	{name: 'category_name' },
	{name: 'excerpt' },
	{name: 'status_verbose' },
	{name: 'date' },
	{name: 'mdate' },
	{name: 'subject' },
	{name: 'priority' }
]);

function renderTopic( value, p, record){
	return String.format( '<span class="topic_header"><b>{0}</b><br>{1}</span><br><br><p>{2}</p>', value, record.data.category_name, record.data.excerpt );
}

function showTicketList(){	

	if( tab_ticket_list == null ){
		var page_size = 25;
		
		var ticket_store = new Ext.data.GroupingStore({
			sortInfo: { field: 'mdate', direction: "DESC"},
			groupField:'status_verbose',
			proxy: new Ext.data.HttpProxy({ url: proxyURL }),
			baseParams: { action: 'ticket_list' },
			reader: new Ext.data.JsonReader({
				totalProperty: "count",    
				root: "rows",
				id: "id"
			}, Ticket )
		});	
		
		ticket_list_grid = new Ext.grid.GridPanel({
			store: ticket_store,
			columns: [
				{header: "", dataIndex: "status_verbose", hidden: true },
				{header: "ID", dataIndex: "id" },
				{header: "Subject", sortable: true, dataIndex: 'subject', renderer: renderTopic },
				{header: "Priority", dataIndex: 'priority' },
				{header: "Last Update", sortable: true, dataIndex: 'mdate', formatter: Ext.util.Format.date }
			],	
			view: new Ext.grid.GroupingView({
				forceFit:true,
				groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Tickets" : "Ticket"]})'
			}),	
			frame:true,
			autoWidth: true,
			height: menuHeight,
			collapsible: false,
			loadMask: true,
			title: "List of currently active tickets",
			bbar: new Ext.PagingToolbar({
				pageSize: page_size,
				store: ticket_store,
				displayInfo: true,
				displayMsg: 'Displaying topics {0} - {1} of {2}',
				emptyMsg: "No tickets to display"				
			})
		});		
		
		ticket_list_grid.on( 'rowclick', function( grid, index, e ){			
			var record = ticket_list_grid.getStore().getAt( index );			
			openTicket( record.id );			
		});
		
				
		// add the panel to the main tab set (where the announcements are printed)
		ticket_tab_panel = new Ext.Panel({
			title: 'Ticket List',
			layout: 'table',
			layoutConfig:{
				columns: 1
			},
			constrainHeader: true,
			closable: true,
			autoScroll:false,
			autoWidth: true,			
			items: [ ticket_list_grid ]	
		});
		
		tab_ticket_list = tabs.add( ticket_tab_panel );
		tab_ticket_list.show();
		tabs.doLayout();
		
		tab_ticket_list.on( 'destroy', function(){ 
			tab_ticket_list 	= null;
			ticket_tab_panel	= null;
			ticket_list_grid	= null;
		});
		
		
		ticket_store.load({
			params: { start: 0, limit: page_size },
			callback: function( oElement, bSuccess, oResponse ){
				if( bSuccess ){					
				}
				else{
				}
			}					  
		});
	}		
}

function openTicket( tid, authkey ){
	
	if( !openTickets[tid] ){	
		var ticket_view_panel = new Ext.Panel({
			title: 'Ticket: ' + tid,
			closable: true,
			collapsible: false,
			defaults: { autoHeight: true },
			html: '<div class="smalltext" style="padding:5px;" align="center">Please select a ticket from the list above</div>',
			autoWidth:true
		});
		
		var tab 				= tabs.add( ticket_view_panel );
		tab.ticketID			= tid;
		tab.authkey				= authkey;
		openTickets[tid] 		= tab;
		ticketContainers[tid]	= ticket_view_panel;
		
		//removemelater
		tab.show();
		
		
		tab.on( 'destroy', function(){
			openTickets[this.ticketID]		= null;
			ticketContainers[this.ticketID]	= null;
		});
		loadTicketData( tid, authkey );
	}
	else{
		openTickets[tid].show();	
	}
	
}

function loadTicketData( tid, authkey ){
	showLoading( ticketContainers[tid] );
	var c 		= new Ext.data.Connection();
	c.timeout	= 10000;
	c.request({
		url: 'index.php',
		loadMask: true,
		method: 'post',
		params: { tsrc: 'showtopic', 'id': tid, "authkey" : authkey },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( oElement, bSuccess, oResponse ){
			if( bSuccess ){		
				ticketContainers[tid].body.update( oResponse.responseText );
				
				var attach_panel = new Ext.Panel({
					collapsible: true,
					defaults: { autoHeight: true },					
					autoWidth: true,
					applyTo: 'attachment_area_' + tid,
					collapsed: true,
					titleCollapse: true,
					autoHeight: true
				});
			
				var reply_panel = new Ext.Panel({
					collapsible: true,
					defaults: { autoHeight: true },					
					autoWidth: true,
					applyTo: 'reply_area_' + tid,
					collapsed: true,
					titleCollapse: true
				});		
				
				openTickets[tid].reply_panel 	= reply_panel;
				openTickets[tid].attach_panel	= attach_panel;
				openTickets[tid].show();
				
				Ext.get( "area_a_" + tid ).setVisible( true, true );
				var r = Ext.get( "area_r_" + tid );
				if( r )
					r.setVisible( true, true );
			}
			else{
				loadTicketData( tid, authkey  );
			}
		}	
	});	
}

/**
 * Add a message to a ticket (reply)
 */
var responding_shown;
function ticketAddMessage( tid ){	

	var message = Ext.get( 'topic_' + tid + '_message' ).getValue();
	message 	= message.trim();	
	var authkey	= openTickets[tid].authkey;
	
	if( !message )
		return;
	
	if( !responding_shown ){
		Ext.MessageBox.show({
		   title: jsl.wait,
		   msg: jsl.wait_server,
		   width: 240,
		   progress: true,
		   closable: false
		});	
		responding_shown = true;
	}
		
	if( message ){
		var c = new Ext.data.Connection();
		c.timeout = 30000;
		c.request({
			url: proxyURL,
			method: 'post',
			params: { action: 'showtopic_reply', reflect_messages: 1, topic: tid, "message": message, "authkey": authkey },
			headers: { 'Accept' : 'application/json' },
			callback: function( options, success, transport ){						
				if( success ){
					var json = Ext.util.JSON.decode( transport.responseText );
					if( json.success ){
						
						if( openTickets[tid].reply_panel ){
							openTickets[tid].reply_panel.collapse();
							if( json.reply_area )
								openTickets[tid].reply_panel.body.update( json.reply_area );
						}					
						Ext.MessageBox.hide();
						ticketReloadMessageHistory( tid );
					}
					else{
						Ext.MessageBox.alert( jsl.response_warning, json.error );
					}
					responding_shown = false;
				}
				else{
					ticketAddMessage( tid );
				}
			}				  
		});	
	}
}


/**
 * Close a particular ticket
 */
function ticketClose( tid ){
	var messageArea = Ext.get( 'topic_' + tid + '_message' );
	
	if( messageArea ){
		var message = messageArea.getValue().trim();	
		var authkey	= openTickets[tid].authkey;

		var c = new Ext.data.Connection();
		c.timeout = 30000;
		c.request({
			url: proxyURL,
			method: 'post',
			params: { action: 'showtopic_close', topic: tid, "message": message, "authkey": authkey },
			headers: { 'Accept' : 'application/json' },
			callback: function( options, success, transport ){						
				if( success ){
					var json = Ext.util.JSON.decode( transport.responseText );
					if( json.success ){
						
						if( openTickets[tid].reply_panel ){
							openTickets[tid].reply_panel.collapse();
							if( json.reply_area )
								openTickets[tid].reply_panel.body.update( json.reply_area );
						}					
						Ext.MessageBox.hide();
						ticketReloadMessageHistory( tid );
					}
					else{
						Ext.MessageBox.alert( jsl.response_warning, json.error );
					}
					responding_shown = false;
				}
				else{
					ticketClose( tid );
				}
			}				  
		});	
	}
}

function ticketReloadMessageHistory( tid ){
	var messageArea = Ext.get( "message_history_" + tid );
	if( messageArea ){
		showLocalizedLoading( messageArea, "Reloading message history..." );		
		var c 		= new Ext.data.Connection();
		c.timeout	= 10000;
		c.request({
			url: 'index.php',
			method: 'post',
			params: { tsrc: 'showtopic_message_history', 'topic': tid },
			headers: {
				'Accept' : 'application/json'
			},
			callback: function( options, success, transport ){						
				if( success ){
					messageArea.update( transport.responseText );
				}
				else{
					ticketReloadMessageHistory( tid );
				}
			}
		});
	}
}

var ticket_upload;
var ticket_upload_n;
var uploadForm;
function showTicketUploadDialog( tid ){
	
	if( !ticket_upload ){
		var file = new Ext.form.TextField({ 
			fieldLabel: 'File', 
			inputType: 'file', // STEP 1 
			name: 'file', 
			id: 'file', 
			allowBlank: true 
		}); 
	
		var simple = new Ext.FormPanel({
			labelWidth: 75,
			url:proxyURL,
			frame:true,
			fileUpload: true, // STEP 2
			items: [file],
			baseParams: { action: 'showtopic_attach', topic: tid },
			buttons: [{
				text: 'Upload',
				handler: function(){ 
					simple.form.submit( { waitMsg:'Uploading ticket attachment...' } );
				} 
			}]
		});		
		
		simple.on( 'beforeaction', function( form, action ){
			showLocalizedLoading( Ext.get( "attachment_box_" + form.ticketID ), "Reloading attachment list..." );							  
		});
		
		simple.on( 'actioncomplete', function( form, action ){
			ticketReloadAttachments( form.ticketID );			
			uploadForm.close();
		});
		
		uploadForm = new Ext.Window({
			layout: 'fit',
			title: "Upload File Attachments",
			width: 400,
			height: 100,       
			items: [ simple ],
			resizable: false
		});
		
		uploadForm.on( 'destroy', function(){
			ticket_upload	= null;
			ticket_upload_n	= null;
			uploadForm		= null;
		});
		
		uploadForm.show();
		simple.el.enctype = 'multipart/form-data'; // STEP 3
		simple.getForm().ticketID = tid;
		ticket_upload_n = tid;
	}	
}

function ticketReloadAttachments( tid ){
	var authkey	= openTickets[tid].authkey;
	var attachment_area = Ext.get( "attachment_box_" + tid );
	
	if( attachment_area ){		

		var c = new Ext.data.Connection();
		c.timeout = 8000;
		c.request({	
			url: 'index.php',
			method: 'post',
			params: { tsrc: 'showtopic_attachments', topic: tid, "authkey": authkey },
			headers: { 'Accept' : 'application/json' },
			callback: function( options, success, transport ){						
				if( success ){
					openTickets[tid].attach_panel.doLayout();
					attachment_area.update( transport.responseText );
				}
				else{
					ticketReloadAttachments( tid );
				}
			}						 
		});	
	}	
}

function ticketRemoveAttachment( aid, tid ){
	var authkey	= openTickets[tid].authkey;
	var attachment_area = Ext.get( "attachment_box_" + tid );	
	
	if( attachment_area ){			
		showLocalizedLoading( attachment_area, "Reloading attachment list..." );			
		var c = new Ext.data.Connection();
		c.timeout = 8000;
		c.request({
			url: proxyURL,
			method: 'post',
			params: { action: 'showtopic_attach_delete', topic: tid, attachmentID: aid, "authkey": authkey },
			headers: { 'Accept' : 'application/json' },
			callback: function( options, success, transport ){						
				if( success ){
					openTickets[tid].attach_panel.doLayout();
					attachment_area.update( transport.responseText );
				}
				else{
					ticketRemoveAttachment( aid, tid );
				}
			}						 
		});	
	}
}


/**
 *
 *
 * DOWNLOADS BLOCK
 *
 *
 */ 
var tab_downloads;
var descriptionPanel;
var Download = Ext.data.Record.create([
	{name: 'category_path'},
	{name: 'name'},
	{name: 'description'},
	{name: 'size'},
	{name: 'downloads'},
	{name: 'updated'}
]);

function showDownloads(){
	
	if( tab_downloads == null ){	
	
		var download_store = new Ext.data.GroupingStore({
			sortInfo: { field: 'name', direction: "ASC"},
			groupField:'category_path',
			proxy: new Ext.data.HttpProxy({ url: proxyURL }),
			baseParams: { action: 'download_list' },
			reader: new Ext.data.JsonReader({
				totalProperty: "count",    
				root: "rows",
				id: "id"
			}, Download )
		});	
	
		var grid = new Ext.grid.GridPanel({
			store: download_store,
			columns: [
				{header: "", dataIndex: "category_path", hidden: true },
				{header: "Filename", width: 0, sortable: true, dataIndex: 'name' },
				{header: "Size", width: 30, sortable: true, dataIndex: 'size', renderer: Ext.util.Format.fileSize, align: 'right' },
				{header: "Downloads", width: 30, sortable: true, dataIndex: 'downloads', align: 'center'},
				{header: "Last Updated", width: 50, sortable: true, dataIndex: 'updated'}
			],	
			view: new Ext.grid.GroupingView({
				forceFit:true,
				groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
			}),	
			frame:true,
			autoWidth: true,
			height: 300,
			loadMask: true,
			collapsible: false,
			title: "Select a file from the list"
		});
		
		// grid click action
		grid.on( 'rowclick', function( grid, index, e ){
			showDownloadDetails( grid.getStore().getAt( index ).id );
		});
		
		
		descriptionPanel = new Ext.Panel({
			title: 'Description',
			closable: false,
			collapsible: false,
			height: 194,
			autoWidth:true
		});
		
		
		// add the panel to the main tab set (where the announcements are printed)
		download_panel = new Ext.Panel({
			title: 'Available Downloads',
			layout: 'table',
			layoutConfig:{
				columns: 1
			},
			constrainHeader: true,
			closable: true,
			autoScroll:false,
			autoWidth: true,
			items: [ grid, descriptionPanel ]	
		});
		
		tab_downloads = tabs.add( download_panel );
		tab_downloads.show();
		tabs.doLayout();
		
		download_store.load({
			callback: function( oElement, bSuccess, oResponse ){
				if( bSuccess ){
					
				}
				else{

				}
			}					  
		});
		
		tab_downloads.on( 'destroy', function(){ 
			tab_downloads 		= null;
			download_panel		= null;
			descriptionPanel	= null;
		});
	}
}

function showDownloadDetails( id ){
	descriptionPanel.body.load({
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'download_details', 'id': id },
		headers: {
			'Accept' : 'application/json'
		}
	});
}



/**
 *
 *
 * FEEDBACK BLOCK
 *
 *
 */ 



var feedbackPanel;
var tab_feedback;
function showFeedbackPanel(){
	if( !tab_feedback ){
		feedbackPanel = new Ext.Panel({
			iconCls: 'feedback',
			title: 'Feedback System',
			closable: true,
			defaults: { autoHeight: true }
		});
		
		tab_feedback = tabs.add( feedbackPanel );
		tab_feedback.on( 'destroy', function(){
			feedbackPanel	= null;								   
			tab_feedback	= null;		   
		});	
	}
	tab_feedback.show();	
	loadFeedbackForms();	
}


var feedbackForms = new Object();
function loadFeedbackForms(){
	showLoading( feedbackPanel );
	var c 		= new Ext.data.Connection();
	c.timeout	= 8000;
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'feedback_list' },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){
			if( !success ){
				loadFeedbackForms();
				return;	
			}
			var json = Ext.util.JSON.decode( transport.responseText );
			
			feedbackPanel.body.update( json.text );
			
			var formObj, formID, form, form_items;
			
			for( var i = 0 ; i < json.forms.length ; i++ ){
				formObj		= json.forms[i];
				formID		= formObj.topic;	
				form_items	= new Array();
				
		
				form_items.push( 
					new Ext.form.ComboBox({
						fieldLabel: jsl.feedback_experience,
						typeAhead: false,
						mode: 'local',
						readOnly: true,
						editable: false,
						displayField: 'display',
						valueField: 'key',
						triggerAction:'all',
						hiddenName: 'experience',
						allowBlank: false,
						width:295,
						store: new Ext.data.SimpleStore({
							fields: [ 'key', 'display'],
							data  : [ [ '-1', jsl.feedback_negative ],	
									  [ '0', jsl.feedback_neutral ],
									  [ '1', jsl.feedback_positive ] ]									
						})
					})
				);
				
				// star questions
				for( var j = 0 ; j < formObj.questions.length ; j++ ){
					form_items.push( 
						new Ext.ux.StarRating({ 
							fieldLabel: formObj.questions[j]['question'], 
							name: formObj.questions[j]['id'] 
						})
					);
				}
				
				form_items.push( 
					new Ext.form.TextArea({ 	
						name: "comment",
						fieldLabel: jsl.feedback_additional,
						emptyText: jsl.feedback_comments,
						width: 295
					})
				);		

				// instantiate the actual form
				form	= new Ext.form.FormPanel({
					topicID: formID,
					labelWidth: 275,
					url: proxyURL,	
					autoHeight: true,
					border: false,
					autoWidth: true,
					buttonAlign: 'right',
					baseParams: { topic: formObj.topic, action: 'feedback_submit' },
					renderTo: 'form_' + formID,
					items: form_items,
					buttons: [{ 
						'text': jsl.feedback_submit, 
						'formID': formID,
						'handler': function( btn, e ){
							feedbackForms[btn.formID].getForm().submit({
								waitMsg: jsl.feedback_thanks, 
								reset: false					  
							});
						}
					}]
				});
				form.on( 'actioncomplete', function( f, action ) { 
					// show the navtable if no validation is required, show the validation confirmation otherwise
					var json = Ext.util.JSON.decode( action.response.responseText );		

					if( json.accepted ){
						Ext.get( "container_" + f.topicID ).ghost( 't', {remove:true} );
					}
					else{
						Ext.MessageBox.alert( jsl.feedback_error, json.error );
					}
				});
				
				feedbackForms[formID] = form;						
				
				
			}						
		}				  
	});	
}




/**
 *
 *
 * PROFILE BLOCK
 *
 *
 */
var tab_profile;
var profile_panel;
function showProfile(){
	if( tab_profile == null ){
		profile_panel = new Ext.Panel({
			title: "User Profile",
			constrainHeader: true,
			closable: true
		});
		
		tab_profile = tabs.add( profile_panel );
		tab_profile.on( 'activate', function(){ setDynamicMenu( 'profile' ); });
		tab_profile.on( 'destroy', function(){ 
			clearDynamicMenu( 'profile' ); 
			tab_profile = null;
		});
		tab_profile.show();
		profileView( 'profile_main' );
	}
	else{
		tab_profile.show();
	}
	
}

/**
 * Profile page view request
 */
function profileView( page ){
	profile_panel.body.load({
		url: 'index.php',
		method: 'post',
		scripts: true,
		params: { tsrc: 'profile_area', subsection: page },
		callback: function( oElement, bSuccess, oResponse ){
			if( !bSuccess )
				profileView( page );			
		}					 
	});	
}


function profileShowChatTranscript( id ){
	profile_panel.body.load({
		url: 'index.php',
		method: 'post',
		scripts: true,
		params: { tsrc: 'profile_chat_transcript_view', "id": id },
		callback: function( oElement, bSuccess, oResponse ){
			if( !bSuccess )
				profileShowChatTranscript( id );			
		}					 
	});	
}



/**
 *
 *
 * ANNOUNCEMENT BLOCK
 *
 *
 */
var tab_ann;
var announcement_panel;
// show the support ticket tab
function showAnnouncement( ann_id ){
	if( tab_ann == null ){
		// add the panel to the main tab set (where the announcements are printed)
		announcement_panel = new Ext.Panel({
			title: "Announcements",
			constrainHeader: true,
			height: Ext.get( 'index_tab' ).getHeight(),
			closable: true
		});
		
		tab_ann = tabs.add( announcement_panel );		
		tab_ann.show();
		tab_ann.on( 'activate', function(){ setDynamicMenu( 'announcements' ); });
		tab_ann.on( 'destroy', function(){ 
			clearDynamicMenu( 'announcements' ); 
			tab_ann = null;
		});

		setDynamicMenu( 'announcements' );
		viewAnnouncement( ann_id );

	}
	else{
		tabs.activate( 'tab_ann' );	
		viewAnnouncement( ann_id );
	}
}

function viewAnnouncement( ann_id ){
	// folder nodes
	if( ann_id == 'X' || ann_id == 'Y' )
		return;
		
	announcement_panel.body.load({
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'announcement_view', annid: ann_id },
		headers: {
			'Accept' : 'application/json'
		}			  
	});		
}




/**
 *
 *
 * KNOWLEDGEBASE BLOCK
 *
 *
 */

// show the knowledgebase area tab (generic utility function)
function showKnowledgebase(){
	assertKB();		
	viewKnowledgebase( 'C0', 0 );	
}


/**
 *  kbcontainer................
 *  kb_left..........
 *  ---------------------------
 * | kbmenu          |         |
 * +-----------------+         |
 * |                 |         |
 * | kbviewport      |  kbtree |
 * +-----------------+---------+
 */
var tab_kb;
var knowledgebase_panel;
var knowledgebase_nav_toggle;
// ensure that the kb area exists
function assertKB(){
	if( tab_kb == null ){	
	
		knowledgebase_nav_toggle = new Ext.Toolbar.Button({
			id: "kb_nav_toggle",
			iconCls: "kbtree",
			text: "Show Tree Navigation",
			tooltip: "Activate this button to view a quick-navigation tree",
			enableToggle: true,
			handler: knowledgebaseNav
		});
	
		// add the panel to the main tab set (where the announcements are printed)
		knowledgebase_panel = new Ext.Panel({
			title: jsl.kb_article,
			constrainHeader: true,
			closable: true,
			autoScroll:false,
			autoHeight: true,			
			tbar: new Ext.Toolbar({
				border: true,
				items: [ knowledgebase_nav_toggle ]				
			})
		});

		tab_kb = tabs.add( knowledgebase_panel );										
		tab_kb.show();		
		showLoading( knowledgebase_panel );

		tab_kb.on( 'destroy', function(){ 
			tab_kb 			= null;
			kb_last_article = null;
			destroyNavPanel();
		});
	}
	else{
		tab_kb.show();	
	}
}

var kb_nav_panel	= null;
var kb_tree			= null;
function knowledgebaseNav( btn, e ){
	if( btn.pressed ){
		if( kb_nav_panel == null ){
			kb_tree = new Ext.tree.TreePanel({
				title: "Knowledgebase",
				animate:true, 
				rootVisible: false,				
				enableDD:false,
				root: new Ext.tree.TreeNode({
					text: jsl.navigation_tree,
					draggable:false,
					id:'0'
				}),				
				autoScroll: true
			});	
			
			kb_nav_panel	= new Ext.Window({
				title: jsl.navigation_tree,
				minHeight: 300,
				minWidth: 400,
				height: 300,
				width: 400,
				autoScroll:false,
				iconCls: 'kbtree',
				tbar: new Ext.Toolbar({
					cls:'top-toolbar',
					items:[ 
						new Ext.form.TextField({
							emptyText:'Find a subject',
							width: dynmenu.width - 6,
							listeners:{
								render: function(f){
									f.el.on('keydown', filterTree, f, { buffer: 350 } );
								}
							}
						})
					]
				}),
				layout: 'fit',
				items: [ kb_tree ]
			});
			
			kb_nav_panel.on( 'destroy', function(){
				knowledgebase_nav_toggle.toggle( false );
				kb_nav_panel	= null;
				kb_tree			= null;
			});		
			
			var sm = kb_tree.getSelectionModel();
			sm.on( 'selectionchange', function(){
				var n = sm.getSelectedNode();
				if( n ){
					viewKnowledgebase( kb_category, n.id );
					return;
				}
			});

			kb_nav_panel.show( btn );
			
			if( kb_last_article != null && kb_tree != null ){
				loadNavigationTree( kb_last_article.c );
				selectArticle( kb_tree, kb_last_article.a );
			}
		}		
	}
	else{
		destroyNavPanel();	
	}
}

function destroyNavPanel(){
	if( kb_nav_panel != null ){
		kb_nav_panel.destroy();
	}	
}

function selectArticle( tree, id ){
	var n = tree.getNodeById( id );
	if( n ){			
		tree.expandPath( n.getPath() );
		n.select();
	}	
}
	

var kb_shown 		= false;
var kb_last_article	= null;
var kb_category		= null;
// Load a particular knowledgebase article
function viewKnowledgebase( cat, article, bypass ){
	if( !bypass && kb_last_article != null && kb_last_article.c == cat && kb_last_article.a == article )
		return;	
		
	kb_last_article = { c : cat, a : article };
	
	// ensure that the article framework is in place
	if( !bypass ){
		assertKB();
		setDynamicMenu( 'kb' );
		tab_kb.show();
		showLoading( knowledgebase_panel );
	}
	
	var c = new Ext.data.Connection();
	c.request({
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'kb', category: cat, act: article },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){						
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
				knowledgebase_panel.body.update( json.article, true );				
						
				// check for a last screen action
				if( json.lsa )
					lastScreenAction = json.lsa;
			}
			else{
				viewKnowledgebase( cat, article, true );
				return;
			}
		}				  
	});	
	
	
	if( kb_category != cat ){
		loadNavigationTree( cat );
		kb_category = cat;
	}
	else{
		if( kb_tree != null )
			selectArticle( kb_tree, article );
	}
	
}

function cleanNode( node ){
	while( node.firstChild ){
		 var c = node.firstChild;
		 node.removeChild(c);
	}	
}

function loadNavigationTree( cat ){
	if( kb_tree != null ){		
		var root = kb_tree.getRootNode();
		cleanNode( root );		
		
		if( cat == 'C0' )
			return;
			
		loadNavigationTreeJSON( cat );
	}
}


function loadNavigationTreeJSON( cat, autoselect ){
	var c = new Ext.data.Connection();
	c.timeout = 5000;
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'knowledgebaseTree', category: cat },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
			
				var root = kb_tree.getRootNode();			
				buildTreeFromJSON( root, json );
				
				if( !root.childrenRendered )
					root.renderChildren();
				
				root.expand();
				if( root.firstChild )
					root.firstChild.expand();

			}
			else{
				loadNavigationTreeJSON( cat, autoselect );
			}
		}				  
	});	
}

function buildTreeFromJSON( node, json ){
	var childArray = Array(json.length);
	
	Ext.each( json, function( j ){
		var child = new Ext.tree.TreeNode({
			text: j.text,
			draggable: false,
			id: j.id,
			cls: j.cls,
			leaf: j.leaf
		});
		
		if( j.children )
			buildTreeFromJSON( child, j.children );
			
		node.appendChild( child );
	});
}


var hiddenPkgs  = [];
var markCount	= [];

// filter the kb tree for hits
function filterTree(e){
	var text = e.target.value;
	Ext.each(hiddenPkgs, function(n){
		n.ui.show();
	});
	
	markCount  = [];	
	hiddenPkgs = [];
	
	if( text.trim().length > 0 ){
		kb_tree.expandAll();
		
		var re = new RegExp( Ext.escapeRe(text), 'i');
		kb_tree.root.cascade( function( n ){
			if( re.test(n.text) )
				markToRoot( n, kb_tree.root );
		});
		
		// hide empty packages that weren't filtered		
		kb_tree.root.cascade(function(n){
			if( ( !markCount[n.id] || markCount[n.id] == 0 ) && n != kb_tree.root ){
				n.ui.hide();
				hiddenPkgs.push(n);
			}
		});
	}
}

function markToRoot( n, root ){
	
	if( markCount[n.id] )
		return;
		
	markCount[n.id] = 1;
	
	if( n.parentNode != null )
		markToRoot( n.parentNode, root );
}


function knowledgebaseSubmitComment( id, cat ){
	var c 	= Ext.get( 'comment_add' );
	var str = c.getValue();
	
	var c = new Ext.data.Connection();
	c.timeout = 5000;
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'comment_kb', category: cat, "id": id, comment: str },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
			
				if( json.success == 1 )
					Ext.get( 'comment-form' ).update( json.message );
				else
					alert( json.message );
			}
			else{
				loadNavigationTreeJSON( cat, autoselect );
			}
		}				  
	});	
}

function knowledgebaseDeleteComment( id ){
	var c = new Ext.data.Connection();
	c.timeout = 5000;
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'comment_kb_delete', "id": id },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
			
				if( json.success == 1 ){
					Ext.get( 'comment_' + id ).remove();	
				}
			}
			else{
				loadNavigationTreeJSON( cat, autoselect );
			}
		}				  
	});	
}


/**
 *
 *
 * TROUBLESHOOTER BLOCK
 *
 *
 */
var tab_tr;
var troubleshooter_panel;

/**
 * Generic troubleshooter startup
 */
function showTroubleshooter(){
	viewTroubleshooter( 'C0', '0' );
}


function assertTroubleshooter(){
	if( tab_tr == null ){			
		// add the panel to the main tab set (where the announcements are printed)
		troubleshooter_panel = new Ext.Panel({
			title: "Troubleshooter",
			constrainHeader: true,
			closable: true,
			autoScroll:false,
			autoHeight: true			
		});

		tab_tr = tabs.add( troubleshooter_panel );										
		tab_tr.show();				
		
		tab_tr.on( 'destroy', function(){ 			
			tab_tr 			= null;
		});
	}
	else{
		tab_tr.show();	
	}
	
	
}

/**
 * Mark that a troubleshooter path solved a problem
 */
function troubleshooterSolved( cat, article ){
	var a = Ext.get( "tr_solved" );
	a.update( "<em>Voting...one moment please...</em>" );
	var c = new Ext.data.Connection();
	c.request({
		url: proxyURL,
		method: 'post',
		params: { action: 'troubleshooter_chain', 'act': article, 'category' : cat },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){						
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
				a.update( json.response );
			}
			else{
				troubleshooterSolved( cat, article );
			}
		}
	});
}

/**
 * Load a particular troubleshooter article
 */
function viewTroubleshooter( cat, article ){
	assertTroubleshooter();
	showLoading( troubleshooter_panel );
	var c = new Ext.data.Connection();
	c.request({
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'troubleshooter', category: cat, act: article },
		headers: {
			'Accept' : 'application/json'
		},
		callback: function( options, success, transport ){						
			if( success ){
				var json = Ext.util.JSON.decode( transport.responseText );
				troubleshooter_panel.body.update( json.article, true );
						
				// check for a last screen action
				if( json.lsa )
					lastScreenAction = json.lsa;
			}
			else{
				viewTroubleshooter( cat, article, true );
				return;
			}
		}				  
	});
}

 
 
 



/**
 *
 *
 * SERVER STATUS BLOCK
 *
 *
 */
var serverPanel;
var tab_server;
function showServerStatus(){
	if( serverPanel == null ){
		serverPanel = new Ext.Panel({
			iconCls: 'server_status',
			title: 'Server Status',
			closable: true,
			defaults: { autoHeight: true }
		});
		
		tab_server = tabs.add( serverPanel );
		tab_server.on( 'destroy', function(){
			serverPanel = null;								   
			tab_server	= null;		   
		});
	}	
	tab_server.show();
	loadServerStatusPanel();
}

function loadServerStatusPanel(){
	serverPanel.body.load({
		timeout: 8000,
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'server_status' },
		callback: function( oElement, bSuccess ){
			if( !bSuccess )
				loadServerStatusPanel();
		}
	});
}







/**
 *
 *
 * DYNAMIC MENU BLOCK
 *
 *
 */

var lsm = "featured";	// last selected dynamic menu


/**
 * Dynamic menu elements
 */
var ann_tree;
var profile_menu;

/**
 * Set the dynamic menu to a specific choice
 */
function setDynamicMenu( s ){
	
	if( lsm == s )
		return;

	
	switch( s ){
		// with the featured menu,  hide the dynmenu
		case 'featured':
			dynmenu.collapse( false );
			dynmenu.el.setOpacity( 0.5, false );
			featured.expand( false );
			featured.el.setOpacity( 1, true );
		break;		
		
		case 'announcements':			
			if( ann_tree == null ){
				ann_tree = new Ext.tree.TreePanel({
					title: "Announcements",
					animate:true, 
					rootVisible: false,
					
					loader: new Ext.tree.TreeLoader({
						dataUrl: proxyURL, 
						baseParams: {
							action: 'announcementTree'					
						}
					}),
					enableDD:false,
					autoScroll:true,
					height: menuHeight,
					root: new Ext.tree.AsyncTreeNode({
						text: jsl.navigation_tree,
						draggable:false,
						id:'1'
					})
				});		
				
				var sm = ann_tree.getSelectionModel();
				sm.on('selectionchange', function(){
					var n = sm.getSelectedNode();
					if( n ){
						viewAnnouncement( n.id );
						return;
					}
				});	
		
				dynmenu.add( ann_tree );		
				dynmenu.doLayout();
				
			}
			
			if( lsm == 'featured' ){
				featured.collapse( false );
				featured.el.setOpacity( 0.5, false );
			}
			dynmenu.expand( false );
			dynmenu.el.setOpacity( 1, true );
			ann_tree.expand();
		break;
		
		case 'profile':
			if( profile_menu == null ){
				profile_menu = new Ext.Panel({
					title: 'Your User Profile',
					layout: 'fit',
					animCollapse: true,
					width: 205,
					shim: false,
					border: true,
					opacity: 0.5,
					collapsed:true,
					titleCollapse:true,
					constrainHeader: true			
				});					
				
				dynmenu.add( profile_menu );
				dynmenu.doLayout();
				
				buildProfileMenu( profile_menu );
			}
		
			if( lsm == 'featured' ){
				featured.collapse( false );
				featured.el.setOpacity( 0.5, false );
			}
			
			dynmenu.expand( false );
			dynmenu.el.setOpacity( 1, true );
			profile_menu.expand();
		
		break;
		
		
		
	}	
	lsm = s;	
}


function buildProfileMenu( panel ){
	panel.body.load({
		url: 'index.php',
		method: 'post',
		params: { tsrc: 'profile' },
		callback: function( oElement, bSuccess, oResponse ){
			if( bSuccess ){
				var x = Ext.select( 'div[id^=profile-]' );
				Ext.each( x.elements, function( d ){
					new Ext.Panel({
						collapsible: true,		  
						applyTo: d,
						titleCollapse: true,
						opacity: 0.8
					});
				});
			}
			else{
				buildProfileMenu( panel );
			}
		}
	});		
}


function clearDynamicMenu( s ){
	switch( s ){
		case 'announcements':
			if( ann_tree != null ){
				dynmenu.remove( ann_tree );
				//ann_tree.destroy();
				ann_tree = null;
			}	
		break;
			
		case 'profile':
			if( profile_menu != null ){
				dynmenu.remove( profile_menu );
				profile_menu = null;
			}
		break;
	}	
}


function showLoading( p ){
	p.body.update( p.getUpdater().indicatorText );
}

// show a contained loading message in an Ext.Element
function showLocalizedLoading( element, loadText ){
	element.update( '<div class="custom_loading" style="width:100%">' + loadText + "</div>" );
}


/**
 *
 *
 * TABBED SEARCH BLOCK
 *
 *
 */
var searchPanelID	= 0;
var searchPanelList	= new Array();
function systemSearch( text ){
	if( !text.trim() )
		return;
		
	var sid = "search-" + searchPanelID++;
	var searchPanel = new Ext.Panel({
		id: sid,
		iconCls: 'search',
		title: Ext.util.Format.ellipsis( text, 10 ),
		closable: true,
		defaults: { autoHeight: true },
		searchText: text
	});
	
	searchPanel.on( 'destroy', function(){
		delete searchPanelList[this.id];										
	});
	
	searchPanelList[sid] = searchPanel;	
	var stab = tabs.add( searchPanel );
	stab.show();
	executeSearch( sid, 0 );
}

function executeSearch( panelID, offset ){
	panel = searchPanelList[panelID];
	
	panel.body.load({
		timeout: 10000,
		url: 'index.php',
		method: 'post',
		scripts: true,
		params: { tsrc: 'search', 'text': panel.searchText, 'offset': offset, 'panel': panel.id },
		callback: function( oElement, bSuccess ){
			if( !bSuccess )
				systemSearch( text );
		}
	});	
}

/**
 *
 *
 * INITIALIZATION BLOCK
 *
 *
 */ 
var tabs;
var featured;
var dynmenu;
var menuHeight;
var searchField;

Ext.onReady( function(){	
	mainToolbar = new Ext.Toolbar({
		renderTo: 'toolbar',
		border:true
	});
					  
	var tbPanel = new Ext.Panel({
		renderTo: 'toolbar_panel',
		items: [ mainToolbar ]								
	});
	
	
	
	var langSelect = getLanguageSelect();
	
	if( !logged_in ){
		mainToolbar.add( "language ", langSelect, "->" );
		
		var resendPassword	= new Ext.Toolbar.Button({ 
			text: jsl.lost_password,
			handler: function( btn, e ){
				Ext.MessageBox.prompt( jsl.password_reminder, jsl.enter_email, sendPassword );
			}
		});		
		
		usernameField = new Ext.form.TextField({
			emptyText: jsl.username_or_email
		});		
		
		passwordField = new Ext.form.TextField({
			inputType: "password" // don't externalize or translate!
		});

		var loginButton = new Ext.Toolbar.Button({ 
			text: jsl.login,
			handler: function( btn, e ){				 
				login();
			}
		});
		
		if( validation_req ){
			var validateButton = new Ext.Toolbar.Button({ 
				text: jsl.validate,
				handler: function( btn, e ){				 
					Ext.MessageBox.prompt( jsl.validation_request, jsl.account_email, sendValidation );
				}
			});
			mainToolbar.add( validateButton, "-" );
		}
		
		rememberCheckbox = new Ext.form.Checkbox({
			autoCreate: true,
			checked:false,
			boxLabel: jsl.store_details
		});
		
		mainToolbar.add( resendPassword, "-", jsl.user + " ", usernameField, "  " + jsl.pass + " ", passwordField, " ", rememberCheckbox, "-", loginButton );		
		
		var field = Ext.get( passwordField.id );
	
		new Ext.KeyMap( field.dom, {
			key: Ext.EventObject.ENTER, 
			fn: function(){ login(); }
		});		
	}
	else{
		addLogoutButton();	
	}
	
	// tabpanel area
	tabs = new Ext.TabPanel({
        renderTo: 'system_tabs',
        resizeTabs: false,
        minTabWidth: 115,
        tabWidth: 135,
        enableTabScroll:true,
		defaults: { autoHeight: true },
		autoWidth: true,
		activeTab: 0,
        frame: true,
		items: [
            { contentEl:'index_tab', title: 'Index', iconCls: 'tab_index'}
		]
    });
	
	tabs.getActiveTab().on( 'activate', 
		function(){ 
			setDynamicMenu( 'featured' );
		}
	);
	
	searchField = new Ext.form.TextField({
		emptyText:'enter search text...',
		width: 150,
		listeners:{
			'specialkey' : function( field, e ){ if( e.getKey() == Ext.EventObject.ENTER ) systemSearch( field.getValue() ); }
		}
	});
	
	var tbPanel = new Ext.Panel({
		renderTo: 'search_panel',
		width: 205,
		items: [ 
			new Ext.Toolbar({
				renderTo: 'searchbar',
				items: [
					searchField,
					" ",
					new Ext.Toolbar.Button({
						text: "Search!",
						handler: function( btn, e ){
							systemSearch( searchField.getValue() );									
						}					   
					})					
				]
			})
		]
	});	
	
	dynmenu = new Ext.Panel({
		title: 'Dynamic Menu',
		layout: 'accordion',
		renderTo: 'dynmenu',
		animCollapse: true,
		width: 205,		
		height:tabs.el.getHeight(),
		shim: false,
		border: true,
		opacity: 0.5,
		collapsed:true,
		constrainHeader: true,		
		layoutConfig: {
			titleCollapse: true,
			animate: false
		}			
	});	
	
	// featured area
	var featured_articles = new Ext.Panel({
		el: 'featured_articles',
		autoScroll:true
	});
	

	var featured_searches = new Ext.Panel({
		el: 'featured_searches',
		autoScroll:true
	});					  

	var panelItems = [ featured_articles, featured_searches ];
	
	var x = Ext.select( 'div[id^=rss_]' );
	Ext.each( x.elements, function( d ){
		panelItems.push( 
			new Ext.Panel({
				el: d,
				autoScroll: true
			})
		);
	});
	
	

	featured = new Ext.Panel({
		title: "Latest in Support",
		layout: 'accordion',
		iconCls: 'accordion',
		applyTo: 'featured_box',
		animCollapse: true,
		width: 205,
		height: tabs.el.getHeight() - dynmenu.el.getHeight() - tbPanel.el.getHeight(),
		shim: false,
		border: true,
		constrainHeader: true,
		layoutConfig: {
			titleCollapse: true,
			animate: false
		},
		items: panelItems
	});
	menuHeight = tabs.el.getHeight() - dynmenu.el.getHeight();
	dynmenu.setHeight( menuHeight );
	
	//window.onbeforeunload = leave;
	
	function leave(){
		return "You're about to leave the support desk's environment, this will reset any windows or navigation you've currently established.";
	}
	
	Ext.form.Field.prototype.msgTarget = 'under';
	Ext.QuickTips.init();
});

