/**
   * Returns the number of items potentially visible to the client.
   *
   * @return items.
   */
  private int getVisibleItemsCount() {
    int cnt = 0;

    for (ResultItemPanel item : items) if (item.isVisibility() && !item.isFiltered()) cnt++;

    return cnt;
  }
  /**
   * Collapses / expands the group.
   *
   * @param col <code>TRUE</code> to collapse.
   */
  public void setCollapsed(boolean col) {
    collapsed = col;

    for (ResultItemPanel item : items) item.setCollapsed(col);

    moreItem.updateVisibility();
  }
  /**
   * Removes the panel of the item from the group.
   *
   * @param item item to remove the panel of.
   * @return panel removed or <code>NULL</code> if not found.
   */
  public ResultItemPanel removeItemPanelFor(ResultItem item) {
    for (ResultItemPanel panel : items) {
      if (item == panel.getItem()) {
        // Panel found
        items.remove(panel);
        recalcView();
        return panel;
      }
    }

    return null;
  }
  /**
   * Sets the limit.
   *
   * @param aItemLimit limit.
   */
  public void setItemLimit(int aItemLimit) {
    itemLimit = aItemLimit;

    int hidden = 0;
    for (int i = 0; i < items.size(); i++) {
      ResultItemPanel item = items.get(i);
      item.setVisibility(i < itemLimit);
      if (i >= itemLimit) hidden++;
    }

    moreItem.setCount(hidden);
  }
  /**
   * Registers item within the group.
   *
   * @param item item.
   * @return index within the group.
   */
  public int register(ResultItemPanel item) {
    int visibleItemsCount = getVisibleItemsCount();

    boolean priority = item.getItem().isPriority();
    int index = priority ? 0 : items.size();
    items.add(index, item);

    boolean filtered = isFiltered(item);
    item.setFiltered(filtered);

    if (!filtered) recalcView();
    if (visibleItemsCount == 0) setVisible(true);

    return index;
  }
  /**
   * Returns <code>TRUE</code> if the item should be filtered out.
   *
   * @param aItem item to check.
   * @return <code>TRUE</code> if the item should be filtered out.
   */
  private boolean isFiltered(ResultItemPanel aItem) {
    if (limitTime == -1L) return false;

    Date date = aItem.getItem().getDate();

    return date == null || date.getTime() <= limitTime;
  }
  /** Recalculates the view. */
  private void recalcView() {
    int more = 0;
    int visible = 0;
    for (ResultItemPanel itm : items) {
      if (itm.isFiltered()) {
        itm.setVisibility(false);
      } else if (visible >= itemLimit) {
        itm.setVisibility(false);
        more++;
      } else {
        itm.setVisibility(true);
        visible++;
      }
    }

    moreItem.setCount(more);
    lbCount.setText(Integer.toString(visible + more));
  }
  /**
   * Sets filtering time. If the time is set to <code>-1</code> then filtering is off. Otherwise it
   * shows the time after which all items are allowed.
   *
   * @param aLimitTime the time used for limiting.
   */
  public void setLimitTime(long aLimitTime) {
    limitTime = aLimitTime;

    int shown = 0;
    int hidden = 0;
    for (ResultItemPanel item : items) {
      item.setFiltered(isFiltered(item));
      item.setVisibility(!item.isFiltered() && shown < itemLimit);

      if (item.isVisible()) shown++;
      else if (!item.isFiltered()) hidden++;
    }

    setVisible(shown > 0);
    moreItem.setCount(hidden);
  }
  /** Invoked when the user asks for more items. */
  private void onShowMore() {
    for (ResultItemPanel item : items) item.setVisibility(true);

    moreItem.setCount(0);
  }