package Bif::DB::Plugin::ChangeIDv1;
use strict;
use warnings;
use Bif::DB::Plugin::ChangeUUIDv1;
use Clone 'clone';
use DBIx::ThinSQL qw/case qv/;

our $VERSION = '0.1.5_7';

my %statements;

while ( my ( $key, $val ) = each %Bif::DB::Plugin::ChangeUUIDv1::statements ) {
    my $new = clone($val);
    $_ =~ s/uuid/id/g for @{ $new->[1] };
    $statements{$key} = $new;
}

my %prepared;

sub Bif::DB::db::changeset_v1 {
    my $self      = shift;
    my $id        = shift;
    my @changeset = ();

    my $begin_change = $prepared{$self}{begin_change} ||= $self->xprepare(
        select => [
            'p.id AS parent_id',
            'c.mtime AS mtime',
            'c.mtimetz AS mtimetz',
            'c.author AS author',
            'c.author_contact AS author_contact',
            'c.author_contact_method AS author_contact_method',
            'c.author_shortname AS author_shortname',
            'c.lang AS lang',
        ],
        from      => 'changes c',
        left_join => 'changes p',
        on        => 'p.id = c.parent_id',
        where     => 'c.id = ?',
    );
    $begin_change->execute($id);
    push( @changeset, $begin_change->hashref );
    $begin_change->finish;

    my $deltas = $prepared{$self}{deltas} ||= $self->xprepare(
        select   => [ 'd.id AS id', 'd.action AS action', ],
        from     => 'deltas d',
        where    => 'd.change_id = ?',
        order_by => 'd.id',
    );
    $deltas->execute($id);

    my $sth;
    foreach my $delta ( $deltas->hashrefs ) {
        $sth = $prepared{$self}{ $delta->{action} } ||=
          $self->xprepare( @{ $statements{ $delta->{action} } } );
        $sth->execute( $delta->{id} );
        if ( my $ref = $sth->hashref ) {
            push( @changeset, $ref );
        }
        else {
            warn "missing delta $delta->{id}: $delta->{action}";
        }
        $sth->finish;
    }

    my $end_change = $prepared{$self}{end_change} ||= $self->xprepare(
        select => [
            'c.action_format AS action_format',
            'n1.id AS action_node_id_1',
            'n2.id AS action_node_id_2',
            'i.id AS identity_id',
            'c.message AS message',
            'c.id AS id',
        ],
        from       => 'changes c',
        inner_join => 'nodes i',
        on         => 'i.id = c.identity_id',
        left_join  => 'nodes n1',
        on         => 'n1.id = c.action_node_id_1',
        left_join  => 'nodes n2',
        on         => 'n2.id = c.action_node_id_2',
        where      => 'c.id = ?',
    );

    $end_change->execute($id);
    push( @changeset, $end_change->hashref );
    $end_change->finish;

    return \@changeset;
}

my %import;

while ( my ( $key, $val ) = each %Bif::DB::Plugin::ChangeUUIDv1::import ) {
    $val =~ s/func_import/func/;
    $import{$key} = $val;
}

sub Bif::DB::db::save_changeset_v1 {
    my $self      = shift;
    my $id        = shift;
    my $changeset = shift;

    my $begin = shift @$changeset;
    my $end   = pop @$changeset;

    $begin->{id} = $id;
    $end->{id}   = $id;

    my @keys = sort keys %$begin;
    my @values = map { qv( $begin->{$_} ) } @keys;

    # Only insert if the id does not exist
    my $have_change = $prepared{$self}{have_change} ||= $self->xprepare(
        select => 'count(id)',
        from   => 'changes c',
        where  => {
            'c.id' => $end->{id},
        },
    );
    $have_change->execute( $end->{id} );
    my $res = $have_change->val;
    $have_change->finish;
    return 0 if $res;

    $self->xdo(
        insert_into => 'func_begin_change',
        values      => $begin,
    );

    foreach my $delta (@$changeset) {
        $delta->{change_id} = $id;
        $self->xdo(
            insert_into => $import{ delete $delta->{_delta} },
            values      => $delta,
        );
    }

    $self->xdo(
        insert_into => 'func_end_change',
        values      => $end,
    );

    return 1;
}

1;

=head1 NAME

=for bif-doc #perl

Bif::DB::Plugin::ChangeIDv1 - read-write helper methods for a bif
database

=head1 VERSION

0.1.5_7 (2015-11-25)

=head1 SYNOPSIS

    use strict;
    use warnings;
    use Bif::DB;
    use Bif::DB::Plugin::ChangeIDv1;

    my $db = Bif::DB->connect(...);

    # Now use dbh/st methods from ChangeIDv1

=head1 DESCRIPTION

B<Bif::DB::Plugin::ChangeIDv1> adds some changeset methods to
L<Bif::DB>.

=head1 DBH METHODS

=over

=item xprepare_changeset_v1() -> $sth

=back

=head1 ST METHODS

=over

=item changeset_v1() -> ArrayRef

=back

=head1 SEE ALSO

L<Bif::DB>

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