// file:          main.cpp in project Searching.
// description:   Root for testing generic searchspace abstractions and concretions.
//                Sak A16(3, 6), PÜ 31.3(3), PÜ 31.5(4, 5, 13)(c, f).
// author:        Karlheinz Hug
// creation date: 2012-06-14
// last update:   2012-07-05

#include <cstdlib>
#include <iostream>
#include <string>
#include <typeinfo>

#include "SearchspaceGeneral.hpp"
#include "SearcharrayGeneral.hpp"
#include "SearchspaceFactory.hpp"

	std::string command_name;

	void show_usage_exit (std::string title)
	{
		std::cout << title << std::endl <<
			"Please call " << command_name << " with these arguments:" << std::endl <<
			command_name << " array_size min_item max_item searched_item space_type item_type" << std::endl <<
			"array_size: integer >= 0"  << std::endl <<
			"min_, max_, searched_item: numbers of item_type with min_item <= max_item" << std::endl <<
			"space_type:" << std::endl <<
			"   l   linear array" << std::endl <<
			"   L   fast linear array with sentinel" << std::endl <<
			"   b   binary array" << std::endl <<
			"   B   fast binary array" << std::endl <<
			"   s   sequence (linked list)" << std::endl <<
			"   S   fast sequence with sentinel" << std::endl <<
			"   t   binary tree" << std::endl <<
			"item_type:" << std::endl <<
			"   c, C   char" << std::endl <<
			"   i, I   integer" << std::endl <<
			"   d, D   double" << std::endl;
		exit(1);
	}

	// For separation of function and i/o, PÜ 31.5(5):
	template <typename T>
	void print (T x)
	{
		std::cout << x << " ";
	}

	template <typename T>
	void test (unsigned int size, T min_item, T max_item, T searched_item, char space_type)
	{
		if (min_item > max_item)
		{
			show_usage_exit("Wrong arguments 2, 3: item range must be nonempty!");
		}
		SearchspaceGeneral<T> * searchspace =
			SearchspaceFactory<T>::new_searchspace(size, min_item, max_item, space_type);
		std::cout << typeid(*searchspace).name() << std:: endl <<
			"searchspace: [ ";
		searchspace->for_all_act(print);
		std::cout << "]" << std::endl <<
			"searched_item " << searched_item <<
			(searchspace->has(searched_item) ? "" : " not") << " found in searchspace." << std::endl;

		// For position of searched item, Sak A 16(8), PÜ 31.5(13(h):
		if (std::tolower(space_type) == 'l' || std::tolower(space_type) == 'b')
		{
			std::cout << "position of searched_item " << searched_item << " in array: " <<
				(dynamic_cast<SearcharrayGeneral<T> *>(searchspace))->some_index(searched_item) << std::endl;
		}
		delete searchspace;
	}

	int main (int argc, char * argv[])
	{
		command_name = argv[0];
		if (argc < 7)
		{
			show_usage_exit("Missing arguments!");
		}
		if (std::atoi(argv[1]) < 0)
		{
			show_usage_exit("Wrong argument 1: array_size must be positive!");
		}
		unsigned int size = std::atoi(argv[1]);
		char space_type   = *(argv[5]);
		char item_type    = tolower(*(argv[6]));

		// For different generic parameters for element type, PÜ 31.5(13)(f):
		switch (item_type)
		{
			case 'c' :
				test<char>(size, std::atoi(argv[2]), std::atoi(argv[3]), std::atoi(argv[4]), space_type);
				break;
			case 'i' :
				test<int>(size, std::atoi(argv[2]), std::atoi(argv[3]), std::atoi(argv[4]), space_type);
				break;
			case 'd' : default :
				test<double>(size, std::atof(argv[2]), std::atof(argv[3]), std::atof(argv[4]), space_type);
				break;
		}
		return 0;
	}
