// ===================================================================
// Class for storing data of one ParolBox.
// $Id: ParolBox.js 3967 2009-11-16 20:47:29Z helmut $

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.ParolBox = function()
{
  this.init();
}

Bible20.Parol.ParolBox.prototype = {
  init: function()
  {
    this._title = "";
    this._updated = "";
    this._lang = "";
    this._ParolBoxID = "";
    this._List = new Array();
    this._Map = new Object();
  },

  filterFrom: function(other, filterFunc)
  {
    try {
      this.init();
      this._title      = other._title;
      this._updated    = other._updated;
      this._lang       = other._lang;
      this._ParolBoxID = other._ParolBoxID;
      this._user       = other._user;
      this._targetDate = other._targetDate;

      for (var i = 0, len = other.getLength(); i < len; ++i) {
        var aParol = other.at(i);
        if (filterFunc(aParol)) {
          this._List.push(aParol);
          // Add both the composite ID and its tail! <--ParolBoxModel.gotoID() [composite]
          this._Map[aParol.getID()] = this._List.length-1,
          this._Map[aParol.getCanonicalID()] = this._List.length-1
        }
      }
    }
    catch (e) {
      alert("ParolBox.filterFrom: " + e);
    }
  },

  getTitle: function()
  {
    return this._title || "";
  },

  getUpdated: function()
  {
    return this._updated || "";
  },

  getParolBoxID: function()
  {
    return this._ParolBoxID || "";
  },

  getReservedBy: function()
  {
    return this._user || "";
  },

  getReservedUntil: function()
  {
    return this._targetDate || "";
  },

  getLength: function()
  {
    return this._List.length;
  },

  getLang: function()
  {
    return this._lang || "";
  },


  at: function(index)
  {
    return this._List[index] || null;
  },

  findParolIndex: function(id)
  {
    if (id == null) throw new Error("ParolBox.findParolIndex: id undefined");
    var parolID = this._Map[id];
    return parolID != undefined ? parolID : null;
  },

  findParol: function(id)
  {
    if (id == null) throw new Error("ParolBox.findParol: id undefined");
    var index = this._Map[id];
    if (index != null) {
      return this._List[index] || null;
    }
    else {
      return null;
    }
  },

  // === modification ===

  // see ParolBoxModel!
  setTitle: function(title)
  {
    this._title = title;
  },

  setUpdated: function(updated)
  {
    this._updated = updated;
  },

  setParolBoxID: function(id)
  {
    this._ParolBoxID = id;
  },

  setLang: function(lang)
  {
    this._lang = lang;
  },

  setReserved: function(user, targetDate)
  {
    this._user = user;
    this._targetDate = targetDate;
  },

  // append(aParol)
  // returns aParol
  append: function(aParol)
  {
    this._List.push(aParol);
    // Add both the composite ID and its tail! <--ParolBoxModel.gotoID() [composite]
  //TODO low 2008-06-28 HS: assume ParolBox does not contain ids "A" as well as "B___A"
    this._Map[aParol.getID()] = this._List.length-1;
    this._Map[aParol.getCanonicalID()] = this._List.length-1;
    return aParol;
  },

  // appendNew(id)
  // returns new Parol inserted having id
  appendNew: function(id)
  {
    aParol = new Bible20.Parol.Parol().setID(id);
    return this.append(aParol);
  },

  // findAppendParol(id)
  // returns Parol found or inserted
  findAppendParol: function(id)
  {
    return this.findParol(id) || this.appendNew(id);
  },

  // remove:
  // if aParol was contained in this, deletes it and returns aParol,
  // otherwise return null
  // 2009-04-07 HS:
  //   using function name "delete" leads to an error in IE 6:
  ///  "Type error: object expected" $&%&%$!!
  remove: function(aParol)
  {
    var index = this._Map[aParol.getID()];
    if (index == null) {
      return null;
    }

    // delete from this._List
    this._List.splice(index, 1);

    // adapt list indexes in this._Map for elements that followed aParol in this._List
    for (var i = index, len = this._List.length; i < len; ++i) {
      this._Map[this._List[i].getID()] = i;
      this._Map[this._List[i].getCanonicalID()] = i;
    }

    // delete entries for aParol from this._Map
    delete this._Map[aParol.getID()];
    delete this._Map[aParol.getCanonicalID()];

    return aParol;
  }
}