// program to generate to data for programs that read ascii files
#include <fstream.h>
#include <iomanip.h>
#include <limits.h>
#include <stdlib.h>
#include "ObjProGen/environ.h"
#include "ObjProComGui/cgidbg.h"
#include "gen_data.h"
#include "ObjProGen/makedir.h"

GenData::GenData(const char * name,int fields,int strt_val, int skp_val,
		int mx_val, format f,int tot,int w,InsertList * lst,double dvs,
			double fac):
			file_name(name),fields_per_line(fields),
			max_val(mx_val),skip_val(skp_val),start_val(strt_val),
			form(f),total_out(tot),
			str(new ofstream(Environment::expand_file_name(name))),
			width(w),
			divisor(dvs),
			multiplier(fac),
			flds(0),
			insert(lst),
			total_count(0)
{
	if (str->good()) {
		out();
		return ;
	}
	cerr << "Cannot create file `" << name << "'.\n" ;
	const char *exp =  Environment::expand_file_name(name) ;
	if (exp != name) cerr << "Name expands to `" << exp << "'.\n" ;
	SystemErrorMessage();
	cerr << "\n" ;
	exit(1);
}

void GenData::out(InsertList& ins)
{
	for (int i = 0 ; i < ins.count;i++) {
		if (total_count  >= total_out) return ;
		if (ins.values) out_val(ins.values[i]);
		else out_val(ins.strings[i]);
	}
}

int GenData::check_insert(int val)
{
	if (total_count >= total_out) return INT_MAX ;
	if (!insert) return INT_MAX ;
	int next = INT_MAX ;
	for (InsertList * item = insert ; item->count; item++) {
		if (total_count >= total_out) return INT_MAX;
		int where = item->where ;
		if (where < val) continue ;
		if (where == val) out(*item);
		else if (where < next) next = where ;
	}
	if (total_count >= total_out) return INT_MAX ;
	while (next < total_count) next = check_insert(next);
		
	return next ;
}

void GenData::out_val(const char *st)
{
	if (total_count >= total_out) return ;
	*str << st ;
	field_out();
}

void GenData::out_val(double v)
{
	if (total_count >= total_out) return ;
	*str << setw(width) << v ;
	field_out();
}

void GenData::field_out()
{
	total_count++;
	if (++flds >= fields_per_line) {
		*str << "\n" ;
		flds = 0 ;
	} else *str << " " ;
}

void GenData::out()
{
	total_count = 0 ;
	flds = 0 ;
	int skip = skip_val ;
	int next_insert = check_insert(0);
	for(;;) {
		int last_i = 0 ;
		int skip = skip_val ;
		for (int i = start_val; i < max_val; i+=skip) {
			if (total_count >= total_out) return ;
			if (i >= 0 && last_i < 0) skip = skip_val;
			last_i = i ;
			skip += 1 + (skip >> 5) ;
			if (form == f_float) out_val(i / divisor * multiplier) ;
			else out_val(i,form);
			if (total_count == next_insert)
				next_insert = check_insert(total_count);
		}
	}
	*str << "\n" ;
}

void main()
{

	if (!CheckSubDir(Environment::expand_file_name(
		"$OPD_ROOT/validate/test_data")))
		exit(1);

	// This file is referenced in $OPD_ROOT/scripts/master_validate.sh
	GenData a("$OPD_ROOT/validate/test_data/read_int.dat",37,-50000,1,50000,
		f_dec,100000,0);

	GenData a1("$OPD_ROOT/validate/test_data/read_int_hex.dat",37,-5007,1,50000,
		f_hex,100000,0);

	static double values1[] = { 1.e37, 1.e39, 1.e250};
	static const char *strs[] = { "1e400","1e-1200","34.5e9999"};
	static InsertList lst[] = {
		{111,3,values1},
		{211,3,0,strs},
		{0,0,0}
	};

	GenData a2("$OPD_ROOT/validate/test_data/read_float.dat",10,-50000,1,
		50000, f_float,100000,0,lst,123689.,1.e5);

	GenData a3("$OPD_ROOT/validate/test_data/read_norm_float.dat",10,-50000,1,
		50000, f_float,100000,0,lst,123000.*45000.,123689.);

	GenData b("$OPD_ROOT/validate/test_data/import_fld.dat", 37,7,3,1024,
		f_dec,100000,4);

	GenData c("$OPD_ROOT/validate/test_data/import_fld_rpt.dat", 37,7,3,1024,
		f_dec,10000,4);

	GenData d("$OPD_ROOT/validate/test_data/import_fld_rpt_shrt.dat", 37,7,3,1024,
		f_dec,3500,4);
}


