use v6.c;
use lib 'xt/lib';

use File::Temp;
use Helpers;
use Test;

use Bailador::CLI;

plan 10;

my $dir = tempdir();
#diag $dir;

my $git_dir = $*CWD;
chdir($dir);
diag $*CWD;
diag "PERL6LIB=" ~ (%*ENV<PERL6LIB> // '');
# diag $*EXECUTABLE;
# $*EXECUTABLE   -> /home/travis/.rakudobrew/bin/../moar-nom/install/bin/perl6
# want to append -> /home/travis/.rakudobrew/moar-nom/install/share/perl6/site/bin';
#                ->$*EXECUTABLE.parent.parent.child('share/perl6/site/bin')
#diag "PATH=" ~  %*ENV<PATH>;

subtest {
    plan 2;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), :out, :err);
    is $p.err.get, 'Usage:' or diag "Rest of STDERR:\n" ~ $p.err.slurp;
    is $p.out.get, Nil;
    #diag $p.out.slurp: :close;
}, 'Show Usage when no parameter is supplied.';

subtest {
    plan 1;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', :out, :err);
    is $p.err.get, 'Usage:' or diag "Rest of STDERR:\n" ~ $p.err.slurp;
    #diag $p.out.slurp: :close;
}, 'Show Usage when <name> is not supplied.';



subtest {
    plan 10;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', 'App-Name', :out, :err);
    my $out = $p.out.slurp: :close;
    like $out, rx:s{Generating App\-Name};
    like $out, rx{App\-Name\/bin\/app.pl6};
    like $out, rx{App\-Name\/t\/app.t};
    like $out, rx{App\-Name\/views\/index.html};
    my $err = $p.err.slurp: :close;
    is $err, '' or diag "Rest of STDERR:\n" ~ $p.err.slurp; # TODO Why is this the empty string and above it is Nil?
    my @main_dir = dir();
    is-deeply @main_dir.map(*.Str), ('App-Name',);

    my @app_dir = dir('App-Name');
    is-deeply @app_dir.map(*.Str).sort, ('App-Name/bin', 'App-Name/t', 'App-Name/views');

    my @views_dir = dir('App-Name/views');
    is-deeply @views_dir.map(*.Str), ('App-Name/views/index.html',);

    my @bin_dir = dir('App-Name/bin/');
    is-deeply @bin_dir.map(*.Str), ('App-Name/bin/app.pl6',);

    my @t_dir = dir('App-Name/t');
    is-deeply @t_dir.map(*.Str), ('App-Name/t/app.t',);
}, 'Create application';

subtest {
    plan 2;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', 'App-Name', :out, :err);
    my $out = $p.out.slurp: :close;
    is $out, q{Generating App-Name
App-Name already exists. Exiting.
};
    my $err = $p.err.slurp: :close;
    is $err, ''; # TODO Why is this the empty string and above it is Nil?
}, 'Will not overwrite existing directory';

subtest {
    plan 10;

    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'new', 'Foo-Bar', :out, :err);
    my $out = $p.out.slurp: :close;
    like $out, rx:s{Generating Foo\-Bar};
    like $out, rx{Foo\-Bar\/bin\/app.pl6};
    like $out, rx{Foo\-Bar\/t\/app.t};
    like $out, rx{Foo\-Bar\/views\/index.html};
    my $err = $p.err.slurp: :close;
    is $err, ''; # TODO Why is this the empty string and above it is Nil?
    my @main_dir = dir();
    is-deeply @main_dir.map(*.Str).sort, ('App-Name', 'Foo-Bar',);

    my @app_dir = dir('Foo-Bar');
    is-deeply @app_dir.map(*.Str).sort, ('Foo-Bar/bin', 'Foo-Bar/t', 'Foo-Bar/views');

    my @views_dir = dir('Foo-Bar/views');
    is-deeply @views_dir.map(*.Str), ('Foo-Bar/views/index.html',);

    my @bin_dir = dir('Foo-Bar/bin/');
    is-deeply @bin_dir.map(*.Str), ('Foo-Bar/bin/app.pl6',);

    my @t_dir = dir('Foo-Bar/t');
    is-deeply @t_dir.map(*.Str), ('Foo-Bar/t/app.t',);
}, 'Create application parameters in the other order';



# Ensure that the tests in the skeleton generated by "bailador new" passess.
subtest {
    plan 3;

    chdir 'App-Name';
    # temp %*ENV<PERL6LIB> = join(':', "$git_dir/lib", |get-path-from-repo());
    # diag %*ENV<PERL6LIB>;
    # my @includes = map { "-I=" ~ $_ } ("$git_dir/lib", |get-path-from-repo());
    my $prove6 = $*EXECUTABLE.parent.parent.child('share/perl6/site/bin/prove6');
    if $prove6.IO.e {
        # my $p = run($prove6, |@includes '-l', :out, :err);
        my $p = run($prove6, "-I=$git_dir/lib", '-l', :out, :err);
        my $exitcode = $p.exitcode;
        is $exitcode, 0, 'program terminated successfully';
        # diag "exitcode: " ~ $exitcode;
        my $out = $p.out.slurp: :close;
        like $out, rx:s/Result\: PASS/;
        # diag $out;
        my $err = $p.err.slurp: :close;
        is $err, '';
    } else {
        skip 'prove6 is not available - you need to install Tap::Harness before Bailador installs it as a dependency', 3;
    }
    # diag $err;
    chdir '..';
}, 'test newly generated app with its test cases';

# Ensure that tha application generated by "bailador new" will work
subtest {
    plan 2;

    chdir 'App-Name';

    my $port = 5007;
    my @args = "--config=host:0.0.0.0,port:$port", "-w={$git_dir.IO.child('t').child('views')}", 'watch', 'bin/app.pl6';
    my @includes = repo-to-includes();
    my $server = Proc::Async.new($*EXECUTABLE, "-I$git_dir/lib", |@includes, $git_dir.IO.child('bin').child('bailador'), |@args);
    $server.stdout.tap; # : -> $s {say "out: ", $s};
    $server.stderr.tap; # : -> $s {say "err: ", $s};
    $server.start;

    # Wait for server to come online
    wait-port($port, times => 600);

    #diag $server;
    #diag $server.^methods;

    my $resp = req("GET / HTTP/1.0\r\nContent-length: 0\r\n\r\n", $port);
    #diag $resp;
    like $resp, rx:s/\<h1\>Bailador App\<\/h1\>/;
    like $resp, rx:s/Version 0\.0\.1/;

    $server.kill(SIGINT);
    chdir '..';
}, 'start app with bin/bailador watch';

# Ensure that tha application generated by "bailador new" will work even if the app.pl6 was moved to the root of the project
subtest {
    plan 2;

    chdir 'App-Name';

    copy "bin/app.pl6", "root.pl6";

    my $port = 5006;
    my @args = "--config=host:0.0.0.0,port:$port", "-w={$git_dir.IO.child('t').child('views')}", 'watch', 'root.pl6';
    my @includes = repo-to-includes();
    my $server = Proc::Async.new($*EXECUTABLE, "-I$git_dir/lib", |@includes, $git_dir.IO.child('bin').child('bailador'), |@args);
    $server.stdout.tap; # : -> $s {say "out: ", $s};
    $server.stderr.tap; # : -> $s {say "err: ", $s};
    $server.start;

    # Wait for server to come online
    wait-port($port, times => 600);

    #diag $server;
    #diag $server.^methods;

    my $resp = req("GET / HTTP/1.0\r\nContent-length: 0\r\n\r\n", $port);
    #diag $resp;
    like $resp, rx:s/\<h1\>Bailador App\<\/h1\>/;
    like $resp, rx:s/Version 0\.0\.1/;

    $server.kill(SIGINT);
    chdir '..';
}, 'test app with watch command without bin directory';

subtest {
    plan 1;
    my $port = 5005;
    my @args = "--config=host:0.0.0.0,port:$port", "-w={$git_dir.IO.child('t').child('views')}", 'watch',
               ~ $git_dir.IO.child('t').child('apps').child('app.pl6');
    my @includes = repo-to-includes();
    my $server = Proc::Async.new($*EXECUTABLE, "-I$git_dir/lib", |@includes, $git_dir.IO.child('bin').child('bailador'), |@args);
    $server.stdout.tap; #: -> $s {say "out: ", $s};
    $server.stderr.tap; #: -> $s {say "err: ", $s};
    $server.start;

    # Wait for server to come online
    wait-port($port, times => 600);

    my $expected = "host:0.0.0.0,port:$port";
    my $response = req("GET /config HTTP/1.0\r\nContent-length: 0\r\n\r\n", $port);
    # diag $response;
    like $response, rx/ $expected /;

    $server.kill(SIGINT);
}, '--config options are stored in BAILADOR env';

subtest {
    plan 1;
    my $p = run-executable-with-includes("-I$git_dir/lib", $git_dir.IO.child('bin').child('bailador'), 'routes', "$git_dir/examples/prefix/prefix.pl6", :out, :err);

    my $exitcode = $p.exitcode;
    is $exitcode, 0, 'program terminated successfully';

    my $out = $p.out.slurp: :close;
    my $err = $p.err.slurp: :close;

    # diag $out;
    # diag $err;
}, 'bin/bailador routes command'

# vim: expandtab
# vim: tabstop=4
