#!/usr/bin/perl

use strict;
use warnings;
use IO::Socket::INET;
use Data::Dumper;
use File::Copy qw( move copy );
use POSIX qw( strftime );
use Time::HiRes qw( gettimeofday sleep );

my $LOGS_TO_HDD = 0;

$SIG{CHLD} = "IGNORE";

$| = 1;

my $end_tag = shift || "";

my $sock = IO::Socket::INET->new(
  #LocalAddr =>$machine_addr,
  LocalPort => 9100,
  Proto => 'tcp',
  Listen => 5,
  Reuse => 1,
);

my $log_dir = "/root/logs/virtual_printer";
my $main_printer = `cat /opt/pos/server/data/registered_printers/0/main`;
chop($main_printer);
my $time = strftime("%Y%m%d_%H%M%S", localtime);
my $filename = "/opt/pos/server/data/tmp/print#0#$main_printer#0#$time.txt";

my %end_document = (
  chr(29).chr(86).chr(1)   => 1, 
  chr(29).chr(86).chr(0)   => 1,
  chr(27).chr(109).chr(10) => 1, 
  chr(27).chr(105)         => 1,
);

$end_document{$end_tag} = 1 if $end_tag;

while(my $client = $sock->accept) {
  my $pid = fork;

  if ($pid == 0) {
    handle_client($client);
  }
  else {
    my_log("New client ".inet_ntoa($client->peeraddr).", forking (child $pid)");
  }
}

while (wait() != -1) {}

sub handle_client {
  my $client = shift;
  my $client_buffer = "";

  while (1) {
    my $buffer = "";
    my $result = sysread $client, $buffer, 128;

    last if length($buffer) == 0;

    $client_buffer .= $buffer;

    if (length($buffer) == 3) {
      my @v = split //, $buffer;

      if (ord($v[0]) == 16 && ord($v[1]) == 4 && ord($v[2]) == 1) {
        my $seq = chr(22);
        syswrite $client, $seq, length($seq);
        $client_buffer = "";
        next;
      }
      elsif (ord($v[0]) == 16 && ord($v[1]) == 4 && ord($v[2]) == 2) {
        my $seq = chr(18);
        syswrite $client, $seq, length($seq);
        $client_buffer = "";
        next;
      }
      elsif (ord($v[0]) == 16 && ord($v[1]) == 4 && ord($v[2]) == 3) {
        my $seq = chr(18);
        syswrite $client, $seq, length($seq);
        $client_buffer = "";
        next;
      }
      elsif (ord($v[0]) == 16 && ord($v[1]) == 4 && ord($v[2]) == 4) {
        my $seq = chr(18);
        syswrite $client, $seq, length($seq);
        $client_buffer = "";
        next;
      }
    }
  }

  my $count = 0;

  foreach my $k (keys %end_document) {
    my $r = index($client_buffer, $k);

    if ($r != -1) {
      if (length($client_buffer) <= 10) {
        my_log("Will ignore print, too small: ".length($client_buffer)." bytes...");
      }
      else {
        my $time = gettimeofday;
        $time =~ s/\.//;

        my $fname = $filename;

        if (open(F, "> $fname")) {
          print F $client_buffer;
          close(F);
        }
        else {
          my_log("Error writing $fname: $!");
        }
      }

      my $seq = chr(22) . chr(18) . chr(18) . chr(18);
      syswrite $client, $seq, length($seq);

      $client_buffer = "";

      last; # terminate the foreach loop
    }
  }

  exit 0,
}

sub my_log {
  my $m = shift || "";

  my $time = strftime("%Y%m%d_%H%M%S", localtime);

  if ($LOGS_TO_HDD) {
    my $log_file = "$log_dir/kvs_vp_".strftime("%Y%m%d", localtime).".log";

    if (open(FL, ">> $log_file")) {
      print FL "$time> $m\n";
      close(FL);
    }
  }

  print STDERR "$time> $m\n";
}

