// ===================================================================
// ParolBoxReader


var Bible20;
if (!Bible20) {
  Bible20 = {};
}
else if (typeof Bible20 != "object") {
  throw new Error("Bible20 already exists and is not an object");
}

if (!Bible20.Parol) {
  Bible20.Parol = {};
}
else if (typeof Bible20.Parol != "object") {
  throw new Error("Bible20.Parol already exists and is not an object");
}

Bible20.Parol.ParolBoxReader = function()
{
  this._NS = "http://bible2.net/service/Parol/ParolBoxList";
}

Bible20.Parol.ParolBoxReader.prototype._flatten = function(node)
{
  try {
    //TODO low HS 2009-12-31 - check ParolBoxReader._flatten implementation for handling of <em>...</em>
    // value as from file may contain "<em>...</em>"
    var s = "";
    while (node) {
      if (node.nodeType == 1) { // Node.ELEMENT_NODE not available in IE6
        var childText = node.firstChild.data;
        if (node.nodeName == "em") {
          s += "<em>" + childText + "</em>"; // surround by delimiters
        }
        else {
          s += childText; // just flatten
        }
      }
      else if (node.nodeType == 3) { // Node.TEXT_NODE not available in IE6
        s += node.data;
      }
      // else: ignore all node types except element and text
      node = node.nextSibling;
    }
    return s;
  }
  catch (e) {
    alert("ParolBoxReader._flatten: " + e);
  }
}

Bible20.Parol.ParolBoxReader.prototype._readPerson = function(aParol, entry, person, method)
{
  try {
    var Person = entry.getElementsByTagName(person)[0];
    if (Person) {
//TODO 2010-02-19 low HS - 0..n author
      aParol[method](Person.getElementsByTagName("name")[0].firstChild.data);
    }
  }
  catch (e) {
    alert("ParolBoxReader._readPerson: " + e.name + ": " + e.message);
  }
}

Bible20.Parol.ParolBoxReader.prototype._readCategories = function(target, element)
{
  try {
    var Categories = Bible20.Parol.ParolBoxReader._getChildrenByTagName(element, "category");
    //Log.debug("Bible20.Parol.ParolBoxReader._readCategories: Categories.length="+Categories.length);
    for (var i = 0; i < Categories.length; ++i) {
      var Category = Categories[i];
      var term = Category.getAttribute("term");
      if (term) {
        var value = Category.firstChild ? Category.firstChild.data : "";
        //Log.debug("ParolBoxReader._readCategories(" + term + ", " + value + ")");//TODO
        if (term == "State" || term == "TextState") {
          value = Number(value);
        }
        target.addCategory(term, value);
      }
    }
  }
  catch (e) {
    alert("ParolBoxReader._readCategories: " + e.name + ": " + e.message);
  }
}

Bible20.Parol.ParolBoxReader.prototype.readParol = function(aParol, entry)
{
  try {
//    aParol.setTitle  (entry.getElementsByTagName("title"  )[0].firstChild.data);
//alert("Bible20.Parol.ParolBoxReader.readParol("+entry.getElementsByTagName("id"     )[0].firstChild.data+")");
    aParol.setID     (entry.getElementsByTagName("id"     )[0].firstChild.data);
    aParol.setUpdated(entry.getElementsByTagName("updated")[0].firstChild.data);

    this._readPerson(aParol, entry, "author", "setAuthor");

    // read categories, first set defaults
    aParol.addCategory("State", 100);
    aParol.addCategory("TextState", 100);
    this._readCategories(aParol, entry);

    // === setup references to IL, L, SL

    var div = entry.getElementsByTagName("div")[0];
    if (div) {
      var pArr = div.getElementsByTagName("p");
      // process all div.P elements
      for (var i = 0; i < pArr.length; ++i) {
        var p = pArr[i];
        if (p.firstChild) {
          // 2009-04-07 HS: IE6 sucks (for HTML in XML at least, some may work in pure HTML):
          //   p.className                 => undefined
          //   p.attributes['class'].value => "Null oder kein Objekt"
          //   p.getAttribute("class")     => ok
          // All three work in Firefox 2!
          aParol["set" + p.getAttribute("class")].call(aParol, this._flatten(p.firstChild)); // setup reference to IL, L, SL
        }
      }
    }

    var Categories = entry.getElementsByTagName("category");
    for (var i = 0; i < Categories.length; ++i) {
      var Category = Categories[i];
      var term  = Category.getAttribute("term");
      var value = Category.firstChild.data;

      aParol["set" + p.getAttribute("class")].call(aParol, this._flatten(p.firstChild)); // setup reference to IL, L, SL
    }

    return this;
  }
  catch (e) {
    alert("ParolBoxReader.readParol: " + e.name + ": " + e.message);
  }
}

Bible20.Parol.ParolBoxReader.prototype.readEntries = function(aParolBox, xmlDoc)
{
  try {
    if (!xmlDoc) throw new Error("ParolBoxReader.read - no xmlDoc");

    var entries = xmlDoc.getElementsByTagName("entry");
    //alert("Bible20.Parol.ParolBoxReader.prototype.readFromDom: read " + entries.length + " entries");
    // var s="XXX ";
    for (var r = 0; r < entries.length; ++r) {
      var entry = entries[r];

      // PairSetDomReader.js creates new Parol with just ID set,
      // allow to find this here and fill in the other properties
      // (but no existing properties will be reset - do not use to overwrite filled Parol!)
      var ID = (entry.getElementsByTagName("id")[0].firstChild.data);
      var aParol = aParolBox.findParol(ID);
      if (aParol) {
        // be sure to reset properties if Parol is read a second time (e.g. after edit)
        aParol.clearOptional();
        this.readParol(aParol, entry);
      }
      else {
        //s += " " + (entry.getElementsByTagName("id")[0].firstChild.data);
        aParol = new Bible20.Parol.Parol();
        this.readParol(aParol, entry);
        //alert("ParolBoxReader.read: adding id " + aParol.getID());

        var aBibleRef = new Bible20.Bible.BibleRef().fromParolID(aParol.getID());
        // [BibleRef]: store BibleRef object in each Parol (e.g. for sorting), 
        aParol.setBibleRef(aBibleRef);

        // append AFTER readParol (needs ID)!
        aParolBox.append(aParol);
      }
    }
    // alert("XXX ParolBoxReader.read=>" + s);
  }
  catch (e) {
    alert("ParolBoxReader.readEntries: " + e);
  }
}

// static function
Bible20.Parol.ParolBoxReader._getChildrenByTagName = function(node, name)
{
  var res = [];
  //var s="";
  for (var Child = node && node.firstChild; Child; Child = Child.nextSibling) {
    //if (Child.nodeType == 1) s+="<"+Child.nodeName+">\n";
    if (Child.nodeType == 1 && Child.nodeName.toLowerCase() == name) {
      res.push(Child);
    }
  }
  //alert("Bible20.Parol.ParolBoxReader._getChildrenByTagName: children = "+s);
  return res;
}

// read(aParolBox, xmlDoc, adaptFunc)
// xmlDoc may be ancestor of "feed" node or "feed" node itself
// Puts data into aParolBox.
// Calls adaptFunc (if given) for each Parol.

Bible20.Parol.ParolBoxReader.prototype.read = function(aParolBox, xmlDoc, adaptFunc, bWithNamespaces, bAdd)
{
  try {
    if (!xmlDoc) throw new Error("ParolBoxReader.read - no xmlDoc");

    // in Html document, tags are returned upper case => use toLowerCase()
    var feed = (xmlDoc.nodeName.toLowerCase() == "feed" && xmlDoc) || xmlDoc.getElementsByTagName("feed")[0];

    //var updated = xmlDoc.getElementsByTagName("updated")[0];
    // 2009-12-11 HS commented out for BibleStudio
    //aParolBox.setUpdated(updated ? updated.firstChild.data : "");

    //var feed = (xmlDoc.nodeName == "feed" && xmlDoc) || xmlDoc.getElementsByTagName("feed")[0];
    //aParolBox.setLang(feed && feed.attributes["xml:lang"] ? feed.attributes["xml:lang"].value : "");

    //var id1 = xmlDoc.getElementsByTagName("id")[0];
    //aParolBox.setParolBoxID( (id1 && id1.firstChild) ? id1.firstChild.data : "");

    // not yet: this._readPerson(aParol, feed, "author", "setAuthor");
    this._readCategories(aParolBox, feed);

    if (bWithNamespaces) {
      // 2009-04-07 HS:
      // getElementsByTagNameNS is not supported by IE 6 (at least),
      // see http://www.zachleat.com/web/2008/05/10/selecting-xml-with-javascript/
      // who proposes
      //   oDoc.setProperty("SelectionNamespaces", "xmlns:whatever='http://example.com/'");
      //   var oDocEl = oDoc.documentElement;
      //   var correctForCase3A = oDocEl.selectNodes('whatever:child');
      //   var correctForCase3B = oDocEl.selectSingleNode('whatever:child');

//TODO low 2008-08-14/2009-12-31 HS - cleanup "b20:..." handling (cf. ParolEdit add-on StartEdit.js)
      var user       = xmlDoc.getElementsByTagNameNS(this._NS, "reservedby")[0];
      var targetDate = xmlDoc.getElementsByTagNameNS(this._NS, "reserveduntil")[0];
      aParolBox.setReserved(
          user       ? user      .firstChild.data : null,
          targetDate ? targetDate.firstChild.data : null
        );
      //alert("ParolBoxReader.read: user=" + this.getReservedBy() + ", targetDate=" + this.getReservedUntil());
    }
    this.readEntries(aParolBox, xmlDoc, adaptFunc, bAdd);
  }
  catch (e) {
    alert("ParolBoxReader.read: " + e.name + ": " + e.message);
  }
}
