// Categories.js
// Javascript file for heirarchical category list

function chhCategories(){}

chhCategories.host = location.host;

//-----------------------------------------------------------------------------
chhCategories.set_categories = function (cats)
//
// Set the array of category names to use
//
{
  for(var i = 0; i < cats.length; ++i) {
    chhCategories._categories[i] = cats[i];
  }
};

//-----------------------------------------------------------------------------
chhCategories.set_count = function (count)
//
// Set the array of numner of posts for categories names to use
//
{
  for(var i = 0; i < count.length; ++i) {
    var name = chhCategories._categories[i];
    if (name) {
      chhCategories._category_count[name] = count[i];
    }
  }
};

//-----------------------------------------------------------------------------
chhCategories.display = function (id)
//
// Display the categories in the node with id 'id'
//
{
  chhCategories._cat_menu(id, '*');
};

//-----------------------------------------------------------------------------
chhCategories.toggle_category = function (name)
//
// Toggle category 'name' expanded / collapsed
//
{
  var section = document.getElementById('chh-category-' + name);
  var icon = document.getElementById('chh-category-' + name + "-icon");
  var hidden = section.style.display == 'none';
  if (hidden) {
    section.style.display = 'block';
    icon.innerHTML = '&#9660;';
    
    // Load if not already done
    if (!section.hasChildNodes()) {
      // insert sub categories
      if (chhCategories._subcategory[name]) {
        for (var i = 0; i != chhCategories._subcategory[name].length; ++i) {
          var subcat = chhCategories._subcategory[name][i];
          chhCategories._cat_menu('chh-category-' + name, subcat);
        }
      }
      chhCategories._load_category_posts('chh-category-' + name, name, 0);
    }
  } else { 
    section.style.display = 'none';
    icon.innerHTML = '&#9658;';
  }
};


//-----------------------------------------------------------------------------
chhCategories.fetch_more = function (name, start)
//
// Fetch more category posts into the node for the given category
//
{
  var section = document.getElementById('chh-category-' + name);

  // Remove the "more" link now we are dealing with it
  var list = section.getElementsByTagName('ul')[0];
  list.removeChild(list.lastChild);

  // Load the next lot of category posts
  chhCategories._load_category_posts('chh-category-' + name, name, start);
};


chhCategories._categories = new Array();
chhCategories._category_count = new Array();
chhCategories._subcategory = new Array();

//-----------------------------------------------------------------------------
chhCategories._cat_menu = function (id, name)
//
// Fill the element 'id' with the category menu for category 'name'
//
{
  var node = document.getElementById(id);
  if (!node) {
    return;
  }

  if (name == '*') {
    // List all categories
    for (var i = 0; i != chhCategories._categories.length; ++i) {
      var c = chhCategories._categories[i];
      if (c.search(/\//) == -1) {
        chhCategories._cat_menu(id, c);
      } else {
        var root = RegExp.leftContext;
        if (!chhCategories._subcategory[root]) {
          chhCategories._subcategory[root] = new Array();
        }
        chhCategories._subcategory[root].push(c);
      }
    }
    return;
  }

  // Menu for a single category
  var catName = name;
  if (name.search(/\//) != -1) {
    catName = RegExp.rightContext;
  }
  var main_div = document.createElement('div');
  var toggle_span = document.createElement('span');
  main_div.appendChild(toggle_span);
  toggle_span.style.cursor = 'pointer';
  toggle_span.onclick = new Function("chhCategories.toggle_category('" + 
    name + "')");
  var icon = document.createElement('span');
  icon.setAttribute('id', 'chh-category-' + name + "-icon");
  icon.innerHTML = '&#9658;';

  toggle_span.appendChild(icon);
  var space = document.createTextNode(' ');
  toggle_span.appendChild(space);
  var link = document.createElement('a');
  link.style.textDecoration = 'none';
  var safe_name = escape(name);
  safe_name = safe_name.replace(/\//g, "%2F");
  link.setAttribute('href', 'http://' +  chhCategories.host +
    '/search/label/' + safe_name);
  var catText = document.createTextNode(catName);
  link.appendChild(catText);
  main_div.appendChild(link);
  var count = chhCategories._category_count[name];
  if (count) {
    // Add count
    var countText = document.createTextNode(" (" + count + ")");
    main_div.appendChild(countText);
  }

  node.appendChild(main_div);
  var div2 = document.createElement('div');
  div2.setAttribute('id', 'chh-category-' + name);
  div2.style.display = 'none';
  div2.style.marginLeft = '1em';
  node.appendChild(div2);

};

//-----------------------------------------------------------------------------
chhCategories._load_category_posts = function(id, cat, start)
//
// Load the categories post for category 'cat' into element with id 'id'
//
{
  // Get target node
  var node = document.getElementById(id);
  if (!node) {
    return;
  }

  var name = cat;
  cat = escape(cat);
  cat = cat.replace(/\//g, '%2F');

  // Put temp text in to start
  var textNode = document.createTextNode("Loading...");
  node.appendChild(textNode);

  // Load the XML
  var xmlhttp = chhCategories.getXMLHttpRequest();
  var async = true;
  var url = "http://" + chhCategories.host + "/feeds/posts/default/-/" + cat;
  url += "?alt=json";
  if (start) {
    url += "&start-index=" + start;
  }
  xmlhttp.open("GET", url, async);
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4) {
      if (xmlhttp.status == 200) {

        // Parse the JSON
        var data = eval('(' + xmlhttp.responseText + ')');

        // Get the entries
        var entries = data.feed.entry;

        // Delete the marker text
        node.removeChild(textNode);

        // Start list
        var list = node.getElementsByTagName('ul')[0];
        if (!list) {
          list = document.createElement('ul');
          node.appendChild(list);
        }

        // Fill from the xml entries
        var sorted_entries = chhCategories._sort(entries);
        for (var i = 0; i !=  sorted_entries.length; ++i) {
          var entry =  sorted_entries[i];
          var titleNode = entry.title;
          var linkNode = entry.link[0];
          for (var j = 0; j != entry.link.length; ++j) {
            linkNode = entry.link[j];
            if (linkNode.rel == 'alternate') {
              break;
            }
          }
          var titleText = titleNode.$t;
          var linkURL = linkNode.href;
          var link = document.createElement('a');
          link.setAttribute('href', linkURL);
          var li = document.createElement('li');
          list.appendChild(li);
          li.appendChild(link);
          var tn = document.createTextNode(titleText);
          link.appendChild(tn);
        }

        // Have we got the lot?
        var totalResultsNode = data.feed.openSearch$totalResults;
        var startIndexNode = data.feed.openSearch$startIndex;

        if (totalResultsNode && startIndexNode) {
          var totalResults = Number(totalResultsNode.$t);
          var startIndex = Number(startIndexNode.$t);
          var next_entry = startIndex + entries.length;
          if (next_entry <= totalResults) {
            // Add node to get the rest
            var nextLink = document.createElement('a');
            nextLink.setAttribute('href', '#');
            nextLink.style.textDecoration = 'none';
            nextLink.style.fontStyle = 'italic';
            var nextText = document.createTextNode("more...");
            nextLink.appendChild(nextText);
            nextLink.onclick =
              new Function("chhCategories.fetch_more('" +
                name + "'," + next_entry + "); return false;");
            list.appendChild(nextLink);
          }
        }
      }
    }
  };
  xmlhttp.send(null);
};

//-----------------------------------------------------------------------------
chhCategories._sort = function(input)
//
// Sort an array of post elements by published date
//
{
  // Make copy into standary array
  var entries = new Array();
  for(var n = 0; n != input.length; ++n) {
    entries[n] = input[n];
  }

  // bubble sort
  for(var i = 1; i != entries.length; ++i) {
    var done = true;
    for (var j = 0; j != entries.length - i; ++j) {
      var published1 = entries[j].published;
      var published2 = entries[j+1].published;
      var date1 = published1.$t;
      var date2 = published2.$t;
      if (date1 < date2) {
        var temp = entries[j];
        entries[j] = entries[j+1];
        entries[j+1] = temp;
        done = false;
      }
    }
    if (done) {
      // Everything already sorted
      break;
    }
  }

  return entries;
};

//-----------------------------------------------------------------------------
chhCategories.getXMLHttpRequest = function() 
//
// Get an XMLHttpRequest object in cross browser way
//
{
  var xmlhttp = null;
  if (self.XMLHttpRequest) {
    xmlhttp = new XMLHttpRequest();
  } else if (self.ActiveXObject) {
    // Try MSXML objects in order of preference
    var msxmls = ["Msxml2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0",
      "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
    for(var i=0; i < msxmls.length; ++i) {
      try {
        xmlhttp = new ActiveXObject(msxmls[i]);
        // If we are still here it worked
        // don't try any more
        break;
      } catch(err) {
        // Do nothing, just try next one if any
      }
    }
  }
  return xmlhttp;
};

//-----------------------------------------------------------------------------
chhCategories.getDOMParser = function() 
//
// Get a DOMParser object in cross browser way
//
{
  var domparser = null;
  if (self.DOMParser) {
    domparser = new DOMParser();
  } else if (self.ActiveXObject) {
    domparser = new Object();
    domparser.parseFromString = function(xml, mime_type) {
      var doc = null;
      try {
        doc = new ActiveXObject("Microsoft.XMLDOM");
        doc.loadXML(xml);
      } catch(err) {}
      return doc;
    };
  }
  return domparser;
};
