#!/usr/bin/perl -w

BEGIN {
    use FindBin qw($RealBin); # warn $FindBin::RealBin;

	use lib (
        "$RealBin/../lib",
        "$RealBin/../setup/hilis3_convert",
		'/home/raj/perl5/lib/perl5',
	);

    use vars qw($SQL_FOR_TABLE $FOREIGN_KEYS $NOW);
    require "$RealBin/../setup/lims.sql";
}

use strict;
use warnings;

use DateTime;
use Data::Dumper;
use Config::Tiny;

use DB;
use Main;
use User;
use YHHN;
use Consent;
use History;
use LabTest;
use Referrer;
use Outreach;
use PreScreen;
use RequestLog;
# use TestResult; # combined with LabTest now
use RequestAudit;
use PatientTrial;
use ReferralSource;

my $src = "$RealBin/../setup/hilis3_convert/.db";
my $cfg = Config::Tiny->read($src); # warn Dumper $cfg; exit;

# switch db to test:
# $cfg->{'_'}->{hilis4_db} = 'test'; # warn Dumper $cfg; exit;

my $DB = DB->new(config => $cfg);

# hashref of DBI & DBIx::Simple db handles for source(hilis3) & destination (hilis4) dbs:
my $db = $DB->connect;

open my $log, '>', "$RealBin/../setup/hilis3_convert/convert.log" or die $!;

my %args = (
	db  => $db,
	sql => {
		table => $SQL_FOR_TABLE,
	},
	path_to_app => "$RealBin/../", # /home/raj/www/apps/HMDS/trunk
    log_file => $log,
);

my $start = DateTime->now(time_zone => 'local'); print $start->datetime, "\n";

# remove_fks(); # exit;
# methods to run:
#------------------------------------------------------------------------------#
#do_referral_sources();
#do_users(); # includes email_addresses (slow)
do_referrers(); exit;
#do_main_conversion();
#do_lab_tests();
#do_patient_trial();
#do_request_audit();
#do_consent();
#do_request_logs();
#do_prescreen();
#do_history();
do_yhhn(); # MUST RUN THIS OR FK RESTORE FAILS ON patient_demographics TABLE & MUST BE DONE BEFORE OUTREACH - patient_demographics table
do_outreach(); # requires hilis3 db *not older than* community_monitoring db 
##do_test();
#------------------------------------------------------------------------------#

# restore_fks();

$DB->disconnect($db);

my $finish = DateTime->now(time_zone => 'local');
my $duration = $finish->subtract_datetime($start);

printf "Process ran for %s hrs %s mins %s secs\n\n",
	$duration->hours, $duration->minutes, $duration->seconds;

sub do_referral_sources {
	my $o = ReferralSource->new(%args);
	$o->convert; timer(); 
}

sub do_referrers {
	my $o = Referrer->new(%args);
	$o->convert; timer(); 
}

sub do_main_conversion {
    $args{cfg} = $cfg; # for Patient to anonymise names
	my $o = Main->new(%args);
	$o->convert; timer(); 
}

sub do_users {
	my $o = User->new(%args);
	$o->convert; timer(); 
}

sub do_history {
	my $o = History->new(%args);
	$o->convert; timer(); 
}

sub do_patient_trial {
	my $o = PatientTrial->new(%args);
	$o->convert; timer(); 
}

sub do_consent {
	my $o = Consent->new(%args);
	$o->convert; timer(); 
}

sub do_request_audit {
	my $o = RequestAudit->new(%args);
	$o->convert; timer(); 
}

sub do_lab_tests {
	my $o = LabTest->new(%args);
	$o->convert; timer(); 
}

sub do_test_results {
	my $o = TestResult->new(%args);
	$o->convert; timer(); 
}

sub do_request_logs {
    my $o = RequestLog->new(%args);
	$o->convert; timer(); 
}

sub do_prescreen {
    my $o = PreScreen->new(%args);
	$o->convert; timer(); 
}

sub do_outreach {
	my $o = Outreach->new(%args);
	$o->convert; timer(); 
}

sub do_yhhn {
	my $o = YHHN->new(%args);
	$o->convert; timer(); 
}

sub do_test {
    use Test;
	Test->new(%args)->block_ref;
}

sub remove_fks {
	my $dbh = $db->{dbh4};
	
	print "Removing FK's .... ";
	
	foreach my $fk ( sort keys %$FOREIGN_KEYS ) {
		my ($tbl) = $fk =~ /fk_(.*)/; # print Dumper $tbl;

		my (@fks) = $FOREIGN_KEYS->{$fk} =~ /(\w+_ibfk_\d)/g; # print Dumper \@fks;

		map { # print qq!ALTER TABLE `$tbl` DROP FOREIGN KEY `$_`!;
			$db->{dbh4}->do( qq!ALTER TABLE `$tbl` DROP FOREIGN KEY `$_`! ); #print " .. OK\n";
		} @fks;
    }
	print "done\n";
}

sub restore_fks {
	my $dbh = $db->{dbh4};

	print "Restoring FK's .... ";
	
	foreach my $fk ( sort keys %$FOREIGN_KEYS ) {  #print $FOREIGN_KEYS->{$fk};
        $dbh->do( $FOREIGN_KEYS->{$fk} );  #print " .. OK\n";
    }
	print "done\n";
}

sub timer {
    my @caller = caller(1); # warn Dumper \@caller;
	
	my $now = DateTime->now(time_zone => 'local');
	
	my $event = _event_timer(); # get event time
	
	my $duration = $now->subtract_datetime($event);
	
	_event_timer($now); # set event time

	printf "%s() ran for %s mins %s secs\n",
		$caller[3], $duration->in_units('minutes'), $duration->seconds;
}

sub _event_timer {
	$NOW ||= $start; # if 1st call
	
	if (my $time = shift) {
		$NOW = $time;
	}
	else {
		return $NOW;
	}
}