/*
 * Copyright 2009  Gregory Haynes <greg@greghaynes.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef QINFINITY_BROWSER_MODEL_H
#define QINFINITY_BROWSER_MODEL_H

#include "communicationmanager.h"

#include <QString>
#include <QList>
#include <QStandardItemModel>
#include <QHash>
#include <QPointer>

namespace QInfinity
{

class ConnectionItem;
class XmlConnection;
class BrowserItemFactory;
class NodeItem;
class Browser;
class BrowserIter;
class NotePlugin;
class ConnectionIndex;

class BrowserModelPrivate;

/**
 * @brief A model representing connections and their available files
 *
 * The BrowserModel provides a model containing connections
 * added with BrowserModel::addConnection.  Add the plugins
 * you wish to use with BrowserModel::addPlugin to allow
 * them to be added each connections' Browser.  You must also
 * call BrowserModel::itemActivated on a directory for it to
 * become populated.  This is usually done by connecting
 * signals from a view to the BrowserModel::itemActivated.
 */
class BrowserModel
	: public QStandardItemModel
{
	Q_OBJECT;

	public:
		/**
		 * @brief Create a new BrowserModel
		 */
		BrowserModel( QObject *parent = 0 );

		/**
		 * @brief Create BrowserModel with specified BrowserItemFactory
		 */
		BrowserModel( BrowserItemFactory *itemFactory,
			QObject *parent = 0 );

		/**
		 * @brief Destroy the BrowserModel
		 */
		~BrowserModel();

		/**
		 * @brief Use factory for creating items.
		 *
		 * If factory is NULL then BrowserItemFactory is used.
		 * factory will be reparented.
		 */
		void setItemFactory( BrowserItemFactory *factory );

		/**
		 * @brief Get factory used by this model.
		 */
		BrowserItemFactory &itemFactory() const;

		/**
		 * @brief Add connection with name for model to represent.
		 * @return ConnectionItem representing connection.
		 *
		 * The connection will be reparented to the BrowserModel.
		 * You can remove the connection by removing the appropriate
		 * row from the model.
		 */
		ConnectionItem *addConnection( XmlConnection &connection,
			const QString &name );

		bool hasChildren( const QModelIndex &parent = QModelIndex() ) const;

		/**
		 * @brief Add a plugin to connections in this model.
		 *
		 * The plugin will be reparented.
		 */
		void addPlugin( NotePlugin &plugin );

		/**
		 * @brief Get added plugins.
		 */
		QList<NotePlugin*> plugins() const;

		/**
		 * @brief Get the current browsers
		 */
		QList<Browser*> browsers() const;
		
		/**
		 * @brief Create a directory on the server.
		 */
		bool createDirectory( const QModelIndex &parent,
			const QString &name );

		/**
		 * @brief Create a note of type plugin on the server.
		 */
		bool createNote( const QModelIndex &parent,
			NotePlugin &plugin,
			const QString &name );

		bool removeRows( int row, int count,
			const QModelIndex &parent );

		CommunicationManager &communicationManager();

	Q_SIGNALS:
		void browserAdded( QInfinity::Browser &browser );
		void connectionAdded( QInfinity::XmlConnection &connection );
		void connectionRemoved( QInfinity::XmlConnection &connection );

	public Q_SLOTS:
		/**
		 * @brief Call this when an item has been expanded.
		 */
		void itemActivated( const QModelIndex &item = QModelIndex() );

	private Q_SLOTS:
		void slotNodeAdded( const BrowserIter &itr );
		void slotNodeRemoved( const BrowserIter &itr );

	private:
		void removeConnectionItem( ConnectionItem *item );
		void deleteNodeItem( NodeItem *item );
		void indexIter( const BrowserIter &iter,
			Browser &browser,
			NodeItem &item );
		void removeIterIndex( const BrowserIter &iter,
			Browser &browser );
		NodeItem *itemFromBrowserIter( const BrowserIter &iter,
			Browser &browser );
		NodeItem *indexToNodeItem( const QModelIndex &index ) const;
		Browser *createBrowser( CommunicationManager &commMgr,
			XmlConnection &connection );

		BrowserModelPrivate *d_ptr;
		Q_DECLARE_PRIVATE(BrowserModel)

};

}

#endif

