#!perl

use 5.010;
use strict;
use warnings;

use Perinci::Access::Schemeless::Hash;
use Test::Exception;
use Test::More 0.98;

my $pa = Perinci::Access::Schemeless::Hash->new(hash => {
    '/'              => [{v=>1.1, 'x.i'=>1}],
    '/Foo/'          => [{v=>1.1, 'x.i'=>2}],
    '/Foo/Bar/'      => [{v=>1.1, 'x.i'=>3}],
    '/Foo/Bar/func1' => [{v=>1.1, summary=>"function 1", args=>{}}],
    '/Foo/Bar/func2' => [{v=>1.1, summary=>"function 2", args=>{}}],
    '/Foo/Bar/Sub/'  => [{v=>1.1, 'i.x'=>4}],
    '/Foo/Baz/'      => [{v=>1.1, 'x.i'=>5}],
    '/Foo/Baz/func3' => [{v=>1.1, summary=>"function 3", args=>{a=>{schema=>["int",{},{}]}}}],
    '/Foo/Qux/Quux'  => [{v=>1.1}],
});

test_request(
    name   => "meta: root",
    argv   => [meta => "/"],
    result => {v=>1.1, 'x.i'=>1},
);
test_request(
    name   => "meta: non-package leaf",
    argv   => [meta => "/Foo/Bar/func1"],
    result => {v=>1.1, summary=>"function 1", args=>{}},
);
test_request(
    name   => "meta: package leaf",
    argv   => [meta => "/Foo/Bar/"],
    result => {v=>1.1, 'x.i'=>3},
);
test_request(
    name   => "meta: intermediate package is autogenerated",
    argv   => [meta => "/Foo/Qux/"],
    resutl => {v=>1.1},
);
test_request(
    name   => "meta: non-existing package leaf",
    argv   => [meta => "/Baz/"],
    status => 404,
);
test_request(
    name   => "meta: non-existing non-package leaf",
    argv   => [meta => "/Foo/Bar/blarg"],
    status => 404,
);

test_request(
    name   => "list: root",
    argv   => [list => "/"],
    result => [qw(Foo/)],
);
test_request(
    name   => "list detail 1",
    argv   => [list => "/", {detail=>1}],
    result => [
        {uri => "Foo/", type=>"package"},
    ],
);
test_request(
    name   => "list: /Foo/",
    argv   => [list => "/Foo/"],
    result => [qw(Bar/ Baz/ Qux/)],
);
test_request(
    name   => "list: /Foo/Bar/",
    argv   => [list => "/Foo/Bar/"],
    result => [qw(Sub/ func1 func2)],
);
test_request(
    name   => "list: /Foo/Qux/",
    argv   => [list => "/Foo/Qux/"],
    result => [qw(Quux)],
);
test_request(
    name   => "list: non-existing package leaf",
    argv   => [list => "/Baz/"],
    status => 404,
);

test_request(
    name   => "child_metas",
    argv   => [child_metas => "/Foo/Bar/"],
    result => {
        'Sub/'  => {v=>1.1, 'i.x'=>4},
        'func1' => {v=>1.1, summary=>"function 1", args=>{}},
        'func2' => {v=>1.1, summary=>"function 2", args=>{}},
    },
);

subtest "invalid hash" => sub {
    dies_ok {
        $pa = Perinci::Access::Schemeless::Hash->new(hash => []) }
        "not given a hash -> dies";

    dies_ok {
        $pa = Perinci::Access::Schemeless::Hash->new(hash => {
            '/' => [{v=>1.1}],
            '/foo/' => {v=>1.1}, # not an array
        }); }
        "hash value not array containing metadata -> dies";
};


DONE_TESTING:
done_testing;

sub test_request {
    my %args = @_;
    my $name = $args{name} // join(" ", @{ $args{argv} });
    subtest $name => sub {
        my $res;
        eval { $res = $pa->request(@{ $args{argv} }) };
        if ($args{dies}) {
            ok($@, "dies");
            return;
        }
        my $exp_status = $args{status} // 200;
        is($res->[0], $exp_status, "status")
            or diag explain $res;
        return unless $exp_status == 200;

        if (exists $args{result}) {
            is_deeply($res->[2], $args{result}, "result")
                or diag explain $res;
        }
    };
}
