#!/usr/bin/perl

use strict;
use warnings;

use Carp qw(confess);
use Data::Dumper;
use File::Path;
use Getopt::Std;
use POSIX qw(ceil);
use XML::LibXML;

use Ernad::Erimp;
use Ernad::Common;
use Ernad::Dates;
#use Ernad::Sort;
use Ernad::Generate;
use Ernad::Sausage;
use Ernad::Yanabino;

binmode(STDOUT,":utf8");

## options
my %o;
getopts("ae:ovd:s", \%o) or die;

my $auto_pilot=$o{'a'} // '';

## allow for a multiplier
my $clear_excess=$o{'e'} // 0;

my $fake_date=$o{'d'} // '';
if($fake_date and not $fake_date=~m|\d{4}-\d{2}-\d{2}|) {
  print "I don't like your -d option $fake_date\n";
  exit;
}

my $impna=$ARGV[0] // '';
if(not $impna) {
  print "I need an impna.\n";
  exit;
}

our $e=Ernad::Erimp->new({'impna'=>$impna});

## check for a holiday
my $today=&Ernad::Dates::today();
my $holiday_regex=$e->{'conf'}->{'holidays'} // '';
if($holiday_regex and $today=~m|$holiday_regex|) {
  $e->echo(__LINE__,"Today, $today is a holiday. I relax.");
  exit;
}

my $target_argument=$ARGV[1] // '';
my $target_number;
my $weekly_average=0;
my $count_papers_in_queue;
if($target_argument=~m|^\d+|) {
  if($target_argument=~m|^0|) {
    print "I can't take a target_argument starting with 0.\n";
    exit;
  }
  $target_number=$target_argument;
}
else {
  $weekly_average=&Ernad::Yanabino::find_weekly_average(365);
  if(not $target_argument) {
    $target_number=$weekly_average;
  }
  elsif($target_argument=~m|\.\d+$|) {
    $count_papers_in_queue=&Ernad::Yanabino::count_papers_in_queue;
    if($count_papers_in_queue < $weekly_average) {
      $target_number=$weekly_average;
    }
    else {
      my $gap=$count_papers_in_queue-$weekly_average;
      $target_number=$weekly_average+int($target_argument*$gap);
    }
  }
  else {
    print "I can't deal with your target_argument '$target_argument'.";
    exit;
  }
}

if($o{'v'}) {
  $count_papers_in_queue=&Ernad::Yanabino::count_papers_in_queue;
  print "count_paper_in_queue is $count_papers_in_queue\n";
}

my $piles_dir=$e->{'dir'}->{'pile'} // die "I don't see the pile_dir.";
my $issues_dir=$e->{'dir'}->{'issues'} // die "I don't see the issues_dir.";

my $issuedate=&Ernad::Dates::today();
if($fake_date) {
  $issuedate=$fake_date;
}
my $today_dir=$piles_dir.'/'.$issuedate;

## clear out today_dir
if($o{'o'}) {
  if($o{'v'} and -d $today_dir) {
    print "I delete $today_dir\n";
  }
  system("rm -rf $today_dir");
}
if(-d $today_dir) {
  print "I found $today_dir, use -o to overwrite\n";
  exit;
}
mkpath($today_dir);

my $count_papers_to_be_fetched=$target_number;

my $eles_fetched;
my $piles;

## excess harvesting
my $list_piles=&Ernad::Yanabino::list_piles($piles_dir);
my $last_issuedate=&Ernad::Yanabino::find_last_issuedate_by_piles($list_piles);

if($clear_excess) {
  $piles=&Ernad::Yanabino::get_piles($piles_dir);
  foreach my $date (keys %$piles) {
    if($o{'v'}) {
      print "for $date, I compare $date with $last_issuedate\n";
    }
    my $diff_date=&Ernad::Dates::diff_dates($date,$last_issuedate);
    if(not $diff_date > 0) {
      next;
    }
    my $file=$piles->{$date};
    my $count_total=&Ernad::Yanabino::count_handles_in_file($file);
    my $total_to_get_from_pile=int($clear_excess * $diff_date * $count_total / 365);
    my $out_file="$today_dir/$date.xml";
    if($o{'v'}) {
      print "For $file, diff_date is $diff_date.\n";
      print "I am getting $total_to_get_from_pile from $file as excess\n";
    }
    my $eles=&Ernad::Yanabino::trim_and_save_file($file,$out_file,$total_to_get_from_pile);
    foreach my $handle (keys %$eles) {
      push(@$eles_fetched,$eles->{$handle});
    }
  }
}

## standard harvest
## while there is at least one paper to fetch
$piles=&Ernad::Yanabino::get_piles($piles_dir);
while($count_papers_to_be_fetched > keys %{$piles}) {
  ## this lists the lastest piles that still have papers
  my $piles=&Ernad::Yanabino::get_piles($piles_dir);
  ## get out if we don't have piles with papers any more
  my $total_piles=scalar keys %$piles or last;
  ## old way, and still documented: round down
  #my $total_to_get_from_pile=int($count_papers_to_be_fetched/$total_piles);
  ## 2017-10-16: round up
  my $total_to_get_from_pile=&ceil($count_papers_to_be_fetched/$total_piles);
  foreach my $date (keys %$piles) {
    my $file=$piles->{$date};
    my $out_file="$today_dir/$date.xml";
    my $eles=&Ernad::Yanabino::trim_and_save_file($file,$out_file,$total_to_get_from_pile);
    my $count_eles=keys %$eles;
    if($o{'v'}) {
      #print "I got $count_eles from $file\n";
    }
    foreach my $handle (keys %$eles) {
      push(@$eles_fetched,$eles->{$handle});
    }
    $count_papers_to_be_fetched -= $count_eles;
  }
}

my $new_papers_root_ele = $e->{'x'}->amf_element();
my $allport_repcode = $e->get_allport_repcode();
my $new_papers_doc  = XML::LibXML::Document->new('1.0','utf-8');
my $new_papers_file = $e->{'dir'}->{'tmp'}.'/'.$e->{'const'}->{'new_papers_file'};
$new_papers_file=~s|\.xml$|_$issuedate.xml|;
my $allport_collection = $e->get_allport_collection();
$allport_collection=Ernad::Generate::inject_issue_date($allport_collection,$issuedate);
$new_papers_root_ele->appendChild($allport_collection);
foreach my $text_ele (@$eles_fetched) {
  $new_papers_root_ele->appendChild($text_ele);
}
$new_papers_doc->setDocumentElement($new_papers_root_ele);
&Ernad::Sausage::inject($new_papers_doc);
$new_papers_doc->toFile($new_papers_file,1);

my $allport_dir=$e->get_allport_dir;
my $xslt_file=$e->{'dir'}->{'style'}.'/'.$e->{'const'}->{'make_allport'};
#my $out=Ernad::Common::xslt_transform($new_papers_doc,$xslt_file);
my $out=$e->{'t'}->transform($new_papers_doc,$e->{'const'}->{'make_allport'});
my $issue_file=$issues_dir.'/'.$issuedate.$e->{'const'}->{'amf_ext'};
#$out->toFile($issue_file);
#print "I wrote $issue_file\n";

if(not $auto_pilot) {
  my $source_dir=$allport_dir.'/'.$e->{'const'}->{'source_dir'};
  my $us_dir=$source_dir.'/'.$e->{'const'}->{'unsorted_dir'};
  my $ps_dir=$source_dir.'/'.$e->{'const'}->{'presorted_dir'};
  if(not -d $us_dir) {
    mkpath $us_dir;
  }
  if(not -d $ps_dir) {
    mkpath $ps_dir;
  }
  if($o{'v'}) {
    print "Deleting previous rifs of that issue\n";
  }
  my $to_delete_us="$us_dir/$issuedate*";
  if($o{'v'}) {
    print "I delete $to_delete_us\n";
  }
  unlink glob $to_delete_us;
  my $to_delete_ps="$ps_dir/$issuedate*";
  if($o{'v'}) {
    print "I delete $to_delete_ps\n";
  }
  unlink glob $to_delete_ps;
  my $fn = $e->{'f'}->by_date( $issuedate );
  my $us_file = "$us_dir/$fn";
  my $ps_file = "$ps_dir/$fn";
  if($o{'v'}) {
    print "saving to $us_file\n";
  }
  #print $out_amf_doc->toString;
  $out->toFile($us_file,2) or die;
  if($o{'v'}) {
    print "saving to $ps_file\n";
  }
  $out->toFile($ps_file,2) or die;
  #my $rifs=&presort_allport($outf);
  #if($adverts_fullfilled_dir) {
  #  &inject_advert($today,$rifs);
  #}
  #&prepare_for_manual_issue();
  exit;
}

my $sent_dir=$allport_dir.'/'.$e->{'const'}->{'sent_dir'};
if($o{'v'}) {
  print "Deleting previous rifs of that issue\n";
}
my $to_delete="$sent_dir/$issuedate*";
if($o{'v'}) {
  print "I delete $to_delete\n";
}
unlink glob $to_delete;
my $fn = $e->{'f'}->by_date( $issuedate );
my $sent_file = "$sent_dir/$fn";
$out->toFile($sent_file,2) or die;
&Ernad::Sausage::inject($new_papers_doc);
### commented for manual check 2018-01-12
### ## publish allport issue
#my $publish_bin=$e->{'dir'}->{'perl'}.'/publish '.$sent_file;
#if($o{'v'}) {
#  print "I run '$publish_bin'\n";
#}
#system($publish_bin);
##
## release
$e->run_bin('unleash',$sent_file);
print($sent_file);

exit;
