#!/usr/bin/perl 

eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell

use strict;
use warnings;
use Carp;
use utf8;
use English;
use Getopt::Long;
use POSIX qw(strftime);

use Basicos::Config;
use Basicos::Prompt;
use Basicos::Templates;

use lib qw(/usr/share/ikiwiki-scripts);
use MyIkiWiki::Tools;
use MyIkiWiki::Pages qw(:all);

our $VERSION = '0.4';

our $_template_base = <<'EOF';
[[meta title="[% title %]"]]
[[meta author="[% author %]"]]
[[tag [% tags %]]]

# [% title %]

EOF

### get values from command-line options, environment and config file ...
our %config = _configure( 
    name        =>  'ikinew',
    file        =>  '.myikiwiki',
    env         =>  'MYIKIWIKI_CONF',
    merge       =>  1,
    variables   =>  {
        page            =>  [ 'page=s',     undef, undef, undef ],
        title           =>  [ 'title=s',    undef, undef, undef ],
        tags            =>  [ 'tags=s',     undef, undef, undef ],
        author          =>  [ 'author=s',   undef, 'author', _build_author_name() ],
        isa_blog        =>  [ 'blog',       undef, undef, 0 ],
        isa_news        =>  [ 'news',       undef, undef, 0 ],
        no_fixme        =>  [ 'no-fixme',   undef, undef, 0 ],
        no_repository   =>  [ 'no-repository', undef, undef, 0 ],
        },
    defaults    =>   {
        template            =>  $_template_base,
        ikiwiki_setup       =>  './ikiwiki.setup',
        editor              =>  q(vim),
        page_extension      =>  q(mdwn),
        fixme_tag           =>  q(fixme),
        blog                =>  {
            default_tag     =>  'blog',
            subpage         =>  'diario', 
        },
        news                =>  {
            default_tag     =>  undef,
            subpage         =>  'news',
        },
        repository          =>  {
            add             =>  q(svn add),
            'mkdir'         =>  q(svn mkdir),
        },
    },
);

# try to build the appropiate page location
if ($config{isa_blog} or $config{isa_news}) {
    ### blog or news mode enabled ...
    $config{page} = _build_page_to_blog( $config{title} );
    $config{tags} = $config{blog}->{default_tag};
    $config{no_fixme} = 1;
    ### page: $config{page}
    ### default tags: $config{tags}
    ### don't add the fixme tag ...
}

do {
    ### prompt for missing values ...
    _prompt_if_missing (
        [ 'Enter the title', \$config{title}, { validate => \&_after_title } ],
        [ 'Enter the new page', \$config{page}, { validate => \&_after_page } ],
        [ 'Enter the author name', \$config{author} ],
        [ 'Enter the tag list (comma separated)', \$config{tags}  ],
    ) or do {
        carp "cancel operation";
        exit (0);
    };        
} while( not $config{page} );

### build the initial content of page ...
my $text_page = _build_page();

### create page file ...
if (_write_page( $config{page}, $text_page)) {
    ### add to repository ...
    _file_to_repo( _page_to_file( $config{page} ) );

    ### tag the page ...
    _update_tags_for_page( $config{page}, _split_tags($config{tags}));

    ### build index pages if we are in blog or news mode
    _build_index_pages( $config{page} ) if $config{isa_blog} or
                                $config{isa_news};
                                
    ### edit the file ...
    _edit_page( $config{page} );
}

sub _after_page {
    my ($field, $value) = @_;

    return defined($value);
}    

sub _after_title {
    my ($field, $value) = @_;

    if ($config{isa_blog} and not $config{page} and $value) {
        $config{page} = _build_page_to_blog( $value );
    }

    return 1;
}

sub _build_page {
    my  $config     = _basicos_config();

    ### cleaning tag list: $config{tags} 
    (my  $tags = $config{tags}) =~ s{,}{ }g;

    ### add the fixme tag
    $tags .= ' ' . $config->{fixme_tag} if not $config{no_fixme};

    return _build_content( $config->{template}, { 
                            title   =>  $config{title},
                            tags    =>  $tags,
                            author  =>  $config{author},
                            } );                                
}

sub _build_timestamp {
    return strftime "%Y/%m/%e", localtime(); 
}

sub _build_author_name {
    my ($name, $gcos) = (getpwuid($UID))[0,6];

    if (defined($gcos)) {
        $gcos =~ s{,}{}g;
    }        

    return $gcos || $name;
}

sub _build_page_to_blog {
    my  $name       =   _name_for_blog_entry(shift);
    my  $page       =   undef;
        
    return undef if not $name;

    if ($config{isa_blog}) {
        $page = _subpage( $name, q(BLOG) );
    }
    elsif ($config{isa_news}) {
        $page = _subpage( $name, q(NEWS) );
    }
    else {
        croak "missing news or blog parameters";
    }
}

__END__
=head1 NAME

ikinew - Build a new entry for ikiwiki

=head1 USAGE

Command line driven:

=head1 OPTIONS

=over

=item --title

Define the title of the new page. It will include in the new page with the
meta plugin and the first level one header.

=item --tags

Define the tags (comma separated) for the new page

=item --page 

Define the page path (relative to the wiki source root)

=item --author

Define the author name for the page. It will include with the meta plugin.

=item --blog

Enable the blog mode for the new entry. This mode build a page name with
the year, month, day of month, hour and minutes in the blog subdirectory.

=item --no-fixme

Don't add the I<fixme> tag to the new page.

=back

=head1 DESCRIPTION

Ikinew helps to build a new ikiwiki page, filling a basic skeleton and adding
tags to the wiki.

The program take these parameters, either by the command line or reading from
the standard input (through L<IO::Prompt> module).

=over

=item * page

This is the path of the new page. Is a ikiwiki page and it's not a file. By
example:

    hardware/printers/hp_laserjet_4
    perl/cpan/io_prompt

=item * title 

This is the title of the page. It will include in the page in two places:

=over

=item Plugin meta 

=item First level one header 

=back

=item * tags

List of comma separated values of tags. The program will build any tag that
not exists previously.

=back

=head2 The configuration file

ikinew can read its configuration from a configuration file. By default this
file is F<.myikiwiki> in the current directory; another location could be
indicated with the environment variable C<MYIKIWIKI_CONF>.

The syntax in this file is described in the L<Config::General> Perl module,
and the default values are the following:

=over 

=item Without section

=over 

=item template

Text in the format of L<Template> Perl module to build the new page.

The default value is:

    [[meta title="[% title %]"]]
    [[meta author="[% author %]"]]
    [[tag [% tags %]]]

    # [% title %]

=item author 

Name and/or email of the page author.

=item ikiwiki_setup

Location of the IkiWiki setup file (default F<./ikiwiki.setup>).

=item editor

Command to execute for edit the new page (default C<vi>).

=item page_extension

Extension for a ikiwiki page (default I<mdwn>).

=item fixme_tag

Default tag to add a new page. Useful for mark a page as "not completed".

=back

=item In the section I<blog>

=over

=item default_tag

Default tag to add a new blog page (default I<blog>).

=item subpage

Location base in the wiki for the blog pages (default I<diario>).

=back

=item In the section I<news>

=over

=item default_tag

Default tag to add a new I<news> page (default none).

=item subpage

Location base in the wiki for the news pages (default I<news>).

=back

=item In the section I<repository>

=over 

=item add

Command to run for add a page to the repository (default C<svn add>).

=item mkdir 

Command to run for build a directory and add to the repository (default C<svn
mkdir>).

=back

=back

=head1 DIAGNOSTICS

A list of every error and warning message that the application can generate
(even the ones that will "never happen"), with a full explanation of each
problem, one or more likely causes, and any suggested remedies. If the
application generates exit status codes (e.g., under Unix), then list the exit
status associated with each error.

=head1 CONFIGURATION AND ENVIRONMENT

The program need read access to the ikiwiki configuration. It search and load
the F<ikiwiki.setup> file in the current directory.

=head1 DEPENDENCIES

=over

=item MyIkiWiki::Pages

=item MyIkiWiki::Tools

=item Getopt::Long

=item POSIX;

=item Basicos::Config

=item Basicos::Prompt

=item Basicos::Templates

=back

=head1 BUGS AND LIMITATIONS

There are no known bugs in this module.

Please report problems to the author.

Patches are welcome.

=head1 AUTHOR

Víctor Moral <victor@taquiones.net>

=head1 LICENCE AND COPYRIGHT

Copyright (c) 2007 "Víctor Moral" <victor@taquiones.net>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

