/* contest-judging image step framework, version 1.0
   allows the contest judges to step through the images in the contest, 
   one at a time, rather than looking at a 12-image contact sheet
   
   expected page format:
   
      pagination nav:
        #first_page, #prev_page, #next_page, #last_page
      
      picks list:
        ol#winning_entries
          li#winning_entry_id
            dl
              dt (title)
              dd ul
                li#winning_item_id
                  a img
                  form
          
      entry list:
        ul#entries
          li#entry_id
            dl
              dt (title)
              dd ul
                li#item_id
                  a img
   
   the primary function is zoom_single_image(item_id) -- and its counterpart, unzoom()
   
   * item_id will generally be of the form 'item_'+id, to avoid collisions 
     if there happens to be an entry with the same id as one of the items
     
   * 'entry_'+id is acceptable as a substitute "item" id:
     in this case, we'll show the first item of the entry
     
   * similarly, 'first' and 'last' are acceptable item_ids, showing the
     appropriate item from the page
     
   * if zoom_single_image is called with a blank item_id, or an item_id that 
     doesn't exist, it will display the first item on the page
   
   
   (c) 2009, NPPA
   written by Stephen Sample
   ------------------------------------------------- */


// allow more useful diagnostics
  function inspect(element) {
    // alert('inspect('+element.id+')');
    var summary = element.id+' (';
    if(typeof(element) === 'object') {
      if(typeof(element.nodeName) !== 'undefined') {
        summary += element.nodeName;
      } else {
        summary += typeof(element);
      }
    } else {
      summary += typeof(element);
    } summary += '): ';
    for(property in element) {
      type = typeof(element.property);
      if(type === 'object') {
        summary += property + ' (';
        if(typeof(element.property.nodeName) !== 'undefined') {
          summary += element.property.nodeName;
        } else {
          summary += type;
        }
        summary += '), ';
      }
    }
    alert(summary); 
  }
  
// compensate for the fact that whitespace in the HTML screws up previousSibling, firstChild, and so on
  function previous_sibling_of(element) {
    // alert("previous_sibling_of("+element.id+")");
    p = element.previousSibling;
    // alert(p.id);
    while (p && p.nodeType !== 1) {
      p = p.previousSibling;
      // alert(p.id);
    } return p;
  }
  
  function next_sibling_of(element) {
    // alert("next_sibling_of("+element.id+")");
    n = element.nextSibling;
    // alert(n.id);
    while (n && n.nodeType !== 1) {
      n = n.nextSibling;
      // alert(n.id);
    } return n;
  }
  
  function first_child_of(element) {
    // alert("first_child_of("+element.id+")");
    var f = element.firstChild;
    while (f && f.nodeType !== 1) {
      f = f.nextSibling;
    } return f;
  }
  
  function last_child_of(element) {
    // alert("last_child_of("+element.id+")");
    var l = element.lastChild;
    while (l && l.nodeType !== 1) {
      l = l.previousSibling;
    } return l;
  }

// get the first and last entries (needed when we call zoom with no item_id)
  
  function get_first_entry() {
    // alert("get_first_entry()");
    var entry_list = document.getElementById("entries");
    var first_entry = first_child_of(entry_list);
    return first_entry;
  }
  
  function get_last_entry() {
    // alert("get_last_entry()");
    var entry_list = document.getElementById("entries");
    var last_entry = last_child_of(entry_list);
    return last_entry;
  }
  

// get the entry info (title, item caption/slug/thumbnail)
  function get_title_of_entry(entry) {
    // alert("get_title_of_entry("+entry.id+")");
    var title = first_child_of(first_child_of(first_child_of(entry))).nodeValue;
    return title;
  }

  function get_first_item_in_entry(entry) {
    // alert("get_first_item_in_entry("+entry.id+")");
    var first_item = first_child_of(first_child_of(next_sibling_of(next_sibling_of(first_child_of(first_child_of(entry))))));
    return first_item;
  }
  
  function get_last_item_in_entry(entry) {
    // alert("get_last_item_in_entry("+entry.id+")");
    var last_item = last_child_of(last_child_of(last_child_of(last_child_of(entry))));
    return last_item;
  }
  
  function get_large_image_url(entry_item) {
    // alert("get_large_image_url("+entry_item.id+")");
    var image_url = first_child_of(entry_item).getAttribute("href");
    // alert(image_url);
    return image_url;
  }

  function get_image_caption(entry_item) {
    // alert("get_image_caption("+entry_item.id+")");
    var image_caption = first_child_of(first_child_of(entry_item)).getAttribute("alt");
    return image_caption;
  }
  
  function get_entry_including_item(entry_item) {
    // alert("get_entry_including_item("+entry_item.id+")");
    // inspect(entry_item);
    var ancestral_entry = entry_item.parentNode.parentNode.parentNode.parentNode;
    // inspect(ancestral_entry);
    return ancestral_entry;
  }
  
  
// get the forward and back links
  function get_previous_page_link() {
    var prev_page = document.getElementById("prev_page");
    if (typeof(prev_page) !== 'undefined' && prev_page) {
      return prev_page.getAttribute("href")+"&itd=last";
    } else {
      return null;
    }
  }
  
  function get_next_page_link() {
    var next_page = document.getElementById("next_page");
    if (typeof(next_page) !== 'undefined' && next_page) {
      return next_page.getAttribute("href")+"&itd=first";
    } else {
      return null;
    }
  }
  
  function get_previous_item_link(entry_item) {
    // alert("get_previous_item_link("+entry_item.id+")");
    // inspect(entry_item);
    
    var link_data_array = [];
    
    var previous_item = previous_sibling_of(entry_item);
    if (previous_item) {
      // alert("previous item exists");
      // inspect(previous_item);
      // return ['<a href="#" onclick="zoom_single_image('+previous_item.getAttribute("id")+')">Previous image</a>', 'item'];
      link_data_array = ['#', "zoom_single_image('"+previous_item.id+"'); return false", 'Previous image', 'item'];
      // alert("array populated");
      return link_data_array;
    } else {
      // alert("no previous item exists: checking for previous entries or pages");
      var ancestral_entry = get_entry_including_item(entry_item);
      // inspect(ancestral_entry);
      var previous_entry = previous_sibling_of(ancestral_entry);
      if(previous_entry) {
        // alert("a previous entry was found");
        // inspect(previous_entry);
        var previous_item = get_last_item_in_entry(previous_entry);
        if(previous_item) {
          // alert("last item in previous entry found");
          // inspect(previous_item);
          // return  ['<a href="#" onclick="zoom_single_image('+previous_item.getAttribute("id")+')">Previous entry</a>', 'entry'];
          link_data_array = ['#', "zoom_single_image('"+previous_item.id+"'); return false", 'Previous entry', 'entry'];
          // alert("array populated");
          return link_data_array;
        } else {
          // alert("the last item could not be found in the previous entry: trying to use the previous page link");
          var previous_page = get_previous_page_link();
          if (previous_page) {
            // alert("a previous page link was found: "+previous_page);
            // return ['<a href="'+previous_page+'">Previous page</a>', 'page'];
            link_data_array = [previous_page, null, 'Previous page', 'page'];
            // alert("array populated");
            return link_data_array;
          } else {
            // alert("no previous page link could be found");
          }
        }
      } else {
        // alert("no previous entry could be found: trying for a previous page link");
        var previous_page = get_previous_page_link();
        if (previous_page) {
          // alert("a previous page link was found: "+previous_page);
          // return ['<a href="'+previous_page+'">Previous page</a>', 'page'];
          link_data_array = [previous_page, null, 'Previous page', 'page'];
          // alert("array populated");
          return link_data_array;
        } else {
          // alert("...but no previous page link could be found");
        }
      }
    }
    return null;
  }
  
  function get_next_item_link(entry_item) {
    // alert("get_next_item_link("+entry_item.id+")");
    // inspect(entry_item);
    
    var link_data_array = [];
    
    var next_item = next_sibling_of(entry_item);
    if (next_item) {
      // alert("next item exists");
      // inspect(next_item);

      // preload the image
      preload_image(next_item);
      
      // define the link
      return ['#', "zoom_single_image('"+next_item.id+"'); return false", 'Next image', 'item'];
    } else {
      var ancestral_entry = get_entry_including_item(entry_item);
      var next_entry = next_sibling_of(ancestral_entry);
      if(next_entry) {
        var next_item = get_first_item_in_entry(next_entry);
        if (next_item) {
          // alert("first item in next entry found");
          
          // preload the image
          preload_image(next_item);
          // define the link
          link_data_array = ['#', "zoom_single_image('"+next_item.id+"'); return false", 'Next entry', 'entry'];
          return link_data_array;
        } else {
          // alert("no next entry found (or no item found in it): trying to use the next page link");
          var next_page = get_next_page_link();
          if (next_page) {
            // alert("a next page link was found: "+next_page);
            
            // return the page link;
            link_data_array = [next_page, null, 'Next page', 'page'];
            return link_data_array;
          } else {
            // alert("no next page link could be found");
          }
        }
      } else {
        // alert("no next entry could be found: trying for a next page link");
        var next_page = get_next_page_link();
        if (next_page) {
          // alert("a next page link was found: "+next_page);

          // return the page link;
          link_data_array = [next_page, null, 'Next page', 'page'];
          return link_data_array;
        } else {
          // alert("...but no next page link could be found");
        }
      }
    }
    return null;
  }
  
  function preload_image(entry_item) {
    var preloaded_image = new Image();
    image_url = get_large_image_url(entry_item);
    preloaded_image.src = image_url;
    return image_url;
  }

  // zoom utilities
  function zoom_single_image(supposed_item_id) {
    // alert("zoom_single_image("+supposed_item_id+")");
    var entry = null; var entry_item = null;
    
    // since there are valid item_ids that aren't really item_ids (like 'first' and 'last'),
    // do some simple pattern-matching to figure out which entry and item to look at
    var item_pattern = /item_(\d+)/i;
    var entry_pattern = /entry_(\d+)/i;
    
    if (item_pattern.test(supposed_item_id)) {
      entry_item = document.getElementById(supposed_item_id);
      entry = get_entry_including_item(entry_item); 
    } else {
      if (entry_pattern.test(supposed_item_id)) {
        // alert("we were passed 'entry_\d+'");
        entry = document.getElementById(supposed_item_id);
      } else if (supposed_item_id === 'last') {
        entry = get_last_entry();
      } else {
        entry = get_first_entry();
      }
      if(entry) {
        entry_item = get_first_item_in_entry(entry);
      }
    }

    // so unless we were given an invalid entry_ or item_id, there should now be valid entry and item
    if (!entry || !entry_item) {
      // alert("entry or entry_item is missing");
      return false;
    } else { // display the image
      var background = document.getElementById("background");
      var zoom_div = document.getElementById("zoom");
      var child_div = document.createElement('div');

      // show UI instructions
      var cth_block = document.createElement('p');
      cth_block.setAttribute('class', 'instructions');
      cth_block.setAttribute('style', 'text-align: center;');
      var cth_link = document.createElement('a');
      cth_link.setAttribute('onclick', 'unzoom(); return false');
      cth_link.setAttribute('href', '#');
      cth_link.innerHTML = '(click the image to return to the multi-image gallery view)';
      cth_block.appendChild(cth_link);
      child_div.appendChild(cth_block);
      // alert("ui note added");
      
      // get the image data
      var image = document.createElement('img');
      image.setAttribute('src', preload_image(entry_item));
      // alert("large image added");
      
      // show the prev and next links
      var nav_link_list = document.createElement('ul');
      nav_link_list.setAttribute('style', 'nav');
      // previous
      var prev_link_block = document.createElement('li');
      prev_link_block.setAttribute('id', 'prev');
      var prev_link = document.createElement('a');
      var prev_link_attrs = get_previous_item_link(entry_item);
      if(prev_link_attrs) {
        // alert('prev link: '+prev_link_attrs.join(', '));
        prev_link.setAttribute('href', prev_link_attrs[0]);
        if(prev_link_attrs[1]) {
          prev_link.setAttribute('onclick', prev_link_attrs[1]);
        } prev_link.innerHTML = prev_link_attrs[2];
        prev_link_block.appendChild(prev_link);
        nav_link_list.appendChild(prev_link_block);
      }
      // pick winner
      var pick_link_block = document.createElement('li');
      var pick_form = document.getElementById('add_'+entry.id.substring(6));
      if(pick_form) {
        pick_link_block.appendChild(pick_form);
      }
      nav_link_list.appendChild(pick_link_block);
      // next
      var next_link_block = document.createElement('li');
      next_link_block.setAttribute('id', 'next');
      var next_link = document.createElement('a');
      var next_link_attrs = get_next_item_link(entry_item);
      if(next_link_attrs) {
        // alert('next link: '+next_link_attrs.join(', '));
        next_link.setAttribute('href', next_link_attrs[0]);
        if(next_link_attrs[1]) {
          next_link.setAttribute('onclick', next_link_attrs[1]);
        } next_link.innerHTML = next_link_attrs[2];
        next_link_block.appendChild(next_link);
        nav_link_list.appendChild(next_link_block);
      }
      // and add the whole list
      child_div.appendChild(nav_link_list);

      // add a link to return to gallery view
      var image_unzoom_link = document.createElement('a');
      image_unzoom_link.setAttribute('onclick', 'unzoom(); return false');
      image_unzoom_link.setAttribute('href', '#');
      image_unzoom_link.appendChild(image);
      child_div.appendChild(image_unzoom_link);
      // alert("unzoom link added");
      
      // show the caption
      var caption_graf = document.createElement('p');
      caption_graf.setAttribute('class', 'caption');
      var caption_unzoom_link = document.createElement('a');
      caption_unzoom_link.setAttribute('onclick', 'unzoom(); return false');
      caption_unzoom_link.setAttribute('href', '#');
      var caption = get_image_caption(entry_item);
      caption_unzoom_link.innerHTML = caption;
      caption_graf.appendChild(caption_unzoom_link);
      child_div.appendChild(caption_graf);
      // alert("caption set: " + caption);
      
      // make sure the div extends below the image
      var clearing_break = document.createElement('br');
      child_div.appendChild(clearing_break);
      // alert("break set");

      // if the zoom div is already visible, clone it and its contents so we can fade between them
      if (zoom_div.style.display === 'block') {
        // alert("supposedly, there's already a full-sized image being displayed");
        var last_zoom_div = zoom_div.clone(true);
        last_zoom_div.setAttribute('id', 'last_image');
        last_zoom_div.style['z-index'] = 550;
      }
      // make sure multiple viewings don't append multiple images to the existing div
      if(zoom_div.hasChildNodes()) {
        zoom_div.replaceChild(child_div, zoom_div.firstChild);
      } else {
        zoom_div.appendChild(child_div);
      }
      // if the zoom div is already shown, cross-fade
      if (zoom_div.style.display === 'block') {
        // show the previous info
        last_zoom_div.style.display = "block";
        // if we've moved between entries, fade it down to show the thumbnails (but don't remove the dark background)
        if(!item_pattern.test(supposed_item_id)) {
          Effect.Fade('last_image', { duration: 0.5 });
        }
        
        // and fade up the new image
        Effect.Appear('zoom', { duration: 0.5 });
        last_zoom_div.parentNode.removeChild(last_zoom_div);
        
      } else {
        // darken the body
        Effect.Appear('background', { from: 0, to: 0.8 });
        Effect.Appear('zoom');
      }
    }
    // alert("done!");
    return false;
  }
  
  function zoom_winning_image(supposed_item_id) {
    // alert("zoom_winning_image("+supposed_item_id+")");
    var entry = null; var entry_item = null;
    
    // since there are valid item_ids that aren't really item_ids (like 'first' and 'last'),
    // do some simple pattern-matching to figure out which entry and item to look at
    var item_pattern = /winning_item_(\d+)/i;
    var entry_pattern = /winning_entry_(\d+)/i;
    
    if (item_pattern.test(supposed_item_id)) {
      // alert("we were passed 'winning_item_\d+'");
      entry_item = document.getElementById(supposed_item_id);
      entry = get_entry_including_item(entry_item); 
    } else {
      if (entry_pattern.test(supposed_item_id)) {
        // alert("we were passed 'winning_entry_\d+'");
        entry = document.getElementById(supposed_item_id);
      } else if (supposed_item_id === 'last') {
        entry = get_last_entry();
      } else {
        entry = get_first_entry();
      }
      if(entry) {
        entry_item = get_first_item_in_entry(entry);
      }
    }

    // so unless we were given an invalid entry_ or item_id, there should now be a valid entry AND item
    if (!entry || !entry_item) {
      // alert("entry or entry_item is missing");
      return false;
    } else { // display the image
      var background = document.getElementById("background");
      var zoom_div = document.getElementById("zoom");
      var child_div = document.createElement('div');

      // show UI instructions
      var cth_block = document.createElement('p');
      cth_block.setAttribute('class', 'instructions');
      cth_block.setAttribute('style', 'text-align: center;');
      var cth_link = document.createElement('a');
      cth_link.setAttribute('onclick', 'unzoom(); return false');
      cth_link.setAttribute('href', '#');
      cth_link.innerHTML = '(click the image to return to the multi-image gallery view)';
      cth_block.appendChild(cth_link);
      child_div.appendChild(cth_block);
      // alert("ui note added");
      
      // get the image data
      var image = document.createElement('img');
      image.setAttribute('src', preload_image(entry_item));
      // alert("large image added");
      
      // add a link to return to gallery view
      var image_unzoom_link = document.createElement('a');
      image_unzoom_link.setAttribute('onclick', 'unzoom(); return false');
      image_unzoom_link.setAttribute('href', '#');
      image_unzoom_link.appendChild(image);
      child_div.appendChild(image_unzoom_link);
      // alert("unzoom link added");
      
      // show the caption
      var caption_graf = document.createElement('p');
      caption_graf.setAttribute('class', 'caption');
      var caption_unzoom_link = document.createElement('a');
      caption_unzoom_link.setAttribute('onclick', 'unzoom(); return false');
      caption_unzoom_link.setAttribute('href', '#');
      var caption = get_image_caption(entry_item);
      caption_unzoom_link.innerHTML = caption;
      caption_graf.appendChild(caption_unzoom_link);
      child_div.appendChild(caption_graf);
      // alert("caption set: " + caption);
      
      // make sure the div extends below the image
      var clearing_break = document.createElement('br');
      child_div.appendChild(clearing_break);
      // alert("break set");

      // if the zoom div is already visible, clone it and its contents so we can fade between them
      if (zoom_div.style.display === 'block') {
        // alert("supposedly, there's already a full-sized image being displayed");
        var last_zoom_div = zoom_div.clone(true);
        last_zoom_div.setAttribute('id', 'last_image');
        last_zoom_div.style['z-index'] = 550;
      }
      // make sure multiple viewings don't append multiple images to the existing div
      if(zoom_div.hasChildNodes()) {
        zoom_div.replaceChild(child_div, zoom_div.firstChild);
      } else {
        zoom_div.appendChild(child_div);
      }
      // if the zoom div is already shown, cross-fade
      if (zoom_div.style.display === 'block') {
        // show the previous info
        last_zoom_div.style.display = "block";
        // if we've moved between entries, fade it down to show the thumbnails (but don't remove the dark background)
        if(!item_pattern.test(supposed_item_id)) {
          Effect.Fade('last_image', { duration: 0.5 });
        }
        
        // and fade up the new image
        Effect.Appear('zoom', { duration: 0.5 });
        last_zoom_div.parentNode.removeChild(last_zoom_div);
        
      } else {
        // darken the body
        Effect.Appear('background', { from: 0, to: 0.8 });
        Effect.Appear('zoom');
      }
    }
    // alert("done!");
    return false;
  }
  
  function unzoom() {
    // re-hide the "zoom" div
    Effect.Fade('zoom');
    
      // for some reason, fade isn't working on the background, so just hide it right away
      var background = document.getElementById("background");
      background.style.display = "none";
      
    return false;
  }
