tagTree = {}; // namespace object

/**
 * @constructor
 * @param o data object. Typically returned from JsHelper::atags() etc.
 * Must contain: id, label, parentId, what, childrenPresent, prefValue
 */
tagTree.Node = function(o) {
  /** node data */
  this.data = o;
  /** node children */
  this.children = [];
  /** parent of this node */
  this.parent = null;
  /** coresponding node in yui tree */
  this.yuiNode = null;
};

tagTree.Node.prototype = {
  /**
   * Add a node as child of this.
   * @param node (tagTree.Node) child node to add
  */
  addChild: function(node) {
    this.children.push(node);
    node.parent = this;
  },
  
  /** Return data object to use when building yui tree */
  yuiData: function() {
    return { label: this.data.label, href: this.data.what, myData: this.data };
  },
  
  /**
  * Walk the tree depth first, and set prefValue based child prefs.
  */
  fixChecks: function() {
    if (this.children.length == 0) {
      var leafPref = tagTree.leafPref(this.data.prefValue);
      this.data.calcPrefValue = leafPref;
      return leafPref;
    }
    var childPrefs = []; // array of calculated prefValue for each child
    childPrefs.push(tagTree.leafPref(this.data.prefValue)); // 'other' child
    for (var i = 0; i < this.children.length; i++) {
      childPrefs.push(this.children[i].fixChecks())
    }
    var ret = []; // prefValue for this node
    var cs; // check state. -1 - not set
    for (var p = 0; p < 7; p++) {
      cs = -1;
      for (var c = 0; c < childPrefs.length; c++) {
        switch (parseInt(childPrefs[c][p], 10)) {
        case 0: cs = ((cs == 0 || cs == -1) ? 0 : 1); break;
        case 1: cs = 1; break;
        case 2: cs = ((cs == -1 || cs == 2) ? 2 : 1); break;
        default: alert('bad data'); cs = 0; // ZAT_TODO: something more helpful here
        }
      }
      ret[p] = cs;
    }
    this.data.calcPrefValue = ret;
    return ret;
  },
  
  /**
   * Add data to tree. 'this' is root of tree to add to.
   * @param dataArray array of objects as returned from JsHelper::atags() etc.
   * parents must appear before children in the array.
  */
  addData: function(dataArray) {
    var parents = {};
    var thisTag;
    parents[this.data.id] = this;
    for (var i = 0; i < dataArray.length; i++) {
      thisTag = dataArray[i];
      parents[thisTag.id] = new tagTree.Node(thisTag);
      parents[thisTag.parentId].addChild(parents[thisTag.id]);
    }
  }
  
};

/** Make a leaf node pref array, only 0s and 2s. */
tagTree.leafPref = function(prefs) {
  var retPref = [];
  for (var i = 0; i < 7; i++) {
    retPref.push((parseInt(prefs[i], 10) == 0) ? 0 : 2);
  }
  return retPref;
};

tagTree.build = function(tags) {
  var ret = {};
  if (tags.spots) {
    var s = new tagTree.Node ({
        id: 0, label: 'Spots', parentId: 0, what: 'Kinds of places',
        alt: '', childrenPresent: true, prefValue: [2,0,2,2,2,2,2]}); // tree of data
    s.addData(tags.spots);
    s.fixChecks();
    ret.spots = s;
  }
  
  if (tags.areas) {
    var a = new tagTree.Node ({
        id: 0, label: 'Areas', parentId: 0, what: 'Cities, States, Countries, etc.',
        alt: '', childrenPresent: true, prefValue: [2,0,2,2,2,2,2]}); // tree of data
    a.addData(tags.areas);
    a.fixChecks();
    ret.areas = a;
  }
  
  if (tags.interests) {
    var i = new tagTree.Node ({
        id: 0, label: 'Interests', parentId: 0, what: 'Special Interests',
        alt: '', childrenPresent: true, prefValue: [2,0,2,2,2,2,2]}); // tree of data
    i.addData(tags.interests);
    i.fixChecks();
    ret.interests = i;
  }
  
  return ret;
};


