/** @file config.cpp
 *
 *	File contains definitions of constants and static struct members declared within config.h file.
 *
 *	See config.h for more info.
 *
 *	(C) Ceslav Przywara 2008, MFF UK Prague
 *
 */

#include <limits>

#include "config.h"

namespace ace {

/* Constants.
 */
namespace constants {

// Reserve most significant bit for counter overflow flag (see ngram.h).
const size_t max_grammity = std::numeric_limits<ngram_type_t>::digits - 1;

const size_t bits_per_char = std::numeric_limits<unsigned char>::digits;

const size_t ngram_within_block = 16*1024;

const size_t default_precision = 10;
	
const size_t max_sentence_length = std::numeric_limits<word_order_t>::max();

const size_t max_collocation_window_size = std::numeric_limits<size_t>::digits;

const char significant_position_mark = '*';

const char insignificant_position_mark = '-';

const size_t sentences_radius_max_size = 2;

const size_t words_radius_max_size = 50;

}


/* TaggedLemma static members definition.
 */
const size_t TaggedLemma::_last_bit_index = sizeof(string_index_t) / sizeof(tag_index_t) - 1;

const string_index_t TaggedLemma::_lemma_bits_mask = std::numeric_limits<string_index_t>::max() >> (sizeof(tag_index_t) * constants::bits_per_char);


/* Settings (default values).
 */
namespace settings {

bool all_thresholds_together = false;

size_t bucket_size = 4; // (real value is 2 ^ bucket_size)

#ifdef _SURFACE_MODE
size_t collocation_window_size = 0;
#endif

ContextWindow context_window;

const char *context_filter_file = 0;

const char *context_output_file = 0;

//const char *context_tag_mask = 0;

size_t crop_ratio = 2;

const char *dir = 0;

const char *morphologic_filter_file = 0;

const char *morphologic_filter_stats_file = 0;

const char *input_file = 0;

ngram_size_t n = 0;

const char *output_file = 0;

size_t precision = constants::default_precision;

bool sort = false;

const char *stats_file = 0;

Sieves sieves;

Thresholds thresholds;

const char *morphologic_tag_mask = 0;

bool verbose = false;


/** Checks, if left tag mask is "lesser" than right tag mask. Lesser means its
 *	not longer and all its significant positions are also significant in the
 *	counterpart.
 *	@return True, if left tag mask is "lesser" than right tag mask.
 */
bool _mask_less_than(const char *lhs, const char *rhs) {
	if ( lhs == 0 ) {
		return true;
	}
	if ( rhs == 0 ) {
		// Right hand arg. can be zero, but not when the left one isn't.
		return false;
	}
	while ( (*lhs) && (*rhs) ) {
		if ( (*lhs == constants::significant_position_mark) && (*rhs == constants::insignificant_position_mark) ) {
			return false;
		}
		++lhs, ++rhs;
	}
	// Left hand argument must be at his end, otherwise it's not lesser.
	return (*lhs == constants::null_char);
}

/*	Interface item implementation.
 */
bool check_mask(const char *mask) {
	if ( mask == 0 ) {
		// Empty mask is allowed.
		return true;
	}
	const char *pc = mask;
	while ( *pc ) {
		if ( (*pc != constants::significant_position_mark) && (*pc != constants::insignificant_position_mark) ) {
			// Only '*' and '-' are allowed...
			return false;
		}
		++pc;
	}
	return true;
}

/*	Interface item implementation.
 */
bool context_tracing_on(void) { return context_output_file != 0; }

/*	Interface item implementation.
 */
bool correct(void) {
	if ( (input_file == 0) || (output_file == 0) || (n <= 1) || (constants::max_grammity < n) ) {
		return false;
	}
	if ( !check_mask(morphologic_tag_mask) ) {
		return false;
	}
	if ( precision == 0 ) {
		return false;
	}
	if ( context_tracing_on() && !context_window.check() ) {
		//|| !check_mask(context_tag_mask) || !_mask_less_than(context_tag_mask, morphologic_tag_mask)) ) {
		return false;
	}
#ifdef _SURFACE_MODE
	if ( (collocation_window_size + 1) < n ) {
		// To small.
		// TODO - move to init? Report?
		collocation_window_size = n - 1;
	} else if ( collocation_window_size > constants::max_collocation_window_size ) {
		return false;
	}	

#endif
	return true;
}

/*	Interface item implementation.
 */
bool ready(void) {
	// Must be non-defaults.
	return (input_file != 0) && (n != 0) && (output_file != 0);
}

} // namespace settings

} // namespace ace
