#!/usr/bin/perl

# Comparador de fecha para los archivos de llamada
sub byDate {
	($year1,$mon1,$day1,$hr1,$min1) = $a =~ /([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/;
	($year2,$mon2,$day2,$hr2,$min2) = $b =~ /([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/;
	
	# Descarto por año
	if ($year1 > $year2) { return 1; }
	elsif ($year1 < $year2) { return -1; }

	# Descarto por mes
	if ($mon1 > $mon2) { return 1; }
	elsif ($mon1 < $mon2) { return -1; }

	# Calculo minutos de lo restante
	$totalmin1 = ($day1 * 24 * 60) + ($hr1 * 60) + $min1;
	$totalmin2 = ($day2 * 24 * 60) + ($hr2 * 60) + $min2;
	if ($totalmin1 > $totalmin2) { return 1; }
	elsif ($totalmin1 < $totalmin2) { return -1; }
	else { return 0; }
}

# Devuelve un listado de archivos de llamada y ordenado por fecha ASC
sub getCallFiles {
	# Obtengo listado de archivos de llamadas y lo ordeno por fecha
	opendir($DIR,"$CONFDATA{datadir}/enproceso") or die 'Could not open dir';
	# Valido solo fisicamente, lo logico ya valido afimonio..
	@files = grep {/[0-9]{12}\.[0-9]{4}$/ && -f "$CONFDATA{datadir}/enproceso/$_"} readdir($DIR);
	@sortedfiles = sort byDate @files;
	closedir($DIR);
	return @sortedfiles;
}

# Levanta una variable del archivo AFINSTAL.CONF
sub getConfVar {
	$CONFIGFILE = shift(@_);
	my $linenumber = shift(@_);
	open(CONFIGFILE) or die "No se pudo abrir el archivo $CONFIGFILE";
	do { $line = <CONFIGFILE> } until $. == $linenumber;
	close(CONFIGFILE);
	chop($line);
	($confvar = $line) =~ s/^.*= (.*)/$1/;
	return $confvar;
}

# Agrega un log entry al logfile del antifraude.pl
sub logEntry {
	my $logentry = shift(@_);
	my $consoleout = shift(@_);
	my $log = "$CONFDATA{logdir}/$CONFDATA{logfile}";
	# Fetch date and Format it
	($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
	$year += 1900; $year = sprintf("%02d", $year % 100); ++$mon;
	$user = getlogin || "Unidentified";
 	$commonstring = "[$mday/$mon/$year $hour:$min:$sec|$user|antifraude]";
	# Append to log
	open(LOGFILE,">>$log") or die "No se pudo abrir el archivo de log";
	seek(LOGFILE,0,2);
	print LOGFILE "$commonstring - $logentry\n";
	close(LOGFILE);

	if ($consoleout) { print("$logentry\n"); }
}

sub badCall {
	my $callreg = shift(@_);
	my $numreg = shift(@_);
	logEntry("El siguiente registro de llamada tiene formato invalido\n$callreg",0);
	print("Warning: El registro de llamada $numreg tiene formato invalido\n");
	
}

sub checkUmbrales {
	local(*callfields) = $_[0];
	my $callsfile = $_[1];
	print("Callfields: @callfields\n");
	print("Callfile: $callsfile\n");
	my $matchedUmbral = 0;
	my $i = 0;

	while (($i <= $#UMBRALES) && ($matchedUmbral == 0)) {
		$umbral = $UMBRALES[$i];
		chomp($umbral);
		($regid,$phoneline,$oridest,$type,$state) = split(';',$umbral);
		if (($state eq 'A') && ($callfields[0] == $phoneline) &&
			 ($callfields[4] eq $type)) {
			# Si es Saliente y coincide el Destino con el Ori/Dest del umbral
			if (($type eq 'S') && ($callfields[5] eq $oridest)) {
				$matchedUmbral = $regid;
			}
			if (($type eq 'E') && ($callfields[6] eq $oridest)) {
				$matchedUmbral = $regid;
			}
		}			
		++$i;
	}

	# Si se matcheo un umbral, grabo una alarma y aviso por consola
	if ($matchedUmbral > 0) {
		# Obtengo algunos datos
		($central = $callsfile) =~ s/^.*\.//;
		$user = getlogin || 'Unidentified';

		# Fetch date and Format it
		($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
		$year += 1900; ++$mon;
		$date = "$year$mon$mday";
		$time = "$hour$min$sec";

		# Preparo el registro de alarma
		$alarmEntry = "$callfields[7];$central;$callfields[0];$callfields[1];$regid;$callfields[2];$callfields[3];$user;$date;$time";

		# Grabamos el registro en el archivo de alarmas
		$alarmlog = "$CONFDATA{datadir}/alarmas/alarmas.txt";
		open(ALARMFILE,">>$alarmlog") or die 'No se pudo abrir el archivo de alarmas';
		seek(ALARMFILE,0,2);
		print ALARMFILE "$alarmEntry\n";
		close(ALARMFILE);

		# Logeo por consola y logfile que hubo una alarma
		logEntry("Alarma: Se ha matcheado el registro procesado con el umbral nro $matchedUmbral",1);
	}
}

# --------- MAIN CODE -------- #
# En la version final, recibo por param el directorio del .conf, por ahora
# recibo un dir donde tengo archivos de llamadas
if ((!$ARGV[0]) || (! -d $ARGV[0])) { 
	print("No se ha ingresado un directorio fuente de llamadas\n");
	exit 1;
}
# Defino some GLOBALS
$CONFDIR = shift;
$CONFDATA{logdir} = getConfVar("$CONFDIR/afinstal.conf",12);
$CONFDATA{logfile} = getConfVar("$CONFDIR/afinstal.conf",13);
$CONFDATA{logsize} = getConfVar("$CONFDIR/afinstal.conf",14);
$CONFDATA{datadir} = getConfVar("$CONFDIR/afinstal.conf",15);
$CONFDATA{alarmlog} = "$CONFDIR/alarmas/alarmas.txt";

# Cargo los UMBRALES en memoria
open(PARAMFILE,"$CONFDIR/umbrales.param") or die "No se pudo abrir el archivo de umbrales";
@UMBRALES = <PARAMFILE>;
close(PARAMFILE);

# For Debug Only
print("\nLogdir: $CONFDATA{logdir}\n");
print("Logfile: $CONFDATA{logfile}\n");
print("Logsize: $CONFDATA{logsize}\n");
print("Datadir: $CONFDATA{datadir}\n\n");

# Proceso los archivos de llamadas
@archivos = getCallFiles();
FILE: foreach $filename (@archivos) {
	$regnum = 0;
	$CALLFILE = "$CONFDATA{datadir}/enproceso/$filename";
	logEntry("Inicio proceso de: $filename",1);

	open(CALLFILE) or ((warn "No se pudo abrir archivo $filename"),next FILE);
	REG: foreach $callreg (<CALLFILE>) {
		logEntry("Procesando Reg: $regnum | Archivo: $filename",1);
		chomp($callreg);
		$fieldcount = split(';',$callreg);
		@fields = @_;
		# Si no tengo 8 campos exactamente, invalido
		if ($fieldcount != 8) { badCall($callreg,$regnum); next REG; }
		# Si la linea no es un numero, invalido
		$fields[0] =~ s/^\s*(\w*)\s*$/$1/;
		if (!($fields[0] =~ /^\d+$/)) { badCall($callreg,$regnum); next REG; }
		# Si tipo llamada ! E|S o no se informa Origen o Destino, invalido
		if (($fields[4] ne 'E') && ($fields[4] ne 'S')) {
			badCall($callreg,$regnum); next REG;
		}
		if (($fields[4] eq 'E') && ($fields[6] eq "")) {
			badCall($callreg,$regnum); next REG;
		}
		if (($fields[4] eq 'S') && ($fields[5] eq "")) {
			badCall($callreg,$regnum); next REG;
		}

		# Ya pase todas las validaciones, ahora busco si exite un umbral
		checkUmbrales(*fields,$filename);
	} continue { ++$regnum }
	close(CALLFILE);

	# La muevo al directorio de procesadas
	rename $CALLFILE,"$CONFDATA{datadir}/procesadas/$filename";

	logEntry("Fin proceso de: $filename",1);
}
