#!/usr/bin/perl

# ---------------------------------------------------------------
# Prontus CMS
# http://www.prontus.cl
# by Altavoz.net
#
# licensed under LGPL license.
# http://www.prontus.cl/license.html
# ---------------------------------------------------------------
# ---------------------------------------------------------------
# PROPOSITO .
# -----------
# Descargar los archivos pertenecientes a un Prontus y arículo desde un almacenamiento S3
#
use strict;
use warnings;
use utf8;

BEGIN {
    use FindBin qw($Bin);
    my $pathLibsProntus = $Bin;
    unshift(@INC, $pathLibsProntus);
}

END {
    &tareas_salida();
}

use sigtrap 'handler' => \&signal_catch, 'INT';
use sigtrap 'handler' => \&signal_catch, 'TERM';
use sigtrap 'handler' => \&signal_catch, 'KILL';

use Net::Amazon::S3;
use JSON;
require HTTP::Headers;

# Captura STDERR
use lib_stdlog;
&lib_stdlog::set_stdlog();
use prontus_varglb; &prontus_varglb::init();
use mime_types;
use glib_fildir_03;
use lib_prontus;
use lib_artic;
use Artic;
use lib_waitlock;
use lib_s3;

use Data::Dumper;

our $LOCK = '';
our $LOCKFH;
our $BD;

main: {
    lib_prontus::setUtf8();

    if (scalar @ARGV < 1) {
        print "Parámetros insuficientes. Modo de uso:\n";
        print "perl $0 <prontus_id>\no\n";
        print "perl $0 <prontus_id> <ts_articulo>\n";
        exit;
    }

    $prontus_varglb::PRONTUS_ID = $ARGV[0];

    if (!lib_prontus::valida_prontus($prontus_varglb::PRONTUS_ID)) {
        print STDERR "Prontus ID no es válido\n";
        exit;
    }

    my $ts = '';
    if (defined($ARGV[1]) && $ARGV[1] =~ /^\d{14}$/) {
        $ts = $ARGV[1];
    } elsif ($ARGV[1]) {
        print "Parámetro [$ARGV[1]] no es válido\n";
        exit;
    }

    my $marca = '';
    if (defined($ARGV[2]) && $ARGV[2] =~ /^\w+$/) {
        $marca = $ARGV[2];
    }

    # revisa concurrencia
    my $params = ' | grep ' . join(' | grep ', @ARGV);
    my $res = `ps auxww |grep prontus_s3_download_real.pl $params | grep -v grep | wc -l`;
    if ($res > 1) {
        print "Proceso ya en ejecución\n";
        exit;
    }

    my $msg_load = &lib_prontus::load_config_by_id($prontus_varglb::PRONTUS_ID);
    if ($msg_load ne '') {
        print STDERR "Ha ocurrido un error: $msg_load\n";
        exit;
    }

    if (!lib_s3::check_config_s3()) {
        print STDERR "S3 no habilitado y/o configurado\n";
        exit;
    }

    my ($result, $msg_err) = &lib_prontus::get_url("https://".$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'S3_ENDPOINT'}, 10);
    if ($msg_err) {
        print STDERR "Error al conectar con endpoint S3 [$msg_err]\n";
        exit;
    }

    lib_s3::connect_s3();
    my $bucket = lib_s3::connect_bucket();

    my @prefixes;

    if ($ts ne '') {
        my $dst_base;
        # marca multimedia
        if ($marca ne 'asocfile') {
            $dst_base = $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_SITE'} . "$prontus_varglb::DIR_EXMEDIA/" . substr($ts, 0, 8) . "$prontus_varglb::DIR_MMEDIA/";
            if ($marca) {
                $dst_base .= $marca;
                $dst_base .= $ts if ($ts);
            }
            $dst_base = substr($dst_base, 1);
            push(@prefixes, $dst_base);
        }
        # archivos adjuntos
        if ($marca eq 'asocfile' || $marca eq '') {
            $dst_base = $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_SITE'} . "$prontus_varglb::DIR_ASOCFILE/" . substr($ts, 0, 8) . "/$ts/";
            $dst_base = substr($dst_base, 1);
            push(@prefixes, $dst_base);
        }
    } else {
        push(@prefixes, $prontus_varglb::PRONTUS_ID);
    }

    foreach my $prefix (@prefixes) {
        my @s3_files = lib_s3::list_files_pattern($bucket, $prefix);
        foreach my $remote (@s3_files) {
            if ($ts eq '' || $remote->key =~ /$ts/) {
                print STDERR "Descargar ". $remote->key . " - " . &lib_prontus::bytes2kb($remote->size) ."\n";
                my $file = "$prontus_varglb::DIR_SERVER/".$remote->key;
                if (-s $file) {
                    print STDERR "Existe [$file], se omite\n";
                    next;
                }
                $file =~ /(.+)\/[^\/]+\.\w+$/;
                glib_fildir_03::check_dir($1);

                $remote->get_filename($file);
            }
        }
    }

    if ($ts ne '') {
        my $artic_obj = Artic->new(
            'prontus_id'         => $prontus_varglb::PRONTUS_ID,
            'public_server_name' => $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'PUBLIC_SERVER_NAME'},
            'cpan_server_name'   => $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'CPAN_SERVER_NAME'},
            'document_root'      => $prontus_varglb::DIR_SERVER,
            'ts'                 => $ts,
            'no_check_dirs'      => 1) || return "Error inicializando objeto articulo: $Artic::ERR TS[$ts]";

        # se asegura el xml mientras se edita y guarda
        $LOCK = "$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_LOCKS'}/$ts.mutex";
        $LOCKFH = &lib_waitlock::lock_file($LOCK);

        $artic_obj->{xml_data} = &glib_fildir_03::read_file($artic_obj->{fullpath_xml});
        if ($marca eq '') {
            # se bajo todo hay que marcar todo como local
            my $xml_temp = $artic_obj->{xml_data};
            while($xml_temp =~ m/<((multimedia_video|multimedia_audio|asocfile_)\w+\.s3)>.+?<\/\1>/sg) {
                my $found = $1;
                $artic_obj->{xml_data} = &lib_prontus::replace_in_xml($artic_obj->{xml_data}, $found, '', 0);
            }
        } elsif ($marca eq 'asocfile') {
            # bajaron todos los asocfile
            my $xml_temp = $artic_obj->{xml_data};
            while($xml_temp =~ m/<(asocfile_\w+\.s3)>.+?<\/\1>/sg) {
                my $found = $1;
                $artic_obj->{xml_data} = &lib_prontus::replace_in_xml($artic_obj->{xml_data}, $found, '', 0);
            }
        } else {
            # marca especifica, por ej: multimedia_video1, multimedia_audio2
            $artic_obj->{xml_data} = &lib_prontus::replace_in_xml($artic_obj->{xml_data}, "$marca.s3", '', 0);
        }
        # se marca articulo como no procesado en s3 para poder cargarlo posteriormente
        $artic_obj->{xml_data} = &lib_prontus::replace_in_xml($artic_obj->{xml_data}, '_s3', 0, 0);

        # actualizamos tamaño del artículo
        # este dato solo se puede obtener desde el xml
        my $s3_size = 0;
        if ($artic_obj->{xml_data} =~ /<_s3_size>(\d+)<\/_s3_size>/) {
            $s3_size = $1;
        }

        my ($disk_size, $imag_size, $asset_size, $media_size) = $artic_obj->get_disk_size();
        my $total_size = $artic_obj->{campos}->{'_s3_size'} + $disk_size;
        $artic_obj->update_art_size($total_size, $disk_size, $imag_size, $asset_size, $media_size);

        $artic_obj->_flush_xml();
        &lib_waitlock::unlock_file($LOCK, $LOCKFH);

        # actualiza datos en bd
        my ($bd, $msg) = &lib_prontus::conectar_prontus_bd();
        if (!ref($bd)) {
            return $msg;
        }
        $artic_obj->art_update_bd($bd);
    }
}
# ---------------------------------------------------------------
# funcion para capturar las señales INT y TERM y logearlas
sub signal_catch {
    print STDERR  "Terminado por signal @_\n";
    exit(0);
}

sub tareas_salida {
    if ($LOCK ne '') {
        &lib_waitlock::unlock_file($LOCK, $LOCKFH);
    }
}
