// 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);
        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.NotImplemented", 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.NotImplemented", 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);
        }
    }
}
