package App::bif::drop::project;
use strict;
use warnings;
use Bif::Mo;
use DBIx::ThinSQL qw/sq/;

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

sub run {
    my $self = shift;
    my $opts = $self->opts;
    my $dbw  = $self->dbw;
    my $info = $self->get_project( $opts->{path} );

    if ( !$opts->{force} ) {
        print "Nothing dropped (missing --force, -f)\n";
        return $self->ok('DropNoForce');
    }

    $dbw->txn(
        sub {
            $opts->{change_id} = $self->new_change;

            if ( $info->{hub_id} ) {
                $self->drop_shallow($info);

                $self->end_change(
                    id            => $opts->{change_id},
                    action_format => "drop project $info->{path} (shallow)",
                    message       => "    [  Dropped Project:        ]\n"
                      . "    [    Path: $info->{path}  ]\n\n"
                      . "(shallow drop - project still exists on hub\n"
                      . " and shared issues will remain)\n",
                );
            }
            else {
                $dbw->xdo(
                    delete_from => 'projects',
                    where       => { id => $info->{id} },
                );

                $self->end_change(
                    id            => $opts->{change_id},
                    action_format => "drop project $info->{path}",
                    message       => "    [  Dropped Project:        ]\n"
                      . "    [    Path: $info->{path}  ]\n",
                );
            }

        }
    );

    return $self->ok('DropProjectShallow') if $info->{hub_id};
    return $self->ok('DropProject');
}

sub drop_shallow {
    my $self = shift;
    my $info = shift;
    my $dbw  = $self->dbw;

    # Drop issues that are not part of any other project
    my $res = $dbw->xdo(
        with => 'x',
        as   => sq(
            select    => [ 'i.id', 'COUNT(i2.id) AS total' ],
            from      => 'issues i',
            left_join => 'issues i2',
            on        => 'i2.src_id = i.id',
            where     => {
                'i.project_id' => $info->{id},
                'i.src_id'     => undef,
            },
            group_by => 'i.id',
            having   => 'total = 0',
        ),
        delete_from => 'issues',
        where       => [
            'id IN ',
            sq(
                select => 'x.id',
                from   => 'x',
            )
        ],
    );

    $res += $dbw->xdo(
        delete_from => 'tasks',
        where       => [
            'task_status_id IN ',
            sq(
                select => 'ts.id',
                from   => 'task_status ts',
                where  => { 'ts.project_id' => $info->{id} },
            )
        ],
    );

    # Delete project topic entities, except those which are
    # our own identities, project entities, or are also
    # other project topic entities.
    $res += $dbw->xdo(
        delete_from => 'entities',
        where       => [
            'id IN ',
            sq(
                select        => 'pte.entity_id',
                from          => 'project_topic_entities pte',
                where         => { 'pte.project_id' => $info->{id} },
                except_select => 'x.entity_id',
                from          => sq(
                    select           => 'bif.identity_id AS entity_id',
                    from             => 'bifkv bif',
                    where            => { 'bif.key' => 'self' },
                    union_all_select => 'pe.entity_id',
                    from             => 'project_entities pe',
                    where            => { 'pe.project_id' => $info->{id} },
                    union_all_select => 'pte.entity_id',
                    from             => 'project_topic_entities pte',
                    where            => { 'pte.project_id !' => $info->{id} },
                )->as('x'),
            ),
        ],
    );

    $res += $dbw->xdo(
        update => 'projects',
        set    => { local => 0 },
        where  => { id => $info->{id} },
    );
    return $res;
}

1;
__END__

=head1 NAME

=for bif-doc #delete

bif-drop-project - remove an project from the repository

=head1 VERSION

0.1.5_3 (2015-06-30)

=head1 SYNOPSIS

    bif drop project PATH [OPTIONS...]

=head1 DESCRIPTION

The bif-drop-project command removes a project from the repository.

=head1 ARGUMENTS

=over

=item PATH

A project path or ID.

=back

=head1 OPTIONS

=over

=item --force, -f

Actually do the drop. This option is required as a safety measure to
stop you shooting yourself in the foot.

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

