### ----------------------------------------------------
### -- Raku::Pod::Render
### -- Licenses: Artistic-2.0
### -- Authors: Richard Hainsworth
### -- File: xt/60-plugin.rakutest
### ----------------------------------------------------
use v6.*;
use Test;
use File::Directory::Tree;
use ProcessedPod;
# A helper sub for RakuClosureTemplates
sub gen-closure-template (Str $tag) is export {
    my $start = '<' ~ $tag ~ '>';
    my $end = '</' ~ $tag ~ '>';
    return sub (%prm, %tml? --> Str) {
        $start ~ (%prm<contents> // '') ~ $end;
    }
}

my $rv;
my $processor = ProcessedPod.new;
my $pc = 0;

plan 12;

use RenderPod::Templating;
my @templates = SetupTemplates.new.required;


my %templates = @templates Z=> @templates.map({ gen-closure-template($_) });
# this creates a set of pseudo templates
%templates<escaped> = sub ($str) {
    "<escp>$str\</escp>"
} ;
$processor.templates(%templates);

=begin pod

=newblocktype Here are some words

=end pod

$rv = $processor.render-block($=pod[$pc]);
unlike $rv, /
'<newblocktype>'
.+ '</newblocktype>'
/, 'new block treated as ordinary named';

$processor.add-custom(['newblocktype',]);
$processor.modify-templates(%( 'newblocktype' => gen-closure-template('newblocktype')));
$rv = $processor.render-block($=pod[$pc++]);
like $rv, /
'<newblocktype>'
.+ '</newblocktype>'
/, 'new block gets template';

$rv = $processor.pod-file.raw-toc.raku;
like $rv, /
'Here are some words'
/, 'Block\'s content has been added to TOC';

=begin pod

=for newblocktype :headlevel<0>
This one is different

=end pod

$processor.render-block($=pod[$pc++]);
$rv = $processor.pod-file.raw-toc.raku;
unlike $rv, /
'This one is different'
/, 'Block\'s content has not been added to TOC with headlevel(0)';

=begin pod

=for newblocktype :!toc
This one is very different

=end pod

$processor.render-block($=pod[$pc++]);
$rv = $processor.pod-file.raw-toc.raku;
unlike $rv, /
'This one is very different'
/, 'Block\'s content has not been added to TOC with :!toc';

=begin pod

Some pod

=for plugin
Here is some custom text
and %%interpolation%% is changed by the custom template

=end pod

my $dir = 'plugin';
rmtree($dir) if $dir.IO.e;
mktree $dir;
"$dir/templates.raku".IO.spurt(q:to/END/);
    %( plugin => sub ( %a, %b ) {
        '<div class="myplugin">'
        ~ %a<contents>.subst(/ '%%' ~ '%%' .+ /, %a<plugin><data> )
        ~ </div>
        },
        myplugin => sub ( %a, %b ) {
        '<div class="myplugin">'
        ~ %a<contents>.subst(/ '%%' ~ '%%' .+ /, %a<newspace><stuff> )
        ~ </div>
        },
    )
    END

"$dir/blocks.raku".IO.spurt(q:to/END/);
    < plugin testing >
    END

$processor.add-plugin('plugin', :config(%(
    :data('NEW WORDS')
)));
$rv = $processor.render-block($=pod[$pc++]);

throws-like { $processor.add-plugin('plugin', :path($dir)) },
        X::ProcessedPod::NamespaceConflict,
        message => / 'overwrite plugin' /,
        'tried to add plugin again';

like $rv, /
'<div class="myplugin">'
.* 'Here is some custom text'
\s+ 'and'
\s+ 'NEW WORDS'
\s+ 'is changed by the custom template'
/, 'plugin works with default name-space';

=begin pod
Some pod

=for testing :template<myplugin> :name-space<newspace>
Here is some custom text
and %%interpolation%% is changed by the custom template

=end pod

$processor.add-data('newspace', %( :stuff('VERY NEWX WORDS'),));

$rv = $processor.render-block($=pod[$pc++]);

like $rv, /
    '<div class="myplugin">'
    .* 'Here is some custom text'
    \s+ 'and'
    \s+ 'VERY NEWX WORDS'
    \s+ 'is changed by the custom template'
    /, 'plugin works with different name-space';

rmtree $dir;
# now in another directory
$dir = 'xt/xplugin';
rmtree($dir) if $dir.IO.e;
mktree($dir);

=begin pod
Some pod

=for testing :template<myplugin>
Here is some custom text
with no data

=end pod

"$dir/templates.raku".IO.spurt(q:to/END/);
    %( myplugin => sub ( %a, %b ) {
        '<div class="myplugin">'
        ~ %a<contents>
        ~ </div>
        },
    )
    END

"$dir/blocks.raku".IO.spurt(q:to/END/);
    < testing >
    END

$processor.add-plugin('xplugin', :path($dir));
$rv = $processor.render-block($=pod[$pc++]);

like $rv, /
'<div class="myplugin">'
.* 'Here is some custom text'
\s+ 'with no data'
/, 'plugin works with blank data in another directory';

rmtree($dir);

# test plugin with two template types
$dir = 'newer-plugin';
# avoid namespace error
rmtree($dir) if $dir.IO.e;
mktree $dir;
"$dir/templates.raku".IO.spurt(q:to/END/);
    %(
        rakuclosuretemplater =>
            %( newer-plugin => sub ( %a, %b ) {
                '<div class="newplugin">'
                ~ 'The next event will be in '
                ~ %a<location>
                ~ '</div>'
                },
            ),
        mustachetemplater =>
            %( newer-plugin =>
                '<div class="newplugin">'
                ~ 'The next event will be in '
                ~ '{{{ location }}}'
                ~ '</div>'
                ,
            ),
    )
    END

"$dir/blocks.raku".IO.spurt(q:to/END/);
    < newer-plugin testing >
    END
$processor.add-plugin($dir);

# create processor using mustache templates
%templates = @templates Z=> @templates.map({ "<$_>\{\{\{ contents }}}</$_>" });
%templates<escaped> = -> %params {
        if (%params<contents> ~~ / \`/) {
            %params<contents> .= trans([q{`}] => [q{``}])
        }
        '{{{ contents }}}'
};
%templates<_templater> = 'MustacheTemplater';
my $must-proc = ProcessedPod.new;
$must-proc.templates(%templates);
$must-proc.add-plugin($dir);
skip 'wait til Crotmp can be used';
## Now force a processor with CroTemplater templates
#%templates = @templates Z=> @templates.map({ "\[beg]<.contents>$_\[end]" });
#my $cro-proc = ProcessedPod.new;
#$cro-proc.templates(%templates);
#throws-like { $cro-proc.add-plugin($dir) },
#        X::ProcessedPod::BadPluginTemplates,
#        'traps lack of CroTemplater alternative in templates',
#        message => / 'Attempted to use ｢crotemplater｣, but the plugin ｢newer-plugin｣' /
#        ;
=begin pod

Some pod

=for newer-plugin :location<Cardiff>

=end pod

$rv = $processor.render-block($=pod[$pc]);
# next test uses same block
like $rv, /
    '<div class="newplugin">'
    'The next event will be in '
    'Cardiff'
    '</div>'
    /, 'Rakuclosure works in multiple templater plugin';

$rv = $must-proc.render-block($=pod[$pc]);
like $rv, /
    '<div class="newplugin">'
    'The next event will be in '
    'Cardiff'
    '</div>'
    /, 'Mustache works in multiple templater plugin';

rmtree($dir);

done-testing;


