package MpmasQLFieldDefinition;
use strict;
use warnings;
use Exporter;
use Storable qw(dclone);
use Data::Dumper;
use SimpleObject;
use MpmasQLFunctionLanguage;
our @ISA = qw(SimpleObject);

sub id {
    return $_[0]->{id};
}
sub type {
    return $_[0]->{type};
}
sub fieldname {
    return $_[0]->{fieldname};
}
sub content {
    return $_[0]->{content};
}
sub content_verbosity {
    return wantarray ? ($_[0]->{cont_verbose}, $_[0]->{cont_verbose_for}) : $_[0]->{cont_verbose};
}
sub fieldname_verbosity {
    return wantarray ? ($_[0]->{fn_verbose}, $_[0]->{fn_verbose_for}) : $_[0]->{fn_verbose};
}
sub set_content_verbosity {
    $_[0]->{cont_verbosity} = $_[1];
}
sub set_fieldname_verbosity {
    $_[0]->{fn_verbosity} = $_[1];
}
sub set_id {
    $_[0]->{id} = $_[1];
}
sub set_type {
    $_[0]->{type} = $_[1];
}
sub set_fieldname {

    $_[0]->{fieldname} = $_[1];
}
sub set_content {
    $_[0]->{content} = $_[1];
}
sub is_a_list_field {
    return 1 if ($_[0]->{type} eq "list");
    return 0;
}
sub thisfor {
    return $_[0]->{thisfor}
}
sub set_thisfor {
    $_[0]->{thisfor} = $_[1];
}
sub conv_rank {
	$_[0]->{rank};
}
sub transform {
    my ($self,$curInstanceId, $curElementId, $thisby, $dyninfo, $specvars,$milplist, $verbose, $instance_attributes, $thismperiod) = @_;
    $specvars = {} unless (defined $specvars);
    $verbose = 0 unless(defined $verbose);
    
    my  @new_untransformed_fields;


    if ($self->id =~ /^mult\d/ ){
		my $x = $self->fieldname;
		my $locvarhash = {(
			instance =>  $curInstanceId,
			classMember =>  $curInstanceId,
			instance_element => $curInstanceId."_".$curElementId,
			element => $curElementId,
			by => $thisby,
			mperiod => $thismperiod
			)};
		if ( substr($milplist->[0],  1) == 3) {
			$locvarhash->{PO} = substr($milplist->[0], 1);
		}	
			
		my %mergedlocvars = ( %$locvarhash , %$specvars, %$instance_attributes);
		
		my ($rt, $rtfor);;
		my ($v,$vf) = $self->fieldname_verbosity;
		eval{
			local $SIG{__WARN__}=sub{};	
			($rt, $rtfor) = MpmasQLFunctionLanguage->interprete($x, \%mergedlocvars, $v ? (not defined $vf or $vf eq $curInstanceId )  : 0 ); 
		};
		print STDERR "Error $@\n Instance: $curInstanceId, Element: ".$curElementId.", Field: $x\n" and exit(1) if $@;
		#@cf has nominally two dimensions, but dimensions actually used depend on return value of sub interprete
		#scalar return -> only $cf[0][0]
		#return of field list -> $cf[...][0] List of field names, $cf[...][1] List of #thisfor values
		if (defined $rt->[0]) {
			for my $j (0..$#{$rt}){
				my $newfield = $self->create_copy;
				$newfield->set_id($rt->[$j]);
				$newfield->set_fieldname($rt->[$j]);
				$newfield->set_thisfor($rtfor->[$j]);
				push @new_untransformed_fields, $newfield;
			}
		}
		return undef, \@new_untransformed_fields;
    }

    my %content_by_milp;
    my $x= $self->content;
    #Decide whether loop for several dynamic stages is necessary and start loop if necessary
    my $numdyn =  0;
    $numdyn = $dyninfo if ($x =~ /&this\s*\(\s*'dyn'\s*/);
    my @milps = ($milplist->[0]);
    @milps = @$milplist if ($x =~ /&this\s*\(\s*'milp'\s*/) or ($x =~ /&this\s*\(\s*'type_of_landowner'\s*/) or ($x =~ /&this\s*\(\s*'market'\s*/) or ($x =~ /&this\s*\(\s*'PO'\s*/);
    for my $thismilp (@milps) {
	    my $content;
	    for my $curDyn (0..$numdyn) {
		    my $locvarhash = { (
			    instance => $curInstanceId,
			    classMember =>  $curInstanceId,
			    instance_element => $curInstanceId."_".$curElementId,
			    element => $curElementId,
			    by => $thisby,
			    field => $self->thisfor,
			    dyn	=> $curDyn,
			    milp => $thismilp,
				mperiod => $thismperiod
			    )};
			if (substr($thismilp, 0, 1) < 3) {
				    $locvarhash->{type_of_landowner} = substr($thismilp, 0, 1);
					$locvarhash->{market} = substr($thismilp, 1);
			}
			elsif (substr($thismilp, 0, 1) == 3) {
					$locvarhash->{PO} = substr($thismilp, 1);
			}
		    my %mergedlocvars = ( %$locvarhash , %$specvars, %$instance_attributes);
		    my $cfcont;
		    my ($v2,$vf2) = $self->content_verbosity;
		    		      
		    eval{
			    local $SIG{__WARN__}=sub{};
			    $cfcont = MpmasQLFunctionLanguage->interprete($x, \%mergedlocvars, $v2 ? (not defined $vf2 or $vf2 eq $curInstanceId ) :0);
		    };
		    print STDERR "Error: $@ Instance $curInstanceId, Element: ".$curElementId." Field: ".$self->id."\n"  and exit(1) if $@;
		    print "Warning: Value for field ".$self->id." of instance $curInstanceId is an array!!! \n Only the first entry in the array is used for now. \n Value definitions may not result in arrays for one single field!.\n Maybe you forgot an aggregation function?\n" if ($#{$cfcont} > 0 and not $self->is_a_list_field);

		    if ($self->is_a_list_field) {
			    my @array;
			    for my $i (@$cfcont) {
				push @array, $i;
			    }
			    if ($numdyn == 0) {
				    $content =  \@array;
			    }
			    else {
				    $content->{$curDyn} = \@array;
			    }
		    }
		    else {
				print STDERR "Error: Value definition results in a list for a non-array field.\n Instance $curInstanceId, Element: ".$curElementId." Field: ".$self->id."\n"  and exit(1) if (ref($cfcont->[0]));
			    if ($numdyn == 0) {
				    $content = $cfcont->[0] || 0;
			    }
			    else {
				    $content->{$curDyn} = $cfcont->[0];
			    }
		    }
	     }	#end of loop over dynamic sets $curDyn
    
     	    print " = (MILP $thismilp) $content\n" if ($verbose and not ref($content));
     	    print " = (MILP $thismilp)".ref($content)."\n" if ($verbose and ref($content));
	    $content_by_milp{$thismilp} = $content;
	 } #end of loop over milps
     return \%content_by_milp, \@new_untransformed_fields;
}
1;
