// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_BASE_MODELS_LIST_MODEL_H_
#define UI_BASE_MODELS_LIST_MODEL_H_

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "ui/base/models/list_model_observer.h"

namespace ui {

// A list model that manages a list of ItemType pointers. Items added to the
// model are owned by the model. An item can be taken out of the model by
// RemoveAt.
template <class ItemType>
class ListModel {
 public:
  ListModel() {}
  ~ListModel() {}

  // Adds |item| at the |index| into |items_|. Takes ownership of |item|.
  void AddAt(size_t index, ItemType* item) {
    DCHECK_LE(index, item_count());
    items_.insert(items_.begin() + index, item);
    NotifyItemsAdded(index, 1);
  }

  // Convenience function to append an item to the model.
  void Add(ItemType* item) {
    AddAt(item_count(), item);
  }

  // Removes the item at |index| from |items_| without deleting it.
  // Returns a scoped pointer containing the removed item.
  scoped_ptr<ItemType> RemoveAt(size_t index) {
    DCHECK_LT(index, item_count());
    ItemType* item = items_[index];
    items_.weak_erase(items_.begin() + index);
    NotifyItemsRemoved(index, 1);
    return make_scoped_ptr<ItemType>(item);
  }

  // Removes all items from the model. This does NOT delete the items.
  void RemoveAll() {
    size_t count = item_count();
    items_.weak_clear();
    NotifyItemsRemoved(0, count);
  }

  // Removes the item at |index| from |items_| and deletes it.
  void DeleteAt(size_t index) {
    scoped_ptr<ItemType> item = RemoveAt(index);
    // |item| will be deleted on destruction.
  }

  // Removes and deletes all items from the model.
  void DeleteAll() {
    ScopedVector<ItemType> to_be_deleted(items_.Pass());
    NotifyItemsRemoved(0, to_be_deleted.size());
  }

  // Moves the item at |index| to |target_index|. |target_index| is in terms
  // of the model *after* the item at |index| is removed.
  void Move(size_t index, size_t target_index) {
    DCHECK_LT(index, item_count());
    DCHECK_LT(target_index, item_count());

    if (index == target_index)
      return;

    ItemType* item = items_[index];
    items_.weak_erase(items_.begin() + index);
    items_.insert(items_.begin() + target_index, item);
    NotifyItemMoved(index, target_index);
  }

  void AddObserver(ListModelObserver* observer) {
    observers_.AddObserver(observer);
  }

  void RemoveObserver(ListModelObserver* observer) {
    observers_.RemoveObserver(observer);
  }

  void NotifyItemsAdded(size_t start, size_t count) {
    FOR_EACH_OBSERVER(ListModelObserver,
                      observers_,
                      ListItemsAdded(start, count));
  }

  void NotifyItemsRemoved(size_t start, size_t count) {
    FOR_EACH_OBSERVER(ListModelObserver,
                      observers_,
                      ListItemsRemoved(start, count));
  }

  void NotifyItemMoved(size_t index, size_t target_index) {
    FOR_EACH_OBSERVER(ListModelObserver,
                      observers_,
                      ListItemMoved(index, target_index));
  }

  void NotifyItemsChanged(size_t start, size_t count) {
    FOR_EACH_OBSERVER(ListModelObserver,
                      observers_,
                      ListItemsChanged(start, count));
  }

  size_t item_count() const { return items_.size(); }

  const ItemType* GetItemAt(size_t index) const {
    DCHECK_LT(index, item_count());
    return items_[index];
  }
  ItemType* GetItemAt(size_t index) {
    return const_cast<ItemType*>(
        const_cast<const ListModel<ItemType>*>(this)->GetItemAt(index));
  }

 private:
  ScopedVector<ItemType> items_;
  ObserverList<ListModelObserver> observers_;

  DISALLOW_COPY_AND_ASSIGN(ListModel<ItemType>);
};

}  // namespace ui

#endif  // UI_BASE_MODELS_LIST_MODEL_H_
