# ABSTRACT: pack novel/bbs content to ebook
package Novel::Robot::Packer;
use strict;
use warnings;
use utf8;
use Encode::Locale;
use Encode;
use File::Temp qw/tempfile /;
use Template;

our $VERSION = 0.21;

sub new {
    my ( $self, %opt ) = @_;

    $opt{type} ||= 'html';

    bless {%opt}, __PACKAGE__;
}

sub set_type {
    my ( $self, $output, $o ) = @_;

    if ( exists $o->{type} ) {
        return $o->{type};
    } elsif ( defined $output
            and ( !exists $o->{output_scalar} ) ) {
        ( $o->{type} ) = $output =~ m#\.([^.]+)$#;
    } else {
        $o->{type} = 'html';
    }

    return $o->{type};
}

sub detect_writer_book_type {
    my ( $self, $input, $o ) = @_;

    $input = decode( locale => $input );
    my ( $writer, $book, $type ) = $input =~ /([^\\\/]+?)-([^\\\/]+?)\.([^.\\\/]+)$/;

    $writer = $o->{writer} if ( defined $o->{writer} );
    $writer //= '';

    $book = $o->{book} if ( defined $o->{book} );
    $book //= '';

    return ( $writer, $book, $type );
}

sub convert_novel {
    my ( $self, $input, $output, $o ) = @_;

    return $input unless ( -f $input and -s $input );

    my ( $writer, $book, $in_type ) = $self->detect_writer_book_type( $input, $o );

    if ( !defined $output ) {
        $output = $input;
        $output =~ s/\.([^.]+)$/.$o->{type}/;
    }
    return $input if ( $output eq $input );

    my ( $out_type ) = $output =~ m#\.([^.]+)$#;

    my %conv = (
        'authors'            => $writer,
        'author-sort'        => $writer,
        'title'              => $book,
        'chapter-mark'       => "none",
        'page-breaks-before' => "/",
        'max-toc-links'      => 0,
    );

    my $conv_str = join( " ", map { qq[--$_ "$conv{$_}"] } keys( %conv ) );
    if ( $o->{type} =~ /\.epub$/ ) {
        $conv_str .= " --dont-split-on-page-breaks ";
    } elsif ( $o->{type} =~ /\.mobi$/ ) {
        $conv_str .= " --mobi-keep-original-images ";
    }

    $conv_str = encode( locale => $conv_str );
    my $cmd = qq[ebook-convert "$input" "$output" $conv_str];
    #print "$cmd\n";
    #system($cmd);
    `$cmd`;

    return $output;
} ## end sub convert_novel

sub main {
    my ( $self, $book_ref, $o ) = @_;

    $self->set_type( $o->{output}, $o );
    $self->format_item_output( $book_ref, $o );

    if ( $o->{type} ne 'html' and ( !exists $o->{output_scalar} ) ) {
        my ( $fh, $html_f ) = tempfile( "run_novel-html-XXXXXXXXXXXXXX", TMPDIR => 1, SUFFIX => ".html" );
        $self->process_html_template( $book_ref, $html_f, $o );
        $self->convert_novel( $html_f, $o->{output}, { type => $o->{type}, writer => $book_ref->{writer}, book => $book_ref->{book} } );
    } else {
        $self->process_html_template( $book_ref, $o->{output}, $o );
    }

    return $o->{output};
}

sub format_item_output {
    my ( $self, $book_ref, $o ) = @_;
    if ( !$o->{output} ) {
        my $html = '';
        $o->{output} =
        exists $o->{output_scalar}
        ? \$html
        : $self->format_default_filename( $book_ref, $o );
    }
    return $o->{output};
}

sub format_default_filename {
    my ( $self, $r, $o ) = @_;

    my $item_info = '';
    if ( exists $o->{min_item_num} and $o->{min_item_num} > 1 ) {
        $item_info = "-$o->{min_item_num}";
    } elsif ( exists $o->{min_page_num} and $o->{min_page_num} > 1 ) {
        $item_info = "-$o->{min_page_num}";
    }
    my $f = "$r->{writer}-$r->{book}$item_info." . $o->{type};
    $f =~ s{[\[\]/><\\`;'\$^*\(\)\%#@!"&:\?|\s^,~]}{}g;
    return encode( locale => $f );
}

sub process_html_template {
    my ( $self, $book_ref, $dst, $o ) = @_;

    my $toc = $o->{with_toc}
    ? qq{<div id="toc"><ul>
    [% FOREACH r IN item_list %]
    [% IF r.content %] <li>[% r.id %]. <a href="#toc[% r.id %]">[% r.writer %] [% r.title %]</a></li> [% END %] 
    [% END %]
    </ul>
    </div>}
    : '';

    my $txt = <<__HTML__;
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
        <html>

        <head>
        <meta charset="UTF-8">
        <meta property="opf.authors" content="[% writer %]">
        <meta property="opf.titlesort" content="[% book %]">
        <title> [% writer %] 《 [% book %] 》</title>
        <style type="text/css">
body {
    font-size: large;
    margin: 1em 8em 1em 8em;
    text-indent: 2em;
    line-height: 145%;
}
#title, .chapter {
    border-bottom: 0.2em solid #ee9b73;
    margin: 0.8em 0.2em 0.8em 0.2em;
    text-indent: 0em;
    font-size: xx-large;
    font-weight: bold;
    padding-bottom: 0.25em;
}
#title, ol { line-height: 150%; }
#title { text-align: center; }
        </style>
        </head>

        <body>
        <div id="title"><a href="[% writer_url %]">[% writer %]</a> 《 <a href="[% url %]">[% book %]</a> 》</div>
        $toc
<div id="content">
    [% FOREACH r IN item_list %]
    [% IF r.content %]
<div class="item">
<div class="chapter">[% r.id %]. <a name="toc[% r.id %]">[% r.writer %] [% r.title %]</a>  [% r.time %]</div>
<div class="content">[% r.content %]</div>
</div>[% END %]
[% END %]
</div>
</body>
</html>
__HTML__
    my $tt = Template->new();
    $tt->process( \$txt, $book_ref, $dst, { binmode => ':utf8' } ) || die $tt->error(), "\n";
    return $dst;
} ## end sub process_html_template

1;

