#!/usr/bin/perl

use strict;
use warnings;

use Carp qw(cluck longmess shortmess croak confess);
use File::Path;
use Data::Dumper;
use List::Util qw(shuffle);
use Statistics::Descriptive;

use Ernad::Common;
use Ernad::Constant;
use Ernad::Files;
use Ernad::Erimp;
use Ernad::Eval::Lunol;
use Krichel::File;

my $verbose=0;

my $type='learning_evaluation';

my $impna=$ARGV[0];
if(not defined($impna)) {
  die "I need the impna.";
}
my $e=Ernad::Erimp->new({'impna'=>$impna});
if(not $e) {
  die "You gave me an invalid impna $impna\n";
}

## do only one repcode
my $only_do_repcode=$ARGV[1] // '';

my $eval_dir=$e->{'dir'}->{'eval'};
if(not -d $eval_dir) {
  mkpath $eval_dir;
}

my $eval_web_dir=$e->{'dir'}->{'eval_web'} or die "eval_web_dir not set in ernad.conf";
if(not $eval_web_dir) {
  confess "I can't find the eval_web_dir $eval_web_dir";
}

my $style_file=$e->{'dir'}->{'style'}.'/'.$type.$e->{'const'}->{'xsl_ext'};
if(not $style_file) {
  confess "I can't find the style_file $style_file";
}

## the all_handle_cache
my $a_h_c;

## learning evaluation
my $les;
my $lunols;

my $ernad_ns=$Ernad::Constant::c->{'ernad_ns'};
my $name='learning_evaluation';

my @repcodes=shuffle $e->list_repcodes();

if($only_do_repcode) {
  &work_on_report($only_do_repcode);
}
else {
  foreach my $repcode (@repcodes) {
    ## temporaray check that we don't have the allport
    ## this is really for most basic security
    if(not $e->{'conf'}) {
      die "I need this here.";
    }
    ## this is temporary, as list_repcodes may have the allport
    if($repcode eq $e->{'conf'}->{'allport_repcode'}) {
      next;
    }
    &work_on_report($repcode);
  }
}
&make_index_page();


sub make_index_page {
  my $index_doc=$e->{'x'}->get_ernad_doc();
  my $index_file="$eval_dir/index.xml";
  my $html_fufi=&Ernad::Files::xml_to_html($index_file,$eval_web_dir);
  my $update_time=&Ernad::Files::does_file_need_renewal($html_fufi,$index_file,$style_file,$eval_dir);
  #if(not $update_time) {
  #  return;
  #}
  my $les_element=$index_doc->createElementNS($ernad_ns,'learning_evaluations');
  foreach my $repcode (@repcodes) {
    print Dumper $les;
    &collect_index_for_report($index_doc,$repcode);
  }
  my @repcodes_by_lunol=sort {$lunols->{$a} <=> $lunols->{$b}}  keys %{$lunols};
  foreach my $repcode (@repcodes_by_lunol) {
    $les_element->appendChild($les->{$repcode});
  }
  my $update_date=&Ernad::Dates::pretty_time($update_time);
  $index_doc->setDocumentElement($les_element);
  &Ernad::Files::save_xml_with_temp("$index_file",$index_doc);
  my $html_doc=$e->{'t'}->transform_file($index_file,'learning_evaluation_index',
                                  {update => "'$update_date'"});
  &Ernad::Files::save_xml_with_temp($html_fufi,$html_doc);
}


sub collect_index_for_report {
  my $index_doc=shift // confess "I need the index_doc here.";
  my $repcode=shift // confess "I need a repcode here.";
  my $out_file="$eval_dir/$repcode.xml";
  if(not -f $out_file) {
    return '';
  }
  my $report_doc=Krichel::File::load($out_file);
  my $report_doc_element=$report_doc->documentElement();
  ## we don't need this issues
  my @issue_elements=$report_doc_element->getElementsByTagNameNS($ernad_ns,'issue');
  foreach my $issue_element (@issue_elements) {
    $e->{'x'}->remove_space_that_follows($issue_element);
    $issue_element->parentNode->removeChild($issue_element);
  }
  #print $report_doc_element->toString();
  my $le_element=$report_doc->getElementsByTagNameNS($ernad_ns,'learning_evaluation')->[0];
  my $lunol=$le_element->getAttribute('average_by_date_lunol');
  ## global variables
  $les->{$repcode}=$le_element;
  $lunols->{$repcode}=$lunol;
}

sub work_on_report {
  my $repcode=shift // confess "I need a repcode here.";
  my $out_file="$eval_dir/$repcode.xml";
  my $le_element;
  my $doc;
  if(-f $out_file) {
    $doc=Krichel::File::load($out_file);
    $le_element=$doc->getElementsByTagNameNS($ernad_ns,'learning_evaluation')->[0];
  }
  else {
    $doc=$e->{'x'}->get_ernad_doc();
    $le_element=$doc->createElementNS($ernad_ns,'learning_evaluation');
    $le_element->setAttribute('repcode',$repcode);
    $doc->documentElement->appendChild($le_element);
  }
  #$e->update_collection_in_doc($doc,$repcode);
  $e->{'x'}->update_collection_in_doc($doc,$repcode);
  &get_eval($repcode,$doc);
  &Ernad::Files::save_xml_with_temp($out_file,$doc);
  my $html_fufi=&Ernad::Files::xml_to_html($out_file,$eval_web_dir);
  my $update_time=&Ernad::Files::does_file_need_renewal($html_fufi,$out_file,$style_file);
  if(not $update_time) {
    return;
  }
  my $update_date=&Ernad::Dates::pretty_time($update_time);
  my $html_doc=$e->{'t'}->transform_file($out_file,$type, {update => "'$update_date'"});
  &Ernad::Files::save_xml_with_temp($html_fufi,$html_doc);
}

sub get_id {
  my $in=shift;
  my ($id,$weight,$crit)=split(' ',$in);
  return $id;
}

sub get_issues_done {
  my $le_element=shift;
  my $issues_done;
  my @issues=$le_element->getElementsByTagNameNS($ernad_ns,'issue')->get_nodelist;
  foreach my $issue_element (@issues) {
    my $issuedate=$issue_element->getAttribute('date') or confess "no date on $issue_element";
    $issues_done->{$issuedate}=1;
  }
  return $issues_done;
}

sub get_eval {
  my $repcode=shift;
  my $doc=shift;
  my $count_get=0;
  my $selected_dir=$e->{'report'}->{$repcode}->{'dir'}->{'selected'};
  my $issues=$e->{'d'}->last_date_times($selected_dir);
  my $issues_done=&get_issues_done($doc);
  my $need_to_update_head=0;
  foreach my $issuedate (reverse sort keys %{$issues}) {
    if(defined($issues_done->{$issuedate})) {
      if($verbose) {
        print "I skip $issuedate\n";
      }
      next;
    }
    else {
      if($verbose) {
        print "I have to do $issuedate\n";
      }
      $need_to_update_head=0;
      &gather_data_for_issue($repcode,$issuedate,$doc) or next;
    }
  }
  &update_averages($doc);
  &update_update_time($doc);
}

sub update_averages {
  my $doc=shift;
  foreach my $name ('lunol','report_total','breadth') {
    &update_average($doc,$name);
  }
}

sub update_update_time {
  my $doc=shift;
  my $ernad_element=$doc->documentElement();
  $ernad_element->setAttribute('last_update',&Ernad::Dates::pretty_time());
}

sub update_average {
  my $doc=shift;
  my $crit=shift;
  my $le_element=$doc->getElementsByTagNameNS($ernad_ns,'learning_evaluation')->[0];
  my @issues=$le_element->getElementsByTagNameNS($ernad_ns,'issue')->get_nodelist;
  my $sizes={};
  foreach my $issue (@issues) {
    my $date=$issue->getAttribute('date') or next;
    my $value=$issue->getAttribute($crit) or next;
    $sizes->{$date}=$value;
  }
  my $average=Ernad::Dates::average_by_date($sizes);
  my $attribute_name='average_by_date_'.$crit;
  $le_element->setAttribute($attribute_name,sprintf("%.4f",$average));
}

sub gather_data_for_issue {
  my $repcode=shift;
  my $issuedate=shift;
  my $doc=shift;
  my $le_element=$doc->getElementsByTagNameNS($ernad_ns,'learning_evaluation')->[0];
  if(not defined($a_h_c->{$issuedate})) {
    my $sent_text=&get_order_text($issuedate) or return;
    my $pos=1;
    foreach my $line (split("\n",$sent_text)) {
      my $id=&get_id($line);
      $a_h_c->{$issuedate}->{$id}=$pos++;
    }
  }
  my $allport_total=scalar(keys %{$a_h_c->{$issuedate}});
  ## gather the arguments for the learning evalutation
  my $eval_args=[$allport_total];
  ## this will also contain data about the criterium
  my $select_text=&get_order_text($issuedate,$repcode,'selected');
  if(not $select_text) {
    if($verbose) {
      print "I have no selected_text at $repcode, $issuedate\n";
    }
    return;
  }
  ## check if this does not contain all the papers
  my $total_selected=scalar(split("\n",$select_text));
  my $total_allport=scalar(keys %{$a_h_c->{$issuedate}});
  if($total_selected == $total_allport) {
    if($verbose) {
      print "All papers select, I am trying ordered at $repcode, $issuedate\n";
    }
    $select_text=&get_order_text($issuedate,$repcode,'ordered');
    if(not $select_text) {
      if($verbose) {
        print "I have no ordered_text at $repcode, $issuedate\n";
      }
      return;
    }
  }
  my $select;
  foreach my $line (split("\n",$select_text)) {
    my $id=&get_id($line);
    $select->{$id}=1;
  }
  my $ps_text=&get_order_text($issuedate,$repcode,'presorted');
  my $issue_element=$doc->createElementNS($ernad_ns,'issue');
  my $pretty_date=$issuedate;
  $pretty_date=~s|-|\x{2012}|g;
  $issue_element->setAttribute('date',$issuedate);
  $issue_element->setAttribute('pretty_date',$pretty_date);
  if(not $ps_text) {
    if($verbose) {
      print "I have no ps_text at $repcode, $issuedate\n";
    }
    $le_element->appendChild($issue_element);
    return;
  }
  my $ps;
  my @lines=split("\n",$ps_text);
  ## find the criterium
  my @parts=split(' ',$lines[0]);
  my $crit=$parts[2] // '';
  my $pos=1;
  if($crit) {
    $issue_element->setAttribute('crit',$crit);
  }
  my $count_texts=0;
  foreach my $line (split("\n",$ps_text)) {
    my $id=&get_id($line);
    if(not defined($select->{$id})) {
      $pos++;
      next;
    }
    my $sps=$a_h_c->{$issuedate}->{$id} // 0;
    if(not $sps) {
      print "I can't fined $id\n";
      print Dumper $a_h_c->{$issuedate};
      exit;
    }
    my $text_element=$doc->createElementNS($ernad_ns,'text');
    $count_texts++;
    $text_element->setAttribute('pos',$pos);
    $text_element->setAttribute('allpos',$sps);
    #$out.="  <text pos=\"$pos\" allpos=\"$sps\"/>\n";
    push(@{$eval_args},$pos);
    $pos++;
    $issue_element->appendChild($text_element);
  }
  my $breadth=sprintf("%.4f", $count_texts/$allport_total);
  $issue_element->setAttribute('allport_total',$allport_total);
  $issue_element->setAttribute('report_total',$count_texts);
  $issue_element->setAttribute('breadth',$breadth);
  my $lunol=&Ernad::Eval::Lunol::lunol($eval_args);
  if($lunol) {
    my $print_lunol=sprintf("%.4f",$lunol);
    $issue_element->setAttribute('lunol',$print_lunol);
  }
  else {
    print "I have no lunol for $issuedate of $repcode\n";
  }
  $le_element->appendChild($issue_element);
}

sub get_order_text {
  my $issuedate=shift;
  my $repcode=shift // $e->get_allport_repcode();
  my $part=shift // 'sent';
  my $sent_dir=$e->{'report'}->{$repcode}->{'dir'}->{$part};
  my $sent_rif=$e->{'d'}->latest_rif($sent_dir,$issuedate);
  if(not $sent_rif) {
    if($verbose) {
      print "I don't have a rif for $repcode $issuedate in $part\n";
    }
    return '';
  }
  if(not -f $sent_rif) {
    confess "I can't open rif $sent_rif.";
  }
  # my $sent_text=$e->{'t'}->transform_file_to_text($sent_rif,'show_order');
  my $sent_text=$e->{'t'}->t($sent_rif,'show_order','chars');
  return $sent_text;
}
