#include "base/bdmbase.h"
#include "base/user_info.h"
#include "generator.h"
#include "additive_generator.h"
#include "size_generator.h"
#include "square_mat_point.h"
#include <iostream>
#include <iomanip>
#include <memory>
#include <stdlib.h>

using namespace std;
using namespace bdm;
using namespace itpp;

UIREGISTER ( size_generator );
UIREGISTER ( additive_generator );
UIREGISTER ( square_mat_point );

const char *generator_file_name = "generator.cfg";
const char *agenda_file_name = "agenda.cfg";
int agenda_length = 10;

int main ( int argc, char const *argv[] ) {
	RNG_randomize();

	bool unknown = false;
	int update_next = 0; // 1 generator file, 2 agenda file, 3 agenda length
	const char **param = argv + 1;
	while ( *param && !unknown ) {
		if ( update_next ) {
			if ( update_next == 1 ) {
				generator_file_name = *param;
			} else if ( update_next == 2 ) {
				agenda_file_name = *param;
			} else {
				int length = atoi ( *param );
				if ( length > 0 ) {
					agenda_length = length;
				} else {
					cerr << "invalid agenda length value ignored" << endl;
				}
			}

			update_next = 0;
		} else {
			if ( !strcmp ( *param, "-a" ) ) {
				update_next = 2;
			} else if ( !strcmp ( *param, "-g" ) ) {
				update_next = 1;
			} else if ( !strcmp ( *param, "-l" ) ) {
				update_next = 3;
			} else {
				unknown = true;
			}
		}

		++param;
	}

	if ( unknown || update_next ) {
		cerr << "usage: " << argv[0] << " [ -g generator.cfg ] [ -a agenda_output.cfg ] [ -l agenda_length ]" << endl;
	} else {
		Array<square_mat_point *> mag ( agenda_length );

		UIFile gspec ( generator_file_name );
		auto_ptr<generator> gen ( UI::build<generator> ( gspec, "generator", UI::compulsory ) );
		for ( int i = 0; i < agenda_length; ++i ) {
			mat m = gen->next();
			square_mat_point *p = new square_mat_point();
			p->set_parameters ( m, randu ( m.rows() ), randu() );
			mag ( i ) = p;
		}

		UIFile fag;
		UI::save ( mag, fag, "agenda" );
		fag.save ( agenda_file_name );

		for ( int i = 0; i < agenda_length; ++i ) {
			square_mat_point *p = mag ( i );
			mag ( i ) = 0;
			delete p;
		}
	}
}
