package App::bif::new::topic;
use strict;
use warnings;
use Bif::Mo;
use IO::Prompt::Tiny qw/prompt/;

our $VERSION = '0.1.5_7';
extends 'App::bif';

sub run {
    my $self = shift;
    my $opts = $self->opts;
    my $dbw  = $self->dbw;

    $dbw->txn(
        sub {
            $self->pause_work;
            my $start = time;

            $opts->{type} ||= prompt( 'Type:', '' )
              || return $self->err( 'TypeRequired', 'type is required' );

            $opts->{title} ||= prompt( 'Title:', '' )
              || return $self->err( 'TitleRequired', 'title is required' );

            if ( !$opts->{project} ) {

                my @paths = $dbw->xarrayrefs(
                    select     => 'n.path',
                    from       => 'projects p',
                    inner_join => 'nodes n',
                    on         => 'n.id = p.id',
                    order_by =>
                      [ 'n.kind = "project" DESC', 'p.local DESC', 'n.path', ],
                );

                if ( 0 == @paths ) {
                    return $self->err( 'NoProjectInRepo',
                        'topic needs a project' );
                }
                elsif ( 1 == @paths ) {
                    $opts->{project} = $paths[0]->[0];
                }
                else {
                    $opts->{project} = prompt( 'Project:', $paths[0]->[0] )
                      || return $self->err( 'ProjectRequired',
                        'project is required' );
                }
            }

            my $pinfo = $self->get_project( $opts->{project} );

            if ( $opts->{status} ) {
                my ( $status_ids, $invalid ) =
                  $dbw->status_ids( $pinfo->{id}, 'topic', $opts->{status} );

                return $self->err( 'InvalidStatus',
                    'unknown status: ' . join( ', ', @$invalid ) )
                  if @$invalid;

                $opts->{topic_status_id} = $status_ids->[0];
            }
            else {
                $opts->{topic_status_id} = $dbw->xval(
                    select => 'ts.id',
                    from   => 'topic_status ts',
                    where  => {
                        'ts.project_id' => $pinfo->{id},
                        'ts.tkind'      => $opts->{type},
                        def             => 1,
                    },
                );

                return $self->err( 'InvalidTopicType',
                        "unknown topic type: $opts->{type} "
                      . "(for project $pinfo->{project})" )
                  unless $opts->{topic_status_id};
            }

            $opts->{link_topic_id} = $dbw->nextval('nodes');
            $opts->{id}            = $dbw->nextval('nodes');
            $opts->{message} ||= $self->prompt_edit( opts => $self );
            $opts->{change_id} = $self->new_change;

            $dbw->xdo(
                insert_into => 'func_new_link_topic',
                values      => {
                    change_id => $opts->{change_id},
                    id        => $opts->{link_topic_id},
                },
            );

            $dbw->xdo(
                insert_into => 'func_new_topic',
                values      => {
                    change_id       => $opts->{change_id},
                    id              => $opts->{id},
                    link_topic_id   => $opts->{link_topic_id},
                    project_id      => $pinfo->{id},
                    topic_status_id => $opts->{topic_status_id},
                    title           => $opts->{title},
                    tkind           => $opts->{type},
                    bill            => $opts->{bill} // 1,
                },
            );

            $self->save_new_work(
                bill => $opts->{bill} // 1,
                change_id => $opts->{change_id},
                node_id   => $opts->{id},
                start     => $start,
                stop      => time,
            );

            $self->end_change(
                id               => $opts->{change_id},
                action_format    => "new $opts->{type} %s",
                action_node_id_1 => $opts->{id},
                message          => $opts->{message},
            );

            $self->resume_work;
        }
    );

    return $self->ok( 'New' . ucfirst( $opts->{type} ) );
}

1;
__END__

=head1 NAME

=for bif-doc #create

bif-new-topic - add a new topic to a project

=head1 VERSION

0.1.5_7 (2015-11-25)

=head1 SYNOPSIS

    bif new topic [TYPE] [TITLE...] [OPTIONS...]

=head1 DESCRIPTION

Add a new topic to a project.

=head1 ARGUMENTS

=over

=item PROJECT

The path of the project to which this topic applies. Prompted for if
not provided.

=item TITLE

The summary of this topic. Prompted for if not provided.

=item TYPE

The type of topic. Typically this is 'task' or 'issue', or 'bug', etc.
Defaults to 'topic'.

=back

=head1 OPTIONS

=over

=item --status, -s STATE

The initial status of the topic. This must be a valid status for the
project as output by the L<bif-list-status>(1) command. A default is
used if not provided.

=item --message, -m MESSAGE

The body of the topic. An editor will be invoked if not provided.

=back

=head1 SEE ALSO

L<bif>(1)

=head1 AUTHOR

Mark Lawrence E<lt>nomad@null.netE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright 2013-2015 Mark Lawrence <nomad@null.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 3 of the License, or (at your
option) any later version.

