// holds an instance of XMLHttpRequest
var xmlHttp = createXmlHttpRequestObject();

// when set to true, display detailed error messages
var showErrors = true;

// initialize the requests cache 
var cache = new Array();
var tab_index;
var tab_values = new Array();
  
function toggle_item_status(item)
{
	var e = document.getElementById(item);
	var t = document.getElementById('text'+item)
	var exp = document.getElementById('expand'+item);
	if(e.src.match(/box_unchecked/))
	{
		e.src = e.src.replace(/box_unchecked/, 'box_checked');
		t.className = t.className+' strike';
		exp.className = exp.className+' strike';
	}
	else
	{
		e.src = e.src.replace(/box_checked/, 'box_unchecked');
		t.className = t.className.replace(/strike/,'');
		exp.className = exp.className.replace(/strike/,'');
	}
}

function get_importance_text(item)
{
	var exp = document.getElementById('expand'+item);
	return exp.className.match(/(low|normal|high)/)[0];
}

function get_importance_index(item)
{
	var imp_levels = new Array("low" , "normal", "high");
	return imp_levels.indexOf(get_importance_text(item));
}

function inc_importance(item)
{
	var imp_levels = new Array("low" , "normal", "high");
	var t = document.getElementById('text'+item);
	var exp = document.getElementById('expand'+item);
	var importance = exp.className.match(/(low|normal|high)/)[0];
	var i = imp_levels.indexOf(importance);
	if(++i > 2)
		i = 0;
	t.className = t.className.replace(/(low|normal|high)/,imp_levels[i]);
	exp.className = exp.className.replace(/(low|normal|high)/,imp_levels[i]);
}

// creates an XMLHttpRequest instance
function createXmlHttpRequestObject() 
{
  // will store the reference to the XMLHttpRequest object
  var xmlHttp;
  // this should work for all browsers except IE6 and older
  try
  {
    // try to create XMLHttpRequest object
    xmlHttp = new XMLHttpRequest();
  }
  catch(e)
  {
    // assume IE6 or older
    var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
                                    "MSXML2.XMLHTTP.5.0",
                                    "MSXML2.XMLHTTP.4.0",
                                    "MSXML2.XMLHTTP.3.0",
                                    "MSXML2.XMLHTTP",
                                    "Microsoft.XMLHTTP");
    // try every prog id until one works
    for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++) 
    {
      try 
      { 
        // try to create XMLHttpRequest object
        xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
      } 
      catch (e) {} // ignore potential error
    }
  }
  
	// return the created object or display an error message
  if (!xmlHttp)
    alert("Error creating the XMLHttpRequest object.");
  else 
    return xmlHttp;
}

// function that displays an error message
function displayError($message)
{
  // ignore errors if showErrors is false
  if (showErrors)
  {
    // turn error displaying Off
    showErrors = false;
		
    // display error message
    alert("Error encountered: \n" + $message);
 
  }
}

function get_list_count()
{
	thisOne = $('thetabs');
	items = thisOne.getElementsByClassName("label");
	return items.length;
}

// Scriptaculous-specific code to define a sortable list and a drop zone
function startup()
{
	
  // Transform an unordered list into a sortable list with draggable items
  //Sortable.create("thetabs",{dropOnEmpty:true,handle:'handle',constraint:false});
  Sortable.create("thelist",
  {
  	dropOnEmpty:true,handle:'handle',constraint:false,
  	onUpdate:function(sortable)
  	{
  		var order = Sortable.serialize(sortable);
  		order = order.replace(/(thelist|\[\]\=)/g,'');
  		order = order.replace(/&/g,',');
  		process(sortable.id, "update_list", order);
  	}
  });

  // Define a drop zone used for deleting tasks
  Droppables.add("trash", 
  {
    onDrop: function(element) 
    {
      process(element.id, "confirm_delete_item");
    }
  });
  
  // Define a drop zone for each list (or "Tab")
  // Skip the first tab or "Active" list since this would be moving to the same list
  for(tab_index = 0; tab_index < get_list_count(); tab_index++)
  	tab_values[tab_index] = $('thetabs_thetabs'+tab_index).value;
  	
  for(tab_index = 0; tab_index < get_list_count(); tab_index++)
  {  	  	
  	if(tab_index > 0)
  	{
  		var id = 'thetabs_thetabs'+tab_index;
  		// 	PHP code generator
  		// 	This is a temporary solution until I can determine why only tab_values[] will work with a constant value.
  		//	This limits the number of lists (or tabs) to 100
  		//	for($i = 0; $i < 100; $i++)
			//		echo "case $i: Droppables.add(id, { onDrop: function(element) { process(element.id, \"confirm_move_item\", tab_values[$i]) } }); break;\n";
  		switch(tab_index)
  		{
  			case 1: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[1]) } }); break;
  			case 2: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[2]) } }); break;
				case 3: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[3]) } }); break;
				case 4: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[4]) } }); break;
				case 5: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[5]) } }); break;
				case 6: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[6]) } }); break;
				case 7: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[7]) } }); break;
				case 8: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[8]) } }); break;
				case 9: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[9]) } }); break;
				case 10: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[10]) } }); break;
				case 11: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[11]) } }); break;
				case 12: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[12]) } }); break;
				case 13: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[13]) } }); break;
				case 14: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[14]) } }); break;
				case 15: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[15]) } }); break;
				case 16: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[16]) } }); break;
				case 17: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[17]) } }); break;
				case 18: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[18]) } }); break;
				case 19: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[19]) } }); break;
				case 20: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[20]) } }); break;
				case 21: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[21]) } }); break;
				case 22: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[22]) } }); break;
				case 23: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[23]) } }); break;
				case 24: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[24]) } }); break;
				case 25: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[25]) } }); break;
				case 26: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[26]) } }); break;
				case 27: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[27]) } }); break;
				case 28: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[28]) } }); break;
				case 29: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[29]) } }); break;
				case 30: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[30]) } }); break;
				case 31: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[31]) } }); break;
				case 32: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[32]) } }); break;
				case 33: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[33]) } }); break;
				case 34: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[34]) } }); break;
				case 35: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[35]) } }); break;
				case 36: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[36]) } }); break;
				case 37: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[37]) } }); break;
				case 38: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[38]) } }); break;
				case 39: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[39]) } }); break;
				case 40: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[40]) } }); break;
				case 41: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[41]) } }); break;
				case 42: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[42]) } }); break;
				case 43: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[43]) } }); break;
				case 44: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[44]) } }); break;
				case 45: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[45]) } }); break;
				case 46: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[46]) } }); break;
				case 47: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[47]) } }); break;
				case 48: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[48]) } }); break;
				case 49: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[49]) } }); break;
				case 50: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[50]) } }); break;
				case 51: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[51]) } }); break;
				case 52: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[52]) } }); break;
				case 53: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[53]) } }); break;
				case 54: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[54]) } }); break;
				case 55: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[55]) } }); break;
				case 56: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[56]) } }); break;
				case 57: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[57]) } }); break;
				case 58: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[58]) } }); break;
				case 59: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[59]) } }); break;
				case 60: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[60]) } }); break;
				case 61: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[61]) } }); break;
				case 62: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[62]) } }); break;
				case 63: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[63]) } }); break;
				case 64: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[64]) } }); break;
				case 65: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[65]) } }); break;
				case 66: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[66]) } }); break;
				case 67: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[67]) } }); break;
				case 68: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[68]) } }); break;
				case 69: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[69]) } }); break;
				case 70: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[70]) } }); break;
				case 71: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[71]) } }); break;
				case 72: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[72]) } }); break;
				case 73: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[73]) } }); break;
				case 74: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[74]) } }); break;
				case 75: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[75]) } }); break;
				case 76: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[76]) } }); break;
				case 77: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[77]) } }); break;
				case 78: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[78]) } }); break;
				case 79: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[79]) } }); break;
				case 80: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[80]) } }); break;
				case 81: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[81]) } }); break;
				case 82: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[82]) } }); break;
				case 83: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[83]) } }); break;
				case 84: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[84]) } }); break;
				case 85: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[85]) } }); break;
				case 86: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[86]) } }); break;
				case 87: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[87]) } }); break;
				case 88: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[88]) } }); break;
				case 89: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[89]) } }); break;
				case 90: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[90]) } }); break;
				case 91: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[91]) } }); break;
				case 92: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[92]) } }); break;
				case 93: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[93]) } }); break;
				case 94: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[94]) } }); break;
				case 95: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[95]) } }); break;
				case 96: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[96]) } }); break;
				case 97: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[97]) } }); break;
				case 98: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[98]) } }); break;
				case 99: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[99]) } }); break;  			
				case 100: Droppables.add(id, { onDrop: function(element) { process(element.id, "confirm_move_item", tab_values[100]) } }); break;  			
  		}
  	} 
  }	
}

// Send request to server
function process(content, action, arguments)
{
  // only continue if xmlHttp isn't void
  if (xmlHttp)
  {
    // initialize the request query string to empty string 
    params = "";
  
		// escape the values to be safely sent to the server 
    content = encodeURIComponent(content);
    arguments = encodeURIComponent(arguments);
    
		// send different parameters depending on action
		switch(action)
		{
			case 'clicked_tab':
				params = "?content=" + content + "&action=clicked_tab&list_id="+content;
				break;
			/*	
			case 'delete_checked':
				var answer = prompt("Are you sure you want to delete ALL checked items in this list?", "Type \"yes\" to confirm.");
				if(answer.toUpperCase() == 'YES')
					params = "?content=" + content + "&action=delete_checked&list_id="+content;
				break;
			*/
			case 'update_list':
				params = "?content=" + content + "&action=update_list&order="+arguments;
				break;
			case 'update_item':
				params = "?content=" + arguments + "&action=update_item&item="+content;
				break;
			case '*new_item':
				var s = content;
				var item_id = s.replace(/thelist\_thelist/, "");
    		var the_list = document.getElementById('the_list');
  			var the_list_new = document.createElement('option');
    		the_list_new.text = content;
    		var the_list_old = the_list.options[the_list.selectedIndex];  
    		try {
   				the_list.add(the_list_new, null); // standards compliant; doesn't work in IE
  			}
  			catch(ex) {
    			the_list.add(the_list_new); // IE only
  			}    		
      	params = "?content=" + content + "&action=new_item&list_id="+list_id+"&item="+item_id;
      	break;
			case 'confirm_delete_item':
				var deleteTask = confirm("Are you sure you want to delete this item?")
      	if(!deleteTask)
      		break;
      case 'delete_item':
      	var s = content;
    		var item_id = s.replace(/thelist\_thelist/, "");
    		Element.hide('thelist_thelist'+item_id);
      	params = "?content=" + content + "&action=delete_item&item="+item_id;
      	break;
      case 'confirm_move_item':      	
				//var moveTask = confirm("Are you sure you want to move this item?")
      	//if(!moveTask)
      	//	break;
      case 'move_item':
      	var s = content;
      	var item_id = s.replace(/thelist\_thelist/, "");
    		Element.hide('thelist_thelist'+item_id);
      	params = "?content=" + content + "&action=move_item&item="+item_id+"&list_id="+arguments;
      	//alert(params);
      	break;
      case 'inc_importance':
     	 	var s = content;
     	 	var item_id = s.replace(/thelist\_thelist/, "");
    		var importance = get_importance_index(item_id);
      	params = "?content=" + content + "&action=set_importance&item="+item_id+"&importance="+importance;
      	break;
      case 'toggle_status':
      	var s = content;
      	var item_id = s.replace(/thelist\_thelist/, "");
      	params = "?content=" + content + "&action=toggle_status&item="+item_id;
      	break;
		}
		
    // don't add null params to cache            
    if(params) cache.push(params);

    // try to connect to the server
    try
    {
      // only continue if the connection is clear and cache is not empty
      if ((xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
           && cache.length>0)
      {
        // get next set of values from cache
        var cacheEntry = cache.shift();
        // initiate the request
        xmlHttp.open("GET", "_scripts/ajax.php" + cacheEntry, true);
        xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlHttp.onreadystatechange = handleRequestStateChange;
        xmlHttp.send(null);
      }
      else
      {
        setTimeout("process();", 1000);  
      }
    }
    // display the error in case of failure
    catch (e)
    {
      displayError(e.toString());
    }
  }
}

// function that retrieves the HTTP response
function handleRequestStateChange() 
{
  // when readyState is 4, we also read the server response
  if (xmlHttp.readyState == 4) 
  {
    // continue only if HTTP status is "OK"
    if (xmlHttp.status == 200) 
    {
      try
      {
        postUpdateProcess();
      }
      catch(e)
      {
        // display error message
        displayError(e.toString());
      }
    } 
    else 
    {
      displayError(xmlHttp.statusText);
    }
  }
}
// Processes server's response
function postUpdateProcess()
{
  // read the response
  var response = xmlHttp.responseText;
  // server error?
 
  if (response.indexOf("ERRNO") >= 0 || response.indexOf("error") >= 0)
    alert(response);
		
  // update the tasks list  
  /*
  document.getElementById("tasksList").innerHTML = response;
  Sortable.create("tasksList");
  document.getElementById("txtNewTask").value = "";
  document.getElementById("txtNewTask").focus(); 
  */
} 

/* handles keydown to detect when enter is pressed */
function key_processor(e) 
{
	// get the event
  e = (!e) ? window.event : e;
  // get the code of the character that has been pressed        
  code = (e.charCode) ? e.charCode :
         ((e.keyCode) ? e.keyCode :
         ((e.which) ? e.which : 0));

	var inp = document.getElementById('input_add_item');
	var li = document.getElementById('list_item');
	var log_in = document.getElementById('input_login');
	var edit_item = document.getElementById('input_edit_item');
			         
  // handle the keydown event       
  //if(e.type == "keydown") 
  {
  	if(code == 27)
  	{
  		// document.getElementById('client_input').action = '';
			hide_inputs();
  	}
  	// Don't do this if loggin in
  	else if(log_in.style.display == 'none' && edit_item.style.display == 'none')
  	{
			
	  	if(inp.style.display == 'none' && 
	  			document.getElementById('input_add_list').style.display == 'none' &&
	  			document.getElementById('input_rename_list').style.display == 'none'
	  		)
			{
				hide_inputs(); 
				document.getElementById('action').value='new_item'; 
				inp.style.display ='block'; 
				li.focus();
			}
  	}
  }
}

/* removes leading and trailing spaces from the string */
function trim(s)
{
  return s.replace(/(^\s+)|(\s+$)/g, "")
}
