use Stenciller::Standard;

our $VERSION = '0.1212'; # VERSION:
# ABSTRACT: One part of a file
# PODNAME: Stenciller::Stencil

class Stenciller::Stencil using Moose {

    my @attrs = qw/before_input input between output after_output/;

    my $order = 1;
    foreach my $attr (@attrs) {
        has $attr => (
            is => 'ro',
            isa => ArrayRef[Str],
            default => sub { [] },
            traits => ['Array'],
            init_arg => undef,
            documentation_order => ++$order,
            documentation => sprintf ('Holds all lines of the %s section.', $attr),
            handles => {
                "has_$attr"    => 'count',
                "add_$attr"    => 'push',
                "all_$attr"    => 'elements',
                "map_$attr"    => 'map',
                "get_$attr"    => 'get',
            },
        );
    }
    has skip => (
        is => 'ro',
        isa => Bool,
        default => 0,
        documentation => 'Should the Stencil not be included in the result?',
    );

    has line_number => (
        is => 'ro',
        isa => Int,
        documentation => 'Can be referenced in the output for easier backtracking.',
    );
    has extra_settings => (
        is => 'ro',
        isa => HashRef,
        default => sub { { } },
        traits => ['Hash'],
        documentation => 'Any extra key-value pairs in the stencil header.',
        handles => {
            get_extra_setting => 'get',
            set_extra_setting => 'set',
            keys_extra_settings => 'keys',
        },
    );
    has loop_values => (
        is => 'ro',
        isa => ArrayRef,
        default => sub { [] },
        traits => ['Array'],
        documentation_order => 0,
        handles => {
            has_loop_values => 'count',
            add_loop_value => 'get',
            all_loop_values => 'elements',
        },
    );

    around BUILDARGS($orig: $class, @args) {
        my %args = @args;
        $args{'loop_values'} = [] if !defined $args{'loop_values'};

        return $class->$orig(%args);
    }

    # Remove all empty lines for each group until we have a line with content, then keep everything
    around add_before_input($orig: $self, $text) {
        return $self->ensure_content($orig, $self->has_before_input, $text);
    }
    around add_input($orig: $self, $text) {
        return $self->ensure_content($orig, $self->has_input, $text);
    }
    around add_between($orig: $self, $text) {
        return $self->ensure_content($orig, $self->has_between, $text);
    }
    around add_output($orig: $self, $text) {
        return $self->ensure_content($orig, $self->has_output, $text);
    }
    around add_after_output($orig: $self, $text) {
        return $self->ensure_content($orig, $self->has_after_output, $text);
    }
    method ensure_content(CodeRef $orig, Int $already_have, $text) {
        $self->$orig($text) if $already_have || $text !~ m{^\s*$};
        return $self;
    }

    method clone_with_loop_value(Str $loop_value) {
        return Stenciller::Stencil->new(
            before_input => $self->map_before_input( sub { $_ =~ s{ \[ var \] }{$loop_value}x }),
                   input => $self->map_input( sub { $_ =~ s{ \[ var \] }{$loop_value}x }),
                 between => $self->map_between( sub { $_ =~ s{ \[ var \] }{$loop_value}x }),
                  output => $self->map_output( sub { $_ =~ s{ \[ var \] }{$loop_value}x }),
                   after => $self->map_after( sub { $_ =~ s{ \[ var \] }{$loop_value}x }),
            (map { $_ => $self->$_ } qw/line_number extra_settings/)
        );
    }

}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Stenciller::Stencil - One part of a file

=head1 VERSION

Version 0.1212, released 2015-02-10.



=head1 SYNOPSIS

    # In a plugin (this is pretty similar to what ToUnparsedText does)
    sub render {
        my $self = shift;
        my @out = ();

        STENCIL:
        foreach my $stencil ($self->stenciller->all_stencils) {
            push @out => join "\n" => $stencil->all_before_input;
            push @out => join "\n" => $stencil->all_input;
            push @out => join "\n" => $stencil->all_between;
            push @out => join "\n" => $stencil->all_output;
            push @out => join "\n" => $stencil->all_after_output;
        }
        return join "\n" => @out;
    }

=head1 DESCRIPTION

A C<Stencil> is one section of the file format defined in L<Stenciller>.

=head1 ATTRIBUTES


=head2 before_input

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Holds all lines of the before_input section.</p>

=end HTML

=head2 input

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Holds all lines of the input section.</p>

=end HTML

=head2 between

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Holds all lines of the between section.</p>

=end HTML

=head2 output

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Holds all lines of the output section.</p>

=end HTML

=head2 after_output

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Holds all lines of the after_output section.</p>

=end HTML

=head2 extra_settings

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#HashRef">HashRef</a>

</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default is a <code>coderef</code>

</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Any extra key-value pairs in the stencil header.</p>

=end HTML

=head2 line_number

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a>

</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Can be referenced in the output for easier backtracking.</p>

=end HTML

=head2 skip

=begin HTML

<table cellpadding="0" cellspacing="0">
<tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Bool">Bool</a>

</td>
<td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default: <code>0</code>

</td>
<td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td></tr>
</table>

<p>Should the Stencil not be included in the result?</p>

=end HTML

=head1 SOURCE

L<https://github.com/Csson/p5-Stenciller>

=head1 HOMEPAGE

L<https://metacpan.org/release/Stenciller>

=head1 AUTHOR

Erik Carlsson <info@code301.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by Erik Carlsson <info@code301.com>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
