// Script for the chat page
/////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////
// Library functions for strings
// They must be in this file to be used
////////////////////////////////////////////////////////

String.prototype.trim = function() 
{
	a = this.replace(/^\s+/, '');
	return a.replace(/\s+$/, '');
};

////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////

var g_script = "chat.php";

////////////////////////////////////////////////////////
// Global variables
////////////////////////////////////////////////////////

var g_command;          // The command that is being executed
var g_message;          // The message string
var g_request;          // The XMLHttpRequest object
var g_timer;            // The Timer object
var g_lastPollTime;     // The time of last poll
var g_pollTimerEvents;  // Number of timer events since last poll
var g_checkTimerEvents; // Number of timer events since last check
var g_username;         // The username
var g_queuedCommand;    // The command that has been queued 
var g_queuedMessage;    // The message that has been queued

////////////////////////////////////////////////////////
// Create a new XMLHttpRequest and set some of its headers
////////////////////////////////////////////////////////

function createNewRequest()
{
  g_request = false;
	
  // For Safari, Firefox, and other non-MS browsers
  if (window.XMLHttpRequest) 
  {
    try
    {
      g_request = new XMLHttpRequest();
    }
    catch (e) 
    {
      g_request = false;
	  } 
	} 
	else if (window.ActiveXObject) 
	{
		// For Internet Explorer on Windows
		try 
		{
			g_request = new ActiveXObject("Msxml2.XMLHTTP");
		} 
		catch (e) 
		{
			try 
			{
				g_request = new ActiveXObject("Microsoft.XMLHTTP");
			} 
			catch (e) 
			{
				g_request = false;
			}
		}
	}

	if (!g_request) 
	{
		location.href = "apology.html";
		return;
	}

}

////////////////////////////////////////////////////////
// Gets an element of the page by element id
////////////////////////////////////////////////////////

function getElement(name)
{
  return document.getElementById(name);
}

////////////////////////////////////////////////////////
// Plays a sound only if desired.
////////////////////////////////////////////////////////

function playSound(sound, loopcount)
{
	if (getElement("checkSounds").checked)
	{
    soundManager.play(sound, 1);
  }
}

////////////////////////////////////////////////////////
// Change the cursor
////////////////////////////////////////////////////////

function cursor_wait() 
{
  document.body.style.cursor = 'wait';
}

function cursor_clear() 
{
  document.body.style.cursor = 'default';
}

////////////////////////////////////////////////////////
// Functions to hides or shows the elements
////////////////////////////////////////////////////////

function showPanels(bShow)
{
  var inputPanel = getElement("fieldMessage");
  var outputPanel = getElement("output_border");
  if ( bShow )
  {
    inputPanel.style.display = 'block'; 
    outputPanel.style.display = 'block'; 
  }
  else
  {
    inputPanel.style.display = 'none'; 
    outputPanel.style.display = 'none'; 
  }
}


function showControls(bShow)
{
  showElement("controls", bShow);
}


function showElement(id, bShow)
{
  var element = getElement(id);
  if ( element != null )
  {
    if ( bShow )
      element.style.display = 'block'
    else
      element.style.display = 'none'
  }
  else
  {
    // For debugging
    alert("Element " + id + " is null");
  }
}

////////////////////////////////////////////////////////
// Button event handlers 
////////////////////////////////////////////////////////

function onButtonLogin()
{
  // Get the username
	g_username = getElement("fieldUsername").value.trim();
	
	if ( g_username == "" )
	{
    // The username is empty so cannot accept it
    alert(g_usernameNeeded);
    return;
  }

  // Can send the request	
  cursor_wait();
  sendRequest("login", null);
}


function onButtonLogout()
{
  // Check that the username is valid
  if ( g_username == null ) return;
  
  if ( confirm(g_closeChatText) )
  {
    makeRequest("logout", null);
  }
}

////////////////////////////////////////////////////////
// Functions to send the request and process the response
////////////////////////////////////////////////////////

function sendRequest(cmd, msg)
{
  // Create a new request
	createNewRequest();
	
	// Make the request body
	var body = "cmd=" + escape(cmd);
	if ( g_username != null )
	{
    body += "&usr=";
    body += escape(g_username);
  }
  if ( msg != null )
  {
    body += "&msg=";
    body += encodeMessage(msg);
  }

  // Sets the current command and message
  g_command = cmd;
  g_message = msg;

  // Launches the request
  g_request.onreadystatechange = onRequestReadyStateChange;
	g_request.open("POST", g_script, true);
	g_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	g_request.send(body);
	
}


function onRequestReadyStateChange()
{
  var DONE = 4;
  if (g_request.readyState != DONE )
  {
    return;
  }

/*  var OK = 200;
  if (g_request.status != OK) 
	{
    alert("Request failed");
    return;
  }
*/
  
  // For debugging
  // alert("Request succeeded");

  // For debugging
  // getElement("responseText").value = g_request.responseText;
  // getElement("responseHeaders").value = request.getAllResponseHeaders();

  // Execute a different function according to the command
       if ( g_command == "msg" ) onMessageResponse();
  else if ( g_command == "poll" ) onPollResponse();
  else if ( g_command == "login" ) onLoginResponse();
  else if ( g_command == "logout" ) onLogoutResponse();
  else if ( g_command == "check" ) onCheckResponse();
  else
  {
    // Some error
  
  
  }
  
  // Reset the status
  g_request = null;
  g_command = null;
  g_message = null;
  
  cursor_clear();
 
}


function makeRequest(cmd, msg)
{
  if ( g_command == null )
  {
    // Can send the request
    sendRequest(cmd, msg);
  }
  else if (g_queuedCommand == null )
  {
    // Cannot send the request but can queue it
    g_queuedCommand = cmd;
    g_queuedMessage = msg;
  }
  else
  {
    // Cannot even queue the request
    alert("Please wait");
  }
}


////////////////////////////////////////////////////////
// Response handlers
////////////////////////////////////////////////////////

function onLoginResponse()
{
  // Hide the login button and show the logout button
  showElement("buttonLogin", false);
  showElement("buttonLogout", true);
  
  // Hide the username text field
  showElement("fieldUsername", false);
  showElement("labelUsername", false);
  
  // Show the input/output panels
  showPanels(true);

  // Clear the output and the input
  clearOutput();
  clearInput();
  
  // Save the username in the cookies
  createCookie("LiveSupportUser", g_username, 1);
  
  // Play the login sound
  playSound("login");
}


function onLogoutResponse()
{
  // Hide the input/output
  showPanels(false);
  
  // Hide the logout button and show the login button
  showElement("buttonLogout", false);
  showElement("buttonLogin", true);
  
  // Show the username text field
  showElement("fieldUsername", true);
  showElement("labelUsername", true);
  
  // Reset the username
  g_username = null;
  getElement("fieldUsername").value = "";
  
  // Reset the cookie
  eraseCookie("LiveSupportUser");
    
  playSound("logout");
  
}


function onPollResponse()
{
  var xmlDoc = g_request.responseXML;
  var messages = xmlDoc.getElementsByTagName("MESSAGE");
	if (messages.length) 
  {
		for (var i = 0; i < messages.length; i++) 
    {
      var encoded = messages[i].childNodes[0].nodeValue;
      var message = decodeHex(encoded);
      appendMessage(g_supportLabel, message);
		}
		
		playSound("talk");
  }	
  
  g_pollTimerEvents = 0;

}


function onMessageResponse()
{
  // To be completed: parse the response
  
  appendMessage(g_username, g_message);
  g_message = null;
  clearInput();
  playSound("talk");
}


function onCheckResponse()
{
  var str = null;
  var bShowControls = null;
  var response = g_request.responseText;
  if ( response == "off" )
  {
    str = g_notAvailableText;
    bShowControls = false;
  }
  else if ( response == "on")
  {
    str = g_availableText;
    bShowControls = true;
  }
  else
  {
    // To be completed
    // Invalid response
    //alert("Invalid response");
    return;
  }
  showControls(bShowControls);
  getElement("status").innerHTML = str;
  g_checkTimerEvents = 0;
}


////////////////////////////////////////////////////////
// Timer handler
////////////////////////////////////////////////////////

function onTimer()
{
  if ( g_command != null )
  {
    // It is still processing the previous request
    return;
  }
  
  // The previous request has been processed
  // See if there is a queued command
  if ( g_queuedCommand != null )
  {
    // There is a queued command
    // Send the request for the queued command
    sendRequest(g_queuedCommand, g_queuedMessage);
    g_queuedCommand = null;
    g_queuedMessage = null;
    return;
  }

  // There is no queued command so can poll or check
  if ( g_username == null )
  {
    // The login has not been done yet, or the user has 
    // logged out, so must check, but only if the timer 
    // events elapsed since the previous check are enough
    if ( g_checkTimerEvents < 4 )
    {
      g_checkTimerEvents++;
      return;
    } 
    sendRequest("check", null);
    return;
  }
 
  // Must poll but only if the timer events elapsed since 
  // the previous poll are enough
  if ( g_pollTimerEvents < 4 )
  {
    g_pollTimerEvents++;
    return;
  }
  
  sendRequest("poll", null);
  
}

////////////////////////////////////////////////////////
// Functions for the input
////////////////////////////////////////////////////////

function onUsernameKeyPress(i, event)
{
	var key = getKey(event);
  if ( ! key ) return;
	// 13 is the ASCII code for the enter key
	if (key != 13) 
	{
	 // Ignore and process it normally
	 return true;
	}

  onButtonLogin();	
  return false;

}


function onInputKeyPress(i, event)
{
	var key = getKey(event);
  if ( ! key ) return;

	// 13 is the ASCII code for the enter key

	if (key != 13) 
	{
	 // Ignore and process it normally
	 return true;
	}
	
	// Prepare the message to send
	// but only if the previous message has been sent
	var message = getElement("fieldMessage").value.trim();
	
  if ( message == "" )
	{
	 return false;
	}
	
	cursor_wait();
  makeRequest("msg", message);
  
  return false;

}


function getKey(event)
{
	// This function is needed because different browsers 
  // hide the keycode in different places
  
  var key = false;

	if (window.event) key = window.event.keyCode;
	else if (event) key = event.which;

	return key;
}



function clearInput()
{
  getElement("fieldMessage").value = "";
}


////////////////////////////////////////////////////////
// Functions for the output
////////////////////////////////////////////////////////

function appendMessage(sender, text)
{
  var outputView = getElement("output");
  var html = "<P><B>";
  html += sender;
  html += ":</B><BR>";
  html += text;
  html += "</P>";    	
  outputView.innerHTML += html;
  outputView.scrollTop = outputView.scrollHeight;
}

function clearOutput()
{
  getElement("output").innerHTML = "";
}

////////////////////////////////////////////////////////
// Functions for the encoding/deconding
////////////////////////////////////////////////////////

function encodeMessage(str)
{
  // Use the functions defined in hexcode.js
  return encodeHex(str);
}

function decodeMessage(str)
{
  // Use the functions defined in hexcode.js
  return decodeHex(str);
}

////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////

function init()
{
  // General initializations
  soundManagerInit();
  getElement("pageTitle").innerHTML = g_pageTitle;

  // Get the username from the cookies
  var username = readCookie("LiveSupportUser");
  
  if ( username != null )
  {
    // There is a username in the cookies
    
    // Hide the login button and show the logout button
    showElement("buttonLogin", false);
    showElement("buttonLogout", true);
  
    // Hide the username text field
    showElement("fieldUsername", false);
    showElement("labelUsername", false);
  
    // Set the current username variable
    g_username = username;
    
    // Show the input/output panels
    showPanels(true);

    // Do not clear the output and the input
  
  }
  else
  {
    // There is no registered username in the cookies
    clearOutput();
    clearInput();
    showElement("buttonLogout", false);
    showPanels(false);
    showControls(false);
    getElement("status").innerHTML = g_checkingText;
    g_username = null;
    getElement("fieldUsername").value = "";
  }

  // Start the timer for polling
  g_pollTimerEvents = 0;
  g_checkTimerEvents = 0;
  g_timer = setInterval("onTimer()", 500);

}

////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////





