### ----------------------------------------------------
### -- Collection
### -- Licenses: Artistic-2.0
### -- Authors: Richard Hainsworth, aka finanalyst
### -- File: xt/35-render.rakutest
### ----------------------------------------------------
use v6.*;
use Test;

use File::Directory::Tree;
use Test::Deeply::Relaxed;
use ProcessedPod;

use Collection;
constant TMP = 'xt/test-dir';
constant MODE = 'test-mode';
constant PLUGS = "{ MODE }/plugins";
constant CONFS = "{ MODE }/configs";
constant TEMPLATES = "{ MODE }/templates";
constant ASSETS = 'assets';
constant HTML = "{ MODE }/html";

plan 12;
my $rv;

bail-out "{ TMP } and { TMP }/{ MODE } must exist. Have source tests been run?"
unless TMP.IO.d and "{ TMP }/{ MODE }".IO.d;
mktree TMP ~ '/' ~ TEMPLATES;
'resources/test_things/html-rakuclosure.raku'.IO.copy:
        TMP ~ '/' ~ TEMPLATES ~ '/mintemp.raku';
mktree TMP ~ '/' ~ TEMPLATES;

#my @pls = <setup1 setup_rend rend2 reporter compiler completer unused>;

chdir TMP;
bail-out "{ PLUGS } and { CONFS } must exit. Have setup tests been run?"
unless PLUGS.IO.d and CONFS.IO.d;

mktree(HTML) unless HTML.IO.d;
mktree ASSETS;
mktree "{ ASSETS }/videos";
mktree "{ ASSETS }/images";

(MODE ~ '/configs/02-plugin.raku').IO.spurt(qq:to/CONF/);
    %(
        plugins-required => %(
            :setup(<setup1 setup_rend>),
            :render(<setup_rend rend2 gather-css asset-mover image-mover>),
            :compilation(<compiler rend2>),
            :transfer(<image-mover gather-css>),
            :report(<reporter>,),
            :completion(<completer>,),
        ),
    );
    CONF
# rewrite the config and plugin test files for render plugins
(PLUGS ~ '/setup_rend/config.raku').IO.spurt(q:to/CONF/);
        %(
        :render,
        :template-raku<setup_rend_templates.raku>,
        :custom-raku<blocks.raku>,
        :setup<proc.raku>,
        )
        CONF

(PLUGS ~ '/rend2/config.raku').IO.spurt(q:to/CONF/);
        %(     
        :render<rend2_render.raku>,
        :template-raku<rend2_templates.raku>,
        :custom-raku<blocks.raku>,
        :css<mystyling.css>,
        :2option,
        :compilation<rend2_compilation.raku>,
        )
        CONF

(PLUGS ~ '/gather-css/config.raku').IO.spurt(q:to/CONF/);
        %(
        :render<css-collect.raku>,
        :template-raku(),
        :custom-raku(),
        :transfer<cleanup.raku>
        )
        CONF

# template raku files
(PLUGS ~ '/setup_rend/setup_rend_templates.raku').IO.spurt(q:to/CONF/);
        %(
        design => sub ( %a, %b ) {
                '<designer-tag>' ~ %a<contents> ~ '</designer-tag>'
        },
        diagram => sub (%a, %b ) {
                '<diag>' ~ %a<contents> ~ '</diag>'
        },
        )
        CONF

(PLUGS ~ '/rend2/rend2_templates.raku').IO.spurt(q:to/CONF/);
        %(
        sorted-table => sub (%a, %b) {
                '<table class="sorted">' ~ %a<contents> ~ '</table>'
        },
        )
        CONF

#block files
(PLUGS ~ '/setup_rend/blocks.raku').IO.spurt(q:to/CONF/);
        <design diagram>
        CONF

#its intentional to overwrite diagram. rend2 comes after setup_rend
(PLUGS ~ '/rend2/blocks.raku').IO.spurt(q:to/CONF/);
        <figure diagram sorted-table>
        CONF

(PLUGS ~ '/rend2/mystyling.css').IO.spurt(q:to/CONF/);
        .design { font-size: large; }
        CONF
(PLUGS ~ '/rend2/rend2_compilation.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %processed, %options ) {
            use Test;
            is $pp.get-data('rend2')<option>, 5, 'option value from Mode config in compilation'
        }
        CONF
(PLUGS ~ '/rend2/rend2_render.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %options ) {
            use Test;
            is $pp.get-data('rend2')<option>, 5, 'option value from Mode config in render';
            [] # empty array of triples
        }
        CONF
#fake compilation
(PLUGS ~ '/compiler/frontmatter.raku').IO.spurt(q:to/CONF/);
    sub ($pr, %processed, %options) { } # do nothing, this is a placeholder
    CONF

#create a plugin that looks for css files, creates a local css file, passes it back
# where it is written to output
(PLUGS ~ '/gather-css/css-collect.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %options ) {
                my $css = '';
                for $pp.plugin-datakeys {
                        my $data = $pp.get-data($_);
                        next unless $data ~~ Associative and $data<css>:exists and $data<css> ~~ Str:D;
                        my $file = ($data<path> ~ '/' ~ $data<css>).IO;
                        $css ~= "\n" ~ $file.slurp;
                }
                'local.css'.IO.spurt($css);
                ( <assets/css/local.css myself local.css >, )
        }
        CONF

(PLUGS ~ '/gather-css/cleanup.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %processed, %options ) {
            'local.css'.IO.unlink;
            [] # empty array of triples
        }
        CONF
$rv = collect(MODE, :no-status, :after<setup>, :no-preserve-state, :recompile);
is $rv[1][2]<Render>[0]<message>, 'Plugin calls cancelled', 'no plugins when stopped by an after';

$rv = collect(MODE, :no-status, :no-preserve-state, :before<render>, :recompile, :full-render);
# The call to collect after render should trigger a test inside the rend2 render sub
isa-ok $rv[0][0], ProcessedPod, 'got the correct object';
is-deeply-relaxed $rv[0][0].custom.Set,
        <figure diagram sorted-table design>.Set,
        'plugin added the custom blocks';
ok $rv[0][0].tmpl<sorted-table>:exists, 'template was added from rend2';
ok $rv[0][0].tmpl<design>:exists, 'template was added from setup_rend';

ok (HTML ~ '/assets/css/local.css').IO.f, 'file exists';
like (HTML ~ '/assets/css/local.css').IO.slurp,
        /
        '.design { font-size: large;'
        /, 'css from other plugin has be copied';

(PLUGS ~ '/rend2/rend2_render.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %options ) {# dummy sub for remaining tests
            [] # empty array of triples
        }
        CONF
#create a plugin that signals a copy of a file from another plugin to the asset - plugin is registered
(PLUGS ~ '/gather-css/css-collect.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %options ) {
                ( <assets/css/mystyling.css rend2 mystyling.css >, )
        }
        CONF

$rv = collect(MODE, :no-status, :no-preserve-state, :before<render>, :full-render);
ok (HTML ~ '/assets/css/mystyling.css').IO.f, 'file exists';

#create a plugin that signals a copy of a file from another plugin to the asset - plugin is not registered
(PLUGS ~ '/gather-css/css-collect.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %options ) {
                ( <assets/css/mystyling.css unused mystyling.css >, )
        }
        CONF

(PLUGS ~ '/unused/nostyling.css').IO.spurt(q:to/CONF/);
        .design { font-size: large; }
        CONF

use Test::Output;
stderr-like { $rv = collect(MODE, :no-status, :no-preserve-state, :before<render>, :full-render)},
       /
       'is not registered as a plugin'
       /, 'transferring from unregistered plugin is ignored with warning';

nok (HTML ~ '/assets/css/nostyling.css').IO.f, 'file was not transferred';
# reset gather-css as it is used later
(PLUGS ~ '/gather-css/css-collect.raku').IO.spurt(q:to/CONF/);
        sub ( $pp, %options ) {
                my $css = '';
                for $pp.plugin-datakeys {
                        my $data = $pp.get-data($_);
                        next unless $data ~~ Associative and $data<css>:exists and $data<css> ~~ Str:D;
                        my $file = ($data<path> ~ '/' ~ $data<css>).IO;
                        $css ~= "\n" ~ $file.slurp;
                }
                'local.css'.IO.spurt($css);
                ( <assets/css/local.css myself local.css >, )
        }
        CONF
# The call to collect after compilation should trigger a test inside a compilation sub
$rv = collect(MODE, :no-status, :no-preserve-state, :after<compilation>, :full-render);
(MODE ~ '/configs/02-plugin.raku').IO.spurt(qq:to/CONF/);
    %(
        plugins-required => %(
            :setup(<setup1 setup_rend>),
            :render(<setup_rend rend2 gather-css asset-mover image-mover>),
            :compilation(<compiler>,),
            :transfer(<image-mover gather-css>),
            :report(<reporter>,),
            :completion(<completer>,),
        ),
    );
    CONF
done-testing;


