// Ortho.cpp : Defines the entry point for the console application.

#include "stdafx.h"

#include <time.h>

#ifdef _MSC_VER
#pragma hdrstop
#endif

using namespace std;

#include "../../Kernel/kernelincludes.h"
#include "../../Kernel/orthogonalize.h"

void Help()
{
	cout << "Syntax: ortho [options] source.pla dest.pla" << endl;
	cout << "Options:" << endl;
	cout << "   -i n      Define the number of iterations. 1 is default." << endl;
	cout << "   -m n      Set the orthogonalization expansion method:" << endl;
	cout << "                1 - fastest" << endl;
	cout << "                2 - moderate" << endl;
	cout << "                3 - slow" << endl;
	cout << "                4 - method 4" << endl;
	cout << "                5 - method 5 (default)" << endl;
	cout << "                6 - method Hoger" << endl;
}

int main(int argc, char* argv[])
{
    PLA *source;
	PLA *result;
    PLA *best;
    int i;
	unsigned j;
	unsigned int it = 1;
    unsigned int opt;
	time_t tim;
    float t1, t2;
	Ortho *orthinst = NULL;
	char *src_file = NULL;
	char *dest_file = NULL;
	unsigned int method = 5;
	bool check = false;

    cout << "Ortho 3.0, (c) April 2010 by Petr Fiser" << endl << endl;
	if ( argc < 3 ) {
        Help();
        exit(1);
    }

    srand((unsigned) time(&tim));
//	srand(2);

	try {
		i = 1;
		while ( i != argc ) {
			if ( argv[i][0] != '-' && src_file == NULL ) src_file = argv[i];
			else if ( argv[i][0] != '-' ) dest_file = argv[i];
			else if ( strcmp( argv[i], "-i" ) == 0 ) {
				i++;
				it = atoi(argv[i]);
			}
			else if ( strcmp( argv[i], "-m" ) == 0 ) {
				i++;
				method = atoi(argv[i]);
			}
			else if ( strcmp( argv[i], "-check" ) == 0 ) {
				check = true;
			}
			else {
				Help();
				exit(1);
			}
			i++;
		}
	} catch (...) {
        Help();
        exit(1);
    }

	if ( src_file == NULL || (!check && dest_file == NULL) || method > 6 ) {
        Help();
        exit(1);
    }

//	try {
		if ( check ) {
			best = new PLA();
			if ( best == NULL) throw RuntimeException( "Ortho: Not enough memory" );
			best->LoadPLA(src_file);
		} else {	
			opt = UINT_MAX;
			best = NULL;
			t1 = GetMyCPUTime();
			for ( j = 0; j < it; j++ ) {
				source = new PLA();
				if ( source == NULL) throw RuntimeException( "Ortho: Not enough memory" );
				source->LoadPLA(src_file);
				orthinst = new Ortho(source);
				if ( orthinst == NULL) throw RuntimeException( "Ortho: Not enough memory" );
				t1 = GetMyCPUTime();
				result = orthinst->Run(method);
				t2 = GetMyCPUTime();
				 cout << t2-t1 << " " << result->getTerms() << endl;
				//cerr << t2-t1 << endl;
				if ( result->getTerms() < opt ) {
					delete best;
					opt = result->getTerms();
					best = result;
				} else delete result;
				delete orthinst;
			}
			t2 = GetMyCPUTime();
			cerr << t2-t1 << endl;

			best->SavePLA(dest_file);
		}
/*	} catch (RuntimeException e) {
		cerr << e.GetMsg() << endl;
		exit(1);
	} catch (IOException e) {
		cerr << e.GetMsg() << endl;
		exit(1);
	}*/
	if ( Ortho(best).IsOrthogonal(best) ) cout << "Orthogonality check OK" << endl;
	else cout << "Orthogonality check failed!" << endl;
    return 0;
}
