#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw( $Bin );
use POSIX qw( strftime );
use Data::Dumper;
use File::Find qw( find );
use HTML::Strip;

my $hs = HTML::Strip->new();

my $file_from = shift;
my $folder_to = shift;
die "Usage: $0 <file_from> <folder_to>\n" unless defined $file_from && defined $folder_to;

my %RULES = (
  is_void         => 'Anula',
  initial_cleanup => '^............',
  request_number  => 'Pedido (\d+)',
  product_line    => '^\s+(\d+) (.*?)$',
  table_number    => 'M\. (\d+)',
  clerk_number    => 'N\.(\d+)',
  lines_to_ignore => [
    '^N',
  ],
);

my( $req_number, $table_number, $clerk_number, $is_void, $lines ) = process(\%RULES, $file_from);
$lines ||= [];

&write_request( $req_number, $table_number, $clerk_number, $is_void, $lines );

&gen_resumed_info();

#
# FUNCTIONS
#

sub process {
  my( $rules, $file ) = @_;

  my $req_number = "";
  my @lines = ();
  my @ret_lines = ();

  if (open(F, "< $file")) {
    while (<F>) {
      s/\n//g;
      s/\r//g;
      push @lines, $_;
    }
    close(F);
  }
  else {
    die "Can't open $file: $!\n";
  }

  my $c = 0;

  LINE: for (@lines) {
    my $line = $_;

    if ($c++ == 0) {
      my $rule_ic = $rules->{initial_cleanup};
      $line =~ s/$rule_ic//;
    }

    $line =~ s/^\s+//;
    $line =~ s/\s+$//g;
    $line =~ tr/\x20-\x7f//cd;
    $line =~ s/^[!]+//;
    $line =~ s/[!]+$//;

    my $rules_lines_to_ignore = $rules->{lines_to_ignore};

    foreach my $rule (@$rules_lines_to_ignore) {
      next LINE if $line =~ /$rule/;
    }

    print STDERR "[DEBUG] #$line#\n";

    my $rule_rn = $rules->{request_number};
    my $rule_pl = $rules->{product_line};
    my $rule_tn = $rules->{table_number};
    my $rule_cn = $rules->{clerk_number};
    my $rule_vd = $rules->{is_void};

    if ($line =~ /$rule_vd/) {
      $is_void = 1;
    }

    if ($line =~ /$rule_rn/) {
      $req_number = $1;
    }

    if ($line =~ /$rule_tn/) {
      $table_number = $1;
    }

    if ($line =~ /$rule_cn/) {
      $clerk_number = $1;
    }

    if ($line =~ /$rule_pl/) {
      my $qty = $1;
      my $name = $2;
      $name =~ s/^\s+//;
      $name =~ s/\s+$//;
      $name = substr($name, 0, 18);

      push @ret_lines, { qty => $qty, product => $name };
    }
  }

  #$req_number = int(rand(1000));
  return ( $req_number, $table_number, $clerk_number, $is_void, \@ret_lines );
}

sub write_request {
  my( $req_number, $table_number, $clerk_number, $is_void, $lines ) = @_;

  $is_void ||= 0;

  if ($is_void && $req_number && scalar @$lines) {
    _handle_void($req_number, $lines);
    return;
  }

  if ($req_number && scalar @$lines) {
    if (! -d "$folder_to") {
      system("mkdir -p $folder_to");
    }

    $req_number = sprintf("%06d", $req_number);

    my $html = "<center><table border=1 cellpadding=0 cellspacing=0>\n";
    $html .= "<tr><td align=left colspan=2>TABLE # <font size=5><b>".$table_number."</b> <font size=3>| ". strftime("%H:%M", localtime)."</td></tr><tr><td align=left colspan=2>ORDER # <font size=5><b>".($req_number*1)."</td></tr>\n";

    my $line_num = 0;

    for (@$lines) {
      if ($line_num++ == 0) {
        $html .= "<!-- PRODUCTS START -->";
      }

      #my $qty = sprintf("%4s", $_->{qty});
      #my $prd = sprintf("%-20s", $_->{product});

      $html .= "<tr id=request><td align=right>".$_->{qty}.
        "</td><td>".$_->{product}."</td></tr>\n";
    }

    $html .= "<!-- PRODUCTS END --></table>\n";
    #$html .= "<tr><td colspan=2 align=center><b>".
    #  strftime("%H:%M", localtime).
    #  "</td></tr></table>\n\n";

    # on big requests, the bottom clock wasnt right, this makes it happy
    if (scalar @$lines > 18) {
      $html .= "\n";
    }

    #$html .= "</table>\n";
    #$html .= "<br>.";

    open(F, "> $folder_to/$req_number") or die "Can't write to $file_from\n";
    print F $html;
    close(F);

    open(F, "> $folder_to/refresh");
    print F "1\n";
    close(F);
  }
}

sub _handle_void {
  my( $req_number, $lines ) = @_;

  $req_number = sprintf("%06d", $req_number);

  print STDERR "> _handle_void - $folder_to/$req_number\n";

  if (! -e $folder_to."/$req_number") {
    print STDERR "We've received a void for a request that doesn't exists...\n";
    return;
  }

  my %to_deduct = ();

  for (@$lines) {
    $to_deduct{$_->{product}} += $_->{qty};
  }

  print STDERR Dumper(\$lines);
  print STDERR Dumper(\%to_deduct);

  my( $start, $end ) = ( 0, 0 );

  my $req_content = "";

  if (open(F, "< $folder_to/$req_number")) {
    while (<F>) {
      my $line = $_;

      if ($line =~ /PRODUCTS START/) {
        $req_content .= $line;
        $start = 1;
      }
      elsif ($line =~ /^<\!\-\- PRODUCTS END \-\->(.*?)$/ && $start) {
        my $rest_of_line = $1;
        $start = 0;

        for (@$lines) {
          $req_content .= "<tr id=void><td bgcolor=red align=right><font color=white><b>".$_->{qty}."</td><td bgcolor=red><font color=white><b>".$_->{product}."</td></tr>\n";
        }

        $req_content .= "<!-- PRODUCTS END -->$rest_of_line\n";
      }
      else {
        $req_content .= $line;
      }
    }
    close(F);
  }

  if ($req_content) {
    open(F, "> $folder_to/$req_number");
    print F $req_content;
    close(F);

    open(F, "> $folder_to/refresh");
    print F "1\n";
    close(F);
  }
}

sub gen_resumed_info {
  my %info = ();

  find( sub {
    return unless -f $File::Find::name;
    return unless /^\d+$/;

    if (open(F, "< $File::Find::name")) {
      while(<F>) {
        my $line = $_;

        if ($line =~ /tr id=(.*?)>/) {
          my $op = $1;

          my $clean_text = $hs->parse( $line );
          $hs->eof;

          my( $qty, $prod ) = $clean_text =~ /^(.*?)\s+(.*?)$/;

          if ($op eq 'void') {
            $info{$prod} -= $qty;
          }
          else {
            $info{$prod} += $qty;
          }
        }
      }
      close(F);
    }
  }, ( "/opt/pos/server/data/kitchen_terminal/EXTERNAL" ));

  open(F, "> /opt/pos/server/data/kitchen_terminal/EXTERNAL/global.info");

  foreach my $rec (reverse sort { $info{$a} <=> $info{$b} } keys %info) {
    print F "$rec§$info{$rec}\n";
  }

  close(F);
}

