// ===================================================================
// Class for showing paged list of items.
//
// Terms:
//
// - set: modify data, no screen update
// - update: screen update

function PageView(pageDivID, curIndexDivID, lastPageDivID, lastElementDivID, selectedClassName)
{
  try {
    this._pageDiv        = pageDivID        ? document.getElementById(pageDivID)        : null;
    this._curIndexDiv    = curIndexDivID    ? document.getElementById(curIndexDivID)    : null;
    this._lastPageDiv    = lastPageDivID    ? document.getElementById(lastPageDivID)    : null;
    this._lastElementDiv = lastElementDivID ? document.getElementById(lastElementDivID) : null;

    this._Collection = []; // keep non-null

    this._selectedClassName = selectedClassName;

    this._PageSize = 10;
    this._CurIndex = null; // may be null for empty list!
    this._SelectedLineIndex = null;
  }
  catch (e) {
    alert("PageView: " + e);
  }
}

PageView.prototype =
{
  toString: function()
  {
    return "PageView";
  },

  getCollection: function()
  {
    return this._Collection;
  },

  setCollection: function(collection)
  {
    this._Collection = collection || [];
  },

  lastPageForLength: function(length) 
  {
    return length ? (Math.floor( (length - 1) / this._PageSize)) : null;
  },

  getPageStartIndex: function()
  {
    //  0.. 9 => 0
    // 10..19 => 10
    return this._CurIndex == null ? 0 : Math.floor(this._CurIndex / this._PageSize) * this._PageSize;
  },

  getCurIndex: function() // maybe null
  {
    return this._CurIndex;
  },

  getCurPage: function()
  {
    //  0.. 9 => 0
    // 10..19 => 1
    return this._CurIndex == null ? 0 : Math.floor(this._CurIndex / this._PageSize);
  },

  getCurCollectionItem: function()
  {
    return (this._Collection.length) ? this._Collection[this._CurIndex] : null;
  },

  // setCurIndex(index)
  // sets this.CurIndex and this._SelectedLineIndex
  // returns true if resulting index is still in current page,
  // otherwise returns false and sets this._SelectedLineIndex to null.
  setCurIndex: function(index)
  {
    var len = this._Collection.length;
    if (index == null || index < 0 || index > len - 1) {
      return;
    }
    if (index < this.getPageStartIndex()
        || index >= this.getPageStartIndex() + this._PageSize) {
      this._SelectedLineIndex = null;
    }    
    this._CurIndex = index;
    return this._SelectedLineIndex;
  },

  getSelectedElement: function()
  {
    if (this._SelectedLineIndex != null) {
      return this.getElementForLineIndex(this._SelectedLineIndex);
    }
    return null;    
  },

  // scrollSelectionIntoView(where)
  // where == true  => top of screen
  // where == false => bottom of screen
  scrollSelectionIntoView: function(where)
  {
    var Sel = this.getSelectedElement();
    if (Sel) {
      Sel.scrollIntoView(where);
    }
  },

  selectLineIndex: function(lineIndex)
  {
    var len = this._Collection.length;
    if (!len) {
      this._CurIndex = null; // empty list
      this._SelectedLineIndex = null;
    }
    else {
      var pageStartIndex = this.getPageStartIndex();
      var endLineIndex = Math.min(this._PageSize, len - pageStartIndex);
      if (lineIndex >= endLineIndex) {
        lineIndex = endLineIndex - 1;
      }
      // lineIndex < endLineIndex = len - pageStartIndex
      this._CurIndex = pageStartIndex + lineIndex;
      // this._CurIndex < len;
    }
    // alert("PageView.selectLineIndex(" + lineIndex + ")");
    if (this._SelectedLineIndex != null) {
      var Prev = this.getElementForLineIndex(this._SelectedLineIndex);
      if (Prev) {
        Prev.className = Prev.className.replace(" " + this._selectedClassName, "");
        //alert("Prev.className=" + Prev.className);
      }
    }
    if (len) {
      this._SelectedLineIndex = lineIndex;
      var Sel = this.getElementForLineIndex(this._SelectedLineIndex);
      if (Sel) {
        Sel.className += " " + this._selectedClassName;
        //alert("Sel.className=" + Sel.className);
      }
    }
    if (this._curIndexDiv) {
      this._curIndexDiv.innerHTML = this._CurIndex + 1;
    }
  },

  navigate: function(dir)
  {
    try {
      var len = this._Collection.length;
      if (!len) {
        this._CurIndex = null;
        this.updatePage();
        return;
      }

      switch (dir) {
      case "first":
        if (this._CurIndex <= 0) {
          return;
        }
        this._CurIndex = 0;
        break;
      case "prev":
        if (this._CurIndex <= 0) {
          return;
        }
        --this._CurIndex;
        break;
      case "next":
        if (this._CurIndex >= len - 1) {
          return;
        }
        ++this._CurIndex;
        break;
      case "last":
        if (this._CurIndex >= len - 1) {
          return;
        }
        this._CurIndex = len - 1;
        break;
      default:
        break;
      }

      this.updatePage();
    }
    catch (e) {
      alert("Fehler beim Navigieren: " + e.name + ": " + e.message);
    }
  },

  // updateCollection:
  // writes lines after page switch, updates selection visualization
  updateCollection: function()
  {
    if (this._Collection.length) {
      this._CurIndex = 0;
    }
    if (this._lastPageDiv) {
      this._lastPageDiv.innerHTML = this.lastPageForLength(this._Collection.length) + 1;
    }
    if (this._lastElementDiv) {
      this._lastElementDiv.innerHTML = this._Collection.length.toString();
    }
  },

  // default callbacks
  _computePageHeader: function()  { return ""; },
  _computePageLine  : function(i) { return i; },
  _computePageFooter: function()  { return ""; },
  _computeEmptyPage : function()  { return ""; },

  computePageLines: function(start, endIndex)
  {
    var html = "";
    for (var index = start; index < endIndex; ++index) {
      html += this._computePageLine(index);
    }
    return html;
  },  

  notifyUpdatePage: function() 
  {
    // default: NOP
  },

  // updatePage:
  // writes lines after page switch, updates selection visualization
  updatePage: function()
  {
    try {
      if (this._pageDiv) {
        var html = "";
        if (this._Collection.length) {
          html = this._computePageHeader();
          var start = this.getPageStartIndex();
          var len = this._Collection.length;
          var endIndex = Math.min(start + this._PageSize, len);
          html += this.computePageLines(start, endIndex);
          html += this._computePageFooter();
        }
        else {
          html = this._computeEmptyPage();
        }
        this._pageDiv.innerHTML = html;
      }
      this._SelectedLineIndex = null; // avoid reset of previous selection!
      if (this._curIndexDiv) {
        this._curIndexDiv.innerHTML = this._CurIndex + 1;
      }
      this.notifyUpdatePage();
    }
    catch (e) {
      alert("PageView.updatePage: " + e.name + ": " + e.message);
    }
  }
}
