/** @file main.cpp
 *
 *	The PACE main file.
 *
 *	See params.cpp for all accepted parameters.
 *
 *	(C) Ceslav Przywara 2008, MFF UK Prague
 *
 */

/** @mainpage Introduction
 *
 *	PACE (Prague Automatic Collocation Extractor) is a processing program
 *	designed for extraction and statistical evaluation of collocations with
 *	syntactic structure from Prague Dependency Treebank 2.0.
 *	PDT is textual corpus with morphologic, semantic
 *	and syntactic annotation. You can find more information about PDT at:
 *	http://ufal.mff.cuni.cz/pdt2.0/
 *
 *	Program was created on bachelor thesis purpose.
 *
 *	(C) Ceslav Przywara 2008, MFF UK Prague
 *
 *	(chester at matfyz dot cz)
 *  
 */


#include <cstdlib>
#include <string>
#include <iostream>

// Settings
#include "config.h"
// Init functions
#include "init.h"
// Notifications
#include "notifier.h"
// Params parsing
#include "params.h"
// Processing
#include "processor.h"
// Output writing
#include "writer.h"

/** Function to be called to terminate program abnormally (due to fatal errors).
 */
void exit_failure(void) {
	ace::notifier::progress.info("\nProgram terminated due to fatal error(s). See stderr output for more info.");
	exit(EXIT_FAILURE);
}

/** Program main function.
 *	@param argc Number of parameters passed to program.
 *	@param argv Values of parameters passed to program.
 *	@return 0, if program exits successfully, non-zero otherwise.
 */
int main(int argc, char** argv) {

	// 0. Parse params if any.
	if ( argc == 1 ) {
		// Let the user know the right way of riding our piece of software :)
		ace::print_usage();
		return EXIT_SUCCESS;
	}
	ace::parse_params(argc, argv);
	if ( !ace::settings::ready() ) {
		ace::notifier::error.fatal_error("Some of the mandatory program parameters are missing!");
		// The user definitely needs to know the right way of riding our piece of software :)
		ace::print_usage();
		exit_failure();
	} else if ( !ace::settings::correct() ) {
		ace::notifier::error.fatal_error("Some of the program parameters are in incorrect format!");
		// Again, let the user know the right way of riding our piece of software :)
		ace::print_usage();
		exit_failure();
	}

	// 
	ace::notifier::progress.info("Performing start-up checks.");

	// 1. Startup init.
	if ( !ace::startup_init() ) {
		// Some error occurred - notification has been already printed out, so...
		exit_failure();
	}

	// Files to be processed.
	ace::filenames_t files_to_process;	
	size_t files_total_size = 0;

	// 2. Open input file and gather data filenames.
	if ( !ace::read_and_check_input_datafiles(files_to_process, files_total_size) ) {
		// Some error occurred - notification has been already printed out, so...
		exit_failure();
	}

	// 3. Open output file (and keep it open!)
	std::ofstream output_file(ace::settings::output_file);
	if ( !output_file ) {
		ace::notifier::error.fatal_error("Cannot open output file: " + std::string(ace::settings::output_file) + "!");
		exit_failure();
	}

	// 4. Open context output file (if context tracing is set on)
	std::ofstream context_output_file;

	if ( ace::settings::context_tracing_on() ) {
		// Open context output file (and keep it open!)
		context_output_file.open(ace::settings::context_output_file);
		if ( !context_output_file ) {
			ace::notifier::error.fatal_error("Cannot open context output file: " + std::string(ace::settings::context_output_file) + "!");
			exit_failure();
		}
	}

	// 5. Open stats output file (if given:)
	std::ofstream stats_output_file;

	if ( ace::settings::stats_file ) {
		// Open and keep it open.
		stats_output_file.open(ace::settings::stats_file);
		if ( !stats_output_file ) {
			ace::notifier::error.fatal_error("Cannot open file to save statistics: " + std::string(ace::settings::stats_file) + "!");
			exit_failure();
		}
	}

	// 5.5 Open morphologic filter stats file (if given:)
	std::ofstream morphologic_filter_stats_output_file;

	if ( ace::settings::morphologic_filter_stats_file ) {
		// Open and keep it open.
		morphologic_filter_stats_output_file.open(ace::settings::morphologic_filter_stats_file);
		if ( !morphologic_filter_stats_output_file ) {
			ace::notifier::error.fatal_error("Cannot open file to save morphologic filter statistics: " + std::string(ace::settings::morphologic_filter_stats_file) + "!");
			exit_failure();
		}
	}

	// 
	ace::notifier::progress.elapsed("Finished performing start-up checks.");

	//
	try {
		// 6. Process input files.
		ace::process(files_to_process, files_total_size);
	} catch ( std::exception& e ) {
		ace::notifier::error.fatal_error(e.what());
		exit_failure();
	}

	// 7.6 Output stats.
	if ( stats_output_file.is_open() ) {
		// Inform & perform (TM).
		ace::notifier::progress.info("Writing statistics file.");		
		ace::write_stats(stats_output_file);
		stats_output_file.close();
		ace::notifier::progress.elapsed("Finished writing statistics file.");
	}

	// 7.7 Output morphologic filter stats.
	if ( morphologic_filter_stats_output_file.is_open() ) {
		// Inform & perform (TM).
		ace::notifier::progress.info("Writing morphologic filter statistics file.");		
		ace::write_morphologic_filter_stats(morphologic_filter_stats_output_file);
		morphologic_filter_stats_output_file.close();
		ace::notifier::progress.elapsed("Finished writing morphologic filter statistics file.");
	}

	// 
	ace::notifier::progress.info("Writing output datafile.");

	// 7. Print the results to the file.
	ace::write(output_file);
	output_file.close();

	// Elapsed:
	ace::notifier::progress.elapsed("Finished writing output datafile.");

	// 7.5 Output contexts.
	if ( context_output_file.is_open() ) {
		// Inform & perform (TM).
		ace::notifier::progress.info("Writing contexts to file.");
		ace::write_contexts(context_output_file);
		context_output_file.close();		
		ace::notifier::progress.elapsed("Finished writing contexts to file.");
	}

	// 8. Nara, papa!:)
	ace::notifier::progress.info("Bye!");

	return EXIT_SUCCESS;
}
