The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#===============================================================================
#
#  DESCRIPTION:  convert pod6 to atom
#
#       AUTHOR:  Aliaksandr P. Zahatski, <zahatski@gmail.com>
#===============================================================================

=head1 NAME

WriteAt::To::Atom - Atom renderer

=head1 SYNOPSIS

        new WriteAt::To::Atom:: 
            lang=>'en', 
            baseurl=>'http://example.com',
            as_entry => 'CHAPTER',

=cut

package WriteAt::To::Atom;
use strict;
use warnings;
use Perl6::Pod::Utl;
use WriteAt::To;
use DateTime::Format::W3CDTF;

use Perl6::Pod::To::XHTML;
use base ( 'Perl6::Pod::To::XHTML', 'WriteAt::To' );
use utf8;

sub new {
    my $class = shift;
    my $self =
      $class->SUPER::new( baseurl => 'http://example.com', lang => 'en', as_entry=>'CHAPTER', @_ );
    return $self;
}

sub get_published {
    my $self = shift;
    my $node = shift || return;
    return $node->get_attr->{published}

      #    unless
}

=head2 get_time_stamp_from_string <str>

Get time stamp from strnigs like this:

        2012-11-27T09:39:19Z
        2012-11-27 09:39:19
        2012-11-27 09:39
        2012-11-27 09
        2012-11-27

return unixtimestamp

=cut

sub get_time_stamp_from_string {
    my $self = shift;
    my $str  = shift;

    #if w3cdtf time
    if ( $str =~ /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|.\d{2}:\d{2})/ ) {
        my $dt = DateTime::Format::W3CDTF->new();
        return $dt->parse_datetime($str)->epoch();
    }
    elsif ( $str =~
        /^(\d{4})-(\d{2})-(\d{2})(?:.(\d{2})(?::(\d{2})(?::(\d{2}))?)?)?/ )
    {
        my $dt = DateTime->new(
            year       => $1,
            month      => $2,
            day        => $3,
            hour       => $4 || 0,
            minute     => $5 || 0,
            second     => $6 || 0,
            nanosecond => 500000000,
        );
        return $dt->epoch;
    }
    die "Bad srting $str";
}

=head2 unixtime_to_string timestamp

Return 

=cut

sub unixtime_to_string {
    my $self = shift;
    my $time = shift || return;
    my ( $sec, $min, $hour, $mday, $mon, $year, $wday ) = gmtime($time);
    $year += 1900;
    return sprintf( "%04d-%02d-%02dT%02d:%02d:%02dZ",
        $year, $mon + 1, $mday, $hour, $min, $sec );
}

sub start_write {
    my $self         = shift;
    my %tags         = @_;
    my $w            = $self->writer;
    my $title        = &WriteAt::get_text( @{ $tags{TITLE} } );
    my $base_url     = $self->{baseurl};
    my $author       = &WriteAt::get_text( @{ $tags{AUTHOR} } );
    my $atomid       = "tag:$base_url, 2012:1";
    my $updated_time = $self->unixtime_to_string( time() );
    $w->raw(<<TXT);
<?xml version="1.0" encoding="utf-8"?>
  <feed xmlns="http://www.w3.org/2005/Atom">
  <title>$title</title>
  <id>$atomid</id>
  <link rel="alternate" href="$base_url" type="text/html"/>
  <link rel="self" href="$base_url/Atom.xml" type="application/atom+xml"/>
  <updated>$updated_time</updated>
  <author>
    <name>$author</name>
    <uri>$base_url</uri>
  </author>
TXT
  # add category if tag exists
  if ( my $desc_node = $tags{DESCRIPTION}->[0] ) {
    if ( my $tags = $desc_node->get_attr()->{tag} ) {
        # save TAGS as ref to array 
        $self->{TAGS} = ref($tags) ? $tags : [$tags];
        #fill categoty tags
        foreach my $tag ( @{$self->{TAGS}} ) {
            $w->raw("<category>$tag</category>\n")
            
        }
    }
  }
}

sub write {
    my $self = shift;
    my $tree = shift;
    my $res ;
    if ($self->{as_entry} eq 'CHAPTER')  {
           $res  =  &WriteAt::make_levels( "CHAPTER", 0, $tree ) ;
    } else {
      #headN
        $self->{as_entry} =~ /(\d+)$/ || die "use in as_entry: head1, head2 ...";
        $res  =  &WriteAt::make_levels( "head", $1, $tree ) ;
    }
    my $w    = $self->writer;

    #first setup published attr for items
    # if default_published
    my $current_time =
        $self->{set_date}
      ? $self->get_time_stamp_from_string( $self->{set_date} )
      : time();
    my @items_to_publish = ();
    my $order            = 0;
    foreach my $entry (@$res) {
        $entry->{order} = ++$order;    #for sort in later
        my $published = $entry->{node}->get_attr->{published};
        #set default publushed = current time
        my $published_time =
            $published
          ? $self->get_time_stamp_from_string($published)
          : $current_time;

        #save publish timesamp for sorting later
        $entry->{pub_time} = $published_time;
        push @items_to_publish, $entry;
    }

    #sort entries
    @items_to_publish =
      sort { $b->{pub_time} <=> $a->{pub_time} || $b->{order} <=> $a->{order} }
      @items_to_publish;
    foreach my $entry (@items_to_publish) {

        # check if need filter by published
        my $published = $entry->{node}->get_attr->{published};
        my $updated   = $entry->{node}->get_attr->{updated} || $published || $self->unixtime_to_string($current_time);
        $published ||= $updated;
        my $title    = &WriteAt::get_text( $entry->{node} );
        my $title_en = &WriteAt::rus2lat($title);

        #strip spaces
        $title_en =~ s/\s+/-/g;
        my $filename = $title_en . ".htm";
        my $url      = $self->{baseurl} . "/" . $filename;
        my $id       = $self->{baseurl} . ";" . $title_en;
        $w->raw(
            qq%<entry xmlns="http://www.w3.org/2005/Atom">
                <title>$title</title>
                 <id>$id</id>
                 <link rel="alternate" href="$url" title="$title" type="text/html"/>
                <published>$published</published>
                <updated>$updated</updated>
                %
        );
        if ( my $tags = $entry->{node}->get_attr->{tag} ) {
            # save TAGS as ref to array 
            my $local_tags = ref($tags) ? $tags : [$tags];
            #union tags fill categoty tags
            foreach my $tag (  @{ $self->{TAGS}|| [] }, @{$local_tags} ) {
                $w->raw("<category>$tag</category>\n")
            }
        }

        my $out = '';
        open( my $fd, ">", \$out );
        my $renderer = new Perl6::Pod::To::XHTML::
          writer  => new Perl6::Pod::Writer( out => $fd, escape => 'xml' ),
          out_put => \$out,
          doctype => 'xhtml',
          header  => 0;

        foreach my $BLOCK_NAME ( keys %{ $self->context->use } ) {
            $renderer->context->use->{$BLOCK_NAME} =
              $self->context->use->{$BLOCK_NAME};
        }

        foreach my $n ( $entry->{childs} ) {
            $renderer->visit($n);
        }
        close $fd;
        my $safe_text = &Perl6::Pod::Writer::_html_escape($out);
        $w->raw('<content type="html">');
        $w->raw($safe_text);
        $w->raw(
            '</content>
        </entry>'
        );

    }

}

sub end_write {
    my $self = shift;
    $self->SUPER::end_write();
    $self->w->raw('</feed>');
}

sub page_template {
    my $self = shift;
    my %keys = @_;
    my $page = <<TXT;
<html>
<head>
<title>{{title}}</title>
</head>
<body>
   {{content}} 
</body>
</html>
TXT
    $page =~ s/\{\{ \s* (\S+) \s* \}\}/ $keys{$1} || ""/gex;
    return $page;
}

1;