#!/usr/bin/perl -w
#
# Zymonic Business Process and Information Management System
# Copyright Zednax Limited 2008 -
# For Authors and Changelog see the subversion history
use strict;

# Modules
use Zymonic::Config;
use Zymonic::DB;
use Zymonic::Table;
use Zymonic::Auth;

# Library path
BEGIN
{
    use vars qw($location $script_name $script_location $utils);
    use Zymonic::Utils qw(clean debug death_handler get_array);
    $main::SIG{__DIE__} = \&death_handler;
}

# Clean path
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/sbin:/usr/sbin";

my $system  = clean( shift @ARGV, "_" );
my $seq_num = clean( shift @ARGV );
my %tables  = map { clean( $_, '*' ) => 1 } @ARGV;
unless ( $system && $seq_num && keys %tables > 0 )
{
    print
"Usage: reset_oracle_sequences.pl [system] [seq_num] [tables (list of table znames, or * to apply to all tables)]";
    exit(1);
}

print "System: $system\n";
my $config = Zymonic::Config->new(
    system_name => $system,
    config_dir  => "/etc/zymonic",
    ip_address  => '127.0.0.1',
    protocol    => 'http'
);

my $db = Zymonic::DB->new( config => $config );

unless ( $db->isa('Zymonic::DB::Oracle') )
{
    print "Not an Oracle DB.\n";
    exit(1);
}

foreach my $table (
    map { $config->get_def( 'Table', $_->{ZName}->{content} ) }
    grep { $tables{'*'} || $tables{ $_->{ZName}->{content} } } get_array( $config->SysDef->{Table} )
  )
{
    my $table_name = ( ref( $table->{SQLName} ) eq 'HASH' ? $table->{SQLName}->{content} : $table->{ZName}->{content} );

    foreach my $key ( get_array( $table->{Key} ) )
    {
        if ( ref( $key->{Autoincrement} ) && $key->{Autoincrement}->{content} eq 'true' )
        {
            my $field = (
                grep {
                    $key->{FieldName}->{content} eq (
                        ref( $_->{SQLName} ) eq 'HASH'
                        ? $_->{SQLName}->{content}
                        : $_->{ZName}->{content}
                      )
                  } map { $config->get_def( 'Field', $_->{ZName}->{content} ) } get_array( $table->{Field} )
            )[0];
            if ($field)
            {
                my $field_name =
                  ( ref( $field->{SQLName} ) eq 'HASH' ? $field->{SQLName}->{content} : $field->{ZName}->{content} );
                my $seq_name = "${table_name}${field_name}s";

                # run changes in eval, ignore errors about it not exists
                eval {
                    my $current_seq_val = $db->run_query(
                        {
                            string => "SELECT $seq_name.nextval AS val FROM DUAL",
                            params => []
                        }
                    )->[0]->{val};

                    if ( $current_seq_val >= $seq_num )
                    {
                        print "$table->{ZName}->{content} sequence already at $current_seq_val.\n";
                    }
                    else
                    {

                        # get difference and incremenrt sequence to that
                        my $diff = $seq_num - $current_seq_val;

                        $db->run_statement(
                            {
                                string => "ALTER SEQUENCE $seq_name INCREMENT BY $diff",
                                params => []
                            }
                        );
                        $db->run_statement(
                            {
                                string => "SELECT $seq_name.nextval AS val FROM DUAL",
                                params => []
                            }
                        );
                        $db->run_statement(
                            {
                                string => "ALTER SEQUENCE $seq_name INCREMENT BY 1",
                                params => []
                            }
                        );

                        print "$table->{ZName}->{content} sequence set from $current_seq_val to $seq_num.\n";
                    }
                    1;
                  }
                  or do
                {
                    my $exception = $@;
                    if ( ref($exception) )
                    {
                        if (   $exception->isa('Zymonic::Exception::Db::Query_Run')
                            && $exception->{sql_err} =~ /does not exist/i )
                        {
                            print "$table->{ZName}->{content} has no sequence.\n";
                        }
                        else
                        {
                            $exception->rethrow;
                        }
                    }
                    else
                    {
                        if ( $exception =~ /does not exist/i )
                        {
                            print "$table->{ZName}->{content} has no sequence.\n";
                        }
                        else
                        {
                            die $exception;
                        }
                    }
                };
            }

        }
    }
}

print "Done.\n";
