#!/usr/bin/perl

#
# This script is used to show these concepts:
#   - connect a station to a network
#   - insert records on a table in a master database
#   - receive them throught the replicate system
#   - do that forever so we can track the system down
#

use strict;
use warnings;
use FindBin qw( $Bin );
use lib "$Bin/../../lib";
use Data::Dumper;
use File::Path qw(make_path remove_tree);
use File::Copy qw( copy move );
use File::Find qw( find );

use App::POS::Counters;
use App::POS::Config;
use App::POS::Machine::Server;

my $area_param = shift;

my $areas_folder = "/opt/pos/server/data/areas";

if (-d "/opt/pos/server/data/kitchen_terminal") {
  system("rm -rf /opt/pos/server/data/kitchen_terminal/*");
}

my $cfg = App::POS::Config->new(
  file => "$Bin/../../etc/config.ini",
);

my $server = App::POS::Machine::Server->new( config => $cfg );
my $info = $cfg->load();
my $db = $server->database();

$info->{KEEP_TABLE_NAMES_ON_CLOSE} ||= 0;

if ($info->{KEEP_TABLE_NAMES_ON_CLOSE}) {
  # save table names
  system("rsync -a /opt/pos/server/data/areas/ /tmp/.areas.$$/");
}

$db->do("TRUNCATE card_sets");
system("rm -rf /opt/pos/server/data/payed_cards/*");

my $areas_table_names = App::POS::Counters->new(
  db => $db,
  name => 'areas_table_names',
);

$areas_table_names->clean();

my $card_sets = {};

if (! -d $areas_folder) {
  system("mkdir $areas_folder");
}
else {
  # does th $areas_folder."/card_sets.txt")is only if we didn't receive an area param
  if (! defined $area_param) {
    #unlink $areas_folder."/tables_to_cards.txt";
    #unlink $areas_folder."/names_to_tables.txt";
    #unlink $areas_folder."/card_sets.txt";

    # backup tables to cards file
    if (-e $areas_folder."/tables_to_cards.txt") {
      &copy( $areas_folder."/tables_to_cards.txt", "/tmp/tables_to_cards.txt" );
    }

    if (-e $areas_folder."/names_to_tables.txt") {
      &copy( $areas_folder."/names_to_tables.txt", "/tmp/names_to_tables.txt" );
    }

    if (-e $areas_folder."/card_sets.txt") {
      &copy( $areas_folder."/card_sets.txt", "/tmp/card_sets.txt" );
    }

    my @folders_to_remove = ();

    find( sub {
      return unless -d $File::Find::name;

      if (/^\d+$/) {
        push @folders_to_remove, $File::Find::name;
      }
    }, ( $areas_folder ));

    if (scalar @folders_to_remove) {
      my $str = join(" ", @folders_to_remove);
      system("rm -rf $str");
    }

    # restore tables to cards file
    if (-e "/tmp/tables_to_cards.txt") {
      &move( "/tmp/tables_to_cards.txt", $areas_folder."/tables_to_cards.txt" );
    }

    if (-e "/tmp/names_to_tables.txt") {
      &move( "/tmp/names_to_tables.txt", $areas_folder."/names_to_tables.txt" );
    }

    if (-e "/tmp/card_sets.txt") {
      &move( "/tmp/card_sets.txt", $areas_folder."/card_sets.txt" );
      $card_sets = &decode_card_sets( $areas_folder."/card_sets.txt" );
    }
  }
}

my $higher_card = -1;

if (scalar keys %$card_sets) {
  foreach my $card (keys %$card_sets) {
    if ($card > $higher_card) {
      $higher_card = $card;
    }
  }
}

if ($higher_card != -1) {
  $higher_card++;
}

if (! exists $info->{AREA}) {
  $info->{AREA} ||= [];
} else {
  if (! ref($info->{AREA})) {
    my $a = delete $info->{AREA};
    push @{ $info->{AREA} }, $a;
  }
}

my %table_hardcoded_names = ();

if (-e $areas_folder."/names_to_tables.txt") {
  my $cur_area = -1;

  open(F, "< $areas_folder/names_to_tables.txt");
  while(<F>) {
    chop;
    next unless $_;

    if (/^=(\d+)$/) {
      $cur_area = $1;
    }
    elsif (/^(\d+)=(.*?)$/) {
      my $k = $cur_area."#".$1;
      $areas_table_names->set_value($k, $2);

      $table_hardcoded_names{$cur_area}->{$1} = $2;
    }
  }
  close(F);
}

my @areas_with_names = keys %table_hardcoded_names;

if (scalar @areas_with_names) {
  my $str = join(",", @areas_with_names);
  my %i = ( areas => $str );
  $server->hash_to_hdd("/opt/pos/server/data/areas/with_fixed_names.txt", \%i);
  #my $i = $server->hash_from_hdd("/opt/pos/server/data/areas/with_fixed_names.txt");
  #print STDERR Dumper($i);
}

my $idx = -1;

foreach my $a (@{$info->{AREA}}) {
    $idx++;

    my $area_num = $idx;

    my $user_area_num = $area_num + 1;

    my $v = $a;

    #Esplanada,50,sell_price1,sell_vat1
    my @toks = split /,/, $v;
    my $tables = $toks[1];

    my $start_idx = 0;

    if (scalar(@toks) >= 7) {
      $toks[6] ||= 1;
      $start_idx = $toks[6]-1;
    }

    $tables ||= 0;

    if (scalar @toks >= 5 && $toks[4] eq 'splits') {
      $tables = 0;
    }

    my $d = $area_num;

    my $folder = "$areas_folder/$d";

    next if defined $area_param && $area_param != $area_num;

    print STDERR "###> AREA $area_num, tables: $tables, folder: $folder\n";

    &remove_tree($folder) if -d $folder;
    &make_path($folder);

    # on areas wo tables, we can set the id where the area will start
    if ($tables == 0) {
      if (scalar @toks >= 7) {
        $toks[6] ||= 0;

        if ($toks[6] > 0) {
          open(F, "> $folder/nextid");
          print F $toks[6]."\n";
          close(F);
        }
      }
    }

    if ($tables == 0 && $higher_card != -1) {
      if (scalar @toks >= 5 && $toks[4] eq 'splits') {
      }
      else {
        open(F, "> $folder/nextid");
        print F $higher_card."\n";
        close(F);
      }
    }

    my $use_table_names = scalar %table_hardcoded_names && exists $table_hardcoded_names{$area_num} ? 1 : 0;

    if ($tables > 0) {
      for (my $i=0; $i<$tables; $i++) {
        my $check_num = $start_idx+1;
        #open(F, "> $folder/$check_num");
        #close(F);

        if ($use_table_names) {
          if (exists $table_hardcoded_names{$area_num}->{$check_num}) {
            open(F, "> $folder/$check_num.name");
            print F $table_hardcoded_names{$area_num}->{$check_num}."\n";
            close(F);
          }
        }

        $start_idx++;
      }
    }
}

if (! -d "/opt/pos/server/data/tmp") {
  system("mkdir -p /opt/pos/server/data/tmp");
}

if ($info->{KEEP_TABLE_NAMES_ON_CLOSE}) {
  # recover saved table names
  find(sub {
    return unless -f $File::Find::name && /\.name$/;
    my @a = split /\//, $File::Find::name;

    my $area = $a[-2];
    my $file = $a[-1];

    copy( $File::Find::name, "/opt/pos/server/data/areas/$area/$file" );
  }, ( "/tmp/.areas.$$/" ) );

  system("rm -rf /tmp/.areas.$$");
}

system("echo 1 > /opt/pos/server/data/tmp/checksrefresh.txt");

sub decode_card_sets {
  my( $f ) = @_;

  my %f = ();

  if (open(F, "< $f")) {
    my %res = ();

    while (<F>) {
      chop;

      my @tok = split /#/, $_;

      if ($tok[0] =~ /,/) {
        for my $k (split /,/, $tok[0]) {
          $res{$k} = 1;
        }
      }
      else {
        $res{$tok[0]} = 1;
      }
    }

    foreach my $k (keys %res) {
      if ($k =~ /\-/) {
        my @t = split /\-/, $k;

        for (my $i=$t[0]; $i<$t[1]; $i++) {
          $f{$i} = 1;
        }
      }
      else {
        $f{$k} = 1;
      }
    }

    close(F);
  }

  return \%f;
}


