// 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;

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

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import io.v.syncbase.core.Permissions;
import io.v.syncbase.core.VError;
import io.v.syncbase.exception.SyncbaseException;

import static com.google.common.truth.Truth.assertThat;
import static io.v.syncbase.TestUtil.createDatabase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class SyncbaseTest {
    @Rule
    public final TemporaryFolder folder = new TemporaryFolder();
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    // To run these tests from Android Studio, add the following VM option to the default JUnit
    // build configuration, via Run > Edit Configurations... > Defaults > JUnit > VM options:
    // -Djava.library.path=/Users/sadovsky/vanadium/release/java/syncbase/build/libs
    @Before
    public void setUp() throws Exception {
        TestUtil.setUpSyncbase(folder.newFolder());
    }

    @After
    public void tearDown() {
        Syncbase.shutdown();
    }

    private static Iterable<Id> getCollectionIds(Database db) throws SyncbaseException {
        List<Id> res = new ArrayList<>();
        for (Iterator<Collection> it = db.getCollections(); it.hasNext(); ) {
            res.add(it.next().getId());
        }
        return res;
    }

    private static boolean idsMatch(Iterable<Id> ids, String blessing, List<String> prefixes) {
        int i = 0;
        for (Id id : ids) {
            if (!idMatch(id, blessing, prefixes.get(i))) {
                return false;
            }
            i++;
        }
        return prefixes.size() == i; // Every id matches, and all prefixes were used.
    }

    private static boolean idMatch(Id id, String blessing, String prefix) {
        return id.getName().startsWith(prefix) && id.getBlessing().equals(blessing);
    }

    private static Iterable<Id> getSyncgroupIds(Database db) throws SyncbaseException {
        List<Id> res = new ArrayList<>();
        for (Iterator<Syncgroup> it = db.getSyncgroups(); it.hasNext(); ) {
            res.add(it.next().getId());
        }
        return res;
    }

    @Test
    public void testCreateDatabase() throws Exception {
        createDatabase();
    }

    @Test
    public void testCreateAndGetCollections() throws Exception {
        Database db = createDatabase();
        assertNotNull(db);
        DatabaseHandle.CollectionOptions opts = new DatabaseHandle.CollectionOptions().
                setWithoutSyncgroup(true).setPrefix("a");

        Collection cxA = db.createCollection(opts);
        assertNotNull(cxA);
        assertTrue(idsMatch(getCollectionIds(db), Syncbase.getPersonalBlessingString(),
                ImmutableList.of("a", Syncbase.USERDATA_NAME)));

        db.createCollection(opts.setPrefix("b"));
        assertTrue(idsMatch(getCollectionIds(db), Syncbase.getPersonalBlessingString(),
                ImmutableList.of("a", "b", Syncbase.USERDATA_NAME)));

        // Note, createDatabase() sets disableSyncgroupPublishing to true, so
        // db.createCollection(opts) is still a purely local operation.
        opts = new DatabaseHandle.CollectionOptions();
        db.createCollection(opts.setPrefix("c"));
        assertTrue(idsMatch(getCollectionIds(db), Syncbase.getPersonalBlessingString(),
                ImmutableList.of("a", "b", "c", Syncbase.USERDATA_NAME)));

        Collection secondCxA = db.createCollection(opts.setPrefix("a"));
        assertFalse(cxA.getId().equals(secondCxA.getId()));
        assertTrue(idsMatch(getCollectionIds(db), Syncbase.getPersonalBlessingString(),
                ImmutableList.of("a", "a", "b", "c", Syncbase.USERDATA_NAME)));
    }

    @Test
    public void testRowCrudMethods() throws Exception {
        Database db = createDatabase();
        Collection cx = db.createCollection();
        assertNotNull(cx);
        assertFalse(cx.exists("foo"));
        assertEquals(cx.get("foo", String.class), null);
        cx.put("foo", "bar");
        assertTrue(cx.exists("foo"));
        assertEquals(cx.get("foo", String.class), "bar");
        cx.put("foo", "baz");
        assertTrue(cx.exists("foo"));
        assertEquals(cx.get("foo", String.class), "baz");
        cx.delete("foo");
        assertFalse(cx.exists("foo"));
        assertEquals(cx.get("foo", String.class), null);
        cx.put("foo", 5);
        assertEquals(cx.get("foo", Integer.class), Integer.valueOf(5));

        // TODO(razvanm): Figure out a way to get the POJOs to work.
//        // This time, with a POJO.
//        class MyObject {
//            String str;
//            int num;
//        }
//        MyObject putObj = new MyObject();
//        putObj.str = "hello";
//        putObj.num = 7;
//        cx.put("foo", putObj);
//        MyObject getObj = cx.get("foo", MyObject.class);
//        assertEquals(putObj.str, getObj.str);
//        assertEquals(putObj.num, getObj.num);
    }

    @Test
    public void testCreateAndGetSyncgroups() throws Exception {
        Database db = createDatabase();
        DatabaseHandle.CollectionOptions opts = new DatabaseHandle.CollectionOptions();
        opts.withoutSyncgroup = true;
        Collection cxA = db.createCollection(opts.setPrefix("a"));
        Collection cxB = db.createCollection(opts.setPrefix("b"));
        Collection cxC = db.createCollection(opts.setWithoutSyncgroup(false).setPrefix("c"));
        assertNotNull(cxA);
        // Note, there's no userdata syncgroup since we set disableUserdataSyncgroup to true.
        assertTrue(idsMatch(getSyncgroupIds(db), Syncbase.getPersonalBlessingString(),
                ImmutableList.of("c")));
        db.syncgroup("sg1", ImmutableList.of(cxA));
        db.syncgroup("sg2", ImmutableList.of(cxA, cxB, cxC));
        assertThat(getSyncgroupIds(db)).containsExactly(
                new Id(Syncbase.getPersonalBlessingString(), cxC.getSyncgroup().getId().getName()),
                new Id(Syncbase.getPersonalBlessingString(), "sg1"),
                new Id(Syncbase.getPersonalBlessingString(), "sg2"));
    }

    @Test
    public void testWatch() throws Exception {
        Database db = createDatabase();
        final SettableFuture<Void> waitOnInitialState = SettableFuture.create();
        final SettableFuture<Void> waitOnChangeBatch = SettableFuture.create();
        Collection collection = db.createCollection();
        collection.put("foo", 1);
        final String collectionName = collection.getId().getName();
        db.addWatchChangeHandler(new Database.WatchChangeHandler() {
            @Override
            public void onInitialState(Iterator<WatchChange> values) {
                // TODO(razvanm): Check the entire contents of each change.
                // 1st change: the collection entity for the "c" collection.
                assertTrue(values.hasNext());
                WatchChange watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.COLLECTION, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                // 2nd change: the row for the "foo" key.
                assertTrue(values.hasNext());
                watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.ROW, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                assertEquals("foo", watchChange.getRowKey());
                // TODO(razvanm): Uncomment after the POJO start working.
                //assertEquals(1, watchChange.getValue());
                // 3rd change: the collection entity for the userdata collection.
                assertTrue(values.hasNext());
                watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.COLLECTION, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(Syncbase.USERDATA_NAME));
                // No more changes.
                assertFalse(values.hasNext());
                waitOnInitialState.set(null);
            }

            @Override
            public void onChangeBatch(Iterator<WatchChange> changes) {
                assertTrue(changes.hasNext());
                WatchChange watchChange = changes.next();
                assertEquals(WatchChange.ChangeType.DELETE, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().startsWith("c"));
                assertEquals("foo", watchChange.getRowKey());

                assertFalse(changes.hasNext());
                waitOnChangeBatch.set(null);
            }

            @Override
            public void onError(Throwable e) {
                VError vError = (VError) e;
                assertEquals("v.io/v23/verror.Unknown", vError.id);
                assertEquals("context canceled", vError.message);
                assertEquals(0, vError.actionCode);
            }
        });
        waitOnInitialState.get(1, TimeUnit.SECONDS);
        collection.delete("foo");
        waitOnChangeBatch.get(1, TimeUnit.SECONDS);
    }

    @Test
    public void testWatchSpecificCollection() throws Exception {
        Database db = createDatabase();
        final SettableFuture<Void> waitOnInitialState = SettableFuture.create();
        final SettableFuture<Void> waitOnChangeBatch = SettableFuture.create();
        Collection collection = db.createCollection();
        collection.put("foo", 1);
        // Note: For ease of test writing, "gar" is a key lexicographically after "foo".
        collection.put("gar", 2);
        final String collectionName = collection.getId().getName();
        Database.AddWatchChangeHandlerOptions opts = new Database.AddWatchChangeHandlerOptions.
                Builder().setCollectionId(collection.getId()).build();
        db.addWatchChangeHandler(new Database.WatchChangeHandler() {
            @Override
            public void onInitialState(Iterator<WatchChange> values) {
                // TODO(razvanm): Check the entire contents of each change.
                // 1st change: the collection entity for the "c" collection.
                assertTrue(values.hasNext());
                WatchChange watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.COLLECTION, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                // 2nd change: the row for the "foo" key.
                assertTrue(values.hasNext());
                watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.ROW, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                assertEquals("foo", watchChange.getRowKey());
                // TODO(razvanm): Uncomment after the POJO start working.
                //assertEquals(1, watchChange.getValue());
                // 3rd change: the row for the "gar" key.
                assertTrue(values.hasNext());
                watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.ROW, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                assertEquals("gar", watchChange.getRowKey());
                // TODO(razvanm): Uncomment after the POJO start working.
                //assertEquals(2, watchChange.getValue());

                // No more changes.
                assertFalse(values.hasNext());
                waitOnInitialState.set(null);
            }

            @Override
            public void onChangeBatch(Iterator<WatchChange> changes) {
                assertTrue(changes.hasNext());
                WatchChange watchChange = changes.next();
                assertEquals(WatchChange.ChangeType.DELETE, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().startsWith("c"));
                assertEquals("foo", watchChange.getRowKey());

                assertFalse(changes.hasNext());
                waitOnChangeBatch.set(null);
            }

            @Override
            public void onError(Throwable e) {
                VError vError = (VError) e;
                assertEquals("v.io/v23/verror.Unknown", vError.id);
                assertEquals("context canceled", vError.message);
                assertEquals(0, vError.actionCode);
            }
        }, opts);
        waitOnInitialState.get(1, TimeUnit.SECONDS);
        collection.delete("foo");
        waitOnChangeBatch.get(1, TimeUnit.SECONDS);
    }


    @Test
    public void testWatchSpecificCollectionWithRowPrefix() throws Exception {
        Database db = createDatabase();
        final SettableFuture<Void> waitOnInitialState = SettableFuture.create();
        final SettableFuture<Void> waitOnChangeBatch = SettableFuture.create();
        Collection collection = db.createCollection();
        collection.put("foo", 1);
        collection.put("bar", 1); // not seen, due to filter
        final String collectionName = collection.getId().getName();
        Database.AddWatchChangeHandlerOptions opts = new Database.AddWatchChangeHandlerOptions.
                Builder().setCollectionId(collection.getId()).setRowKeyPrefix("f").build();
        db.addWatchChangeHandler(new Database.WatchChangeHandler() {
            @Override
            public void onInitialState(Iterator<WatchChange> values) {
                // TODO(razvanm): Check the entire contents of each change.
                // 1st change: the collection entity for the "c" collection.
                assertTrue(values.hasNext());
                WatchChange watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.COLLECTION, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                // 2nd change: the row for the "foo" key.
                assertTrue(values.hasNext());
                watchChange = (WatchChange) values.next();
                assertEquals(WatchChange.EntityType.ROW, watchChange.getEntityType());
                assertEquals(WatchChange.ChangeType.PUT, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().equals(collectionName));
                assertEquals("foo", watchChange.getRowKey());
                // TODO(razvanm): Uncomment after the POJO start working.
                //assertEquals(1, watchChange.getValue());

                // No more changes.
                assertFalse(values.hasNext());
                waitOnInitialState.set(null);
            }

            @Override
            public void onChangeBatch(Iterator<WatchChange> changes) {
                assertTrue(changes.hasNext());
                WatchChange watchChange = changes.next();
                assertEquals(WatchChange.ChangeType.DELETE, watchChange.getChangeType());
                assertTrue(watchChange.getCollectionId().getName().startsWith("c"));
                assertEquals("foo", watchChange.getRowKey());

                assertFalse(changes.hasNext());
                waitOnChangeBatch.set(null);
            }

            @Override
            public void onError(Throwable e) {
                VError vError = (VError) e;
                assertEquals("v.io/v23/verror.Unknown", vError.id);
                assertEquals("context canceled", vError.message);
                assertEquals(0, vError.actionCode);
            }
        }, opts);
        waitOnInitialState.get(1, TimeUnit.SECONDS);
        collection.delete("foo");
        collection.delete("bar"); // not noticed due to filter.
        waitOnChangeBatch.get(1, TimeUnit.SECONDS);
    }

    @Test
    public void testRunInBatch() throws Exception {
        Database db = createDatabase();

        // We need a box class to store the id of the created collection since we want to refer to
        // it after the batch is over.
        class TestOperation implements Database.BatchOperation {
            private Id id;

            @Override
            public void run(BatchDatabase db) {
                try {
                    DatabaseHandle.CollectionOptions opts = new DatabaseHandle.CollectionOptions()
                            .setWithoutSyncgroup(true);
                    Collection c = db.createCollection(opts);
                    c.put("foo", 10);
                    id = c.getId();
                } catch (SyncbaseException e) {
                    e.printStackTrace();
                    fail(e.toString());
                }
            }
        }

        TestOperation op = new TestOperation();
        db.runInBatch(op);
        assertEquals(db.getCollection(op.id).get("foo", Integer.class), Integer.valueOf(10));
    }

    @Test
    public void testSyncgroupInviteUsers() throws Exception {
        Database db = createDatabase();
        Collection collection = db.createCollection();
        Syncgroup sg = collection.getSyncgroup();

        User alice = new User("alice");
        User bob = new User("bob");
        User carol = new User("carol");

        // First let us confirm that alice, bob, and carol have no access at all.
        AccessList acl0 = sg.getAccessList();
        assertNull(acl0.getAccessLevelForUser(alice));
        assertNull(acl0.getAccessLevelForUser(bob));
        assertNull(acl0.getAccessLevelForUser(carol));

        // Alice can read now.
        sg.inviteUser(new User("alice"), AccessList.AccessLevel.READ);
        AccessList acl1 = sg.getAccessList();
        assertEquals(acl1.getAccessLevelForUser(alice), AccessList.AccessLevel.READ);
        assertNull(acl1.getAccessLevelForUser(bob));
        assertNull(acl1.getAccessLevelForUser(carol));

        // Bob can both read and write now.
        sg.inviteUser(new User("bob"), AccessList.AccessLevel.READ_WRITE);
        AccessList acl2 = sg.getAccessList();
        assertEquals(acl2.getAccessLevelForUser(alice), AccessList.AccessLevel.READ);
        assertEquals(acl2.getAccessLevelForUser(bob), AccessList.AccessLevel.READ_WRITE);
        assertNull(acl2.getAccessLevelForUser(carol));

        // Alice and Carol get full access now. (Tests overwrite and multiple invites.)
        sg.inviteUsers(ImmutableList.of(new User("alice"), new User("carol")),
                AccessList.AccessLevel.READ_WRITE_ADMIN);
        AccessList acl3 = sg.getAccessList();
        assertEquals(acl3.getAccessLevelForUser(alice), AccessList.AccessLevel.READ_WRITE_ADMIN);
        assertEquals(acl3.getAccessLevelForUser(bob), AccessList.AccessLevel.READ_WRITE);
        assertEquals(acl3.getAccessLevelForUser(carol), AccessList.AccessLevel.READ_WRITE_ADMIN);
    }

    @Test
    public void testAccessListParsing() throws Exception {
        // TODO(alexfandrianto): Test the test constants. They have "...", so we can't do it yet.

        // Let's give some arbitrary permissions to alice and bob.
        Permissions aliceBobAdmins = new Permissions(("{\"Admin\":{\"In\":[\"dev.v" +
                ".io:o:app:alice\",\"dev.v.io:o:app:bob\"]},\"Write\":{\"In\":[\"dev.v" +
                ".io:o:app:alice\",\"dev.v.io:o:app:bob\"]},\"Read\":{\"In\":[\"dev.v" +
                ".io:o:app:alice\",\"dev.v.io:o:app:bob\"]}}").getBytes());
        new AccessList(aliceBobAdmins);

        // NOT OK: Admin + !writer
        try {
            Permissions aliceBobAdminsButAliceNotWriter = new Permissions(
                    ("{\"Admin\":{\"In\":[\"dev.v.io:o:app:alice\",\"dev.v.io:o:app:bob\"]}," +
                            "\"Write\":{\"In\":[\"dev.v.io:o:app:bob\"]},\"Read\":{\"In\":[\"dev" +
                            ".v.io:o:app:alice\",\"dev.v.io:o:app:bob\"]}}")
                            .getBytes());
            new AccessList(aliceBobAdminsButAliceNotWriter);
            fail("Should have errored because Alice is an admin but not a writer.");
        } catch (IllegalArgumentException e) {
            // This is supposed to fail.
        }

        // NOT OK: Admin + Writer + !Reader
        try {
            Permissions aliceBobWritersButAliceNotReader = new Permissions(
                    ("{\"Admin\":{\"In\":[\"dev.v.io:o:app:bob\"]}," +
                            "\"Write\":{\"In\":[\"dev.v.io:o:app:alice\",\"dev.v" +
                            ".io:o:app:bob\"]}," +
                            "\"Read\":{\"In\":[\"dev.v.io:o:app:bob\"]}}").getBytes());
            new AccessList(aliceBobWritersButAliceNotReader);
            fail("Should have errored because Alice is a writer but not a reader.");
        } catch (IllegalArgumentException e) {
            // This is supposed to fail.
        }
    }

    @Test
    public void unsupportedAuthenticationProvider() {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Unsupported provider: bogusProvider");

        Syncbase.login("", "bogusProvider", new Syncbase.LoginCallback() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onError(Throwable e) {
            }
        });
    }
}
