#!/usr/bin/perl

# ---------------------------------------------------------------
# Prontus CMS
# http://www.prontus.cl
# by Altavoz.net
#
# licensed under LGPL license.
# http://www.prontus.cl/license.html
# ---------------------------------------------------------------

# -------------------------------COMENTARIO GLOBAL---------------
# ---------------------------------------------------------------
# PROPOSITO.
# -----------
# Indexa el tamaño ocupado de los artículos
# ---------------------------------------------------------------
# LLAMADAS A ARCHIVOS EXTERNOS.
# ------------------------------
#
# ---------------------------------------------------------------
# INVOCACIONES ACEPTADAS.
# ------------------------
# Por linea de comando
# ---------------------------------------------------------------

# ---------------------------------------------------------------
# DIRECTIVAS DE COMPILACION.
# ---------------------------
use utf8;
use strict;

BEGIN {
    use FindBin qw($Bin);
    my $pathLibsProntus = $Bin;
    unshift(@INC,$pathLibsProntus);
    $pathLibsProntus =~ s/\/[^\/]+\/?$//;
    unshift(@INC,$pathLibsProntus);
}

END {
    &tareas_salida();
}

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

##libs##
use lib_stdlog;
lib_stdlog::set_stdlog($0, 51200);
use prontus_varglb;
prontus_varglb::init();

use Artic;
use File::Copy;
our $S3_LIB_ENABLED = 0;
eval {require Net::Amazon::S3;};
if ($@) {
    $S3_LIB_ENABLED = 0;
} else {
    $S3_LIB_ENABLED = 1;
}
require HTTP::Headers;
use JSON;
use POSIX;
use URI::Escape;
use glib_dbi_03;
use glib_fildir_03;
use glib_hrfec_03;
use glib_str_03;
use lib_mam;
use lib_maxrunning;
use lib_prontus;
use lib_waitlock;
use lib_s3;
##/libs##

my $LOCK = '';
my $LOCKFH;
my $S3_ENABLED = 0;
my $BUCKET;

main: {
    &lib_prontus::setUtf8();

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

    if (lib_maxrunning::myselfRunningArgs() > 1) {
        print STDERR " Hay otro proceso corriendo: $0 $ARGV[0]\n";
        exit;
    }

    $prontus_varglb::PRONTUS_ID = $ARGV[0];
    my $force_all = $ARGV[1] || 0;

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

    my $msg_load = &lib_prontus::load_config_by_id($prontus_varglb::PRONTUS_ID);
    if ($msg_load ne '') {
        print STDERR "Error al cargar configuracion: $msg_load\n";
        exit;
    }

    my $msg_err_bd = '';
    ($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}, $msg_err_bd) = &lib_prontus::conectar_prontus_bd();
    if (! ref($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID})) {
        print STDERR "ERROR al conectar a BD: $msg_err_bd\n";
        print STDERR "No se procesará este prontus\n";
        exit;
    }

    if (lib_s3::check_config_s3()) {
        $S3_ENABLED = 1;
        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;
        }

        if ($S3_LIB_ENABLED) {
            lib_s3::connect_s3();
            $BUCKET = lib_s3::connect_bucket();
        }
    } else {
        print STDERR "S3 no habilitado y/o configurado\n";
    }

    # actualizar todo
    if ($force_all) {
        my $ruta_dir = $prontus_varglb::DIR_SERVER . $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_SITE'} . $prontus_varglb::DIR_ARTIC;

        my @lisdir = &glib_fildir_03::lee_dir($ruta_dir);
        @lisdir = grep !/^\./, @lisdir; # Elimina directorios . y ..

        # Para cada dirfecha
        foreach my $dirfecha (@lisdir) {
            print STDERR "Procesando artics de [$prontus_varglb::PRONTUS_ID][$dirfecha/xml]\n";
            if (-d "$ruta_dir/$dirfecha/xml") {
                &procesa_files("$ruta_dir/$dirfecha/xml", $prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID});
            }
        }
    } else {
        # actualizar solo los que tienen valor 0
        my $sql = 'select ART_ID from ART where ART_TOTAL_SIZE=0';
        my $art_id;
        my $salida = glib_dbi_03::ejecutar_sql_bind($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}, $sql, \($art_id));
        while ($salida->fetch) {
            &update_artic($art_id);
        }
        $salida->finish;

    }
}

# ---------------------------------------------------------------
sub procesa_files {
    # Lee todos los articulos del directorio y agrega la info a la bd.
    my ($ruta_dir_xml, $base) = @_;

    my @lisfile = glib_fildir_03::lee_dir($ruta_dir_xml);

    foreach my $k_xml (@lisfile) {
        if ((-s "$ruta_dir_xml/$k_xml") && ($k_xml =~ /^(\d{14})\.(xml)$/) && (! -d "$ruta_dir_xml/$k_xml")) {
            &update_artic($1);
        }
    }
}

sub update_artic {
    my $ts = $_[0];

    # 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);

    my $artic_obj;
    # se instancia el articulo
    unless($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)
        ) {
        print STDERR "[Error] inicializando objeto articulo: $Artic::ERR\n";
        return;
    }

    $artic_obj->{xml_data} = glib_fildir_03::read_file($artic_obj->{fullpath_xml});

    # archivo no tiene el tamaño total, asi que se calcula y actualiza
    # calculamos desde el disco para obtener un dato preciso
    my ($disk_size, $imag_size, $asset_size, $media_size) = $artic_obj->get_disk_size();

    my ($s3_size, $s3_media_size, $s3_asset_size) = (0, 0, 0);
    if ($S3_ENABLED && $S3_LIB_ENABLED) {
        ($s3_media_size, $s3_asset_size) = lib_s3::get_art_size($ts, $BUCKET);
        $s3_size = $s3_media_size + $s3_asset_size;
    }

    my $total_size = $s3_size + $disk_size;
    $artic_obj->update_art_size($total_size, $disk_size, $imag_size, $asset_size, $media_size);
    $artic_obj->update_s3_size($s3_size, $s3_media_size, $s3_asset_size);

    glib_fildir_03::write_file($artic_obj->{fullpath_xml}, $artic_obj->{xml_data});

    # xml de articulo ya se actualizó, se libera el mutex
    &lib_waitlock::unlock_file($LOCK, $LOCKFH);

    # actualizamos la tabla de artículos
    my $res = $artic_obj->art_update_bd($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID});
    if (!$res) {
        print STDERR  "Error actualizando la tabla ART: $Artic::ERR";
    }
}

# ---------------------------------------------------------------
# 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);
    }
}
