/* chatURL - URL do aktualizacji wiadomości */
var chatURL = "chat.php";
/* tworzy obiekty XMLHttpRequest, które zaktualizują wiadomości rozmowy i pobiorą wybrany kolor*/
var xmlHttpGetMessages = createXmlHttpRequestObject();
var xmlHttpGetColor = createXmlHttpRequestObject();
/* zmienna, która określa jak często łączyć się z serwerem*/
var updateInterval = 1000; // w milisekundach
// ustawione na true, wyświetla szczegółowy komunikat o błędach
var debugMode = true;
/* rozpoczyna zapisywanie wiadomości w pamięci podręcznej */
var cache = new Array();
/* lastMessageID - tidentyfikator najświeższej wiadomości rozmowy */
var lastMessageID = -1; 
/* mouseX, mouseY - współrzędne kursora myszy */
var mouseX,mouseY;
/* tworzy instancję obiektu XMLHttpRequest */
function createXmlHttpRequestObject() 
{
  //przechowa referencję do obiektu XMLHttpRequest 
  var xmlHttp;
  // powinno zadziałać dla przeglądarek nowszych niż IE6
  try
  {
    // próbuje utworzyć obiekt XMLHttpRequest
    xmlHttp = new XMLHttpRequest();
  }
  catch(e)
  {
    // zakładając że przeglądarką jest IE6 lub starsza
    var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
                                    "MSXML2.XMLHTTP.5.0",
                                    "MSXML2.XMLHTTP.4.0",
                                    "MSXML2.XMLHTTP.3.0",
                                    "MSXML2.XMLHTTP",
                                    "Microsoft.XMLHTTP");
    // sprawdza każdy prog id, aż któryś zadziała
    for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++) 
    {
      try 
      { 
        // próbuje utworzyć obiekt XMLHttpRequest
        xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
      } 
      catch (e) {}
    }
  }
  // zwraca utworzony obiekt lub wyświetla wiadomość o błędzie
  if (!xmlHttp)
    alert("Błąd podczas tworzenia obiektu XMLHttpRequest.");
  else 
    return xmlHttp;
}
/* ta funkcja rozpoczyna rozmowę; jest wykonywana w chwili załadowania strony */
function init() 
{
  // pobiera odwołanie do okna tekstowego, w którym użytkownik wpisuje nową wiadomość
  var oMessageBox = document.getElementById("messageBox");
  // zapobiega uruchomieniu funkcji autouzupełniania
  oMessageBox.setAttribute("autocomplete", "off");    
  // zapewnia nadanie użytkownikowi nazwy (np. generowanej automatycznie)
  checkUsername();
  // rozpoczyna aktualizację nowego okna
  requestNewMessages();
}

// funkcja, która zapewnia, że użytkownik dostanie nazwę, choćby generowaną automatycznie
function checkUsername()
{
  // zapewnia nadanie użytkownikowi nazwy (np. generowanej automatycznie)
  var oUser=document.getElementById("userName");
  if(oUser.value == "")
    oUser.value = "Gość" + Math.floor(Math.random() * 1000);
} 
/* funkcja wywołana po wciśnięciu przycisku "Wyślij"*/
function sendMessage()
{
  // zachowuje wiadomość w zmiennych lokalnych i czyści okienko tekstowe
  var oCurrentMessage = document.getElementById("messageBox");
  var currentUser = document.getElementById("userName").value;
  var currentColor = '#000000';
  // nie wysyła pustych wiadomości
  if (trim(oCurrentMessage.value) != "" &&
      trim(currentUser) != "" && trim (currentColor) != "")
  {
    // jeśli musimy wysłać i pobrać wiadomość
    params =  "mode=SendAndRetrieveNew" +
              "&id=" + encodeURIComponent(lastMessageID) + 
              "&color=" + encodeURIComponent(currentColor) + 
              "&name=" + encodeURIComponent(currentUser) + 
              "&message=" + encodeURIComponent(oCurrentMessage.value);
    // dodaje wiadomość do kolejki
    cache.push(params);
    // czyści okno tekstowe
    oCurrentMessage.value = "";
  }
}

/* funkcja wywołana po wciśnięciu przycisku "Usuń wszystko" */
function deleteMessages()
{
    document.getElementById("scroll").innerHTML = "";
    //lastMessageID = -1;
}

/* wysyła asynchroniczne żądanie, aby pobrać nowe wiadomości, wysłać je lub usunąć*/
function requestNewMessages()
{  
  // pobiera nazwę użytkownika i kolor ze strony
  var currentUser = document.getElementById("userName").value;
  var currentColor = '#000000';// document.getElementById("color").value;
  // kontynuuje jeśli xmlHttpGetMessages nie jest pusty
  if(xmlHttpGetMessages)
  {
    try
    {
      // nie zaczyna nowej operacji na serwerze, jeśli jakaś jest wykonywana
      if (xmlHttpGetMessages.readyState == 4 || 
          xmlHttpGetMessages.readyState == 0) 
      {
        // przechowa parametry potrzebne do wykonania żądania na serwerze
        var params = "";
        // jeśli w kolejce czekają wiadomości, to pobiera najstarszą
        if (cache.length>0)
          params = cache.shift();
        // jeśli pamięć jest pusta, pobiera nową wiadomość
        else
          params = "mode=RetrieveNew" +
                   "&id=" +lastMessageID;
        // wywołuje działania po stronie serwera
        xmlHttpGetMessages.open("POST", chatURL, true);
        xmlHttpGetMessages.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlHttpGetMessages.onreadystatechange = handleReceivingMessages;
 
        xmlHttpGetMessages.send(params);
      }
      else
      {
        // sprawdza ponownie czy są nowe wiadomości
        setTimeout("requestNewMessages();", updateInterval);
      }
    }
    catch(e)
    {
      displayError(e.toString());
    }
  }
}

/* funkcja obsługująca odpowiedź HTTP podczas aktualizacji wiadomości*/
function handleReceivingMessages() 
{
  // kontynuuje jeśli proces jest zakończony
  if (xmlHttpGetMessages.readyState == 4) 
  {
    // kontynuuje, jeśli status HTTP ma wartość "OK"
    if (xmlHttpGetMessages.status == 200) 
    {
      try
      {
        // przetwarza odpowiedź serwera
        readMessages();
      }
      catch(e)
      {
        // wyświetla wiadomość o błędzie
        displayError(e.toString());
      }
    } 
    else
    {
      // wyświetla wiadomość o błędzie
      displayError(xmlHttpGetMessages.statusText);
    }
  }
}

/* funkcja obsługująca odpowiedź serwera podczas aktualizacji wiadomości*/
function readMessages()
{  
  // pobiera odpowiedź serwera
  var response = xmlHttpGetMessages.responseText;
  // błąd serwera?
  if (response.indexOf("ERRNO") >= 0 
      || response.indexOf("błąd:") >= 0
      || response.length == 0)
    throw(response.length == 0 ? "Pusta odpowiedź serwera." : response);
  // pobiera element dokumentu
  response = xmlHttpGetMessages.responseXML.documentElement;
  // pobiera flagę określającą czy okno rozmowy zostało wyczyszczone czy nie
  clearChat = 
           response.getElementsByTagName("clear").item(0).firstChild.data;
  // jeśli flaga ma wartość true, trzeba wyczyścić okno wiadomości
  if(clearChat == "true")
  {
    // czyści okno wiadomości i zeruje id
    document.getElementById("scroll").innerHTML = "";
    lastMessageID = -1;
 
  }
  // pobiera tablice z odpowiedzi serwera
  idArray = response.getElementsByTagName("id");
  nameArray = response.getElementsByTagName("name");
  timeArray = response.getElementsByTagName("time");
  messageArray = response.getElementsByTagName("message");
  // dodaje nową wiadomość do okna rozmowy
  displayMessages(idArray, nameArray, timeArray, messageArray);
  // przechowuje lokalnie ID ostatniej otrzymanej wiadomości
  if(idArray.length>0)
    lastMessageID = idArray.item(idArray.length - 1).firstChild.data;
  // ponownie uruchamia sekwencję
  setTimeout("requestNewMessages();", updateInterval);
}

/* funkcja dodająca nowe wiadomości do okna rozmowy */
function displayMessages(idArray, nameArray, timeArray, messageArray)
{
  // każdy przebieg pętli dodaje nową wiadomość
  for(var i=0; i<idArray.length; i++)
  {
    // pobiera szczegóły wiadomości
    var time = timeArray.item(i).firstChild.data.toString();
    var name = nameArray.item(i).firstChild.data.toString();
    var message = messageArray.item(i).firstChild.data.toString();
    // tworzy kod HTML, który wyświetli wiadomość
    var htmlMessage = "";
    htmlMessage += "<div class=\"item\">"; 
    htmlMessage += "[" + time + "] " + name + ": <span style=\"color:#000000\">";
    htmlMessage += message.toString();
    htmlMessage += "</span></div>";
    // wyświetla wiadomość
    displayMessage (htmlMessage);
  }
}
// wyświetla wiadomość
function displayMessage(message)
{
  // pobiera obiekt scroll
  var oScroll = document.getElementById("scroll");
  // sprawdza, czy pasek jest przewinięty
  var scrollDown = (oScroll.scrollHeight - oScroll.scrollTop <= 
                    oScroll.offsetHeight );
  // wyświetla wiadomość
  oScroll.innerHTML += message;
  // przewija na dół pasek przewijania
  oScroll.scrollTop = scrollDown ? oScroll.scrollHeight : oScroll.scrollTop;
}

// funkcja wyświetlająca komunikat o błędzie
function displayError(message)
{
  // wyświetla wiadomość o błędzie ze szczegółami technicznymi, jeśli debugMode ma ustawienie true
  displayMessage("Błąd podczas dostępu do serwera! "+
    (debugMode ? "<br/>" + message : ""));
}
/*obsługuje zdarzenie keydown aby określić, kiedy wciśnięto Enter*/ 
function handleKey(e) 
{
  // pobiera zdarzenie
  e = (!e) ? window.event : e;
  // pobiera kod wciśniętego znaku
  code = (e.charCode) ? e.charCode : ((e.keyCode) ? e.keyCode :
    ((e.which) ? e.which : 0));
  // obsługuje zdarzenie keydown
  if (e.type == "keydown") 
  {
    // jeśli został wciśnięty Enter (kod 13) 
    if(code == 13)
    {
      // wysyła bieżącą wiadomość
      sendMessage();
    }
  }
}
/* usuwa spacje z początku i końca łańcucha*/
function trim(s)
{
    return s.replace(/(^\s+)|(\s+$)/g, "")
}

/* funkcja, która oblicza współrzędne kursora na stronie*/
function getMouseXY(e) 
{
  // specyficzne dla przeglądarki 
  if(window.ActiveXObject)
  {
    mouseX = window.event.x + document.body.scrollLeft;
    mouseY = window.event.y + document.body.scrollTop;    
  }
  else
  {
    mouseX = e.pageX;
    mouseY = e.pageY;
  }
}