/*
 * RandomStringFactory.h
 *
 *  Created on: 27. 3. 2014
 *      Author: Jan Travnicek
 */

#ifndef RANDOM_STRING_FACTORY_H_
#define RANDOM_STRING_FACTORY_H_

#include <alib/set>
#include <alib/random>
#include <alib/vector>

#include <exception/CommonException.h>

#include <string/LinearString.h>

namespace string {

namespace generate {

/**
 * Generator of random strings.
 *
 */
class RandomStringFactory {
public:
	/**
	 * Generates a random string of given size.
	 *
	 * \param size the length of the generated string
	 * \param alphabetSize size of the alphabet (1-26 for characters and 0-INT_MAX for integers)
	 * \param randomizedAlphabet selects random symbols from a-z range if true
	 * \param integerSymbols use integers as symbols in the generated string is true, randomize alphabet is not used if integer alphabet is requested
	 *
	 * \return random string
	 */
	static string::LinearString < std::string > generateLinearString ( size_t size, size_t alphabetSize, bool randomizedAlphabet, bool integerSymbols );

	/**
	 * Generates a random string of given size.
	 *
	 * \param size the length of the generated string
	 * \param alphabetSize size of the alphabet (1-26 for characters)
	 * \param randomizedAlphabet selects random symbols from a-z range if true
	 *
	 * \return random string
	 */
	static string::LinearString < std::string > generateLinearString ( size_t size, size_t alphabetSize, bool randomizedAlphabet );

	/**
	 * Generates a random string of given size
	 * \tparam SymbolType the type of symbols of the random string
	 *
	 * \param size the length of the generated string
	 * \param alphabet alphabet of the generated string
	 *
	 * \return random string
	 */
	template < class SymbolType >
	static string::LinearString < SymbolType > generateLinearString ( size_t size, ext::set < SymbolType > alphabet );
};

template < class SymbolType >
string::LinearString < SymbolType > RandomStringFactory::generateLinearString ( size_t size, ext::set < SymbolType > alphabet ) {

	if ( alphabet.empty ( ) )
		throw exception::CommonException ( "Alphabet size must be greater than 0." );

	ext::vector < SymbolType > alphabetList ( alphabet.begin ( ), alphabet.end ( ) );
	ext::vector < SymbolType > elems;

	for ( size_t i = 0; i < size; i++ )
		elems.push_back ( alphabetList[ext::random_devices::semirandom ( ) % alphabetList.size ( )] );

	return string::LinearString < SymbolType > ( elems );
}

} /* namespace generate */

} /* namespace string */

#endif /* RANDOM_STRING_FACTORY_H_ */
