#!/usr/bin/perl
package MpmasResults;
use strict;
use warnings;
use SimpleObject;
use IndexedTable;
use Storable qw(dclone store retrieve);
use Data::Dumper;
use CtUtilities;

our @ISA = qw(SimpleObject);

sub create {
	my $class = shift;
	my $mpmasbasedirectory = shift;
	my $scenarioname = shift(@_) . "_";
	my $options = shift;

	my $self = {};

	my $mpmasoutdir = $mpmasbasedirectory."/"."out/";
	my $mpmasouttestdir = $mpmasbasedirectory."/"."out/test/";
	my $mpmasindir = $mpmasbasedirectory."/"."input/dat/";


	
	if ($options =~ /-p\s*([\d-]?\d)(\s+[\d-]?\d)*/) {
			my ($ly,$uy);
			if (defined $2) {
				$ly = $1;
				$uy = $2;
			}
			else {
				$ly = $1;
				$uy = $1;	
			}
			$self->{periods} = [($ly..$uy)];
	}
	else {
		my @ufiles = glob "${mpmasoutdir}${scenarioname}u*";
		my @periods;
		for my $i (@ufiles) {
			$i =~ /${mpmasoutdir}${scenarioname}u([\d-]+)\.out/;
			
			push @periods, sprintf("\%d", $1);
		}
		@periods = sort {$a <=> $b} @periods;
		
		$self->{periods} = \@periods;

	}
	print "Importing periods: ". join (" ", @{$self->{periods}})."\n";
	my $what = "uk";
	if ($options =~ /-f\s+([\w\s]+)/) {
		$what = $1; 
	}
	$self->{loaded} = $what;
	print "Loading files: $what ...\n";
	#Read in infofiles
	my $activities = IndexedTable->create_from_ascii($mpmasindir.$scenarioname."ActivityInfo.txt", 1, "ActivityInfo", '\t',1);
	my $constraints = IndexedTable->create_from_ascii($mpmasindir.$scenarioname."ConstraintInfo.txt", 1, "ConstraintInfo", '\t',1);
	my $networkobjects = IndexedTable->create_from_ascii($mpmasindir.$scenarioname."ObjectInfo.txt", 1, "ObjectInfo", '\t',1);
	$self->{ActivityInfo} = $activities;
	$self->{ConstraintInfo} = $constraints;	
	$self->{ObjectInfo} = $networkobjects;
	
	if ($what =~ /u/) {
		#Read in activities
		my @ucolnames = ("DataType","AgentID",	"CatchmentID",	"SectorID","FarmsteadID","PopulationID","ClusterID","NetworkID","SegmentID","TypeOfExpectations","ColorInMaps","X-coordinate","Y-coordinate","NumberOfPlots");
		for my $uc ($activities->query([],0)) {
			push @ucolnames, $activities->query([$uc],2);
		}
		my %utab;
		for my $i (@{$self->{periods}}) {
			$utab{$i} = IndexedTable->create_from_ascii($mpmasoutdir.$scenarioname."u".sprintf("%02d", $i).".out", 2, "u$i", '\t',0);
			return undef unless (defined $utab{$i});
			$utab{$i}->add_columnnames(@ucolnames);
	
		}
		$self->{Utab} = \%utab;
	}
	if ($what =~ /k/) {
		#Read in RHS
		my @rhsnames = ("DataType","AgentID",	"CatchmentID",	"SectorID","FarmsteadID","PopulationID","ClusterID","NetworkID","SegmentID","TypeOfExpectations","ColorInMaps","X-coordinate","Y-coordinate","NumberOfPlots");
		for my $cc ($constraints->query([],0)) {
			push @rhsnames, $constraints->query([$cc],2);
		}
		my %ctab;
		for my $i (@{$self->{periods}}) {
			$ctab{$i} = IndexedTable->create_from_ascii($mpmasoutdir.$scenarioname."k".sprintf("%02d", $i).".out", 2, "k$i", '\t',0);
			return undef unless (defined $ctab{$i});
			$ctab{$i}->add_columnnames(@rhsnames);
		
		}
		$self->{Ctab} = \%ctab;
	}
	if ($what =~ /lt2/) {
		my @lt2names = qw (_seed  _pop  _clu _catch _agentid _fstid _sec _numplots);
		my $fh;
		my %lt2tab;
		my @lt2files = glob "${mpmasoutdir}${scenarioname}*.lt2";
		for my $l (@lt2files) {
			$l =~ /${mpmasoutdir}${scenarioname}(\d)(\d+).lt2/;
			my $curPop = $1;
			my $curClu = $2;
			open ($fh, "<", $l) or die $!."\n";
			print "Reading $l... \n";
			RIN: while (<$fh>) {
				my $line = $_;
				chomp($line);
				next if ($. < 9);
				$line =~ s/^\s*//;
				$line =~ s/\s*$//;
				if ($. == 9) {
					my @header = split (/\s+/, $line);
					my $i = 8;
					do {
						$header[$i] = "h".$header[$i];
						$i++;
					} while ($header[$i] < 0);
					@lt2names = (@lt2names, @header[8..$#header]);		
				}
				else {
					my @fields = split  (/\s+/, $line);
					last RIN if ($fields[5] == -1);
					for my $i (0..$#fields) {
						
						$lt2tab{$curPop}->{$curClu}->{$fields[5]}->{$lt2names[$i]} = $fields[$i];
					}
				}
		
			}
			
			close $fh;
		}
		$self->{lotteryresult} = \%lt2tab;
		

	}
	bless $self, $class;

};

sub periods {
	return @{ $_[0]->{periods} };
}
sub loaded {
	return $_[0]->{loaded} ;
}

sub lt2totab {
	my $self = shift;
	my $fn_ad = shift;	
	my $fn_hd = shift;
	my $fn_ai = shift;
	my $dbheader = shift ||0;
	print "Writing household members to $fn_hd\n";
	print "Writing asset distribution to $fn_ad\n";
	print "Writing agent info to $fn_ai\n";		
	my $lt2tab = $self->{lotteryresult};
	open (my $fh_ad, ">", $fn_ad) or die "Error when trying to create $fn_ad: $!\n";
	open (my $fh_hd, ">", $fn_hd) or die "Error when trying to create $fn_hd: $!\n";
	open (my $fh_ai, ">", $fn_ai) or die "Error when trying to create $fn_ai: $!\n";
	print $fh_ad "farmstead_id\tasset\tvalue\n";
	print $fh_hd "farmstead_id\tsexagecat\tvalue\n";
	print $fh_ai "farmstead_id\tpop\tclu\tcatchment\tagent_id\tsec\tnumplots\n";
	if ($dbheader) {
		print $fh_ad "INT\tVARCHAR(150)\tDOUBLE\n" ;
		print $fh_hd "INT\tVARCHAR(150)\tDOUBLE\n";
		print $fh_ai "INT\tINT\tINT\tINT\tINT\tINT\tINT\n";
		print $fh_ad "k\tk\tn\n";
		print $fh_hd "k\tk\tn\n";
		print $fh_ai "k\tn\tn\tn\tn\tn\tn\n";
	}
	for my $pop (keys %$lt2tab) {
		for my $clu (keys %{$lt2tab->{$pop} }) {
			for my $fst (keys %{$lt2tab->{$pop}->{$clu} }) {
				my $fstr = sprintf("%.0f", $fst);
				print $fh_ai join("\t", $fstr, $pop, $clu, $lt2tab->{$pop}->{$clu}->{$fst}->{_catch}, $lt2tab->{$pop}->{$clu}->{$fst}->{_agentid}, $lt2tab->{$pop}->{$clu}->{$fst}->{_sec}, $lt2tab->{$pop}->{$clu}->{$fst}->{_numplots})."\n";
				for my $item (keys %{$lt2tab->{$pop}->{$clu}->{$fst} }) {
						if ($item =~ /^_/) {
							next;
						}		
						elsif ($item =~ /^h/) {
							$item =~ /^h(\d+)./;
							my $itemf = $1;
							print $fh_hd "$fstr\t$itemf\t".$lt2tab->{$pop}->{$clu}->{$fst}->{$item}."\n" unless ($lt2tab->{$pop}->{$clu}->{$fst}->{$item} <= 0);
						}
						else {
							my $oid = sprintf("%.0f",$item);
							print $fh_ad "$fstr\t". $self->{ObjectInfo}->query([$oid],2)."\t".$lt2tab->{$pop}->{$clu}->{$fst}->{$item}."\n" unless ($lt2tab->{$pop}->{$clu}->{$fst}->{$item} < 0);

						}
			
				}
			}
		}
	}
	close ($fh_ad);close($fh_hd); close( $fh_ai);
}
sub lt2sum {
	my $self = shift;
	my $lt2tab = $self->{lotteryresult};
	my $sumtab = {};
	for my $pop (keys %$lt2tab) {
		for my $clu (keys %{$lt2tab->{$pop} }) {
			for my $fst (keys %{$lt2tab->{$pop}->{$clu} }) {
				my $fstr = sprintf("%.0f", $fst);
				for my $item (keys %{$lt2tab->{$pop}->{$clu}->{$fst} }) {
						if ($item =~ /^_/) {
							next;
						}		
						elsif ($item =~ /^h/) {
							$item =~ /^h(\d+)./;
							my $itemf = "HHMemberGroup_".$1;
							$sumtab->{$pop}->{$clu}->{$itemf} +=  $lt2tab->{$pop}->{$clu}->{$fst}->{$item} unless ($lt2tab->{$pop}->{$clu}->{$fst}->{$item} < 0);
						}
						else {
							my $oid = sprintf("%.0f",$item);
							my $oname = $self->{ObjectInfo}->query([$oid],2);
							$sumtab->{$pop}->{$clu}->{$oname} +=  $lt2tab->{$pop}->{$clu}->{$fst}->{$item} unless ($lt2tab->{$pop}->{$clu}->{$fst}->{$item} < 0);
						}
				}
			}
		}
	}
	return $sumtab;
}
sub lt2dist {
	my $self = shift;
	my $lt2tab = $self->{lotteryresult};
	my $sumtab = {};
	for my $pop (keys %$lt2tab) {
		for my $clu (keys %{$lt2tab->{$pop} }) {
			for my $fst (keys %{$lt2tab->{$pop}->{$clu} }) {
				my $fstr = sprintf("%.0f", $fst);
				for my $item (keys %{$lt2tab->{$pop}->{$clu}->{$fst} }) {
						if ($item =~ /^_/) {
							next;
						}		
						elsif ($item =~ /^h/) {
							$item =~ /^h(\d+)./;
							my $itemf = "HHMemberGroup_".$1;
							my $level = $lt2tab->{$pop}->{$clu}->{$fst}->{$item};
							$sumtab->{$pop}->{$clu}->{$itemf}->{$level} += 1  unless ($lt2tab->{$pop}->{$clu}->{$fst}->{$item} < 0);
						}
						else {
							my $oid = sprintf("%.0f",$item);
							my $oname = $self->{ObjectInfo}->query([$oid],2);
							my $level = $lt2tab->{$pop}->{$clu}->{$fst}->{$item};
							$sumtab->{$pop}->{$clu}->{$oname}->{$level} += 1  unless ($lt2tab->{$pop}->{$clu}->{$fst}->{$item} < 0);
						}

				}
			}
		}
	}
	return $sumtab;

}
sub total_solution_by_group {
	my $self = shift;
	my $classification = shift;
	(print "Activity Classification $classification does not exist in this resultset\n" and return undef) unless ($self->{ActivityInfo}->exists_columnname($classification));
	
	
	my $num_lp_columns = $self->{ActivityInfo}->query([],0);
	
	my $returnhash = {};
	for my $p ($self->periods) {
		
		for my $ag ($self->{Utab}->{$p}->query(["02"],0)) {
			for my $lpc (0..$num_lp_columns -1 ) {
				my $ofc = $self->{ActivityInfo}->query_by_columnname([$lpc], "OutfileCol");
				my $group = $self->{ActivityInfo}->query_by_columnname([$lpc], $classification);
				
				next if ($group eq "-1");
				$returnhash->{$group}{$p} = 0 unless (exists $returnhash->{$group}{$p});
				$returnhash->{$group}{$p} += $self->{Utab}->{$p}->query(["02", $ag], $ofc); 
			}
		}
	}
	return $returnhash;
}
sub total_rhs_by_group {
	my $self = shift;
	my $classification = shift;
	(print "Constraint Classification $classification does not exist in this resultset\n" and return undef) unless ($self->{ConstraintInfo}->exists_columnname($classification));
	
	
	my $num_lp_rows = $self->{ConstraintInfo}->query([],0);
	
	my $returnhash = {};
	for my $p ($self->periods) {
		
		for my $ag ($self->{Ctab}->{$p}->query(["04"],0)) {
			for my $lpc (0..$num_lp_rows -1 ) {
				my $ofc = $self->{ConstraintInfo}->query_by_columnname([$lpc], "OutfileCol");
				my $group = $self->{ConstraintInfo}->query_by_columnname([$lpc], $classification);
				
				next if ($group eq "-1");
				$returnhash->{$group}{$p} = 0 unless (exists $returnhash->{$group}{$p});
				$returnhash->{$group}{$p} += $self->{Ctab}->{$p}->query(["04", $ag], $ofc); 
			}
		}
	}
	return $returnhash;
}

sub rhsgroup_distribution_for_period {
	my $self = shift;
	my $classification = shift;
	my $period = shift;

	(print "Constraint Classification $classification does not exist in this resultset\n" and return undef) unless ($self->{ConstraintInfo}->exists_columnname($classification));
	#$| = 1;
	#print "$classification // $period\n";
	my $num_lp_rows = $self->{ConstraintInfo}->query([],0);
	my $returnhash = {};	
	my $intermediatehash = {};
	my $numhash = {};
	for my $ag ($self->{Ctab}->{$period}->query(["04"],0)) {
		my $pop = $self->{Ctab}->{$period}->query(["04", $ag],6);
		my $clu = $self->{Ctab}->{$period}->query(["04", $ag],7);
		$numhash->{$pop}->{$clu} = 0 unless (exists $numhash->{$pop}->{$clu});
		$numhash->{$pop}->{$clu} += 1;
		for my $lpc (0..$num_lp_rows -1 ) {
			my $ofc = $self->{ConstraintInfo}->query_by_columnname([$lpc], "OutfileCol");
			my $group = $self->{ConstraintInfo}->query_by_columnname([$lpc], $classification);
			
			next if ($group eq "-1");
			my $level = $self->{Ctab}->{$period}->query(["04", $ag], $ofc); 
			$intermediatehash->{$pop}->{$clu}->{$group}->{$level} = 0 unless (exists $intermediatehash->{$pop}->{$clu}->{$group}->{$level});
			$intermediatehash->{$pop}->{$clu}->{$group}->{$level} += 1;
		
		}
	}
	
	for my $p (keys %{$intermediatehash}	) {
		for my $c (keys %{$intermediatehash->{$p}}) {
			for my $g (keys %{$intermediatehash->{$p}->{$c} }) {
				my %levelhash = ();
				for my $l (keys %{$intermediatehash->{$p}->{$c}->{$g} }) {
					$levelhash{$l} = $intermediatehash->{$p}->{$c}->{$g}->{$l} /$numhash->{$p}->{$c};
				}
				my %levelcumul;
				my $sum = 0;
				for my $l (sort{$a <=> $b} keys %levelhash) {
					$sum += $levelhash{$l};
					$levelcumul{$l} = $sum;
				}
				$returnhash->{$p}->{$c}->{$g} = \%levelcumul;
			}
		}
	}
	return $returnhash;
}
1;
