// make a global movies variable so we can use it elsewhere
var g_movieArrays = new Array;
var g_movies;
var EXPANDED_HEIGHT = 250;
var LINE_HEIGHT = 32;

var g_guessObj;

// default guess object for the index page
// this object gets reassigned on the quiz page
var g_guessObj = {
  // a no-op
  getId : function (label) {
    return label;
  }
}

function ajaxLookupMovie(e)
{
  // first send the main wtf data via AJAX so that the parent
  // record can be there by the time the oekaki applet wants to
  // add items
  var xmlhttp = new XMLHttpRequest();

  f = xGetElementById(g_guessObj.getId("textMovie"));

  // append date to the query so stupid IE doesn't cache
  var dt = new Date();
  var qs = "title=" + f.value + "&d=" + escape(dt.getTime());
  xmlhttp.open('GET', 'lookup_movie.php?' + qs, true);

  xmlhttp.onreadystatechange = function() {
    var ul;
    if (xmlhttp.readyState == 4) {
      //alert(new XMLSerializer().serializeToString(xmlhttp.responseXML));
      g_movies = xmlhttp.responseXML.getElementsByTagName("movie");
      f = xGetElementById(g_guessObj.getId("textMovie"));
      id = xGetElementById(g_guessObj.getId("hiddenMovieId"));

      // we're counting on movie nodes having title and id in all cases
      ret = "";
      d = xGetElementById(g_guessObj.getId("titleList"));

      // clear the status
      setStatus("");

      // No result
      if (g_movies.length < 1) {
	setStatus("No movies match your search. Try again.");
	return;
      }

      var b_exactMatch = false;
      for (var i = 0; i < g_movies.length; i++) {
	// if there's an exact match make note of it
	if (g_movies[i].getAttributeNode("score").nodeValue == 1000) {
	  b_exactMatch = true;
	}

	// we put the first hit right into the text search box
	if (i == 0) {
	  f.value = unescape(g_movies[i].getAttributeNode("title").nodeValue);
	  id.value = g_movies[i].getAttributeNode("id").nodeValue;

	  if (g_movies[i].getAttributeNode("year").nodeValue != "") {
	    f.value += " (" + g_movies[i].getAttributeNode("year").nodeValue + ")";
	  }
	  // set the text green
	  f.className = "searchBoxValid textMovieWidth";

	  // color the button and change its text to answer mode
	  but = xGetElementById(g_guessObj.getId(g_saveOrGuessButtonId));
	  but.className = "searchFindButtonValid";
	  but.value = g_answerText;

	  // it'll always be enabled for searching but on creation
	  // we need to toggle it back and forth
	  but.disabled = false;
	}
	// if there is more than one result we make a list
	// and even include the first hit in the list
	if (g_movies.length > 1) {
	  if (i == 0) {
	    ul = document.createElement("ul");
	    att = document.createAttribute("id");
	    ul.setAttributeNode(att);
	    ul.setAttribute("id", g_guessObj.getId("resultlist"));
	  }

	  data = unescape(g_movies[i].getAttributeNode("title").nodeValue);
	  if (g_movies[i].getAttributeNode("year").nodeValue != "") {
	    data += " (" + g_movies[i].getAttributeNode("year").nodeValue + ")";
	  }
	  // make the a tag
	  var a = document.createElement("a");
	  att = document.createAttribute("href");
	  a.setAttributeNode(att);
	  a.setAttribute("href", g_movies[i].getAttributeNode("id").nodeValue, 0);

	  // name them all the same
	  att = document.createAttribute("name");
	  a.setAttributeNode(att);
	  a.setAttribute("name", "movie_result", 0);
	  
	  att = document.createAttribute("id");
	  a.setAttributeNode(att);
	  a.setAttribute("id", g_guessObj.getId(g_movies[i].getAttributeNode("id").nodeValue), 0);
	  //a.setAttribute("id", g_movies[i].getAttributeNode("id").nodeValue, 0);

	  // set the on click event handler
	  //a.onclick = movieListClick;
	  xAddEventListener(a, "click", onMovieListClick);

	  a.appendChild(document.createTextNode(data));
	  
	  // build the list item
	  li = document.createElement("li");

	  // attach the text to it
	  //li.appendChild(document.createTextNode(data));
	  li.appendChild(a);

	  // and attach it to the list
	  ul.appendChild(li);
	}
      }

      // change the button back to Find
      // it's only there on create
      save = xGetElementById(g_guessObj.getId(g_saveOrGuessButtonId));
      if (save) {
	save.disabled = false;
	save.value = g_answerText;
      }
      if (ul) {
	d.appendChild(ul);
      }

      // if there's an exact match hide the list
      if (b_exactMatch && g_movies.length > 1) {
	ul.style.visibility = "hidden";
	ul.style.display = "none";
      }

      // possible match results
      // zero matches are reported above with short circuit
      if (b_exactMatch) {
	if (g_movies.length > 1) {
	  var expandLinkId = g_guessObj.getId("expandLink");
	  setStatus("One exact match and <a href=\"\" id=\"" + expandLinkId + "\">" + 
		     (g_movies.length - 1) + " partial matches (show...)</a>");

	  xAddEventListener(g_guessObj.getId("expandLink"), "click", function(e) { 
	    // already hidden so we'll be opening
	    if (ul.style.visibility == "hidden") {
	      ul.style.visibility = "visible";
	      ul.style.display = "block";
	      
	      // let's just force it to EXPANDED_HEIGHT
	      // this makes it go to the bottom, as it exceeds
	      var h = xHeight(ul) > EXPANDED_HEIGHT ? EXPANDED_HEIGHT : xHeight(ul) + 25;
	      xHeight(g_guessObj.getId("titleList"), h);
	    }
	    // showing, so we're hiding on this event
	    else {
	      ul.style.visibility = "hidden";
	      ul.style.display = "none";
	      xHeight(g_guessObj.getId("titleList"), 0);
	    }
	    xStopPropagation(e);
	    xPreventDefault(e);
	  });
	}	
	else
	  setStatus("One exact match");
      }
      else if (g_movies.length > 0) {
	setStatus(g_movies.length + " partial matches");
	var h = xHeight(ul) > EXPANDED_HEIGHT ? EXPANDED_HEIGHT : xHeight(ul) + 25;
	xHeight(g_guessObj.getId("titleList"), h);
      }
      
      // disable the find button on the draw page
      if (g_drawPage) {
	var f = xGetElementById(g_guessObj.getId("buttonFind"));
	f.disabled = true;
      }
      // otherwise give focus to the answer button on guessing
      else {
	var aBut = xGetElementById(g_guessObj.getId(g_saveOrGuessButtonId));
	aBut.focus();
      }
    }
  }

  // send the request asynchronously
  xmlhttp.send(null);

  // clear the div
  clearNodeById(g_guessObj.getId("titleList"));
  xHeight(g_guessObj.getId("titleList"), 0);

  // clear the status
  setStatus("");

  s = xGetElementById(g_guessObj.getId("statusLine"));
  //s.firstChild.nodeValue = "Looking...";
  s.appendChild(document.createTextNode("Looking..."));
}

// this wipes out all nodes underneath a given node
function clearNodeById(n_id) {
  n = xGetElementById(n_id);
  if (n.hasChildNodes()) {
    for (var i = n.childNodes.length - 1; i >= 0;  i--) {
      n.removeChild(n.childNodes[i]);
    }
  }
}

function buildQueryFromForm(f) {
  var ret = "";
  for (var i = 0; i < f.elements.length; i++) {
    if (f.elements[i].type == 'checkbox') {
      if (f.elements[i].checked) {
	ret += f.elements[i].name + "=" + escape(f.elements[i].value);
      }
    }
    else {
      ret += f.elements[i].name + "=" + escape(f.elements[i].value);
    }
    
    if (i < f.elements.length - 1) 
      ret += "&";
  }
  return ret;
}

// using innerHTML because we want to build links
// without going super DOM crazy
function setStatus(html) {
  s = xGetElementById(g_guessObj.getId("statusLine"));

  s.innerHTML = html;
}

function onSearchWtfSubmit(e) {
  ajaxLookupMovie(e);
  xStopPropagation(e);
  xPreventDefault(e);

  return false;
}

// handle when the user clicks on a movie title from the 
// alternate list. Change the hidden variable and populate
// the text bar.
function onMovieListClick(e) {
  xStopPropagation(e);
  xPreventDefault(e);

  ev = new xEvent(e);

  // parse off the id if there happens to be a trailing _<num>
  var id_num = ev.target.id.match(/(\d+)_?(\d*)/);

  // if this comes from a quiz there will be a number at the end
  var q_num = "";
  if (id_num[2]) {
    q_num = "_" + id_num[2];

    // this'll make other things realize we've focused on a new question
    activateQuestion(id_num[2]);
  }

  t = xGetElementById(g_guessObj.getId("textMovie"));
  id = xGetElementById(g_guessObj.getId("hiddenMovieId"));
  
  // set the id to the movie id (without the _<qnum> part)
  id.value = id_num[1];

  // this gets the element in the list
  t.value = ev.target.firstChild.nodeValue;

  // close out the list
  // put this link in the expand span
  //  clearNodeById("expandSpan");
  xHeight("titleList" + q_num, 0);

  setStatus("");

  return true;
}

// to set the color of text back to black
function onTextMovieKeypress(e) {
  xe = new xEvent(e);

  // do this check to prevent arrow keys from changing things
  if (xe.keyCode >= 46 || xe.keyCode == 8) {
    xe.target.className = "searchBox textMovieWidth";
    id = xGetElementById(g_guessObj.getId("hiddenMovieId"));
    save = xGetElementById(g_guessObj.getId(g_saveOrGuessButtonId));

    // if the inputbox is changed we should flag it so
    // we make sure the movie is good
    id.value = 0;

    if (save) {
      // set back to normal
      save.className = "searchFindButton";
      save.value = g_findText;
      if (g_drawPage) {
	// disable the save button
	save.disabled = true;

	// enable the find button
	var f = xGetElementById(g_guessObj.getId("buttonFind"));
	f.disabled = false;
      }
    }
  }

  return true;
}

// Handles both general guesses and quiz guesses
// Quiz guesses are still recorded as general guesses
// to feed the difficulty statistics
function ajaxCheckGuess(quizId, questionNum)
{
  f = xGetElementById(g_guessObj.getId("hiddenMovieId"));

  // if the guessed id matches the correct id return right away
  if (f.value == g_ccid) {
    interfaceRight();
  }
  // if it's wrong, show the wrong box and...
  else {
    interfaceWrong();

    // ...go on to get the movie name and year from another ajax request
    var xmlhttp = new XMLHttpRequest();

    // append date to the query so stupid IE doesn't cache
    var dt = new Date();
    var qs = "id=" + g_ccid + "&d=" + escape(dt.getTime());
    xmlhttp.open('GET', 'lookup_movie.php?' + qs, true);
    
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4) {
	var movies = xmlhttp.responseXML.getElementsByTagName("movie");
	var ca = xGetElementById(g_guessObj.getId("correctAnswer"));
	ca.innerHTML = "<a href=\"/movie.php?id=" + movies[0].getAttributeNode("id").nodeValue + "\">" +
          unescape(movies[0].getAttributeNode("title").nodeValue) + " (" +
          movies[0].getAttributeNode("year").nodeValue + ")</a> ";
      }
    }
    // send the request asynchronously
    xmlhttp.send(null);
  }
  // in both cases we want to record the guess
  var xmlhttp2 = new XMLHttpRequest();

  // append date to the query so stupid IE doesn't cache
  // we don't need to handle the result because we don't need
  // to show anything
  var dt = new Date();
  var qs = "wtfId=" + g_wtfId + "&guessId=" + f.value + "&d=" + escape(dt.getTime());

  // we pass two extra vars for quizzes 
  // we'll probably need to record results in a JS datastructure here
  // for an overall score on the page
  if (quizId && questionNum)
    qs += "&quizId=" + quizId + "&questionNum=" + questionNum;

  xmlhttp2.open('GET', 'check_guess.php?' + qs, true);
  xmlhttp2.send(null);
}

function ajaxSendRating(wtfId, rating)
{
  var xmlhttp = new XMLHttpRequest();

  // append date to the query so stupid IE doesn't cache
  var dt = new Date();
  var qs = "wtfId=" + wtfId + "&rating=" + rating + "&d=" + escape(dt.getTime());

  xmlhttp.open('GET', 'rate.php?' + qs, true);

  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4) {
      var status = xmlhttp.responseXML.getElementsByTagName("status");
      //var isChanged = status[0].getAttributeNode("changed").nodeValue;
      var rating = status[0].getAttributeNode("rating").nodeValue;
      
    }
  }
  // send the request asynchronously
  xmlhttp.send(null);

  // update the new rating by setting the star global
  for (var i = 1; i <= 5; i++) {
    s = xGetElementById(g_guessObj.getId("star_" +  i));
    if (i <= rating) {
        g_origImgSrcs[i - 1] = "/images/rating_hover.gif";
    }
    else {
        g_origImgSrcs[i - 1] = "/images/rating_off.gif";
    }
  }
  
  // refresh
  for (var i = 1; i <= 5; i++) {
    s = xGetElementById(g_guessObj.getId("star_" + i));
    s.childNodes[0].src = g_origImgSrcs[i - 1];
  }

  // set the focus on the "next" link
  // mostly to get it off a star
  s = xGetElementById(g_guessObj.getId("aNextOne"));
  if (s) {
    s.focus();
  }
}

/* Cookie Handlers to write, read and delete cookies */
function createCookie(name,value,days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else var expires = "";
  document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i=0;i < ca.length;i++) {
    var c = ca[i];
    while (c.charAt(0)==' ') c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
  }
  return null;
}

function eraseCookie(name) {
  createCookie(name,"",-1);
}
/* end cookie handlers */
