### ----------------------------------------------------
### -- Config::BINDish
### -- Licenses: Artistic-2.0
### -- Authors: Vadim Belman <vrurg@lflat.org>
### -- File: t/060-expandable.rakutest
### ----------------------------------------------------
use v6.d;
use Test::Async;
use Config::BINDish::Expandable;
use Config::BINDish::INET;
use Config::BINDish;

plan 3;

subtest "Nesting" => {
    plan 2;
    my $cfg-src = q:to/CFG/;
        default-server "S%d";
        server "S1" {
            url https://s1.local;
        }
        server "S2" {
            url https://s2.local;
        }
        resources {
            url "{/server("{/default-server}")/url}";
        }
        CFG

    for 1,2 -> $id {
        my $cfg = Config::BINDish.new(:!strict);
        $cfg.read(string => sprintf($cfg-src, $id));
        is $cfg.get(:resources => "url"),
           sprintf('https://s%d.local', $id),
           "URL is for server S$id";
    }
}

subtest "Base", {
    plan 13;

    if $*VM.osname.starts-with('mswin') {
        %*ENV<HOME> ||= %*ENV<USERPROFILE>;
    }

    my $cfg-src = q:to/CFG/;

        name "test config";
        description "Meaningless {name}...";
        test1 "block {server(S1, addr)/name} is visible";
        test2 "path from a subblock: {server(S1, addr)/resource(Img)/path}";
        test3 "integer: {server(S1, addr)/resource(Img)/max-size}";
        test4 "subblock name with spaces: {server(S1, addr)/meta('spaced name')/id}";
        test5 "environment HOME: {$HOME}";
        test6 "environment NOHOME: {$NOHOME?}"; # Just make sure this doesn't break parsing

        server "S1" addr {
            name "server addresses";
            description "Block about {name}.";
            test1 "block-related: {meta("spaced name")/id}";
            base https://localhost;
            resource "Img" {
                path "img";
                max-size 1024;
            }
            meta "spaced name" {
                id 42;
            }
            general {
                scripts "v3.14";
                sub-url "{../base}/sub";
                deep {
                    sub-sub-url "{../../base}/sub-sub"
                }
            }
        }

        server "S1" path {
            root "/usr/local/www";
            img-pool "{root}/{/server("S1", addr)/resource(Img)/path}";
            scripts "{root}/scripts/{/server(S1, addr)/general/scripts}";
        }
        CFG

    my $cfg = Config::BINDish.new(:!strict);
    lives-ok { $cfg.read(string => $cfg-src) }, "config parsed";

    my $top = $cfg.top;

    is $top.value('description'), "Meaningless test config...", "the most basic expansion case at top-level";
    is $top.get(:server('S1', 'addr') => 'description'),
       "Block about server addresses.",
       "the most basic expansion case in a block";

    is $top.value('test1'),
       "block server addresses is visible",
       "top-level option see a later declared block";

    is $top.value('test2'),
       "path from a subblock: img",
       "top-level option see a second-level block";

    is $top.value("test3"),
       "integer: 1024",
       "can expand with a non-string value";

    is $top.value("test4"),
       "subblock name with spaces: 42",
       "subblock is seen when its name contains whitespaces";

    is $top.value("test5"),
        "environment HOME: " ~ %*ENV<HOME>,
        "expanded from environment";

    my $blk1 = $top.block("server", name => "S1", class => 'addr');

    is $blk1.value("test1"), "block-related: 42", "relative expansion within a block";

    my $blk2 = $top.block("server", :name<S1>, :class<path>);

    is $blk2.value("img-pool"), "/usr/local/www/img", "expanded from both local and another block options";
    is $blk2.value("scripts"), "/usr/local/www/scripts/v3.14", "reference to a nameless block";

    my $sub-blk = $blk1.block("general");
    is $sub-blk.value("sub-url"), "https://localhost/sub", "reference to parent block";
    $sub-blk = $sub-blk.block("deep");
    is $sub-blk.value("sub-sub-url"), "https://localhost/sub-sub", "reference to parent of the parent block";
}

subtest "Errors" => {
    plan 2;
    my $cfg-src = q:to/CFG/;
        # Without optional marker '?' after the $NOHOME this must fail
        test-env "environment NOHOME: {$NOHOME}";
        CFG

    throws-like
        {
            my $cfg = Config::BINDish.new(:!strict);
            $cfg.read(string => $cfg-src);
        },
        Config::BINDish::X::Macro::DoesntExists,
        "no environment variable throws",
        :what('Environment variable'),
        :name<NOHOME>;

    throws-like
        {
            my $cfg = Config::BINDish.new(:!strict);
            $cfg.read(string => q<test-bad "{$}">);
        },
        Config::BINDish::X::Parse::General,
        "no environment variable name in macro";
}

done-testing;


