### ----------------------------------------------------
### -- File::TreeBuilder
### -- Licenses: 
### -- Authors: Luc St-Louis <lucs@pobox.com>
### -- File: t/main.rakutest
### ----------------------------------------------------
use Test;
use Test::Selector;
use File::Temp;
use File::TreeBuilder;

# --------------------------------------------------------------------
sub node-bad ($test-id, Str $text) {
    t $test-id => {
        my $node;
        throws-like(
            { $node = Node.from-text($text) },
            NodeX::MalformedLine,
        ) or dd $node;
    }
}

node-bad | « bd1 'foo' »;
node-bad | « bd2 '.' »;
node-bad | « bd3 'o foo' »;
node-bad | « bd4 ' /xx foo' »;
node-bad | « bd5 '/ dir foo' »;
node-bad | « bd6 '. file .' »;
node-bad | « bd7 '   . file .' »;
node-bad | « bd8 '. file x foo' »;

# --------------------------------------------------------------------
sub node-good (
    Str  $test-id,
    Str  $text,
    Int  $exp_lead,
    Str  $exp_name,
    Str  $exp_text = '_',
    Str  $exp_hkey = '_',
    Str  $exp_perm = '_',
) {
    t $test-id => {
        my $N = Node.from-text($text);
        is($N.lead, $exp_lead, "Expecting lead length '$exp_lead'.");
        is($N.name, $exp_name, "Expecting node name '$exp_name'.");
        $exp_text ne '_' && is($N.text, $exp_text, "Expecting text '$exp_text'.");
        $exp_hkey ne '_' && is($N.hkey, $exp_hkey, "Expecting hkey '$exp_hkey'.");
        $exp_perm ne '_' && is($N.perm, $exp_perm, "Expecting perm '$exp_perm'.");
    }
}

node-good | « gd1 '  . foo'         2 foo »;
node-good | « gd2 '. foo'           0 foo »;
node-good | « gd3 '  / foo'         2 foo »;
node-good | « gd4 '/o fob'          0 'f b' »;
node-good | « gd5 '/ foo'           0 foo »;
node-good | « gd6 '. foo . txt'     0 foo   txt »;
node-good | « gd7 ". foo % a-'key"  0 foo   _   a-\'key »;
node-good | « gd8 '.644 foo'        0 foo   _   _       644 »;
node-good | « gd9 '.345_ f_b'       0 'f b' _   _       345 »;
node-good | « gdA '.222é féb'       0 'f b' _   _       222 »;
node-good | « gdB '.222< f<b'       0 'f b' _   _       222 »;
node-good | « gdC ". foo % s!+à"    0 foo   _   s!+à »;

# --------------------------------------------------------------------
use MONKEY-TYPING;
augment class File::TreeBuilder {
    trusts GLOBAL;
}

sub bad-FileTree (
    $exp_line-num,
    $exp_excep,
    Str $tree-desc,
    Hash $contents-href?,
) {
    my $FTB = File::TreeBuilder.new;
    throws-like(
        { $FTB!File::TreeBuilder::build-nodes(
            $tree-desc,
            $contents-href,
        ) },
        $exp_excep,
        line-num => $exp_line-num,
    );
}

t bf1 => { bad-FileTree(1, NodeX::NoFileDataHash,  ". file % foo") }
t bf2 => { bad-FileTree(1, NodeX::MissingFileData, ". file % bar", %(qux => "Qux")) }

# --------------------------------------------------------------------
t bf2a => { bad-FileTree(
    2,
    NodeX::MalformedLine,
    "/ d1\n    . \n    . f2 % bar",
    %(qux => "Qux"),
) }

t bf3 => { bad-FileTree(
    3,
    NodeX::MissingFileData,
    "/ d1\n    . f1\n    . f2 % bar",
    %(qux => "Qux"),
) }

t bf4 => { bad-FileTree(
    3,
    NodeX::InvalidIndent,
    q:to/EoD/,
    / d1
        . f1
            . f2
    EoD
) }

t bf5 => { bad-FileTree(
    3,
    NodeX::InvalidIndent,
    q:to/EoD/,
    / d1
            . f1
        / d2
    EoD
) }

t bf6 => { bad-FileTree(
    7,
    NodeX::InvalidIndent,
    q:to/EoD/
        / d1
          #
            / d2
                / d3

        / d4
              / d5
        EoD
    ,
) }

# --------------------------------------------------------------------
my %data;

%data<a1> = {
    tree-desc => q:to/EoDesc/
        . f1
        / foo

            . bar

            /700 baz
          # A comment.
                / dd
                    .411 fff
            / ggg
            . hhh
        . mlerp
        EoDesc
    ,
    exp => q:to/EoE/
        . f1
        / foo
        . foo/bar
        # a blank line
        / foo/baz 700
        # a comment
        / foo/baz/dd
        . foo/baz/dd/fff 411
        / foo/ggg
        . foo/hhh
        . mlerp
        EoE
    ,
};

# --------------------------------------------------------------------
sub confirm-build ($test-id, $tree-desc, $exp) {
    t $test-id => sub {
        my $root = tempdir;
        build-tree(
            $root,
            $tree-desc,
        );
        for @$exp.lines -> $expe {
            my ($exp-type, $exp-path, $exp-perms) = $expe.split: /\s+/;
            if ($exp-type eq '#') {
                ok(True, "Expecting to skip '$expe'.");
                next;
            }
            elsif ($exp-type eq '/') {
                ok("$root/$exp-path".IO.d, "Expecting directory '$exp-path'.");
            }
            else {
                ok("$root/$exp-path".IO.f, "Expecting file '$exp-path'.");
            }
            if ($exp-perms.defined) {
                my $got-perms = +"$root/$exp-path".IO.mode.parse-base: 8;
                is(+"$root/$exp-path".IO.mode, $exp-perms.parse-base(8), "Expecting correct mode.");

            }
        }
    };
}

confirm-build('ab1', %data<a1><tree-desc>, %data<a1><exp>);

# --------------------------------------------------------------------
done-testing;



