#!/usr/bin/perl

use strict;
use Getopt::Long qw(HelpMessage);
use Pod::Usage;

my $options = {
        execute        	=> 1 ,
	path		=> '',
	dumpf		=> '',
	userdb		=> '',
};

my $dummy  =0;
my $result = GetOptions(
	"x|execute=s"           => \$$options{'execute'},
	"p|path=s"           	=> \$$options{'path'},
	"d|dumpf=s"           	=> \$$options{'dumpf'},
	"u|userdb=s"            => \$$options{'userdb'},
) or pod2usage(-verbose=>2);

sub new {
        my ($type) = $_[0];
        my ($self) = {};
        $self->{'options'}      = $options;
        bless($self, $type);
        return($self);
}

sub main (){
        my ($self) = @_;

	print "
	MANUAL DE PARAMETROS OPCIONALES:
	USAR \"-u\" para especificar un usuario con privilegios para pg_dump / pg_dumpall, toma por defecto que existe el usuario llamado root en PostgreSQL
	USAR \"-d\" para especificar un archivo dump PostgreSQL
	USAR \"-p\" para especificar un path, ej -p /tmp, toma por defecto el path \".\"
	USAR \"-x 0\" para especificar la NO ejecucion del pg_dumpall, toma por defecto -x 1\n\n";

	my $db;
	my $file;
	my $dirname="DB";
	my $user;

	if ($self->{'options'}->{'userdb'} ne ''){
		$user=$self->{'options'}->{'userdb'};
	} else {
		$user='root';
	}

	if ($self->{'options'}->{'execute'} == 1){
		if (($db=$self->listado($user))==-1){
			return -1;
		}

		print "De acuerdo a la configuracion puede solicitarse la clave del usuario $user en PostgreSQL\n";
		my $command;
		if ($db eq 'ALLDBS'){
			$dirname='pg_dumpall';
			$file="schema.sql";
			$command="pg_dumpall --schema-only --file=$file -U $user ";
		} else {
			$file="schema_$db.sql";
			$dirname=$db;
			$command="pg_dump --schema-only --file=$file  -U $user $db";
		}

		print "\n\nEjecutando Comando: \n";
		print "$command\n";
		system $command;

		if ($? == -1) {
			print "failed to execute: $!\n";
			return -1;
		}
	} elsif ($self->{'options'}->{'dumpf'} ne ''){
		# verificar que exista el archivo y volcar el parametro a $file
		print "Tomando el parametro \"".$self->{'options'}->{'dumpf'}."\" como archivo a trabajar\n";
		$file=$self->{'options'}->{'dumpf'};
	} else {
		# error
		print "Falta parametro para encontrar el Archivo dump de PostgreSQL \"-d\" \n";
		return -1;
	}


	open(CURSOR,$file) or die "No se encuentra el archivo \"$file\" \nERROR: $!\n";

	my $name='';
	my $type='';
	my $schema='';
	my $owner='';
	my $none='';
	my $fOpen=0;
	my $relPath;

	if ($self->{'options'}->{'path'} ne ''){
		$relPath=$self->{'options'}->{'path'}."/$dirname/";
	} else {
		$relPath="./$dirname/";
	}
	print "PATH de trabajo: ".$relPath."\n\n";

        my @registros=<CURSOR>;

	foreach my $reg (@registros){

		if ($reg =~ m/^-- Name/){

			my ($a,$b,$c,$d) = split ('; ',$reg);
			($none,$name) = split (': ',$a);
			($none,$type) = split (': ',$b);
			($none,$schema)= split (': ',$c);
			($none,$owner)= split (': ',$d);

			if ($name && $type && $schema){
				if ($schema eq '-'){
					$self->fs(\$fOpen,$relPath."GLOBAL/$type/",$name);
				} else {
					$self->fs(\$fOpen,$relPath."$schema/$type/",$name);
					print OBJ "SET search_path=$schema,pg_catalog;\n";
				}
				$fOpen=1;
			} else {
				# No se reconoce el objeto!!!
				# Sirve para debug, detectar y incluir estructuras
				print "No reconosco: ".$reg."\n";
				$name='';
				$type='';
				$schema='';
				$owner='';
				$fOpen=0;
			}
		} elsif ($reg =~ m/^-- PostgreSQL database/){
			# inicio o reconeccion.
			$fOpen=0;
			next;
		} elsif ($reg =~ m/^\\connect/){
			next;
                } elsif ($reg =~ m/^--\n/){
                        next;
                } elsif ($reg =~ m/^SET search_path/){
                        next;
		} elsif ($reg =~ m/^-- Role memberships/){
			$self->fs(\$fOpen,$relPath,"Role memberships");
			$fOpen=1;
		} elsif ($reg =~ m/^-- Roles/){
			$self->fs(\$fOpen,$relPath,"Roles");
			$fOpen=1;
		} elsif ($reg =~ m/^-- Database creation/){
			$self->fs(\$fOpen,$relPath,"Database creation");
			$fOpen=1;
		} elsif ($fOpen==1) {
			# escribo el archivo.
			print OBJ $reg; 
		} else {
			# Sirve para debug, detectar y incluir estructuras, esto sale por Std Output	
			# print "Paso por alto a: ".$reg."\n";
		}
	}

	if ($fOpen==1){
		close (OBJ);
	}
	close (CURSOR);

	if ($self->{'options'}->{'execute'} == 1){
                print "Borrando el archivo $file\n";
                system "rm $file";
        }

	return 0;
}

sub fs{
	my ($self,$fOpen,$path,$name) = @_;

	if ($$fOpen==1){
		close (OBJ);
		$$fOpen=0;
	}
	# Creo la estructura de directorio a mi gusto.
	system "mkdir -p \"$path\"";

	# creo archivo!!
	open (OBJ,">",$path.$name.".sql");

	return 0;
}

sub listado{
	my ($self,$user) = @_;

	my $command="psql -l -U $user";
	print "\n\nEjecutando Comando: $command\n";
	my @resultados = `$command`;

	if (@resultados==0){
		print "Error en la ejecucion: $command\n";
		return -1;
	}
	
	my $i=1;
	my $list=0;
	print "\n\n";
	my @array;

        foreach my $reg (@resultados){

		if ($reg =~ m/\s*\(*\)/){
                        $list=0;
                }

		if ($list==1){
			if ($i<10){
				if ($i==1){
					print "00 -  *** TODAS LAS BASES ***\n";
				}
				print "0$i";
			} else {
				print $i;
			}
                        print " - $reg";
			$i++;
			my ($none,$name) = split(/\s+/,$reg);
			push(@array,$name);
                } else {
                        print "     $reg";
                }

		if ($reg =~ m/\s*------/){ 
			# titulo
			$list=1;
		}
	}


	print "Ingrese una Opcion: ";
	my $opc=<STDIN>;
	while ($opc !~ /\d/) {
		print "Ingrese una Opcion: ";
		$opc=<STDIN>;
	}
	chop($opc);

	if ($opc<0 || $opc>=$i){
		print "Opcion: $opc INVALIDA\n";
		return -1;
	}
	print "Opcion: $opc, Cargando ";
	my $db;
	if ($opc==0){
		print "TODAS LAS BASES\n";
		$db='ALLDBS';
	} elsif($opc>0) {
		$db=$array[($opc-1)];
		print "Base: ".$db."\n";
	} else{
		return -1;
	}

	return $db;
}

my $pp = new();
if ($pp->main()==-1){
	print "\nSALIO CON ERROR!\n";
} else {
	print "\nEJECUCION EXITOSA\n";
}


