/** @file init.cpp
 *
 *	Definition (implementation) of initialization module interface.
 *
 *	See init.h for more info.
 *
 *	(C) Ceslav Przywara 2008, MFF UK Prague
 *
 */

#include <fstream>

// Settings
#include "config.h"
// Static members initialization
#include "evaluation.h"
// Self header file
#include "init.h"
// Static members initialization
#include "ngram.h"
// Hash function tables check.
#include "ngrams.h"
// Errors, warnings
#include "notifier.h"
// Global vars "set up"
#include "persistent.h"

namespace ace {

/*	Interface item implementation - for info see description in header file.
 */
bool read_and_check_input_datafiles(filenames_t& files_to_process, size_t& files_total_size) {
	
	std::ifstream file_list(settings::input_file);
	
	if ( !file_list ) {
		notifier::error.fatal_error("Cannot open the file: " + std::string(settings::input_file) + "!");
		return false;
	}
	
	bool status = true;
	
	std::ifstream tmp;

	std::string dir = (settings::dir == 0) ? std::string() : std::string(settings::dir);
	
	while ( file_list ) {
		std::string str;
		std::getline(file_list, str);
		// Ignore empty lines.
		if ( !str.empty() ) {
			// Check, if file can be opened for reading.
			tmp.open((dir + str).c_str());
			if ( !tmp ) {
				// What a pity...
				notifier::error.fatal_error("Input datafile : " + dir + str + " cannot be opened for reading!");
				status = false;
			} else {
				// Count file length.
				tmp.seekg(0, std::ios::end);
				std::streampos pos = tmp.tellg();
				tmp.seekg(0, std::ios::beg);
				if ( pos > 0 ) { // tellg() returns -1 in case of failure.
					files_total_size += pos;
				}
				// Close and store.
				tmp.close();
				files_to_process.push_back(dir + str);
			}
		}
	}
	
	file_list.close();

	if ( files_to_process.empty() ) {
		notifier::error.fatal_error("Input data files list is empty!");
		return false;
	}

	// Otherwise.
	return status;
}
	
/*	Interface item implementation - for info see description in header file.
 */
bool startup_init(void) {
	
	NGram::init();
	
	NGramToken::init();

	if ( !NGramHashCounter::check(settings::n) ) {
		// TODO: This should be compile time error.
		notifier::error.fatal_error("Predefined # counter tables are to small!");
	}

	EvaluationTables::init();
	
	persistent::ngrams.init(constants::ngram_within_block);

	// TODO: Literals -m!
	
	// Read morphological filter rules?
	if ( settings::morphologic_filter_file != 0 ) {
		// Morphological filter is set on.
		if ( settings::morphologic_tag_mask == 0 ) {
			// No tag info to use with filter!
			notifier::error.warning("Extraction of morphologic information is not set on (parameter -m not specified). Morphologic filter will not be applied...");
		}
		// Otherwise read the rules.
		else if ( !persistent::morphologic_filter.read_rules(settings::morphologic_filter_file, settings::n) ) {
			// Error, rules cannot be read.
			notifier::error.fatal_error("Cannot read rules from file: " + std::string(settings::morphologic_filter_file) + "!");
			return false;
		}
	}

	if ( settings::morphologic_filter_stats_file != 0 ) {
		// 
		if ( settings::morphologic_filter_file == 0 ) {
			// Sorry man, but stats just cannot be sucked out from the toe...:)
			notifier::error.warning("Morphologic filter is not turn on (parameter -f not specified). Morphologic filter stats cannot be retrieved...");
		}
	}
	
	// Read context filter rules?
	if ( settings::context_filter_file != 0 ) {
				
		if ( settings::context_output_file == 0 ) {
			// No context output file specified!
			notifier::error.warning("Context output file is not specified (parameter -c). Morphologic filter for N-gram context will not be applied...");
		} else if ( settings::morphologic_tag_mask == 0 ) {
			// No tag info to use with filter!
			notifier::error.warning("Extraction of morphologic information is not set on (parameter -m is not specified). Morphologic filter for N-gram context will not be applied...");
		}
		// Otherwise read the rules.
		else if ( !persistent::context_filter.read_rules(settings::context_filter_file) ) {
			// Error, rules cannot be read.
			notifier::error.fatal_error("Cannot read rules from file: " + std::string(settings::context_filter_file) + "!");
			return false;
		}
	}
	
	// Some statistics can be obtained only for bigrams...
	if ( settings::n != 2 ) {
		if ( settings::thresholds.mutual_information > 0.0 ) {
			notifier::error.warning("Mutual information evaluation only available for N equal 2. Threshold ignored...");
		}
		if ( settings::thresholds.pearsons_coefficient > 0.0 ) {
			notifier::error.warning("Pearson's coefficient evaluation only available for N equal 2. Threshold ignored...");
		}
		if ( settings::thresholds.t_test > 0.0 ) {
			notifier::error.warning("t test evaluation only available for N equal 2. Threshold ignored...");
		}
		if ( settings::thresholds.z_score > 0.0 ) {
			notifier::error.warning("z score evaluation only available for N equal 2. Threshold ignored...");
		}
	}

	return true;
}

} // namespace ace
