package App::bif::push::topic;
use strict;
use warnings;
use feature 'state';
use Bif::Mo;
use DBIx::ThinSQL qw/concat qv/;

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

sub run {
    my $self = shift;
    my $opts = $self->opts;
    my $info = $self->get_node( $opts->{id}, 'topic' );
    my $dbw  = $self->dbw;

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

            my $src = $dbw->xval(
                select => 'n.path',
                from   => 'nodes n',
                where  => { 'n.id' => $info->{id}, },
            );

            foreach my $path ( @{ $opts->{path} } ) {

                my $pinfo = $self->get_project($path);

                my $dest = $dbw->xval(
                    select     => 'n.path',
                    from       => 'topics t',
                    inner_join => 'topics t2',
                    on         => {
                        't2.link_topic_id' => \'t.link_topic_id',
                        't2.project_id'    => $pinfo->{id},
                    },
                    inner_join => 'nodes n',
                    on         => 'n.id = t2.id',

                #                    inner_join => 'topic_status ts',
                #                    on         => 'ts.id = t2.topic_status_id',
                    where => { 't.id' => $info->{id} },
                );

                if ($dest) {
                    if ( $opts->{err_on_exists} ) {
                        return $self->err( 'DestinationExists',
                            "$src already linked with $dest\n" );
                    }
                    else {
                        print "$src already linked with $dest\n";
                        next;
                    }
                }

=cut

# Not yet sure what I should be doing here. Will comment it out until
# after the next topic reorganisation

                my @unsatisfied = map { $_->[0] } $dbw->xarrayrefs(
                    select        => 'p.path',
                    from          => 'project_topics pi',
                    inner_join    => 'projects p',
                    on            => 'p.id = pi.project_id',
                    inner_join    => 'hubs h',
                    on            => 'h.id = p.hub_id',
                    where         => { 'pi.topic_id' => $info->{id} },
                    except_select => 'p2.path',
                    from          => 'projects p',
                    inner_join    => 'hub_related_projects hrp',
                    on            => 'hrp.hub_id = p.hub_id',
                    inner_join    => 'projects p2',
                    on            => 'p2.id = hrp.project_id',
                    inner_join    => 'hubs h',
                    on            => 'h.id = p2.hub_id',
                    where         => { 'p.id' => $pinfo->{id} },
                );

                if (@unsatisfied) {
                    my $name = $dbw->xval(
                        select     => ['n.name'],
                        from       => 'nodes n',
                        inner_join => 'hubs h',
                        on         => 'h.id = p.hub_id',
                        where      => { 'n.id' => $pinfo->{id} },
                    );

                    @unsatisfied = join ', ', @unsatisfied;

                    return $self->err( 'NoCooperation',
                        "$path\@$name has no cooperation with @unsatisfied" );
                }
=cut

                $opts->{message} ||= $self->prompt_edit;

                $opts->{change_id} =
                  $self->new_change( parent_id => $info->{first_change_id}, );

                $opts->{message} //= 'junk';

                $opts->{topic_status_id} = $dbw->xval(
                    select => 'id',
                    from   => 'topic_status',
                    where  => {
                        project_id => $pinfo->{id},
                        tkind      => $info->{tkind},
                        def        => 1,
                    },
                );

                $opts->{id} = $dbw->nextval('nodes');

                $dbw->xdo(
                    insert_into => [
                        'func_new_topic', qw/
                          change_id
                          id
                          link_topic_id
                          project_id
                          topic_status_id
                          title
                          tkind
                          bill
                          /
                    ],
                    select => [
                        qv( $opts->{change_id} ),       qv( $opts->{id} ),
                        't.link_topic_id',              qv( $pinfo->{id} ),
                        qv( $opts->{topic_status_id} ), 't.title',
                        't.tkind',                      'n.bill',
                    ],
                    from       => 'topics t',
                    inner_join => 'nodes n',
                    on         => 'n.id = t.id',
                    where      => { 't.id' => $info->{id} },
                );

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

                $dest = $dbw->xval(
                    select => 'n.path',
                    from   => 'nodes n',
                    where  => { 'n.id' => $opts->{id}, },
                );

                $self->end_change(
                    id               => $opts->{change_id},
                    action_format    => "push $info->{tkind} %s %s",
                    action_node_id_1 => $info->{id},
                    action_node_id_2 => $opts->{id},
                    message          => "[ forked: $src -> $dest ]\n\n"
                      . $opts->{message},
                );
            }

            $self->resume_work;
        }
    );

    return $self->ok( 'Push' . ucfirst( $info->{tkind} ) );
}

1;
__END__

=head1 NAME

=for bif-doc #sync

bif-push-topic - push an topic to another project

=head1 VERSION

0.1.5_7 (2015-11-25)

=head1 SYNOPSIS

    bif push topic ID PATH [OPTIONS...]

=head1 DESCRIPTION

The B<bif-push-topic> command is used to modify the relationship
between a node and a previously unrelated project. The type of the
node being pushed determines the type of relationship changes that are
possible.

Pushing an topic for example "shares" that node with another project.
Comments made in any project for that topic will appear everywhere
else, but status changes are project-specific.  In order for that to be
possible however, the destination project must already be cooperating
with all of the projects already associated with the topic.

=head1 ARGUMENTS & OPTIONS

=over

=item ID

An topic ID. Required.

=item PATH

The destination project PATH. Required.

=item --error-on-exists

Raise an error in the event the topic already exists at the destination
project.

=item --message, -m MESSAGE

The push message if desired.

=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.

