/*
  Free Download Manager Copyright (c) 2003-2007 FreeDownloadManager.ORG
*/

    

#include "libtorrent/piece_picker.hpp"

#include "test.hpp"

using namespace libtorrent;

int test_main()
{
	using namespace libtorrent;

	{
		const int num_pieces = 6;
			  
		
		piece_picker p(4, num_pieces * 4);

		
		std::vector<bool> have(num_pieces, false);
		have[0] = true;

		std::vector<piece_picker::downloading_piece> unfinished;
		piece_picker::downloading_piece partial;
		partial.index = 1;
		partial.finished_blocks[0] = true;
		partial.finished_blocks[2] = true;
		unfinished.push_back(partial);
		
		p.files_checked(have, unfinished);

		p.mark_as_filtered(4);
	
		TEST_CHECK(p.is_filtered(4) == true);
		TEST_CHECK(p.is_filtered(3) == false);
		
		p.mark_as_filtered(3);
		TEST_CHECK(p.is_filtered(3) == true);
		p.mark_as_unfiltered(3);
		TEST_CHECK(p.is_filtered(3) == false);
	
		TEST_CHECK(p.num_filtered() == 1);
		TEST_CHECK(p.num_have_filtered() == 0);

		std::vector<bool> filtered_pieces;
		p.filtered_pieces(filtered_pieces);
		bool expected1[] = {false, false, false, false, true, false};
		TEST_CHECK(std::equal(filtered_pieces.begin()
			, filtered_pieces.end(), expected1));

		std::vector<bool> peer1(num_pieces, false);
		std::vector<bool> peer2(num_pieces, false);
		std::vector<bool> peer3(num_pieces, false);

		peer1[2] = true;
		p.inc_refcount(2);

		peer1[3] = true;
		peer2[3] = true;
		p.inc_refcount(3);
		p.inc_refcount(3);

		peer1[4] = true;
		peer2[4] = true;
		peer3[4] = true;
		p.inc_refcount(4);
		p.inc_refcount(4);
		p.inc_refcount(4);

		peer1[5] = true;
		peer2[5] = true;
		peer3[5] = true;
		p.inc_refcount(5);
		p.inc_refcount(5);
		p.inc_refcount(5);
		
		
		
		
		
		
		
		

		
		
		

		std::vector<piece_block> picked;
		picked.clear();
		p.pick_pieces(peer1, picked, 1, false, tcp::endpoint());
		TEST_CHECK(picked.size() == 1);
		TEST_CHECK(picked.front().piece_index == 2);

		
		
		picked.clear();
		p.pick_pieces(peer2, picked, 1, false, tcp::endpoint());
		TEST_CHECK(picked.size() == 1);
		TEST_CHECK(picked.front().piece_index == 3);

		

		picked.clear();
		p.pick_pieces(peer3, picked, 1, false, tcp::endpoint());
		TEST_CHECK(picked.size() == 1);
		TEST_CHECK(picked.front().piece_index == 5);

		
		
		peer1[1] = true;
		peer2[1] = true;
		peer3[1] = true;
		p.inc_refcount(1);
		p.inc_refcount(1);
		p.inc_refcount(1);
		
		picked.clear();
		p.pick_pieces(peer3, picked, 1, false, tcp::endpoint());
		TEST_CHECK(picked.size() == 1);
		TEST_CHECK(picked.front().piece_index == 1);
		
		

		TEST_CHECK(picked.front().block_index != 0);
		TEST_CHECK(picked.front().block_index != 2);

		
		
		
		
		
		
		
		
		
		
		
		

		
		
		p.mark_as_downloading(piece_block(1, 1), tcp::endpoint(address::from_string("1.1.1.1"), 0));
		p.mark_as_downloading(piece_block(1, 3), tcp::endpoint(address::from_string("1.1.1.1"), 0));
		p.mark_as_downloading(piece_block(2, 0), tcp::endpoint(address::from_string("1.1.1.1"), 0));

		std::vector<piece_picker::downloading_piece> const& downloads = p.get_download_queue();
		TEST_CHECK(downloads.size() == 2);
		TEST_CHECK(downloads[0].index == 1);
		TEST_CHECK(downloads[0].finished_blocks[0] == 1);
		TEST_CHECK(downloads[0].finished_blocks[1] == 0);
		TEST_CHECK(downloads[0].finished_blocks[2] == 1);
		TEST_CHECK(downloads[0].finished_blocks[3] == 0);
		TEST_CHECK(downloads[0].requested_blocks[1] == 1);
		TEST_CHECK(downloads[0].requested_blocks[3] == 1);

		TEST_CHECK(downloads[1].index == 2);
		TEST_CHECK(downloads[1].finished_blocks[0] == 0);
		TEST_CHECK(downloads[1].finished_blocks[1] == 0);
		TEST_CHECK(downloads[1].finished_blocks[2] == 0);
		TEST_CHECK(downloads[1].finished_blocks[3] == 0);
		TEST_CHECK(downloads[1].requested_blocks[0] == 1);
		TEST_CHECK(downloads[1].requested_blocks[1] == 0);
		TEST_CHECK(downloads[1].requested_blocks[2] == 0);
		TEST_CHECK(downloads[1].requested_blocks[3] == 0);

		TEST_CHECK(p.is_downloading(piece_block(1, 1)));
		TEST_CHECK(p.is_downloading(piece_block(1, 3)));
		TEST_CHECK(p.is_downloading(piece_block(2, 0)));
		TEST_CHECK(!p.is_downloading(piece_block(2, 1)));

		picked.clear();
		p.pick_pieces(peer1, picked, 1, false, tcp::endpoint());
		TEST_CHECK(picked.size() == 2);

		piece_block expected3[] = { piece_block(2, 0), piece_block(2, 1) };
		TEST_CHECK(std::equal(picked.begin()
			, picked.end(), expected3));

		
		
		
		

		picked.clear();
		p.pick_pieces(peer1, picked, 1, true, tcp::endpoint());

		
		
		TEST_CHECK(picked.size() == 4);
	
		piece_block expected4[] =
		{
			piece_block(3, 0), piece_block(3, 1)
			, piece_block(3, 2), piece_block(3, 3)
		};
		TEST_CHECK(std::equal(picked.begin()
			, picked.end(), expected4));

		
		

		picked.clear();
		p.pick_pieces(peer1, picked, 100, true, tcp::endpoint());

		TEST_CHECK(picked.size() == 14);
	
		piece_block expected5[] =
		{
			piece_block(3, 0), piece_block(3, 1)
			, piece_block(3, 2), piece_block(3, 3)
			, piece_block(5, 0), piece_block(5, 1)
			, piece_block(5, 2), piece_block(5, 3)
			, piece_block(2, 0), piece_block(2, 1)
			, piece_block(2, 2), piece_block(2, 3)
			, piece_block(1, 1), piece_block(1, 3)
		};
	
		TEST_CHECK(std::equal(picked.begin()
			, picked.end(), expected5));

		
		

		picked.clear();
		p.pick_pieces(peer1, picked, 100, true, tcp::endpoint(address::from_string("1.1.1.1"), 0));

		TEST_CHECK(picked.size() == 11);
	
		piece_block expected6[] =
		{
			piece_block(2, 1), piece_block(2, 2)
			, piece_block(2, 3)
			, piece_block(3, 0), piece_block(3, 1)
			, piece_block(3, 2), piece_block(3, 3)
			, piece_block(5, 0), piece_block(5, 1)
			, piece_block(5, 2), piece_block(5, 3)
		};
	
		TEST_CHECK(std::equal(picked.begin()
			, picked.end(), expected6));

		
		
		p.mark_as_finished(piece_block(4, 2), tcp::endpoint());
	}
	
	return 0;
}

