package Pod::Knit::Document;
our $AUTHORITY = 'cpan:YANICK';
# ABSTACT: a Pod::Knit document
$Pod::Knit::Document::VERSION = '0.0.1';
use strict;
use warnings;

use Log::Any '$log', prefix => 'PKnit::Doc: ';

use Path::Tiny;
use XML::Writer;
use XML::WriterX::Simple;
use List::Util qw/ reduce /;

use Pod::Knit;
use Pod::Knit::PodParser;

use Moose;

with 'Pod::Knit::Output::Pod';

use MooseX::MungeHas { has_ro => [ 'is_ro' ] };

use experimental 'signatures';







has_ro knit => (
    predicate => 1,
);


has_ro plugins => (
    lazy => 1, 
    traits => [ 'Array' ],
    default => sub {
        my $self = shift;
        $self->has_knit ? $self->knit->plugins : [];
    },
    handles => { all_plugins => 'elements' },
);


has_ro file => (
    predicate => 'has_file',
);


has_ro content => sub {
    $_[0]->has_file and path( $_[0]->file )->slurp;
};



sub podparser {
    my $self = shift;
    
    my $parser = Pod::Knit::PodParser->new;
    $_->setup_podparser($parser) for grep { $_->can('setup_podparser') }
        $self->all_plugins;
    return $parser;
}


has xml_pod => (
    is => 'rw',
    lazy => 1,
    default => sub($self) {
        my $parser = $self->podparser;

        return $parser->parse($self->content)
            =~ s/(?<=<)(\w+)/\L$1/gr
            =~ s/(?<=<\/)(\w+)/\L$1/gr;
    }
);


sub clone {
    my $self = shift;

    __PACKAGE__->new(
        plugins => [],
        map { $_ => $self-> $_ }  qw/ content xml_pod knit file /
    );
}



sub as_code ($self ) {
    return join "\n", grep { 
        not /^=/../^=cut/
    } split "\n", $self->content;
}


sub as_string ($self) {
    return join "\n\n__END__\n\n", $self->as_code, $self->as_pod;
}


sub xml_write($self,@data) {
    my $writer = XML::Writer->new( OUTPUT => 'self' );
    $writer->produce(@data);
    $writer->to_string;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Pod::Knit::Document

=head1 VERSION

version 0.0.1

=head1 SYNOPSIS

    use Pod::Knit::Document;
    
    my $doc = Pod::Knit::Document->new( file => 'Foo.pm' );
    
    say $doc->as_code;
    say $doc->as_pod;
    say $doc->as_string;

=head1 DESCRIPTION

Represents a document (a Perl module or script) that is to be munged by
<Pod::Knit> plugins.

=head1 POD ERRORS

Hey! B<The above document had some coding errors, which are explained
below:>

=over

=item Around line 46:

=cut found outside a pod block.  Skipping to next block.

=back

=head1 attributes

=head3 knit

Main L<Pod::Knit> object from which the document was (potentially) created.
Optional.

=head3 plugins

ArrayRef of plugins used on this document. Plugins that have a
C<setup_podparser> method will be used when setting up the C<podparser>.

Defaults to the plugins associated with the master L<Pod::Knit> object as
defined in C<knit>.

=head3 file

Filename of the document. Optional.

=head3 content

Original content of the document. If not provided, defaults to the content
of C<file>.

=head3 xml_pod

XML representation of the POD. The base tags used by standard POD are

    whole document     | <document>
    =headN Foo         | <head*N*>
    =over ... =back    | <over-text>
    =item title        | <item-text>title</item-text>
    paragraph          | <para>
    verbatim           | <verbatimformatted>
    B<>, I<>, C<> L<>  | <b>, <i>, <c> <l>

All tags have a C<start_line> attribute indicating the first line in the
source file.

=head1 methods

=head3 podparser

Creates a L<Pod::Knit::PodParser> parser. All found C<setup_podparser>
plugin methods found will be invoked with the parser as its first argument,
giving the plugins a chance to define new tags and the like.

=head3 clone

Creates a new L<Pod::Knit::Document> object cloning the data of the current
one.

=head3 as_code

Returns the code part of the document (i.e., all that is not POD).

=head3 as_pod

Returns the POD. Generated by L<Pod::Knit::Output::Pod>.

=head3 as_string

Returns the whole document, code and POD.

=head1 AUTHOR

Yanick Champoux <yanick@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2018 by Yanick Champoux.

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

Full text of the license can be found in the F<LICENSE> file included in
this distribution.

=cut

