/*
 *  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
 */

#include <hnbase/sha1transform.h>
#include <hncore/fileslist.h>
#include <hncore/sharedfile.h>
#include <hncore/partdata.h>
#include <hncore/metadata.h>
#include <hncore/metadb.h>
#include <hncore/hydranode.h>
#include <hncore/bt/torrentinfo.h>
#include <hncore/bt/files.h>
#include <boost/spirit.hpp>

using namespace Bt;
using namespace boost::spirit;

int main(int argc, char *argv[]) {
#if defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
        std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
#endif
	assert(argc == 2);
	std::string data;
	std::ifstream f(argv[1], std::ios::binary);
	char buf[10240];
	while (f) {
		f.read(buf, 10240);
		data.append(std::string(buf, f.gcount()));
	}
	TorrentInfo ti(data);

	Sha1Transform t;
	t.sumUp(data.data(), data.size());
	Hash<SHA1Hash> tHash = t.getHash();

	boost::format customData("btorrent:%s:%d");

	// bring up configuration before creating downloads
	Hydranode::instance().preInit(argc, argv);
	Hydranode::instance().initConfig();

	// ok, now that we have the info, create the neccesery objects
	// first create the normal downloads, but add infohash key to them,
	// so that we can find them later on
	std::vector<TorrentInfo::TorrentFile> files = ti.getFiles();
	for (uint32_t i = 0; i < files.size(); ++i) {
		MetaData *md = new MetaData(files[i].getSize());
		md->addFileName(files[i].getName());
		md->addCustomData((customData % tHash.decode() % i).str());
		MetaDb::instance().push(md);
		FilesList::instance().createDownload(files[i].getName(), md);
	}

	// locate our newly-created download objects
	std::map<uint32_t, SharedFile*> myDownloads;
	FilesList::SFIter it = FilesList::instance().begin();
	while (it != FilesList::instance().end()) {
		SharedFile *sf = *it++;
		if (!sf->getMetaData()) {
			continue;
		}
		MetaData *md = sf->getMetaData();
		for (uint32_t i = 0; i < md->getCustomCount(); ++i) {
			std::string data = md->getCustomData(i);
			std::string hash;
			uint32_t num = 0;
			parse_info<> nfo = parse(
				data.c_str(), data.c_str() + data.size(),
				"btorrent:" >> *alnum_p[push_back_a(hash)]
				>> ':' >> uint_p[assign_a(num)]
			);
			if (nfo.full) {
				myDownloads[num] = sf;
				break;
			}
		}
	}
	std::map<uint32_t, SharedFile*>::iterator it2(myDownloads.begin());
	std::vector<SharedFile*> sharedFiles;
	std::vector<PartData*> tempFiles;
	while (it2 != myDownloads.end()) {
		sharedFiles.push_back((*it2).second);
		tempFiles.push_back((*it2).second->getPartData());
		++it2;
	}
	TorrentFile *tf = new TorrentFile(sharedFiles);
	PartialTorrent *pt = new PartialTorrent(tempFiles);
	MetaData *md = new MetaData(tf->getSize());
	md->addFileName(tf->getName());
	md->addHashSet(new HashSet<SHA1Hash>(ti.getHashes()));
	tf->setMetaData(md);
	pt->setMetaData(md);
	FilesList::instance().push(tf);
}