// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2014 Emweb bvba, Herent, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
#ifndef WIDENTITY_PROXY_MODEL_H_
#define WIDENTITY_PROXY_MODEL_H_

#include <vector>

#include <Wt/WAbstractProxyModel>

namespace Wt {

/*! \class WIdentityProxyModel Wt/WIdentityProxyModel Wt/WIdentityProxyModel
 * \brief A proxy model that proxies its source model unmodified.
 *
 * A WIdentityProxyModel simply forwards the structure of the source model,
 * without any transformation. WIdentityProxyModel can be used as a base class
 * for implementing proxy models that reimplement data(), but retain all
 * other characteristics of the source model.
 */
class WT_API WIdentityProxyModel : public WAbstractProxyModel
{
public:
  /*! \brief Constructor.
   */
  WIdentityProxyModel(WObject *parent = 0);

  virtual ~WIdentityProxyModel();

  /*! \brief Returns the number of columns.
   *
   * Translates the parent index to the source model,
   * and returns the number of columns of the source model.
   */
  int columnCount(const WModelIndex &parent = WModelIndex()) const;

  /*! \brief Returns the number of rows.
   *
   * Translates the parent index to the source model,
   * and returns the number of rows of the source model.
   */
  int rowCount(const WModelIndex &parent = WModelIndex()) const;

  /*! \brief Returns the parent for a model index.
   *
   * Translates the child index to the source model,
   * and translates its parent back to this proxy model.
   */
  WModelIndex parent(const WModelIndex &child) const;

  /*! \brief Returns the child index for the given row and column.
   *
   */
  WModelIndex index(int row, int column, const WModelIndex &parent = WModelIndex()) const;

  /*! \brief Maps a proxy model index to the source model.
   *
   * Returns a model index with the same row and column as
   * the source index. The parent index is mapped recursively.
   */
  WModelIndex mapFromSource(const WModelIndex &sourceIndex) const;

  /*! \brief Maps a source model index to the proxy model.
   *
   * Returns a model index with the same row and column as
   * the proxy index. The parent index is mapped recursively.
   */
  WModelIndex mapToSource(const WModelIndex &proxyIndex) const;

  /*! \brief Sets the source model.
   *
   * The source model provides the actual data for the proxy
   * model.
   *
   * Ownership of the source model is <i>not</i> transferred.
   *
   * All signals of the source model are forwarded to the
   * proxy model.
   */
  void setSourceModel(WAbstractItemModel *sourceModel);

  /*! \brief Inserts one or more columns.
   *
   * Inserts \c count columns at column \c column in the
   * source model.
   *
   * Forwards the result indicating success from the source model.
   */
  bool insertColumns(int column, int count, const WModelIndex &parent = WModelIndex());

  /*! \brief Inserts one or more rows.
   *
   * Inserts \c count rows at row \c row in the source model.
   *
   * Forwards the result indicating success from the source model.
   */
  bool insertRows(int row, int count, const WModelIndex &parent = WModelIndex());

  /*! \brief Removes columns.
   *
   * Removes \c count columns at column \c column in the source model.
   *
   * Forwards the result indicating success from the source model.
   */
  bool removeColumns(int column, int count, const WModelIndex &parent = WModelIndex());

  /*! \brief Removes rows.
   *
   * Removes \c count rows at row \c row in the source model.
   *
   * Forwards the result indicating success from the source model.
   */
  bool removeRows(int row, int count, const WModelIndex &parent = WModelIndex());

  using WAbstractProxyModel::setHeaderData;

  /*! \brief Set header data for a column or row.
   *
   * Sets the header data for a column or row in the source model.
   *
   * Forwards the result indicating success from the source model.
   */
  bool setHeaderData(int section, Orientation orientation, const boost::any& value, int role = EditRole);

private:
  std::vector<Wt::Signals::connection> modelConnections_;

  void sourceColumnsAboutToBeInserted(const WModelIndex &parent, int start, int end);
  void sourceColumnsAboutToBeRemoved(const WModelIndex &parent, int start, int end);
  void sourceColumnsInserted(const WModelIndex &parent, int start, int end);
  void sourceColumnsRemoved(const WModelIndex &parent, int start, int end);
  void sourceRowsAboutToBeInserted(const WModelIndex &parent, int start, int end);
  void sourceRowsAboutToBeRemoved(const WModelIndex &parent, int start, int end);
  void sourceRowsInserted(const WModelIndex &parent, int start, int end);
  void sourceRowsRemoved(const WModelIndex &parent, int start, int end);
  void sourceDataChanged(const WModelIndex &topLeft, const WModelIndex &bottomRight);
  void sourceHeaderDataChanged(Orientation orientation, int start, int end);
  void sourceLayoutAboutToBeChanged();
  void sourceLayoutChanged();
  void sourceModelReset();
};

} // namespace Wt

#endif // #ifndef WIDENTITY_PROXY_MODEL_H_
