package net.onrc.onos.core.datastore.hazelcast;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
import net.onrc.onos.core.datastore.ObjectDoesntExistException;
import net.onrc.onos.core.datastore.ObjectExistsException;
import net.onrc.onos.core.datastore.WrongVersionException;
import net.onrc.onos.core.datastore.hazelcast.HZTable.VersionedValue;
import net.onrc.onos.core.datastore.utils.ByteArrayComparator;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

public class HZTableTest {
    @Rule
    public TestName name = new TestName();

    static final String TEST_TABLE_NAME = "TableForUnitTest" + UUID.randomUUID();
    HZTable table;

    @Before
    public void setUp() throws Exception {
        table = (HZTable) HZClient.getClient().getTable(TEST_TABLE_NAME);
    }

    @After
    public void tearDown() throws Exception {
        HZClient.getClient().dropTable(table);
    }

    public void assertEntryInTable(final byte[] key, final byte[] value, final long version) {
        VersionedValue valueblob = table.getBackendMap().get(key);
        assertNotNull(valueblob);
        assertArrayEquals(value, valueblob.getValue());
        assertEquals(version, valueblob.getVersion());
    }

    public void assertKeyNotInTable(final byte[] key) {
        VersionedValue valueblob = table.getBackendMap().get(key);
        assertNull(valueblob);
    }

    @Test
    public void testGetInitialVersion() {
        final long version1 = HZTable.getInitialVersion();
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version1);

        final long version2 = HZTable.getInitialVersion();
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version2);
        assertNotEquals(version1, version2);
    }

    @Test
    public void testGetNextVersion() {
        final long nextVersion = HZTable.getNextVersion(1);
        assertNotEquals(nextVersion, HZClient.VERSION_NONEXISTENT);
        assertNotEquals(nextVersion, 1);

        final long nextVersion1 = HZTable.getNextVersion(Long.MAX_VALUE);
        assertNotEquals(nextVersion1, HZClient.VERSION_NONEXISTENT);
        assertNotEquals(nextVersion1, Long.MAX_VALUE);

        final long nextVersion11 = HZTable.getNextVersion(HZClient.VERSION_NONEXISTENT - 1);
        assertNotEquals(nextVersion11, HZClient.VERSION_NONEXISTENT);
        assertNotEquals(nextVersion11, HZClient.VERSION_NONEXISTENT - 1);
    }

    @Ignore // nothing to test for now
    @Test
    public void testHZTable() {
        fail("Not yet implemented");
    }

    @Test
    public void testGetTableName() {
        assertEquals(TEST_TABLE_NAME, table.getTableName());
    }

    @Test
    public void testVersionNonexistant() {
        assertEquals(HZClient.VERSION_NONEXISTENT, table.getVersionNonexistant());
    }

    @Test
    public void testGetTableId() {
        // for Hazelcast implementation IKVTableID is table itself
        assertEquals(table, table.getTableId());
    }

    @Test
    public void testCreate() throws ObjectExistsException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        final long version = table.create(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);

        assertEntryInTable(key, value, version);
    }

    @Test(expected = ObjectExistsException.class)
    public void testCreateConflict() throws ObjectExistsException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        final long version = table.create(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);

        assertEntryInTable(key, value, version);

        table.create(key, value);
        fail("Should have thrown exception");
    }

    @Test
    public void testForceCreate() {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        final long version = table.forceCreate(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);


        final long version1 = table.forceCreate(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version1);
        assertNotEquals(version, version1);
        assertEntryInTable(key, value, version1);
    }

    @Test
    public void testRead() throws ObjectDoesntExistException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        // put data to read
        final long version = table.forceCreate(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);

        // test body
        final IKVEntry readValue = table.read(key);
        assertArrayEquals(key, readValue.getKey());
        assertArrayEquals(value, readValue.getValue());
        assertEquals(version, readValue.getVersion());
    }


    @Test(expected = ObjectDoesntExistException.class)
    public void testReadNotExist() throws ObjectDoesntExistException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);

        table.read(key);
        fail("Should have thrown exception");
    }

    @Test
    public void testUpdateByteArrayByteArrayLongSuccess() throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        // put data to update
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);

        final long version = table.update(key, value, oldVersion);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);
    }

    @Test(expected = ObjectDoesntExistException.class)
    public void testUpdateByteArrayByteArrayLongFailNoOldValue()
            throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        final long oldVersion = 0xDEAD;

        final long version = table.update(key, value, oldVersion);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);
    }

    @Test(expected = WrongVersionException.class)
    public void testUpdateByteArrayByteArrayLongFailWrongVersion()
            throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        // put data to update
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);
        // some one updates (from different thread/process in reality)
        table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);


        table.update(key, value, oldVersion);
        fail("Should have thrown exception");
    }

    @Test
    public void testUpdateByteArrayByteArraySuccess() throws ObjectDoesntExistException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        // put data to update
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);

        final long version = table.update(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);
    }

    @Test(expected = ObjectDoesntExistException.class)
    public void testUpdateByteArrayByteArrayFailNoOldValue() throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        final long version = table.update(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);
        fail("Should have thrown exception");
    }

    @Test
    public void testUpdateByteArrayByteArraySuccessIgnoreVersion()
            throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);
        final byte[] value = "SomeValue".getBytes(StandardCharsets.UTF_8);

        // put data to update
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);
        // someone updates (from different thread/process in reality)
        table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);


        final long version = table.update(key, value);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
        assertEntryInTable(key, value, version);
    }

    @Test
    public void testDelete() throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);

        // put data to delete
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);

        long version = table.delete(key, oldVersion);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEquals(oldVersion, version);
        assertKeyNotInTable(key);
    }

    @Test(expected = ObjectDoesntExistException.class)
    public void testDeleteFailNoEntry() throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);

        final long oldVersion = 0xDEAD;

        try {
            table.delete(key, oldVersion);
        } catch (ObjectDoesntExistException | WrongVersionException e) {
            assertKeyNotInTable(key);
            throw e;
        }
        fail("Should have thrown exception");
    }

    @Test(expected = WrongVersionException.class)
    public void testDeleteFailWrongVersion() throws ObjectDoesntExistException, WrongVersionException {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);

        // put data to delete
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);
        // someone updates (from different thread/process in reality)
        final long latestVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, latestVersion);

        try {
            table.delete(key, oldVersion);
        } catch (ObjectDoesntExistException | WrongVersionException e) {
            assertEntryInTable(key, oldValue, latestVersion);
            throw e;
        }
        fail("Should have thrown exception");
    }


    @Test
    public void testForceDelete() {
        final byte[] key = name.getMethodName().getBytes(StandardCharsets.UTF_8);
        final byte[] oldValue = "OldValue".getBytes(StandardCharsets.UTF_8);

        // put data to delete
        final long oldVersion = table.forceCreate(key, oldValue);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEntryInTable(key, oldValue, oldVersion);

        long version = table.forceDelete(key);
        assertNotEquals(HZClient.VERSION_NONEXISTENT, oldVersion);
        assertEquals(oldVersion, version);
        assertKeyNotInTable(key);
    }

    @Test
    public void testGetAllEntries() {
        final int dataSetSize = 100;
        final Map<byte[], VersionedValue> testdata = new TreeMap<>(ByteArrayComparator.BYTEARRAY_COMPARATOR);
        for (int i = 0; i < dataSetSize; ++i) {
            final byte[] key = (name.getMethodName() + i).getBytes(StandardCharsets.UTF_8);
            final byte[] value = ("Value" + i).getBytes(StandardCharsets.UTF_8);

            // put data to delete
            final long version = table.forceCreate(key, value);
            assertNotEquals(HZClient.VERSION_NONEXISTENT, version);
            assertEntryInTable(key, value, version);

            testdata.put(key, new VersionedValue(value, version));
        }

        Iterable<IKVEntry> datastore = table.getAllEntries();
        for (IKVEntry entry : datastore) {
            VersionedValue expectedValue = testdata.get(entry.getKey());
            assertNotNull(expectedValue);
            assertArrayEquals(expectedValue.getValue(), entry.getValue());
            assertEquals(expectedValue.getVersion(), entry.getVersion());

            testdata.remove(entry.getKey());
        }

        assertTrue(testdata.isEmpty());
    }

    @Test
    public void testToString() {
        assertEquals("[HZTable " + TEST_TABLE_NAME + "]", table.toString());
    }

}
