/*                                                                      *
 * Pixelate - Copyright (c) 2007-2009 - planzero.org                    *
 * See LICENCE for licence information. Check planzero.org for updates! *
 *                                                                      */

// Uncomment the following line if you want to see debugging info through the Firebug Firefox add-on
//debug=true;

// Fallback in case debug is enabled, and the Firebug console isn't there
if (typeof(console)=='undefined') debug=undefined;

// Global variables available to all functions
var xmlHttp;
var a, s, x, y;

// Our simple mutex. I'm using the term loosly; don't write in ;-)
var busy=false;


// This is the initial function that is called when the user clicks
// on a pixel to toggle its value
function toggle_pixel(_s, _x, _y, c) {

  // Set the <a href..> object reference (_locally)
  _a=document.getElementById('p:' +_x + ':' + _y);

  // Set the pixel class to state 1 to show that it has been clicked on
  _a.className='pixel_state_1';

  // Check to see whether our mutex is free
  if (busy==false) {

    // Set the mutex to busy
    busy=true;
    if (typeof(debug)!='undefined') console.debug('Mutex enabled for ' + _x + ':' + _y + '.');

    // Move the local parameters over to the global variables
    a=_a;
    s=_s;
    x=_x;
    y=_y;

    // Call the real toggle pixel function
    toggle_pixel_real();

  } else {

    if (typeof(c)=='undefined') c=0;

    // If we've looped 300 times (60 seconds), timeout and set the pixel error state
    if (c>=300) {
      return toggle_pixel_error(_a, 'Timeout waiting for mutex to become free.');
    } else {
      // Wait 200ms, then see whether pixelate is still busy
      setTimeout('toggle_pixel("' + _s + '", ' + _x + ', ' + _y + ', ' + ++c + ')', 200);
    }
  }

}


// This function actually toggles the pixel on or off
function toggle_pixel_real() {

  // Initiate the xmlHttp object
  xmlHttp=xmlinit();

  if (typeof(debug)!='undefined') console.debug('toggle_pixel_real() called.');

  // Initiate the connection to the server to toggle the pixel
  try {
    geturl="pixelate.php?s=" + s + "&x=" + x + '&y=' + y + '&z=1';
    if (typeof(debug)!='undefined') console.debug('Calling: ' + geturl);
    xmlHttp.open("GET", geturl, true);
    xmlHttp.onreadystatechange=handlestatechange;
    //xmlHttp.onreadystatechange=function() { handlestatechange(c, a, s, x, y) };
    xmlHttp.send(null);

  }
  // Couldn't connect to server
  catch(e) {
    return toggle_pixel_error(a, 'Couldn\'t connect to server:\n' + e.toString());
  }

}



function handlestatechange() {

  // xmlHttp.readyState
  // 1 = send() has not been called yet
  // 2 = send() has been called, headers and status are available
  // 3 = Downloading, responseText holds the partial data
  // 4 = Finished all operations

  // This should never happen..
  if (typeof(xmlHttp)=='undefined') {
    return toggle_pixel_error(a, 'xmlHttp is not defined.');
  }

  if (typeof(debug)!='undefined') {
    console.debug('xmlHttp.readyState is now: ' + xmlHttp.readyState);
  }
 
  a.className='pixel_state_' + xmlHttp.readyState;

  if (xmlHttp.readyState==4) {

    if (xmlHttp.status==200) {
      // Everything went okay, start processing the returned data
      handle_response(xmlHttp.responseXML);
      // Drop out of the script here (this is the final exit point)
      return false;
    } else {
      // Something went wrong, raise an error
      return toggle_pixel_error(a, 'A server error occured processing the toggle request:\n' + '[' + xmlHttp.status + '] ' + xmlHttp.statusText);
    }

  }

}


function handle_response(responseXML) {

  // Check the validity of the XML response
  if (responseXML==null || responseXML.length==0 ||
      responseXML.getElementsByTagName('pixel').length==0 ||
      responseXML.getElementsByTagName('pixel').item(0).firstChild==null ||
      (responseXML.getElementsByTagName('pixel').item(0).firstChild.data=='false' &&
      (responseXML.getElementsByTagName('error').length==0 || 
       responseXML.getElementsByTagName('error').item(0).firstChild==null))) {
    return toggle_pixel_error(a, 'A malformed XML response was received.');
  }

  // Check the XML data to see whether an error was returned
  var root=responseXML.documentElement;
  var pixel=root.getElementsByTagName('pixel');
  var error=root.getElementsByTagName('error');

  if (pixel.item(0).firstChild.data=='false') {
    return toggle_pixel_error(a, 'Error: ' + error.item(0).firstChild.data);
  }

  a.className=(s=='on') ? 'pixel_on' : '';

  a.setAttribute('onclick', 'toggle_pixel(\'' + ((s=='on') ? 'off' : 'on') + '\',' + x + ',' + y + '); return false');
  a.setAttribute('href', '?s=' + ((s=='on') ? 'off' : 'on') + '&x=' + x + '&y=' + y);

  // We've finished, release the mutex
  if (typeof(debug)!='undefined') console.debug('Mutex released for ' + x + ':' + y + '.');
  busy=false;

}


// Handle errors toggling pixels
function toggle_pixel_error(_a, errmsg) {
  _a.className='pixel_state_error';
  _a.setAttribute('title', errmsg);
  if (typeof(debug)!='undefined') console.error(errmsg);
  busy=false;  // This could cause pixels to get stuck in certain circumstances :'(
  return false;
}

// XML initialisation function
function xmlinit() {

  var xmlHttp;

  try {
    xmlHttp=new XMLHttpRequest();
  }
  catch(e) {
    var xmlHttpVersions=new Array('MSXML2.XMLHTTP.7.0',
                                  'MSXML2.XMLHTTP.6.0',
                                  'MSXML2.XMLHTTP.5.0',
                                  'MSXML2.XMLHTTP.4.0',
                                  'MSXML2.XMLHTTP.3.0',
                                  'MSXML2.XMLHTTP',
                                  'Microsoft.XMLHTTP');
    for (var i=0; i<xmlHttpVersions.length && !xmlHttp; i++) {
      try {
        xmlHttp=new ActiveXObject(xmlHttpVersions[i]);
      }
      catch(e) { }
    }
  }

  if (!xmlHttp) {
    errmsg='Error creating XMLHttpRequest object!';
    if (typeof(debug)!='undefined') console.error(errmsg);
    alert(errmsg);
  } else {
    if(typeof(debug)!='undefined') console.info('XMLHttpRequest object created');
    return xmlHttp;
  }

}

