#!/usr/bin/env perl
require 5.008;
use warnings;
use strict;
use File::Compare;

unshift(@INC, '.');
require qpdf_test_helpers;

chdir("qpdf") or die "chdir testdir failed: $!\n";

require TestDriver;

cleanup();

my $td = new TestDriver('json');

my @json_files = (
    ['outlines-with-actions', []],
    ['outlines-with-old-root-dests', []],
    ['page-labels-and-outlines', []],
    ['page-labels-num-tree', []],
    ['image-streams', []],
    ['image-streams-small', []],
    ['field-types', []],
    ['field-types', ['--show-encryption-key']],
    ['image-streams', ['--decode-level=all']],
    ['image-streams', ['--decode-level=specialized']],
    ['attachment-fields', []],
    ['page-labels-and-outlines', ['--json-key=objects']],
    ['page-labels-and-outlines', ['--json-key=pages']],
    ['page-labels-and-outlines', ['--json-key=pagelabels']],
    ['page-labels-and-outlines', ['--json-key=outlines']],
    ['page-labels-and-outlines',
     ['--json-key=outlines', '--json-key=pages']],
    ['page-labels-and-outlines',
     ['--json-key=objects', '--json-object=trailer']],
    ['page-labels-and-outlines',
     ['--json-key=objects', '--json-object=trailer', '--json-object=2 0 R']],
    ['field-types', ['--json-key=acroform']],
    ['need-appearances', ['--json-key=acroform']],
    ['V4-aes', ['--json-key=encrypt']],
    ['V4-aes', ['--json-key=encrypt', '--show-encryption-key']],
);
my $n_tests = 25 + (2 * scalar(@json_files));
foreach my $d (@json_files)
{
    my ($file, $xargs) = @$d;
    my $out = "json-$file";
    foreach my $x (@$xargs)
    {
        my $y = $x;
        $y =~ s/^.*=//;
        $y =~ s/\s.*//;
        $out .= "-$y";
    }
    my $in = "$file.pdf";
    $td->runtest("json v1 $out",
                 {$td->COMMAND =>
                      ['qpdf', '--json=1', '--test-json-schema',
                       @$xargs, $in]},
                 {$td->FILE => "$out-v1.out", $td->EXIT_STATUS => 0},
                 $td->NORMALIZE_NEWLINES);
    for (@$xargs)
    {
        s/--json-key=objects/--json-key=qpdf/;
    }
    $td->runtest("json v2 $out",
                 {$td->COMMAND =>
                      ['qpdf', '--json=2', '--test-json-schema', @$xargs, $in]},
                 {$td->FILE => "$out-v2.out", $td->EXIT_STATUS => 0},
                 $td->NORMALIZE_NEWLINES);
}

$td->runtest("bad json stream data (inline)",
             {$td->COMMAND =>
                  "qpdf --json-output=2 --decode-level=all" .
                  " --json-stream-data=inline bad-data.pdf a.json"},
             {$td->FILE => "bad-data-json.out", $td->EXIT_STATUS => 3},
             $td->NORMALIZE_NEWLINES);
$td->runtest("check (inline)",
             {$td->FILE => "a.json"},
             {$td->FILE => "json-bad-data-json-inline-v2.out"},
             $td->NORMALIZE_NEWLINES);
$td->runtest("bad json stream data (file)",
             {$td->COMMAND =>
                  "qpdf --json-output=2 --decode-level=all" .
                  " --json-stream-data=file --json-stream-prefix=auto" .
                  " bad-data.pdf a.json"},
             {$td->FILE => "bad-data-json.out", $td->EXIT_STATUS => 3},
             $td->NORMALIZE_NEWLINES);
$td->runtest("check (file)",
             {$td->FILE => "a.json"},
             {$td->FILE => "json-bad-data-json-file-v2.out"},
             $td->NORMALIZE_NEWLINES);
$td->runtest("check stream (file)",
             {$td->FILE => "auto-4"},
             {$td->FILE => "bad-data-4.out"});

foreach my $l (qw(none generalized specialized all))
{
    if ($l ne 'all')
    {
        # We don't want a dependency on the exact value of the
        # uncompressed jpeg, which can differ depending on which jpeg
        # library is use.
        $td->runtest("image-streams json inline: $l",
                     {$td->COMMAND =>
                          "qpdf image-streams-small.pdf - --json-output=2" .
                          " --decode-level=$l --json-stream-data=inline"},
                     {$td->FILE => "json-image-streams-$l-inline-v2.out",
                          $td->EXIT_STATUS => 0},
                     $td->NORMALIZE_NEWLINES);
    }
    $td->runtest("image-streams json file: $l",
                 {$td->COMMAND =>
                      "qpdf image-streams-small.pdf - --json-output=2" .
                      " --decode-level=$l --json-stream-data=file" .
                      " --json-stream-prefix=auto" .
                      " --json-object=12 --json-object=16 --json-object=18"},
                 {$td->FILE => "json-image-streams-$l-file-v2.out",
                      $td->EXIT_STATUS => 0},
                 $td->NORMALIZE_NEWLINES);
    # object 12: /FlateDecode
    # object 16: /DCTDecode
    # object 18: /RunLengthDecode
    my %exp_compression = (
        '12' => {'none' => 1},
        '16' => {'none' => 1, 'generalized' => 1, 'specialized' => 1},
        '18' => {'none' => 1, 'generalized' => 1},
        );

    foreach my $obj (qw(12 16 18))
    {
        my $compressed = (exists $exp_compression{$obj}{$l});
        my $suf = $compressed ? "compressed" : "uncompressed";
        if (($obj eq '16') && (! $compressed))
        {
            # Rather than testing the uncompressed DCT, just make sure
            # it is different from the compressed DCT.
            my $same = (compare(
                            "auto-$obj",
                            "image-streams-small-$obj-compressed.out") ?
                        "same" : "different");
            $td->runtest("check stream data ($obj, $l)",
                         {$td->STRING => $same},
                         {$td->STRING => "same"});
        }
        else
        {
            $td->runtest("check stream data ($obj, $l)",
                         {$td->FILE => "auto-$obj"},
                         {$td->FILE => "image-streams-small-$obj-$suf.out"});
        }
    }
}

$td->runtest("file to stdout without prefix",
             {$td->COMMAND =>
                  "qpdf image-streams-small.pdf - --json-output=2" .
                  " -json-stream-data=file"},
             {$td->FILE => "file-stdout-needs-prefix.out",
                  $td->EXIT_STATUS => 2},
             $td->NORMALIZE_NEWLINES);

cleanup();
$td->report($n_tests);
