/*
 *  Copyright (C) 2005 Alo Sarv <madcat_@users.sourceforge.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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * \file files.h      Interface for TorrentFile and PartialTorrent classes
 */

#ifndef __BT_FILES_H__
#define __BT_FILES_H__

#include <hncore/sharedfile.h>
#include <hncore/partdata.h>
#include <hncore/hasher.h>

namespace Bt {

class TorrentFile : public SharedFile {
public:
	TorrentFile(const std::vector<SharedFile*> &files);
	virtual std::string read(uint64_t begin, uint64_t end);
private:
	std::map<uint64_t, SharedFile*> m_children;
	typedef std::map<uint64_t, SharedFile*>::iterator Iter;

	~TorrentFile();
};

class PartialTorrent : public PartData {
public:
	PartialTorrent(const std::vector<PartData*> &files);
protected:
	virtual void doWrite(uint64_t begin, const std::string &data);
	virtual void verifyRange(Range64 range, const HashBase *ref);
	virtual void corruption(uint64_t begin, uint64_t end);
private:
	// Map of children, keyed by begin offset
	std::map<uint64_t, PartData*> m_children;
	typedef std::map<uint64_t, PartData*>::iterator Iter;
	// Map of children, keyed by object, for reverse lookups
	std::map<PartData*, uint64_t> m_childrenReverse;
	typedef std::map<PartData*, uint64_t>::iterator RIter;

	~PartialTorrent();
	void onDataAdded(PartData *file, uint64_t offset, uint32_t amount);
	void onChildCorruption(PartData *file, uint64_t begin, uint64_t end);
};

/**
 * Customized hasher for torrent files. Since chunks can cross file boundaries
 * in torrents, we need to read data possibly from arbitary number of files,
 * and concatenate the data together.
 */
class TorrentHasher : public HashWork {
public:
	/**
	 * Construct custom hasher
	 *
	 * @param files      Files from which to read data
	 * @param begin      Relative position in files[0] to begin reading
	 * @param end        Relative position in files.back() to end reading
	 * @param ref        Reference hash
	 */
	TorrentHasher(
		const std::vector<boost::filesystem::path> &files,
		uint64_t begin, uint64_t end, const HashBase *ref
	);
protected:
	/**
	 * Read next data from file
	 *
	 * @param pos      Current position in file
	 * @return         Number of bytes read
	 */
	virtual uint64_t readNext(uint64_t pos);
private:
	//! Files for this work
	std::vector<boost::filesystem::path> m_files;

	//! Iterator for the above vector
	typedef std::vector<boost::filesystem::path>::iterator Iter;

	//! Current file being hashed
	Iter m_curFile;
};

}

#endif