package MpmasCropSimilarity;

use strict;
use warnings;
use Exporter;
use Storable qw(dclone);
use Data::Dumper;
use List::Util qw[min max];
use CtUtilities qw(queryhash extqueryhash);
use MpmasInputfile;
use MpmasInputBlock;
our @ISA = qw(MpmasInputfile);

sub filename {
	return "CropSimilarity";
}

sub required {
	my $self = shift;
	return ($self->config_entry("CROP_MODEL") > 0);
}
sub prepare_shared {
    my ($self) = @_;

    my @sorted_cropping_activities;
    $self->{similarity_levels} = 0;
    $self->{similarity_codes} = {} ;
    $self->{curmaxcode} = [];
    
    if (not defined $self->config_entry("CROP_SIMILARITY")) {
		return;
	}
    if ($self->config_entry("CROP_MODEL") == 1) {
		print STDERR "Error: You set CROP_MODEL == 1 (TSPC), but mpmasql is not able to create TSPC files yet\n";
		exit(1);
    }
    elsif ($self->config_entry("MULTIPERIOD") ) {   
		if (defined $self->config_entry("CROP_SIMILARITY")) {
			$self->{similaritytab} = $self->config_entry("CROP_SIMILARITY")->transform($self->get_dbh,3);
			#print STDERR "Error: CROP_SIMILARITY not yet implemented for multiperiod models\n";
			#exit(1);
			
			my $temp = $self->{similaritytab}->regrouped_copy([(3,1,2)], "temp");
			
			$self->{similarity_levels} = scalar @{[ $temp->query([],0)]};
			
		}

	} #end multiperiod
    elsif ($self->config_entry("CROP_MODEL") == 3 and ($self->config_entry("STATICNRU" ) == 0 or $self->config_entry("STATICNRU" ) >= 2 or not $self->config_entry("EXTERNALCGFORMAT0") ))   {
		if (defined $self->config_entry("CROP_SIMILARITY")) {
			my $similaritytab = $self->config_entry("CROP_SIMILARITY")->transform($self->get_dbh,3);
			
			for my $ca (@{ $self->get_global("Sorted_Xn_Activities_Per_Soil")}) {
				my $x = {};
				my $s = $ca->[2];
				my $k = $ca->[1];
				$x->{id} = $s."_".$k;
				$x->{name} = $s."_".$k;
				
				for my $f ($similaritytab->query([$s, $k], 0) ) {
					unless (defined $f) {
						print STDERR "Error: Missing entries for NRU $s, Slot $k in CROP_SIMILARITY\n";
						exit(1);
					}
					if ($f > $self->{similarity_levels} ) {
					  $self->{similarity_levels} = $f;
					  $self->{curmaxcode}->[$f] = 0;
					}
					unless ( exists $self->{similarity_codes}->{$f}->{ $similaritytab->query([$s, $k, $f],4) }  ) {
					  $self->{similarity_codes}->{$f}->{ $similaritytab->query([$s, $k, $f],4) } = ++ $self->{curmaxcode}->[$f];
					}
					$x->{similarity}->[$f] = $similaritytab->query([$s, $k, $f],4);
				}
				$x->{similarity}->[0] = $s."_".$k;
				
				push  @sorted_cropping_activities, $x;
			
			}
		}
		else {
			$self->{curmaxcode}->[1] = 0;
			for my $ca (@{ $self->get_global("Sorted_Xn_Activities_Per_Soil")}) {
				my $x = {};
				$x->{id} = $ca->[3];
				$x->{name} = $ca->[2];
				$x->{similarity}->[1] = $ca->[3];	
				$self->{similarity_levels} = 1;
				++ $self->{curmaxcode}->[1] ;
				push  @sorted_cropping_activities, $x;
			}
		}
	}
	else {
		my @sas;
		if ($self->config_entry("CROP_MODEL") == 3 and $self->config_entry("STATICNRU" ) == 1 and $self->config_entry("EXTERNALCGFORMAT0")) {
			@sas = @{ $self->get_global("Sorted_Xn_Activity_Objects") };
		}
		elsif ($self->config_entry("CROP_MODEL") == 2) {
			@sas = @{ $self->get_global("Sorted_CropWat_Activities")  };
		}
	    else {
			print STDERR "Error: Invalid value for CROP_MODEL\n";
			exit(1);
		}
		for my $ca (@sas) {
			my $x = {};
			$x->{id} = $ca->id;
			$x->{name} = $ca->name;
			for my $f ($ca->subelement_fields("yield_expectation") ) {
				next unless ($f =~ /similarity_(\d+)/);
				my $l = $1;
				if ($l > $self->{similarity_levels} ) {
				  $self->{similarity_levels} = $l;
				  $self->{curmaxcode}->[$l] = 0;
				}
				unless ( exists $self->{similarity_codes}->{$l}->{ $ca->subelement_field("yield_expectation", $f) }  ) {
				  $self->{similarity_codes}->{$l}->{ $ca->subelement_field("yield_expectation", $f) } = ++ $self->{curmaxcode}->[$l];
				}
				$x->{similarity}->[$l] = $ca->subelement_field("yield_expectation", $f);
			}
			$x->{similarity}->[0] = $ca->id;
			
			push  @sorted_cropping_activities, $x;
		}
    }
    $self->{sorted_cropping_activities} = \@sorted_cropping_activities;

 #   for my $ca (@sorted_cropping_activities) {
#		for my $f ($ca->subelement_fields("yield_expectation") ) {
#			next unless ($f =~ /similarity_(\d+)/);
#			my $l = $1;
#			if ($l > $self->{similarity_levels} ) {
#			  $self->{similarity_levels} = $l;
#			  $self->{curmaxcode}->[$l] = 0;
#			}
#			unless ( exists $self->{similarity_codes}->{$l}->{ $ca->subelement_field("yield_expectation", $f) }  ) {
#			  $self->{similarity_codes}->{$l}->{ $ca->subelement_field("yield_expectation", $f) } = ++ $self->{curmaxcode}->[$l];
#			}
#		}
#		$ca->add_subelement_field("yield_expectation", "similarity_0", $ca->id);
 #   }
}
sub prepare_special {
    my ($self) = @_;
    my $block = MpmasInputBlock->new(3,10);
    $block->add_comment_row("THE CROP SIMILARITY FILE");
    $block->add_empty_rows(1);
    $block->add_comment_row(1, "CROP SIMILARITIES");
    $block->add_comment_row(1.1, "BASIC PARAMETERS");
    $block->add_comment_row("","", "Variable","Value");
    $block->add_row("","","Levels of similarity",$self->{similarity_levels});
    $block->add_empty_rows(1);
    

    if ($self->{similarity_levels} > 0) {
		
		$block->add_comment_row(1.2,"MATRIX OF CROP SIMILARITIES");
		$block->add_comment_row("","", "", "Levels");
		
		if ($self->config_entry("MULTIPERIOD") ) {
			$block->add_comment_row("","", "", "CropManagementID", "NRU", 1..$self->{similarity_levels});
			
			for my $n ($self->{similaritytab}->query([],0) ) {
				for my $c ($self->{similaritytab}->query([$n],0) ) {
					my @row;
					for my $l (1 .. $self->{similarity_levels}) {
						
						my $clu = $self->{similaritytab}->query([$n, $c, $l],4);
						if (defined $clu)
						{
							push @row, $clu;
						}
						else
						{
							push @row, -1; 	
						}
					}
					$block->add_row("", "", "",  $c, $n, @row);

				}
			}
		}
		else {
			$block->add_comment_row("","Activity code", "Activity description", 1..$self->{similarity_levels});
			for my $x (@{ $self->{sorted_cropping_activities} }) {
				my @row;
				for my $l (1..$self->{similarity_levels}) {
				  my $p = 0;
				  my $g;
				  while ($p <= $l) {
					  my $l2 = $l-$p;
					  $g =  $x->{similarity}[$l2];
					  last if (defined $g);
					  $p++;
				  }
				  unless ( exists $self->{similarity_codes}->{$l}->{ $g }  ) {
					  $self->{similarity_codes}->{$l}->{ $g } = ++ $self->{curmaxcode}->[$l];
				  }
				  push @row, $self->{similarity_codes}->{$l}->{ $g };
				}
				$block->add_row("", $x->{id}, $x->{name}, @row);
			}
		}
    }
    $self->add_block($block);
}
