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