#!perl
use Cassandane::Tiny;

sub test_cvt_cyrusdb
{
    my ($self) = @_;

    xlog $self, "test cvt_cyrusdb between annotation db and flat files (BZ2686)";

    my $folder = 'INBOX';
    my $fentry = '/private/comment';
    my $mentry = '/comment';
    my $mattrib = 'value.priv';
    my $evilchars = " \t\r\n\0\001";

    my $store = $self->{store};
    $store->set_fetch_attributes('uid', "annotation ($mentry $mattrib)");
    my $talk = $store->get_client();
    my $admintalk = $self->{adminstore}->get_client();

    xlog $self, "store annotations";
    my $data = $self->make_random_data(2, maxreps => 20, separators => $evilchars);
    $talk->setmetadata($folder, $fentry, $data);
    $self->assert_str_equals('ok', $talk->get_last_completion_response());

    xlog $self, "add some messages";
    my $uid = 1;
    my %exp;
    for (1..10)
    {
        my $msg = $self->make_message("Message $_");
        $exp{$uid} = $msg;
        $msg->set_attribute('uid', $uid);
        my $data = $self->make_random_data(7, maxreps => 20, separators => $evilchars);
        $msg->set_annotation($mentry, $mattrib, $data);
        $talk->store('' . $uid, 'annotation',
                    [$mentry, [$mattrib, $data]]);
        $self->assert_str_equals('ok', $talk->get_last_completion_response());
        $uid++;
    }

    xlog $self, "Check the messages are all there";
    $self->check_messages(\%exp);

    xlog $self, "Check the mailbox annotation is still there";
    my $res = $talk->getmetadata($folder, $fentry);
    $self->assert_str_equals('ok', $talk->get_last_completion_response());
    $self->assert_deep_equals({
        $folder => { $fentry => $data }
    }, $res);

    xlog $self, "Shut down the instance";
    $self->{store}->disconnect();
    $self->{adminstore}->disconnect();
    $talk = undef;
    $admintalk = undef;
    $self->{instance}->stop();
    $self->{instance}->{re_use_dir} = 1;

    xlog $self, "Convert the global annotation db to flat";
    my $basedir = $self->{instance}->{basedir};
    my $global_db = "$basedir/conf/annotations.db";
    my $global_flat = "$basedir/xann.txt";
    my $format = $self->{instance}->{config}->get('annotation_db');
    $format = $format // 'twoskip';

    $self->assert_not_file_test($global_flat, '-f');
    $self->{instance}->run_command({ cyrus => 1 },
                                   'cvt_cyrusdb',
                                   $global_db, $format,
                                   $global_flat, 'flat');
    $self->assert_file_test($global_flat, '-f');

    xlog $self, "Convert the mailbox annotation db to flat";
    my $datapath = $self->{instance}->folder_to_directory('user.cassandane');
    my $mailbox_db = "$datapath/cyrus.annotations";
    my $mailbox_flat = "$basedir/xcassann.txt";

    $self->assert_not_file_test($mailbox_flat, '-f');
    $self->{instance}->run_command({ cyrus => 1 },
                                   'cvt_cyrusdb',
                                   $mailbox_db, $format,
                                   $mailbox_flat, 'flat');
    $self->assert_file_test($mailbox_flat, '-f');

    xlog $self, "Move aside the original annotation dbs";
    rename($global_db, "$global_db.NOT")
        or die "Cannot rename $global_db to $global_db.NOT: $!";
    rename($mailbox_db, "$mailbox_db.NOT")
        or die "Cannot rename $mailbox_db to $mailbox_db.NOT: $!";
    $self->assert_not_file_test($global_db, '-f');
    $self->assert_not_file_test($mailbox_db, '-f');

    xlog $self, "restore the global annotation db from flat";
    $self->{instance}->run_command({ cyrus => 1 },
                                   'cvt_cyrusdb',
                                   $global_flat, 'flat',
                                   $global_db, $format);
    $self->assert_file_test($global_db, '-f');

    xlog $self, "restore the mailbox annotation db from flat";
    $self->{instance}->run_command({ cyrus => 1 },
                                   'cvt_cyrusdb',
                                   $mailbox_flat, 'flat',
                                   $mailbox_db, $format);
    $self->assert_file_test($mailbox_db, '-f');

    xlog $self, "Start the instance up again and reconnect";
    $self->{instance}->start();
    $talk = $store->get_client();

    xlog $self, "Check the messages are still all there";
    $self->check_messages(\%exp);

    xlog $self, "Check the mailbox annotation is still there";
    $res = $talk->getmetadata($folder, $fentry);
    $self->assert_str_equals('ok', $talk->get_last_completion_response());
    $self->assert_deep_equals({
        $folder => { $fentry => $data }
    }, $res);
}
