#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw( $Bin );
use lib "$Bin/../../lib";
use POSIX qw( strftime );
use Data::Dumper;
use File::Path qw( make_path remove_tree );
use File::Copy qw( copy move );
use DBI;
use App::POS::DB::Postgres;
use App::POS::Config;
use Cwd;

# change when done
my $BACKUP_DESTINATION = shift;
my $DONT_INCLUDE_AREAS = shift;
die "Usage: $0 <dest_dir> [<dont_include_areas>]\n" unless defined $BACKUP_DESTINATION;

make_path($BACKUP_DESTINATION) unless -d $BACKUP_DESTINATION;

if (! -e "/opt/pos/.business_date") {
  die "Can't find /opt/pos/.business_date\n";
}

open(F, "< /opt/pos/.business_date");
my $biz_date = <F>;
chop($biz_date);
my @toks = split /\-/, $biz_date;
close(F);

my $CUR_MASK = $toks[0].$toks[1];

my $DATABASE = "pos";
my $TMP_DIR = "/opt/pos_backup";
#my $TMP_DIR = "/home/mmanso/pos_backup";

my %PARTIAL_TABLES = (
  sales_headers => 1,
  sales_payments => 1,
  sales_hashes_products => 1,
  sales_hashes => 1,
  sales_details => 1,
);

#############################################
## BEGIN
#############################################

my $CFG = App::POS::Config->new( file => "/opt/pos/etc/config.ini" );
my $CONFIG = $CFG->load_fixed();

my $dsn = 'DBI:Pg:dbname='.$DATABASE.';host=127.0.0.1';
my $user = 'root';
my $passwd = '';

my $db = App::POS::DB::Postgres->new(dbh => DBI->connect($dsn,$user,$passwd,{}));

my @tables = $db->select("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'");

my %existing_masks = ();

foreach my $table (@tables) {
  foreach my $part (keys %PARTIAL_TABLES) {
    if ($table->{table_name} =~ /^$part/) {
      if (my( $mask ) = $table->{table_name} =~ /(\d\d\d\d\d\d)$/) {
        $existing_masks{ $mask } = 1;
      }
    }
  }
}

# clean tmp backup dir, if exists
remove_tree($TMP_DIR) if -d $TMP_DIR;

# copy files
&copy_files();

# historial
foreach my $k (keys %existing_masks) {
  if ($k ne $CUR_MASK) {
    &backup_particular_mask( $k, \%existing_masks, 1 );
  }
}

# actual
&backup_particular_mask( $CUR_MASK, \%existing_masks, 0 );

# generate final ZIP file
my $cur_dir = getcwd();
my $cur_date = &strftime("%Y%m%d_%H%M%S", localtime);
chdir($TMP_DIR);
system("zip -q -r /opt/backup_$cur_date.zip *");
move( "/opt/backup_$cur_date.zip", "$BACKUP_DESTINATION/backup_$cur_date.zip" );
chdir($cur_dir);

# clean tmp backup dir, if exists
remove_tree($TMP_DIR) if -d $TMP_DIR;

#
# Functions
#

sub backup_particular_mask {
  my( $mask, $existing_masks, $is_archive ) = @_;

  my $destination = "";
  my $backup_name = "";

  if ($is_archive) {
    $destination = "$BACKUP_DESTINATION/archive";
    $backup_name = "$mask.dump";

    # ignore already archived months
    return if -e "$destination/$backup_name";

    print STDERR "backup_particular_mask > $mask > $destination/$backup_name\n";
  }
  else {
    $destination = "$TMP_DIR/server/data/database";
    $backup_name = "db.dump";
    print STDERR "backup_particular_mask > $mask\n";
  }

  make_path($destination) unless -d $destination;

  my $exclude_string = &build_exclude_string($existing_masks, $mask);

  my $command = "pg_dump -Fc -U root $exclude_string $DATABASE > \"$destination/$backup_name\"";
  system($command);
}

sub copy_files {
  make_path("$TMP_DIR/etc");
  make_path("$TMP_DIR/etc/machine");
  make_path("$TMP_DIR/server/data/database");
  make_path("$TMP_DIR/common/data");
  make_path("$TMP_DIR/common/print_templates");
  make_path("$TMP_DIR/common/bin");
  make_path("$TMP_DIR/lib");
  make_path("$TMP_DIR/common/skins/".$CONFIG->{LANG});

  &copy( "/opt/pos/common/skins/".$CONFIG->{LANG}."/main.png", "$TMP_DIR/common/skins/".$CONFIG->{LANG} );
  &copy( "/opt/pos/common/skins/".$CONFIG->{LANG}."/login.png", "$TMP_DIR/common/skins/".$CONFIG->{LANG} );
  &copy( "/opt/pos/common/skins/".$CONFIG->{LANG}."/checks.png", "$TMP_DIR/common/skins/".$CONFIG->{LANG} );

  system("cp -r /opt/pos/lib/* \"$TMP_DIR/lib\"");

  &copy( "/opt/pos/common/bin/pos", "$TMP_DIR/common/bin/pos" );

  &copy( "/root/weckOFFICE/etc/config.xml", "$TMP_DIR/etc" )
    if -e "/root/weckOFFICE/etc/config.xml";

  &copy( "/etc/network-config/settings.txt", "$TMP_DIR/etc/machine" )
    if -e "/etc/network-config/settings.txt";

  &copy( "/etc/X11/xorg.conf", "$TMP_DIR/etc/machine" )
    if -e "/etc/X11/xorg.conf";

  &copy( "/etc/default/grub", "$TMP_DIR/etc/machine" )
    if -e "/etc/default/grub";

  &copy( "/etc/rc.local", "$TMP_DIR/etc/machine" )
    if -e "/etc/rc.local";

  &copy( "/root/.fluxbox/startup", "$TMP_DIR/etc/machine" )
    if -e "/root/.fluxbox/startup";

  &copy( "/opt/bin/machine_calibrate", "$TMP_DIR/etc/machine" )
    if -e "/opt/bin/machine_calibrate";

  &copy( "/opt/pos/hardlock", "$TMP_DIR/hardlock" )
    if -e "/opt/pos/hardlock";

  system("cp -r /opt/pos/*.png \"$TMP_DIR\"");
  system("cp -r /opt/pos/common/print_templates/* \"$TMP_DIR/common/print_templates\"");
  system("cp -r /opt/pos/common/data/* \"$TMP_DIR/common/data\"");
  system("cp -r /opt/pos/server/data/* \"$TMP_DIR/server/data\"");
  system("rm -rf \"$TMP_DIR/common/data/sales_*.zip\"");
  system("rm -rf \"$TMP_DIR/common/data/backup_*.zip\"");
  system("rm -rf \"$TMP_DIR/common/data/custom_scales\"");
  system("rm -rf \"$TMP_DIR/common/data/DB_*.xls\"");
  system("cp -r /opt/pos/etc/* \"$TMP_DIR/etc\"");

  # don't save images main library, to keep backup lighter
  system("rm -rf \"$TMP_DIR/server/data/images\"");

  if (defined $DONT_INCLUDE_AREAS) {
    system("rm -rf \"$TMP_DIR/server/data/areas\"");
  }
}

sub build_exclude_string {
  my( $masks, $the_one_to_use ) = @_;

  my $str = "";

  foreach my $mask (keys %$masks) {
    next if $mask eq $the_one_to_use;

    foreach my $part (keys %PARTIAL_TABLES) {
      $str .= "--exclude-table=".$part."_".$mask." \\\n";
    }
  }

  $str =~ s/\s\\\n$//;

  return $str;
}

