/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.store.primitives.resources.impl;

import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import io.atomix.resource.ResourceType;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.onlab.util.Tools;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;

import static org.junit.Assert.assertArrayEquals;
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;

/**
 * Unit tests for {@link AtomixConsistentTreeMap}.
 */
public class AtomixConsistentTreeMapTest extends AtomixTestBase {
    private final String keyFour = "hello";
    private final String keyThree = "goodbye";
    private final String keyTwo = "foo";
    private final String keyOne = "bar";
    private final byte[] valueOne = Tools.getBytesUtf8(keyOne);
    private final byte[] valueTwo = Tools.getBytesUtf8(keyTwo);
    private final byte[] valueThree = Tools.getBytesUtf8(keyThree);
    private final byte[] valueFour = Tools.getBytesUtf8(keyFour);
    private final byte[] spareValue = Tools.getBytesUtf8("spareValue");
    private final List<String> allKeys = Lists.newArrayList(keyOne, keyTwo,
                                                            keyThree, keyFour);
    private final List<byte[]> allValues = Lists.newArrayList(valueOne,
                                                              valueTwo,
                                                              valueThree,
                                                              valueFour);
    @BeforeClass
    public static void preTestSetup() throws Throwable {
        createCopycatServers(3);
    }

    @AfterClass
    public static void postTestCleanup() throws Throwable {
        clearTests();
    }

    @Override
    protected ResourceType resourceType() {
        return new ResourceType(AtomixConsistentTreeMap.class);
    }

    /**
     * Tests of the functionality associated with the
     * {@link org.onosproject.store.service.AsyncConsistentMap} interface
     * except transactions and listeners.
     */
    @Test
    public void testBasicMapOperations() throws Throwable {
        //Throughout the test there are isEmpty queries, these are intended to
        //make sure that the previous section has been cleaned up, they serve
        //the secondary purpose of testing isEmpty but that is not their
        //primary purpose.
        AtomixConsistentTreeMap map = createResource("basicTestMap");
        //test size
        map.size().thenAccept(result -> assertEquals(0, (int) result)).join();
        map.isEmpty().thenAccept(result -> assertTrue(result)).join();
        //test contains key
        allKeys.forEach(key -> map.containsKey(key).
                thenAccept(result -> assertFalse(result)).join());
        //test contains value
        allValues.forEach(value -> map.containsValue(value)
                .thenAccept(result -> assertFalse(result)).join());
        //test get
        allKeys.forEach(key -> map.get(key).
                thenAccept(result -> assertNull(result)).join());

        //populate and redo prior three tests
        allKeys.forEach(key -> map.put(key, allValues
                .get(allKeys.indexOf(key))).thenAccept(
                result -> assertNull(result)).join());
        //test contains key
        allKeys.forEach(key -> map.containsKey(key).
                thenAccept(result -> assertTrue(result)).join());
        //test contains value
        allValues.forEach(value -> map.containsValue(value)
                .thenAccept(result -> assertTrue(result)).join());
        //test get
        allKeys.forEach(key -> map.get(key).
                thenAccept(
                        result -> assertArrayEquals(
                                allValues.get(allKeys.indexOf(key)),
                                result.value())).join());
        //test all compute methods in this section
        allKeys.forEach(key -> map.computeIfAbsent(
                key, v -> allValues.get(allKeys.indexOf(key)
                )).thenAccept(result ->
                                assertArrayEquals(
                                        allValues.get(allKeys.indexOf(key)),
                                        result.value())).join());
        map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
        map.isEmpty().thenAccept(result -> assertFalse(result)).join();
        allKeys.forEach(key -> map.computeIfPresent(key, (k, v) -> null).
                thenAccept(result -> assertNull(result)).join());
        map.isEmpty().thenAccept(result -> assertTrue(result)).join();
        allKeys.forEach(key -> map.compute(key, (k, v) ->
                            allValues.get(allKeys.indexOf(key))).
                            thenAccept(result -> assertArrayEquals(
                                    allValues.get(allKeys.indexOf(key)),
                                    result.value())).join());
        map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
        map.isEmpty().thenAccept(result -> assertFalse(result)).join();
        allKeys.forEach(key -> map.computeIf(key,
                                         (k) -> allKeys.indexOf(key) < 2,
                                         (k, v) -> null).thenAccept(result -> {
            if (allKeys.indexOf(key) < 2) {
                assertNull(result);
            } else {
                assertArrayEquals(allValues.get(allKeys.indexOf(key)),
                                  result.value());
            }
        }).join());
        map.size().thenAccept(result -> assertEquals(2, (int) result)).join();
        map.isEmpty().thenAccept(result -> assertFalse(result)).join();
        //test simple put
        allKeys.forEach(
                key -> map.put(key, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> {
                    if (allKeys.indexOf(key) < 2) {
                        assertNull(result);
                    } else {
                        assertArrayEquals(
                                allValues.get(allKeys.indexOf(key)),
                                result.value());
                    }
                }).join());
        map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
        map.isEmpty().thenAccept(result -> assertFalse(result)).join();
        //test put and get for version retrieval
        allKeys.forEach(
                key -> map.putAndGet(key, allValues.get(allKeys.indexOf(key))).
            thenAccept(firstResult -> {
                map.putAndGet(key, allValues.get(allKeys.indexOf(key))).
                    thenAccept(secondResult -> {
                    assertArrayEquals(allValues.get(allKeys.indexOf(key)),
                                      firstResult.value());
                    assertArrayEquals(allValues.get(allKeys.indexOf(key)),
                                      secondResult.value());
                    assertTrue((firstResult.version() + 1) ==
                                       secondResult.version());
                });
            }).join());
        //test removal
        allKeys.forEach(key -> map.remove(key).thenAccept(
                result -> assertArrayEquals(
                        allValues.get(allKeys.indexOf(key)), result.value()))
                .join());
        map.isEmpty().thenAccept(result -> assertTrue(result));
        //repopulating, this is not mainly for testing
        allKeys.forEach(key -> map.put(
                key, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> {
                        assertNull(result);
                }).join());

        //Test various collections of keys, values and entries
        map.keySet().thenAccept(
                keys -> assertTrue(
                        stringArrayCollectionIsEqual(keys, allKeys)))
                .join();
        map.values().thenAccept(
                values -> assertTrue(
                        byteArrayCollectionIsEqual(values.stream().map(
                                v -> v.value()).collect(
                                Collectors.toSet()), allValues)))
                .join();
        map.entrySet().thenAccept(entrySet -> {
            entrySet.forEach(entry -> {
                assertTrue(allKeys.contains(entry.getKey()));
                assertTrue(Arrays.equals(entry.getValue().value(),
                             allValues.get(allKeys.indexOf(entry.getKey()))));
            });
        }).join();
        map.clear().join();
        map.isEmpty().thenAccept(result -> assertTrue(result)).join();

        //test conditional put
        allKeys.forEach(
                key -> map.putIfAbsent(
                        key, allValues.get(allKeys.indexOf(key))).
                        thenAccept(result -> assertNull(result)).join());
        allKeys.forEach(
                key -> map.putIfAbsent(
                        key, null).
                        thenAccept(result ->
                                   assertArrayEquals(result.value(),
                                        allValues.get(allKeys.indexOf(key))))
                        .join());
        // test alternate removes that specify value or version
        allKeys.forEach(
                key -> map.remove(key, spareValue).thenAccept(
                        result -> assertFalse(result)).join());
        allKeys.forEach(
                key -> map.remove(key, allValues.get(allKeys.indexOf(key)))
                        .thenAccept(result -> assertTrue(result)).join());
        map.isEmpty().thenAccept(result -> assertTrue(result)).join();
        List<Long> versions = Lists.newArrayList();

        //repopulating set for version based removal
        allKeys.forEach(
                key -> map.putAndGet(key, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> versions.add(result.version())).join());
        allKeys.forEach(
                key -> map.remove(key, versions.get(0)).thenAccept(
                        result -> {
                            assertTrue(result);
                            versions.remove(0);
                        }).join());
        map.isEmpty().thenAccept(result -> assertTrue(result)).join();
        //Testing all replace both simple (k, v), and complex that consider
        // previous mapping or version.
        allKeys.forEach(
                key -> map.put(key, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> assertNull(result)).join());
        allKeys.forEach(key -> map.replace(
                key, allValues.get(3 - allKeys.indexOf(key)))
                .thenAccept(result -> assertArrayEquals(
                        allValues.get(allKeys.indexOf(key)), result.value()))
                .join());
        allKeys.forEach(key -> map.replace(key,
                                           spareValue,
                                           allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> assertFalse(result))
                .join());
        allKeys.forEach(key -> map.replace(
                key, allValues.get(3 - allKeys.indexOf(key)),
                allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> assertTrue(result)).join());
        map.clear().join();
        map.isEmpty().thenAccept(result -> assertTrue(result)).join();
        versions.clear();
        //populate for version based replacement
        allKeys.forEach(
                key -> map.putAndGet(
                        key, allValues.get(3 - allKeys.indexOf(key)))
                        .thenAccept(result ->
                            versions.add(result.version())).join());
        allKeys.forEach(key -> map.replace(
                key, 0, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> assertFalse(result))
                .join());
        allKeys.forEach(key -> map.replace(
                key, versions.get(0), allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> {
                    assertTrue(result);
                    versions.remove(0);
                }).join());
    }

    @Test
    public void mapListenerTests() throws Throwable {
        final byte[] value1 = Tools.getBytesUtf8("value1");
        final byte[] value2 = Tools.getBytesUtf8("value2");
        final byte[] value3 = Tools.getBytesUtf8("value3");

        AtomixConsistentTreeMap map = createResource("treeMapListenerTestMap");
        TestMapEventListener listener = new TestMapEventListener();

        // add listener; insert new value into map and verify an INSERT event
        // is received.
        map.addListener(listener).thenCompose(v -> map.put("foo", value1))
                .join();
        MapEvent<String, byte[]> event = listener.event();
        assertNotNull(event);
        assertEquals(MapEvent.Type.INSERT, event.type());
        assertTrue(Arrays.equals(value1, event.newValue().value()));

        // remove listener and verify listener is not notified.
        map.removeListener(listener).thenCompose(v -> map.put("foo", value2))
                .join();
        assertFalse(listener.eventReceived());

        // add the listener back and verify UPDATE events are received
        // correctly
        map.addListener(listener).thenCompose(v -> map.put("foo", value3))
                .join();
        event = listener.event();
        assertNotNull(event);
        assertEquals(MapEvent.Type.UPDATE, event.type());
        assertTrue(Arrays.equals(value3, event.newValue().value()));

        // perform a non-state changing operation and verify no events are
        // received.
        map.putIfAbsent("foo", value1).join();
        assertFalse(listener.eventReceived());

        // verify REMOVE events are received correctly.
        map.remove("foo").join();
        event = listener.event();
        assertNotNull(event);
        assertEquals(MapEvent.Type.REMOVE, event.type());
        assertTrue(Arrays.equals(value3, event.oldValue().value()));

        // verify compute methods also generate events.
        map.computeIf("foo", v -> v == null, (k, v) -> value1).join();
        event = listener.event();
        assertNotNull(event);
        assertEquals(MapEvent.Type.INSERT, event.type());
        assertTrue(Arrays.equals(value1, event.newValue().value()));

        map.compute("foo", (k, v) -> value2).join();
        event = listener.event();
        assertNotNull(event);
        assertEquals(MapEvent.Type.UPDATE, event.type());
        assertTrue(Arrays.equals(value2, event.newValue().value()));

        map.computeIf(
                "foo", v -> Arrays.equals(v, value2), (k, v) -> null).join();
        event = listener.event();
        assertNotNull(event);
        assertEquals(MapEvent.Type.REMOVE, event.type());
        assertTrue(Arrays.equals(value2, event.oldValue().value()));

        map.removeListener(listener).join();
    }

    /**
     * Tests functionality specified in the {@link AtomixConsistentTreeMap}
     * interface, beyond the functionality provided in
     * {@link org.onosproject.store.service.AsyncConsistentMap}.
     */
    @Test
    public void treeMapFunctionsTest() {
        AtomixConsistentTreeMap map = createResource("treeMapFunctionTestMap");
        //Tests on empty map
        map.firstKey().thenAccept(result -> assertNull(result)).join();
        map.lastKey().thenAccept(result -> assertNull(result)).join();
        map.ceilingEntry(keyOne).thenAccept(result -> assertNull(result))
                .join();
        map.floorEntry(keyOne).thenAccept(result -> assertNull(result)).join();
        map.higherEntry(keyOne).thenAccept(result -> assertNull(result))
                .join();
        map.lowerEntry(keyOne).thenAccept(result -> assertNull(result)).join();
        map.firstEntry().thenAccept(result -> assertNull(result)).join();
        map.lastEntry().thenAccept(result -> assertNull(result)).join();
        map.pollFirstEntry().thenAccept(result -> assertNull(result)).join();
        map.pollLastEntry().thenAccept(result -> assertNull(result)).join();
        map.lowerKey(keyOne).thenAccept(result -> assertNull(result)).join();
        map.floorKey(keyOne).thenAccept(result -> assertNull(result)).join();
        map.ceilingKey(keyOne).thenAccept(result -> assertNull(result))
                .join();
        map.higherKey(keyOne).thenAccept(result -> assertNull(result)).join();
        map.delete().join();

        allKeys.forEach(key -> map.put(
                key, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> assertNull(result)).join());
        //Note ordering keys are in their proper ordering in ascending order
        //both in naming and in the allKeys list.

        map.firstKey().thenAccept(result -> assertEquals(keyOne, result))
                .join();
        map.lastKey().thenAccept(result -> assertEquals(keyFour, result))
                .join();
        map.ceilingEntry(keyOne)
                .thenAccept(result -> {
                    assertEquals(keyOne, result.getKey());
                    assertArrayEquals(valueOne, result.getValue().value());
                })
                .join();
        //adding an additional letter to make keyOne an unacceptable response
        map.ceilingEntry(keyOne + "a")
                .thenAccept(result -> {
                    assertEquals(keyTwo, result.getKey());
                    assertArrayEquals(valueTwo, result.getValue().value());
                })
                .join();
        map.ceilingEntry(keyFour + "a")
                .thenAccept(result -> {
                    assertNull(result);
                })
                .join();
        map.floorEntry(keyTwo).thenAccept(result -> {
            assertEquals(keyTwo, result.getKey());
            assertArrayEquals(valueTwo, result.getValue().value());
        })
                .join();
        //shorten the key so it itself is not an acceptable reply
        map.floorEntry(keyTwo.substring(0, 2)).thenAccept(result -> {
            assertEquals(keyOne, result.getKey());
            assertArrayEquals(valueOne, result.getValue().value());
        })
                .join();
        // shorten least key so no acceptable response exists
        map.floorEntry(keyOne.substring(0, 1)).thenAccept(
                result -> assertNull(result))
                .join();

        map.higherEntry(keyTwo).thenAccept(result -> {
            assertEquals(keyThree, result.getKey());
            assertArrayEquals(valueThree, result.getValue().value());
        })
                .join();
        map.higherEntry(keyFour).thenAccept(result -> assertNull(result))
                .join();

        map.lowerEntry(keyFour).thenAccept(result -> {
            assertEquals(keyThree, result.getKey());
            assertArrayEquals(valueThree, result.getValue().value());
        })
                .join();
        map.lowerEntry(keyOne).thenAccept(result -> assertNull(result))
                .join();
        map.firstEntry().thenAccept(result -> {
            assertEquals(keyOne, result.getKey());
            assertArrayEquals(valueOne, result.getValue().value());
        })
                .join();
        map.lastEntry().thenAccept(result -> {
            assertEquals(keyFour, result.getKey());
            assertArrayEquals(valueFour, result.getValue().value());
        })
                .join();
        map.pollFirstEntry().thenAccept(result -> {
            assertEquals(keyOne, result.getKey());
            assertArrayEquals(valueOne, result.getValue().value());
        });
        map.containsKey(keyOne).thenAccept(result -> assertFalse(result))
                .join();
        map.size().thenAccept(result -> assertEquals(3, (int) result)).join();
        map.pollLastEntry().thenAccept(result -> {
            assertEquals(keyFour, result.getKey());
            assertArrayEquals(valueFour, result.getValue().value());
        });
        map.containsKey(keyFour).thenAccept(result -> assertFalse(result))
                .join();
        map.size().thenAccept(result -> assertEquals(2, (int) result)).join();

        //repopulate the missing entries
        allKeys.forEach(key -> map.put(
                key, allValues.get(allKeys.indexOf(key)))
                .thenAccept(result -> {
                    if (key.equals(keyOne) || key.equals(keyFour)) {
                        assertNull(result);
                    } else {
                        assertArrayEquals(allValues.get(allKeys.indexOf(key)),
                                          result.value());
                    }
                })
                .join());
        map.lowerKey(keyOne).thenAccept(result -> assertNull(result)).join();
        map.lowerKey(keyThree).thenAccept(
                result -> assertEquals(keyTwo, result))
                .join();
        map.floorKey(keyThree).thenAccept(
                result -> assertEquals(keyThree, result))
                .join();
        //shortening the key so there is no acceptable response
        map.floorKey(keyOne.substring(0, 1)).thenAccept(
                result -> assertNull(result))
                .join();
        map.ceilingKey(keyTwo).thenAccept(
                result -> assertEquals(keyTwo, result))
                .join();
        //adding to highest key so there is no acceptable response
        map.ceilingKey(keyFour + "a")
                .thenAccept(reslt -> assertNull(reslt))
                .join();
        map.higherKey(keyThree).thenAccept(
                result -> assertEquals(keyFour, result))
                .join();
        map.higherKey(keyFour).thenAccept(
                result -> assertNull(result))
                .join();
        map.delete().join();

    }

    private AtomixConsistentTreeMap createResource(String mapName) {
        try {
            AtomixConsistentTreeMap map = createAtomixClient().
                    getResource(mapName, AtomixConsistentTreeMap.class)
                    .join();
            return map;
        } catch (Throwable e) {
            throw new RuntimeException(e.toString());
        }
    }
    private static class TestMapEventListener
            implements MapEventListener<String, byte[]> {

        private final BlockingQueue<MapEvent<String, byte[]>> queue =
                new ArrayBlockingQueue<>(1);

        @Override
        public void event(MapEvent<String, byte[]> event) {
            try {
                queue.put(event);
            } catch (InterruptedException e) {
                Throwables.propagate(e);
            }
        }

        public boolean eventReceived() {
            return !queue.isEmpty();
        }

        public MapEvent<String, byte[]> event() throws InterruptedException {
            return queue.take();
        }
    }

    /**
     * Returns two arrays contain the same set of elements,
     * regardless of order.
     * @param o1 first collection
     * @param o2 second collection
     * @return true if they contain the same elements
     */
    private boolean byteArrayCollectionIsEqual(
            Collection<? extends byte[]> o1, Collection<? extends byte[]> o2) {
        if (o1 == null || o2 == null || o1.size() != o2.size()) {
            return false;
        }
        for (byte[] array1 : o1) {
            boolean matched = false;
            for (byte[] array2 : o2) {
                if (Arrays.equals(array1, array2)) {
                    matched = true;
                    break;
                }
            }
            if (!matched) {
                return false;
            }
        }
        return true;
    }

    /**
     * Compares two collections of strings returns true if they contain the
     * same strings, false otherwise.
     * @param s1 string collection one
     * @param s2 string collection two
     * @return true if the two sets contain the same strings
     */
    private boolean stringArrayCollectionIsEqual(
            Collection<? extends String> s1, Collection<? extends String> s2) {
        if (s1 == null || s2 == null || s1.size() != s2.size()) {
            return false;
        }
        for (String string1 : s1) {
            boolean matched = false;
            for (String string2 : s2) {
                if (string1.equals(string2)) {
                    matched = true;
                    break;
                }
            }
            if (!matched) {
                return false;
            }
        }
        return true;
    }

    /**
     * Inner entry type for testing.
     * @param <K>
     * @param <V>
     */
    private class InnerEntry<K, V> implements Map.Entry<K, V> {
        private K key;
        private V value;
        public InnerEntry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            V temp = this.value;
            this.value = value;
            return temp;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof InnerEntry)) {
                return false;
            }
            InnerEntry other = (InnerEntry) o;
            boolean keysEqual = false;
            boolean valuesEqual = false;
            if (this.key instanceof byte[]) {
                if (other.getKey() instanceof byte[]) {
                    keysEqual =  Arrays.equals((byte[]) this.key,
                                               (byte[]) other.getKey());
                } else {
                    return false;
                }
            } else {
                keysEqual = this.getKey().equals(other.getKey());
            }

            if (keysEqual) {
                if (this.value instanceof byte[]) {
                    if (other.getValue() instanceof byte[]) {
                        return Arrays.equals((byte[]) this.value,
                                             (byte[]) other.getValue());
                    } else {
                        return false;
                    }
                } else {
                    return this.key.equals(other.getKey());
                }
            }
            return false;
        }

        @Override
        public int hashCode() {
            return 0;
        }
    }
}
