/*
** 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 1, 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, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- December 1997
 */

/*
 * MultiFiles.h --- class to store multiple files by directory
 */

#ifndef MULTIFILES_H
#define MULTIFILES_H

#include "TextBinary.h"

#include "CPStr.h"
#include <vector>

#ifdef _MSC_VER
	using namespace std;
#endif

class CvsArgs;

/// Used internally
class FileEntry
{
public:
	FileEntry();
	FileEntry(const char* filename, const UFSSpec* macspec = 0L, const char* currRevision = 0L);
	FileEntry(const FileEntry& entry);

	inline FileEntry& operator=(const FileEntry& entry);

protected:
	CStr m_file;	/*!< Filename */
	CStr m_currRev;	/*!< Current revision */
	UFSSpec m_spec;	/*!< Mac spec */

friend class MultiFilesEntry;
friend class MultiFiles;
};

/// Used internally
class MultiFilesEntry
{
public:
	MultiFilesEntry();
	MultiFilesEntry(const char* path);
	MultiFilesEntry(const MultiFilesEntry& entries);

	MultiFilesEntry& operator=(const MultiFilesEntry& entries);

	void setdir(const char* newdir);
	void add(const char* file, const UFSSpec* spec = 0L, const char* currRevision = 0L);
	
	inline bool get(int index, CStr& path, CStr& fileName, CStr& currRev) const;

	inline int NumFiles(void) const;
	inline const char* getdir() const;

	const char* add(CvsArgs& args) const;
	const char* addfolder(CvsArgs& args, CStr& uppath, CStr& folder) const;

protected:
	CStr m_dir;						/*!< Directory */
	std::vector<FileEntry> m_files;

friend class MultiFiles;
};

/// Store multiple files by directory
class MultiFiles
{
public:
	MultiFiles();

	void newdir(const char* dir);
	void newfile(const char* file, const UFSSpec* spec = 0L, const char* currRevision = 0L);

	typedef std::vector<MultiFilesEntry>::const_iterator const_iterator;
	
	const_iterator begin() const { return m_dirs.begin(); }
	const_iterator end() const { return m_dirs.end(); }

	bool getdir(int index, CStr& path) const;

	int NumDirs(void) const { return m_dirs.size(); }
	int TotalNumFiles(void) const;

	void reset();

	bool Normalize();
	
protected:
	std::vector<MultiFilesEntry> m_dirs;
};

/// A pair of MultiFiles::const_iterator and index allowing to identify the FileEntry
class MultiFilesEntryIndex
{
public:
	MultiFilesEntryIndex(int index, MultiFiles::const_iterator mfi)
		: m_index(index), m_mfi(mfi)
	{
	}

	inline int GetIndex() const;
	inline MultiFiles::const_iterator GetIterator() const;

private:
	int m_index;
	MultiFiles::const_iterator m_mfi;
};

//////////////////////////////////////////////////////////////////////////
// FileEntry inline implementation

inline FileEntry& FileEntry::operator=(const FileEntry& entry)
{
	m_file = entry.m_file;
	m_currRev = entry.m_currRev;
	m_spec = entry.m_spec;
	
	return *this;
}

//////////////////////////////////////////////////////////////////////////
// MultiFilesEntry

/*!
	Get the file in the current directory
	\param index File index
	\param path Return path
	\param fileName Return filename
	\param currRev Return current revision
	\return true on success, false otherwise
*/
inline bool MultiFilesEntry::get(int index, CStr& path, CStr& fileName, CStr& currRev) const
{
	if( index < 0 || (size_t)index >= m_files.size() )
		return false;
	
	path = m_dir;
	fileName = m_files[index].m_file;
	currRev = m_files[index].m_currRev;
	
	return true;
}

/// Get the number of files in the current dir
inline int MultiFilesEntry::NumFiles(void) const
{
	return m_files.size();
}

/// Get the current directory
inline const char* MultiFilesEntry::getdir() const
{
	return m_dir;
}

//////////////////////////////////////////////////////////////////////////
// MultiFilesEntryIndex

/// Get the index
inline int MultiFilesEntryIndex::GetIndex() const
{
	return m_index;
}

/// Get the iterator
inline MultiFiles::const_iterator MultiFilesEntryIndex::GetIterator() const
{ 
	return m_mfi;
}

#endif /* MULTIFILES_H */
