use v5.18;
use autodie;
use utf8;
use Carp qw(confess);
use Test::More;
use Test::Exception;
use FindBin qw($Bin);
use File::Glob qw(bsd_glob);
use File::Spec;
use JSON qw(decode_json);
use Data::Dumper;
use JSONLD;

use Moo;
use Attean;
use Type::Tiny::Role;

our $debug	= 0;
$JSONLD::debug	= $debug;
our $PATTERN;
if ($debug) {
	$PATTERN = qr/tc020/;
} else {
	$PATTERN	= /./;
}

sub load_json {
	my $file	= shift;
	open(my $fh, '<', $file);
	my $j	= JSON->new();
	$j->boolean_values(0, 1);
	return $j->decode(do { local($/); <$fh> });
}

$Data::Dumper::Sortkeys	= 1;
my $path	= File::Spec->catfile( $Bin, 'data', 'json-ld-api-w3c' );
my $manifest	= File::Spec->catfile($path, 'expand-manifest.jsonld');
my $d		= load_json($manifest);
my $tests	= $d->{'sequence'};
my $base	= IRI->new(value => $d->{'baseIri'} // 'http://example.org/');
foreach my $t (@$tests) {
	my $id		= $t->{'@id'};
	next unless ($id =~ $PATTERN);
	
	my $input	= $t->{'input'};
	my $expect	= $t->{'expect'};
	my $name	= $t->{'name'};
	my $purpose	= $t->{'purpose'};
	my $options	= $t->{'option'} // {};
	my $_base	= $options->{'base'};
	my $spec_v	= $options->{'specVersion'} // '';
	my @types	= @{ $t->{'@type'} };
	my %types	= map { $_ => 1 } @types;

	my $test_base;
	if (defined($_base)) {
		$test_base	= IRI->new(value => $_base, base => $base)->abs;
	} else {
		$test_base	= IRI->new(value => $input, base => $base)->abs;
	}
	my $j		= JSON->new->canonical(1)->allow_nonref(1);
	$j->boolean_values(0, 1);
	if ($spec_v eq 'json-ld-1.0') {
		diag("IGNORING JSON-LD-1.0-only test $id\n");
	} elsif ($types{'jld:PositiveEvaluationTest'}) {
		note($id);
		my $jld			= JSONLD->new(base_iri => IRI->new($test_base));
		my $infile		= File::Spec->catfile($path, $input);
		my $outfile		= File::Spec->catfile($path, $expect);
		my $data		= load_json($infile);
		my $expected	= $j->encode(load_json($outfile));
		if ($debug) {
			warn "Input file: $infile\n";
			warn "INPUT:\n===============\n" . JSON->new->pretty->encode($data); # Dumper($data);
		}
		my $expanded	= eval { $jld->expand($data) };
		if ($@) {
			diag("Died: $@");
		}
		my $got			= $j->encode($expanded);
		if ($debug) {
			my @data	= (
				['EXPECTED', $expected],
				['OUTPUT__', $got],
			);
			my @files;
			foreach my $d (@data) {
				my ($name, $data)	= @$d;
				warn "=======================\n";
				my $filename	= "/tmp/json-ld-$$-$name.out";
				open(my $fh, '>', $filename) or die $!;
				push(@files, $filename);
				my $out	= Data::Dumper->Dump([$j->decode($data)], ["*$name"]);
				warn $out;
				print {$fh} $out;
				close($fh);
			}
			unless ($got eq $expected) {
				system('/usr/local/bin/bbdiff', '--wait', '--resume', @files);
			}
		}
		is($got, $expected, "$id: $name");
	} elsif ($types{'jld:NegativeEvaluationTest'}){
		diag("IGNORING NegativeEvaluationTest $id\n");
	} else {
		diag("Not a recognized evaluation test: " . Dumper(\@types));
		next;
	}
}

done_testing();
