package t::TestKotonoha;
use Config;
use FindBin;
use File::Basename;
use File::Spec;
use Test::Base -Base;
use URI::Escape ();
use Net::Kotonoha;

our @EXPORT = qw(test_requires test_requires_network test_requires_command test_plugin_deps
                 run_eval_expected run_eval_expected_with_capture
                 slurp_file file_contains file_doesnt_contain);

our($BaseDir, $BaseDirURI);
{
    my @path = File::Spec->splitdir($FindBin::Bin);
    while (defined(my $dir = pop @path)) {
        if ($dir eq 't') {
            $BaseDir = File::Spec->catfile(@path);
            $BaseDirURI = join "/", map URI::Escape::uri_escape($_), @path;
            last;
        }
    }
}

=item test_requires

Checks to see if the module can be loaded.

   test_requires("Your::Momma");
   test_requires("Your::Momma",3.141); # version 3.141 or later

If this fails rather than failing tests this B<skips all tests>.

=cut

sub test_requires() {
    my($mod, $ver) = @_;

    if ($ver) {
        eval qq{use $mod $ver};
    } else {
        eval qq{use $mod};
    }

    if ($@) {
        if ($@ =~ /^Can't locate/) {
            plan skip_all => "Test requires module '$mod' but it's not found";
        }
        else {
            plan skip_all => "$@";
        }
    }
}

=item run_eval_expected

Add a new test run across all blocks to check that
the expected blocks can be evaled succesfully.  During
these evaluations the expected input is availible from
C<$context>.

One extra test failure will happen per block that's expected
output throws an error when evaluated.  No successes are
generated by this code, but the expected code may in
turn generate many sucesses or failures.

=cut

sub run_eval_expected {
    run {
        my $block = shift;
        
        # context is being pulled out here so that
        # the eval box can see it
        my $context = $block->input; # it's not always true
        
        eval $block->expected;
        fail $@ if $@;
    };
}

=item run_eval_expected_with_capture

Add new test run across all blocks to check that
the expected blocks can be evaled succesfully.  During
these evaluations the expected input is availible from
C<$context>, and warnings created by the filters
are avalible from C<$warnings>.

=cut

sub run_eval_expected_with_capture {
    filters_delay;
    for my $block (blocks) {
      
        # capture all the warnings from the filters
        # this is often used in the tests as a way to find
        # out what has happened (e.g. the Growl plugin)
        my $warnings;
        {
            local $SIG{__WARN__} = sub { $warnings .= "@_" };
            $block->run_filters;
        }
        
        # context is being pulled out here so that
        # the eval box can see it
        my $context = $block->input;
        
        eval $block->expected;
        fail $@ if $@;
    }
}

=item slurp_file($filename)

Returns the contents of the file, as a single scalar

=cut

sub slurp_file() {
    my $file = shift;
    open my $fh, $file or return;
    return join '', <$fh>;
}

=item file_contains($filename, $regexp)

Test if the file (specified by filename) matches the passed regexp.

=cut

sub file_contains() {
    my($file, $pattern) = @_;

    like slurp_file($file), $pattern;
}

=item file_doesnt_contains($filename, $regexp)

Test the file (specified by filename) doesnt matches the passed regexp.
If the file doesn't exist, this test will fail.

=cut

sub file_doesnt_contain() {
    my($file, $pattern) = @_;
    $pattern = qr/\Q$pattern\E/ unless ref $pattern;

    my $content = slurp_file($file) or return fail("$file: $!");
    unlike $content, $pattern;
}

1;
