// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.syncbase.internal;

import com.google.common.util.concurrent.SettableFuture;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import io.v.syncbase.core.CollectionRowPattern;
import io.v.syncbase.core.Id;
import io.v.syncbase.core.SyncgroupMemberInfo;
import io.v.syncbase.core.SyncgroupSpec;
import io.v.syncbase.core.VError;
import io.v.syncbase.core.VersionedPermissions;
import io.v.syncbase.core.VersionedSyncgroupSpec;
import io.v.syncbase.core.WatchChange;

import static io.v.syncbase.core.TestConstants.anyCollectionPermissions;
import static io.v.syncbase.core.TestConstants.anyDbPermissions;
import static io.v.syncbase.core.TestConstants.anySyncgroupPermissions;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class DatabaseTest {
    @ClassRule
    public static final TemporaryFolder folder = new TemporaryFolder();

    @BeforeClass
    public static void setUp() throws Exception {
        System.loadLibrary("syncbase");
        Service.Init(folder.newFolder().getAbsolutePath(), true, 0);
        Service.Login("", "");
    }

    @AfterClass
    public static void tearDown() throws Exception {
        Service.Shutdown();
    }

    @Test
    public void createDatabase() {
        Id dbId = new Id("idp:a:angrybirds", "create_db");
        String dbName = dbId.encode();

        // The instance is empty so creating of a database should succeed.
        try {
            Database.Create(dbName, anyDbPermissions());
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }

        // Creating the same database should raise an exception.
        boolean exceptionThrown = false;
        try {
            Database.Create(dbName, anyDbPermissions());
        } catch (VError vError) {
            assertEquals("v.io/v23/verror.Exist", vError.id);
            assertNotNull(vError.message);
            assertNotNull(vError.stack);
            assertEquals(0, vError.actionCode);
            exceptionThrown = true;
        }
        assertTrue(exceptionThrown);
    }

    @Test
    public void destroyDatabase() {
        Id dbId = new Id("idp:a:angrybirds", "destroy_db");
        String dbName = dbId.encode();
        try {
            // The instance is empty so creating of a database should succeed.
            Database.Create(dbName, anyDbPermissions());
            Database.Destroy(dbName);
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void existsDatabase() {
        Id dbId = new Id("idp:a:angrybirds", "exists_db");
        String dbName = dbId.encode();
        try {
            // We have not created the database yet so Exists should fail.
            assertFalse(Database.Exists(dbName));
            // The instance is empty so creating of a database should succeed.
            Database.Create(dbName, anyDbPermissions());
            // Exists should succeed now.
            assertTrue(Database.Exists(dbName));
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void permissions() {
        Id dbId = new Id("idp:a:angrybirds", "permissions_db");
        String dbName = dbId.encode();
        try {
            Database.Create(dbName, anyDbPermissions());
            VersionedPermissions versionedPermissions1 = Database.GetPermissions(dbName);
            assertNotNull(versionedPermissions1);
            assertTrue(versionedPermissions1.version.length() > 0);
            String json = new String(versionedPermissions1.permissions.json);
            assertTrue(json.contains("Admin"));

            Database.SetPermissions(dbName, versionedPermissions1);
            VersionedPermissions versionedPermissions2 = Database.GetPermissions(dbName);
            assertNotEquals(versionedPermissions1.version, versionedPermissions2.version);
            assertEquals(json, new String(versionedPermissions2.permissions.json));
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void abortDatabase() {
        Id dbId = new Id("idp:a:angrybirds", "abort_db");
        String dbName = dbId.encode();
        Id collectionId = new Id("...", "collection");
        String collectionName = Util.NamingJoin(Arrays.asList(dbName, collectionId.encode()));
        try {
            Database.Create(dbName, anyDbPermissions());
            String batchHandle = Database.BeginBatch(dbName, null);
            Collection.Create(collectionName, batchHandle, anyCollectionPermissions());
            Database.Abort(dbName, batchHandle);
            batchHandle = Database.BeginBatch(dbName, null);
            // This should work because we Abort the previous batch.
            Collection.Create(collectionName, batchHandle, anyCollectionPermissions());
            Database.Commit(dbName, batchHandle);
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void listCollections() {
        Id dbId = new Id("idp:a:angrybirds", "list_db");
        String dbName = dbId.encode();
        try {
            Database.Create(dbName, anyDbPermissions());
            String batchHandle = Database.BeginBatch(dbName, null);
            assertNotNull(batchHandle);
            List<Id> collections = Database.ListCollections(dbName, batchHandle);
            assertNotNull(collections);
            assertEquals(0, collections.size());
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void getResumeMarker() {
        Id dbId = new Id("idp:a:angrybirds", "get_resume_marker");
        String dbName = dbId.encode();
        try {
            Database.Create(dbName, anyDbPermissions());
            String batchHandle = Database.BeginBatch(dbName, null);
            byte[] marker = Database.GetResumeMarker(dbName, batchHandle);
            assertNotNull(marker);
            assertTrue(marker.length > 0);
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void createSyncgroup() {
        Id dbId = new Id("idp:a:angrybirds", "create_syncgroups");
        String dbName = dbId.encode();
        Id sgId = new Id("...", "syncgroup");
        Id collectionId = new Id("...", "collection");
        String collectionName = Util.NamingJoin(Arrays.asList(dbName, collectionId.encode()));
        try {
            Database.Create(dbName, anyDbPermissions());
            String batchHandle = Database.BeginBatch(dbId.encode(), null);
            Collection.Create(collectionName, batchHandle, anyCollectionPermissions());
            Database.Commit(dbName, batchHandle);
            SyncgroupSpec spec = new SyncgroupSpec();
            spec.collections = singletonList(collectionId);
            spec.permissions = anySyncgroupPermissions();
            SyncgroupMemberInfo info = new SyncgroupMemberInfo();
            // TODO(razvanm): Pick some meaningful values.
            info.syncPriority = 1;
            info.blobDevType = 2;
            Database.CreateSyncgroup(dbName, sgId, spec, info);
            List<Id> syncgroups = Database.ListSyncgroups(dbName);
            assertEquals(1, syncgroups.size());
            Id actual = syncgroups.get(0);
            assertEquals(sgId.blessing, actual.blessing);
            assertEquals(sgId.name, actual.name);

            VersionedSyncgroupSpec verSpec = Database.GetSyncgroupSpec(dbName, sgId);
            assertNotNull(verSpec.version);
            assertTrue(verSpec.version.length() > 0);
            assertNotNull(verSpec.syncgroupSpec);
            assertEquals(1, verSpec.syncgroupSpec.collections.size());
            // The trim is used to remove a new line.
            assertEquals(
                    new String(spec.permissions.json),
                    new String(verSpec.syncgroupSpec.permissions.json).trim());
            actual = syncgroups.get(0);
            assertEquals(sgId.blessing, actual.blessing);
            assertEquals(sgId.name, actual.name);

            verSpec.syncgroupSpec.description = "Dummy description";
            Database.SetSyncgroupSpec(dbName, sgId, verSpec);
            assertEquals(verSpec.syncgroupSpec.description, Database.GetSyncgroupSpec(dbName, sgId).syncgroupSpec.description);

            Map<String, SyncgroupMemberInfo> members = Database.GetSyncgroupMembers(dbName, sgId);
            assertNotNull(members);
            assertEquals(1, members.size());
            assertTrue(members.keySet().iterator().next().length() > 0);
            assertEquals(info.syncPriority, members.values().iterator().next().syncPriority);
            assertEquals(info.blobDevType, members.values().iterator().next().blobDevType);
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void listSyncgroups() {
        Id dbId = new Id("idp:a:angrybirds", "list_syncgroups");
        String dbName = dbId.encode();
        try {
            Database.Create(dbName, anyDbPermissions());
            List<Id> syncgroups = Database.ListSyncgroups(dbName);
            assertNotNull(syncgroups);
            assertEquals(0, syncgroups.size());
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
    }

    @Test
    public void destroySyncgroup() {
        Id dbId = new Id("idp:a:angrybirds", "destroy_syncgroup");
        String dbName = dbId.encode();
        Id sgId = new Id("idp:u:alice", "syncgroup");
        // TODO(razvanm): We'll have to update this after the destroy lands.
        boolean exceptionThrown = false;
        try {
            Database.Create(dbName, anyDbPermissions());
            Database.DestroySyncgroup(dbName, sgId);
        } catch (VError vError) {
            assertEquals("v.io/v23/verror.NoExist", vError.id);
            exceptionThrown = true;
        }
        assertTrue(exceptionThrown);
    }

    @Test
    public void joinSyncgroup() {
        Id dbId = new Id("idp:a:angrybirds", "join_syncgroup");
        String dbName = dbId.encode();
        Id sgId = new Id("idp:u:alice", "syncgroup");
        boolean exceptionThrown = false;
        try {
            Database.JoinSyncgroup(
                    dbName, "", new ArrayList<String>(), sgId, new SyncgroupMemberInfo());
        } catch (VError vError) {
            assertEquals("v.io/v23/verror.NoExist", vError.id);
            assertNotNull(vError.message);
            assertNotNull(vError.stack);
            assertEquals(0, vError.actionCode);
            exceptionThrown = true;
        }
        assertTrue(exceptionThrown);
    }

    @Test
    public void leaveSyncgroup() {
        Id dbId = new Id("idp:a:angrybirds", "leave_syncgroups");
        String dbName = dbId.encode();
        Id sgId = new Id("idp:u:alice", "syncgroup");
        boolean exceptionThrown = false;
        try {
            Database.Create(dbName, anyDbPermissions());
            Database.LeaveSyncgroup(dbName, sgId);
        }  catch (VError vError) {
            assertEquals("v.io/v23/verror.NotImplemented", vError.id);
            exceptionThrown = true;
        }
        assertTrue(exceptionThrown);
    }

    @Test
    public void ejectFromSyncgroup() {
        Id dbId = new Id("idp:a:angrybirds", "eject_from_syncgroup");
        String dbName = dbId.encode();
        Id sgId = new Id("idp:u:alice", "syncgroup");
        boolean exceptionThrown = false;
        try {
            Database.Create(dbName, anyDbPermissions());
            Database.EjectFromSyncgroup(dbName, sgId, "");
        }  catch (VError vError) {
            assertEquals("v.io/v23/verror.NoExist", vError.id);
            exceptionThrown = true;
        }
        assertTrue(exceptionThrown);
    }

    @Test
    public void watchPattersEmptyPattern() {
        Id dbId = new Id("idp:a:angrybirds", "watch_patterns_empty");
        String dbName = dbId.encode();
        final SettableFuture<Void> done = SettableFuture.create();
        try {
            Database.Create(dbName, anyDbPermissions());
            String batchHandle = Database.BeginBatch(dbName, null);
            byte[] marker = Database.GetResumeMarker(dbName, batchHandle);
            List<CollectionRowPattern> patterns = singletonList(new CollectionRowPattern());
            Database.WatchPatterns(dbName, marker, patterns, new Database.WatchPatternsCallbacks() {
                @Override
                public void onChange(WatchChange watchChange) {
                    fail("Unexpected onChange: " + watchChange);
                }

                @Override
                public void onError(VError vError) {
                    assertEquals("v.io/v23/verror.BadArg", vError.id);
                    done.set(null);
                }
            });
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
        try {
            done.get(1, TimeUnit.SECONDS);
        } catch (InterruptedException | TimeoutException | ExecutionException e) {
            fail("Timeout waiting for onError");
        }
    }

    @Test
    public void watchPatterns() {
        Id dbId = new Id("idp:a:angrybirds", "watch_patterns");
        String dbName = dbId.encode();
        Id collectionId = new Id("...", "collection");
        String collectionName = Util.NamingJoin(Arrays.asList(dbName, collectionId.encode()));
        String keyName = Util.NamingJoin(Arrays.asList(collectionName, "key"));
        // Reference: release/go/src/v.io/v23/vom/testdata/data81/vomdata.vdl
        byte[] vomValue = {(byte)0x81, 0x06, 0x03, 'a', 'b', 'c'};
        final SettableFuture<Void> done = SettableFuture.create();
        try {
            Database.Create(dbName, anyDbPermissions());
            String batchHandle = Database.BeginBatch(dbName, null);
            Collection.Create(collectionName, batchHandle, anyCollectionPermissions());
            CollectionRowPattern pattern = new CollectionRowPattern();
            pattern.collectionBlessing = collectionId.blessing;
            pattern.collectionName = collectionId.name;
            List<CollectionRowPattern> patterns = singletonList(pattern);
            Database.WatchPatterns(dbName, new byte[]{}, patterns,
                    new Database.WatchPatternsCallbacks() {
                @Override
                public void onChange(WatchChange watchChange) {
                    done.set(null);
                }

                @Override
                public void onError(VError vError) {
                    assertEquals("v.io/v23/verror.Unknown", vError.id);
                    assertEquals("context canceled", vError.message);
                    assertEquals(0, vError.actionCode);                }
            });
            Database.Commit(dbName, batchHandle);

            batchHandle = Database.BeginBatch(dbName, null);
            Row.Put(keyName, batchHandle, vomValue);
            Database.Commit(dbName, batchHandle);
        } catch (VError vError) {
            vError.printStackTrace();
            fail(vError.toString());
        }
        try {
            done.get(1, TimeUnit.SECONDS);
        } catch (InterruptedException|ExecutionException|TimeoutException e) {
            fail("Timeout waiting for onChange: " + e);
        }
    }
}
