#!/usr/bin/env perl

use v5.10;
use Cwd;
use File::Copy;
use File::Copy::Recursive 'dircopy';
use File::Path 'remove_tree';
use Dancer2::Core::Runner;
use Dancer2::Core::App;
use Strehler;
use Strehler::Schema;
use Term::ReadKey;
use Authen::Passphrase::BlowfishCrypt;

my $strehler_root = $INC{'Strehler.pm'};
$strehler_root =~ s/\.pm$//;
my %available_commands = ('commands' => 'show available commands',
                          'statics' => 'copy of static resources needed by Strehler to Dancer2 App',
                          'demo' => 'create a complete Dancer2 App with Strehler already configured, for trial purpose',
                          'initdb' => 'generate strehler tables on the wanted database',
                          'layout' => 'import Strehler Admin layout, mandatory for admin interface extension',
                      );

my $command = shift;
my @parameters = @ARGV;

print "\n### Strehler CMS Manager ###\n\n";
print "Strehler Version: " . $Strehler::VERSION . "\n\n";

if($command eq 'statics')
{
    statics(@parameters);
}
elsif($command eq 'initdb')
{
    initdb(@parameters);
}
elsif($command eq 'layout')
{

    layout(@parameters);
}
elsif($command eq 'demo')
{
    print "-demo- command: $available_commands{'demo'}\n\n";
    my $app  = shift @parameters || 'StrehlerDemo';
    say "STEP 1: Creating Dancer App... $app";
    system("dancer2 -a $app");
    print "\n\n";
    chdir $app;
    demo_components();
    statics();
    initdb(undef, 1);
    layout();
    say "Demo SUCCESSFULLY DEPLOYED!";
    say "Run Dancer2 devserver under $app, go to ADDRESS:PORT/admin, insert admin as user and as password and ENJOY!\n\n";
}
else
{
    if($command eq 'commands')
    {
        print "-commands- command: $available_commands{'commands'}\n\n";
    }
    else
    {
        print "Wrong command provided. I'll show you available commands\n\n";
    }
    for(keys %available_commands)
    {
        say $_ . " => " . $available_commands{$_};
    }
    print "\n\n";
}

sub statics
{
    my $public_dir = shift || 'public';

    print "-statics- command: $available_commands{'statics'}\n\n";

    my $origin = $strehler_root . '/public/strehler';

    my $app_directory = getcwd();
    my $destination = $app_directory . '/' . $public_dir;

    if(! -d $destination)
    {
        say "Directory $destination doesn't exists!";
        if($public_dir eq 'public')
        {
            print "\"public\" directory used as standard dancer static files directory. Different from yours? Pass your directory as second parameter to the script\n";
        }
        print "\n\n";
        exit();
    }

    my $nocopy = 0;
    if(-d $destination . '/strehler')
    {
        say "Deleting old $destination" . '/strehler';
        my $deleted = remove_tree($destination . '/strehler');
        if($deleted == 0)
        {
            print "COPY FAILED! Impossibile to delete old directory: $!\n\n";
            $nocopy = 1;
        }
        else
        {
            say "$deleted old files correctly removed";
        }
    }
    if(! $nocopy)
    {
        $File::Copy::Recursive::CPRFComp = 1;
        say "Copying statics from $origin to $destination...";
        my $done = dircopy($origin, $destination);
        if(! $done)
        {
            print "COPY FAILED! A problem occured: $!\n\n";
        }
        else
        {
            print "SUCCESS! Files copied in your Dancer2 App!\n\n";
        }
    }
    if(-d $destination . '/upload')
    {
        print "Upload directory already present\n\n" 
    }
    else
    { 
        my $done = mkdir $destination . '/upload';
        say "Creating upload directory... $destination/upload";
        if(! $done)
        {
            print "UPLOAD DIRECTORY CREATION FAILED! A problem occured: $!\n\n";
        }
        else
        {
            print "SUCCESS! Upload directory created!\n\n";
        }
    }
}

sub initdb
{
    my $wanted_schema = shift; 
    my $demo = shift || 0;

    print "-initdb- command: $available_commands{'initdb'}\n\n";

    my $dsn;
    my $user;
    my $password;

    if(! $demo)
    {
        my $runner = Dancer2::Core::Runner->new( caller => getcwd() . "/bin" );
        my $app = Dancer2::Core::App->new(
            name            => "dummy",
            environment     => $runner->environment,
            location        => $runner->location,
            runner_config   => $runner->config,
            postponed_hooks => $runner->postponed_hooks,
        );
  
        if(! $app->config->{'plugins'}->{'DBIC'})
        {
            say "Can't read config.yml or no DBIC plugin configured in it\n";
            exit();
        }
        my $schema_name = $wanted_schema || 'default';
        if(! $app->config->{'plugins'}->{'DBIC'}->{$schema_name} && $wanted_schema)
        {
            say "Schema $wanted_schema doesn't exists in the config.yml file we're using!\n";
            exit();
        }
        if(! $wanted_schema && ! $app->config->{'plugins'}->{'DBIC'}->{'default'})
        {
            my @availables = keys %{$app->config->{'plugins'}->{'DBIC'}};
            $schema_name = $availables[0];
        }
        $dsn = $app->config->{'plugins'}->{'DBIC'}->{$schema_name}->{'dsn'};
        $user = $app->config->{'plugins'}->{'DBIC'}->{$schema_name}->{'user'};
        $password = $app->config->{'plugins'}->{'DBIC'}->{$schema_name}->{'pass'};
        print "Schema: $schema_name\n\n";
        say "DSN: $dsn";
        say "User: $user";
        say "Password: $password";
        my $continue = "";
        while($continue ne 'Y' && $continue ne 'N')
        {
            ReadMode(1, *STDIN);
            say "\nWARNING: this script will ERASE (DROP TABLE) all the tables with a name used by Strehler tables. Are you sure you want to continue? (y/n)";
            $continue = <STDIN>;
            ReadMode(0);
            chomp $continue;
            $continue = uc($continue);
        }
        if($continue eq 'N')
        {
            print "NO DEPLOY. Exiting...\n\n";
            exit();
        }
    }
    else
    {
        $dsn = "dbi:SQLite:dbname=demo.sqlite";
        $user = undef;
        $password = undef;
    }
    my $schema = Strehler::Schema->connect($dsn, $user, $password);
    $schema->deploy( { add_drop_table => 1 } );
    my $user_password;
    if(! $demo)
    {
        ReadMode(2, *STDIN);
        say "Enter password for admin:";
        $user_password = <STDIN>;
        say "Re-type password:";
        my $user_password_confirm = <STDIN>;
        ReadMode(0);
        if(! ($user_password eq $user_password_confirm))
        {
            say "Password inputs don't match!";
            exit(0);
        }
        chomp $user_password;
    }
    else
    {
        $user_password = 'admin';
    }
    my $ppr = Authen::Passphrase::BlowfishCrypt->new(
                    cost => 8, salt_random => 1,
                    passphrase => $user_password);
    my $hash = $ppr->hash_base64;
    my $salt = $ppr->salt_base64;
    $schema->populate('User', [[qw/user password_hash password_salt role/],
                              ['admin', $hash, $salt, 'admin']]);

    print "Database deploy COMPLETED!\n\n";
}

sub layout
{
    my $views_dir  = shift  || 'views';
    print "-layout- command: $available_commands{'layout'}\n\n";
    my $origin = $strehler_root . '/views/layouts/admin.tt';

    my $app_directory = getcwd();
    my $destination = $app_directory . '/' . $views_dir . '/layouts';

    if(! -d $destination)
    {
        say "Directory $destination doesn't exists!";
        if($views_dir eq 'views')
        {
            print "\"views\" directory used as standard dancer views files directory. Different from yours? Pass your directory as second parameter to the script\n";
        }
        print "\n\n";
        exit();
    }

    say "Copying layout from $origin to $destination...";
    my $done = copy($origin, $destination . '/admin.tt');
    if(! $done)
    {
        print "\nCOPY FAILED! A problem occured: $!\n\n";
    }
    else
    {
        print "\nSUCCESS! Files copied in your Dancer2 App!\n\n";
    }
}

sub demo_components
{
    my $origin = $strehler_root . '/demo';
    my $app_directory = getcwd();
    my $destination = $app_directory;
    
    my %demo_resources = (
        'config.yml' => 'config.yml',
        'Demo.pm.ex' => 'lib/Demo.pm',
        'Site.pm.ex' => 'lib/Site.pm',
        'app.pl' => 'bin/app.pl',
        'strehler-home.tt' => 'views/strehler-home.tt',
        'home.tt' => 'views/home.tt',
        'article.tt' => 'views/article.tt',
        'main.tt' => 'views/layouts/main.tt'
    );
    say "Demo resources will be injected in the app...";
    say "$origin -> $destination";
    foreach my $file (keys %demo_resources)
    {
        say $demo_resources{$file} . "...";
        my $done = copy($origin . "/" . $file, $destination . '/' . $demo_resources{$file});
        if(! $done)
        {
            print "\nCOPY FAILED! A problem occured: $!\n\n";
        }
    }
}
