/*
 * Copyright 2016 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.collect.Lists;
import com.google.common.collect.Multiset;
import com.google.common.collect.TreeMultiset;
import com.google.common.io.Files;
import io.atomix.catalyst.transport.Address;
import io.atomix.catalyst.transport.LocalTransport;
import io.atomix.copycat.server.CopycatServer;
import io.atomix.copycat.server.storage.Storage;
import io.atomix.copycat.server.storage.StorageLevel;
import io.atomix.manager.state.ResourceManagerState;
import io.atomix.resource.ResourceType;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.util.Tools;

import java.io.File;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 * Tests the {@link AsyncConsistentSetMultimap}.
 */
public class AsyncConsistentSetMultimapTest extends AtomixTestBase {
    private final File testDir = Files.createTempDir();
    private final String keyOne = "hello";
    private final String keyTwo = "goodbye";
    private final String keyThree = "foo";
    private final String keyFour = "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 List<String> allKeys = Lists.newArrayList(keyOne, keyTwo,
                                                            keyThree, keyFour);
    private final List<byte[]> allValues = Lists.newArrayList(valueOne,
                                                              valueTwo,
                                                              valueThree,
                                                              valueFour);

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

    /**
     * Test that size behaves correctly (This includes testing of the empty
     * check).
     */
    @Ignore
    @Test
    public void testSize() throws Throwable {
        clearTests();
        AsyncConsistentSetMultimap map = createResource(3);
        //Simplest operation case
        map.isEmpty().thenAccept(result -> assertTrue(result));
        map.put(keyOne, valueOne).
                thenAccept(result -> assertTrue(result)).join();
        map.isEmpty().thenAccept(result -> assertFalse(result));
        map.size().thenAccept(result -> assertEquals(1, (int) result))
                .join();
        //Make sure sizing is dependent on values not keys
        map.put(keyOne, valueTwo).
                thenAccept(result -> assertTrue(result)).join();
        map.size().thenAccept(result -> assertEquals(2, (int) result))
                .join();
        //Ensure that double adding has no effect
        map.put(keyOne, valueOne).
                thenAccept(result -> assertFalse(result)).join();
        map.size().thenAccept(result -> assertEquals(2, (int) result))
                .join();
        //Check handling for multiple keys
        map.put(keyTwo, valueOne)
                .thenAccept(result -> assertTrue(result)).join();
        map.put(keyTwo, valueTwo)
                .thenAccept(result -> assertTrue(result)).join();
        map.size().thenAccept(result -> assertEquals(4, (int) result))
                .join();
        //Check size with removal
        map.remove(keyOne, valueOne).
                thenAccept(result -> assertTrue(result)).join();
        map.size().thenAccept(result -> assertEquals(3, (int) result))
                .join();
        //Check behavior under remove of non-existant key
        map.remove(keyOne, valueOne).
                thenAccept(result -> assertFalse(result)).join();
        map.size().thenAccept(result -> assertEquals(3, (int) result))
                .join();
        //Check clearing the entirety of the map
        map.clear().join();
        map.size().thenAccept(result -> assertEquals(0, (int) result))
                .join();
        map.isEmpty().thenAccept(result -> assertTrue(result));

        map.destroy().join();
        clearTests();
    }

    /**
     * Contains tests for value, key and entry.
     */
    @Ignore
    @Test
    public void containsTest() throws Throwable {
        clearTests();
        AsyncConsistentSetMultimap map = createResource(3);

        //Populate the maps
        allKeys.forEach(key -> {
            map.putAll(key, allValues)
                    .thenAccept(result -> assertTrue(result)).join();
        });
        map.size().thenAccept(result -> assertEquals(16, (int) result)).join();

        //Test key contains positive results
        allKeys.forEach(key -> {
            map.containsKey(key)
                    .thenAccept(result -> assertTrue(result)).join();
        });

        //Test value contains positive results
        allValues.forEach(value -> {
            map.containsValue(value)
                    .thenAccept(result -> assertTrue(result)).join();
        });

        //Test contains entry for all possible entries
        allKeys.forEach(key -> {
            allValues.forEach(value -> {
                map.containsEntry(key, value)
                        .thenAccept(result -> assertTrue(result)).join();
            });
        });

        //Test behavior after removals
        allValues.forEach(value -> {
            final String[] removedKey = new String[1];
            allKeys.forEach(key -> {
                map.remove(key, value)
                        .thenAccept(result -> assertTrue(result)).join();
                map.containsEntry(key, value)
                        .thenAccept(result -> assertFalse(result)).join();
                removedKey[0] = key;
            });
            //Check that contains key works properly for removed keys
            map.containsKey(removedKey[0])
                    .thenAccept(result -> assertFalse(result));
        });

        //Check that contains value works correctly for removed values
        allValues.forEach(value -> {
            map.containsValue(value)
                    .thenAccept(result -> assertFalse(result)).join();
        });

        map.destroy().join();
        clearTests();
    }

    /**
     * Contains tests for put, putAll, remove, removeAll and replace.
     * @throws Exception
     */
    @Ignore
    @Test
    public void addAndRemoveTest() throws Exception {
        clearTests();
        AsyncConsistentSetMultimap map = createResource(3);

        //Test single put
        allKeys.forEach(key -> {
            //Value should actually be added here
            allValues.forEach(value -> {
                map.put(key, value)
                        .thenAccept(result -> assertTrue(result)).join();
                //Duplicate values should be ignored here
                map.put(key, value)
                        .thenAccept(result -> assertFalse(result)).join();
            });
        });

        //Test single remove
        allKeys.forEach(key -> {
            //Value should actually be added here
            allValues.forEach(value -> {
                map.remove(key, value)
                        .thenAccept(result -> assertTrue(result)).join();
                //Duplicate values should be ignored here
                map.remove(key, value)
                        .thenAccept(result -> assertFalse(result)).join();
            });
        });

        map.isEmpty().thenAccept(result -> assertTrue(result)).join();

        //Test multi put
        allKeys.forEach(key -> {
            map.putAll(key, Lists.newArrayList(allValues.subList(0, 2)))
                    .thenAccept(result -> assertTrue(result)).join();
            map.putAll(key, Lists.newArrayList(allValues.subList(0, 2)))
                    .thenAccept(result -> assertFalse(result)).join();
            map.putAll(key, Lists.newArrayList(allValues.subList(2, 4)))
                    .thenAccept(result -> assertTrue(result)).join();
            map.putAll(key, Lists.newArrayList(allValues.subList(2, 4)))
                    .thenAccept(result -> assertFalse(result)).join();

        });

        //Test multi remove
        allKeys.forEach(key -> {
            //Split the lists to test how multiRemove can work piecewise
            map.removeAll(key, Lists.newArrayList(allValues.subList(0, 2)))
                    .thenAccept(result -> assertTrue(result)).join();
            map.removeAll(key, Lists.newArrayList(allValues.subList(0, 2)))
                    .thenAccept(result -> assertFalse(result)).join();
            map.removeAll(key, Lists.newArrayList(allValues.subList(2, 4)))
                    .thenAccept(result -> assertTrue(result)).join();
            map.removeAll(key, Lists.newArrayList(allValues.subList(2, 4)))
                    .thenAccept(result -> assertFalse(result)).join();
        });

        map.isEmpty().thenAccept(result -> assertTrue(result)).join();

        //Repopulate for next test
        allKeys.forEach(key -> {
            map.putAll(key, allValues)
                    .thenAccept(result -> assertTrue(result)).join();
        });

        map.size().thenAccept(result -> assertEquals(16, (int) result)).join();

        //Test removeAll of entire entry
        allKeys.forEach(key -> {
            map.removeAll(key).thenAccept(result -> {
                assertTrue(
                        byteArrayCollectionIsEqual(allValues, result.value()));
            }).join();
            map.removeAll(key).thenAccept(result -> {
                assertFalse(
                        byteArrayCollectionIsEqual(allValues, result.value()));
            }).join();
        });

        map.isEmpty().thenAccept(result -> assertTrue(result)).join();

        //Repopulate for next test
        allKeys.forEach(key -> {
            map.putAll(key, allValues)
                    .thenAccept(result -> assertTrue(result)).join();
        });

        map.size().thenAccept(result -> assertEquals(16, (int) result)).join();

        allKeys.forEach(key -> {
            map.replaceValues(key, allValues)
                    .thenAccept(result ->
                        assertTrue(byteArrayCollectionIsEqual(allValues,
                                                              result.value())))
                    .join();
            map.replaceValues(key, Lists.newArrayList())
                    .thenAccept(result ->
                        assertTrue(byteArrayCollectionIsEqual(allValues,
                                                              result.value())))
                    .join();
            map.replaceValues(key, allValues)
                    .thenAccept(result ->
                        assertTrue(result.value().isEmpty()))
                    .join();
        });


        //Test replacements of partial sets
        map.size().thenAccept(result -> assertEquals(16, (int) result)).join();

        allKeys.forEach(key -> {
            map.remove(key, valueOne)
                    .thenAccept(result ->
                                        assertTrue(result)).join();
            map.replaceValues(key, Lists.newArrayList())
                    .thenAccept(result ->
                        assertTrue(byteArrayCollectionIsEqual(
                                Lists.newArrayList(valueTwo, valueThree,
                                                   valueFour),
                                result.value())))
                    .join();
            map.replaceValues(key, allValues)
                    .thenAccept(result ->
                                        assertTrue(result.value().isEmpty()))
                    .join();
        });

        map.destroy().join();
        clearTests();
    }

    /**
     * Tests the get, keySet, keys, values, and entries implementations as well
     * as a trivial test of the asMap functionality (throws error).
     * @throws Exception
     */
    @Ignore
    @Test
    public void testAccessors() throws Exception {
        clearTests();
        AsyncConsistentSetMultimap map = createResource(3);

        //Populate for full map behavior tests
        allKeys.forEach(key -> {
            map.putAll(key, allValues)
                    .thenAccept(result -> assertTrue(result)).join();
        });

        map.size().thenAccept(result -> assertEquals(16, (int) result)).join();

        allKeys.forEach(key -> {
                map.get(key).thenAccept(result -> {
                    assertTrue(byteArrayCollectionIsEqual(allValues,
                                                          result.value()));
                }).join();
            });

        //Test that the key set is correct
        map.keySet()
                .thenAccept(result ->
                            assertTrue(stringArrayCollectionIsEqual(allKeys,
                                                                    result)))
                .join();
        //Test that the correct set and occurrence of values are found in the
        //values result
        map.values().thenAccept(result -> {
            final Multiset<byte[]> set = TreeMultiset.create(
                    new ByteArrayComparator());
            for (int i = 0; i < 4; i++) {
                set.addAll(allValues);
            }
            assertEquals(16, result.size());
            result.forEach(value -> assertTrue(set.remove(value)));
            assertTrue(set.isEmpty());

        }).join();

        //Test that keys returns the right result including the correct number
        //of each item
        map.keys().thenAccept(result -> {
            final Multiset<String> set = TreeMultiset.create();
            for (int i = 0; i < 4; i++) {
                set.addAll(allKeys);
            }
            assertEquals(16, result.size());
            result.forEach(value -> assertTrue(set.remove(value)));
            assertTrue(set.isEmpty());

        }).join();

        //Test that the right combination of key, value pairs are present
        map.entries().thenAccept(result -> {
            final Multiset<Map.Entry<String, byte[]>> set =
                    TreeMultiset.create(new EntryComparator());
            allKeys.forEach(key -> {
                allValues.forEach(value -> {
                    set.add(new DefaultMapEntry(key, value));
                });
            });
            assertEquals(16, result.size());
            result.forEach(entry -> assertTrue(set.remove(entry)));
            assertTrue(set.isEmpty());
        }).join();


        //Testing for empty map behavior
        map.clear().join();

        allKeys.forEach(key -> {
            map.get(key).thenAccept(result -> {
                assertTrue(result.value().isEmpty());
            }).join();
        });

        map.keySet().thenAccept(result -> assertTrue(result.isEmpty())).join();
        map.values().thenAccept(result -> assertTrue(result.isEmpty())).join();
        map.keys().thenAccept(result -> assertTrue(result.isEmpty())).join();
        map.entries()
                .thenAccept(result -> assertTrue(result.isEmpty())).join();

        map.destroy();
        clearTests();
    }


    private AsyncConsistentSetMultimap createResource(int clusterSize) {
        try {
            createCopycatServers(clusterSize);
            AsyncConsistentSetMultimap map = createAtomixClient().
                    getResource("testMap", AsyncConsistentSetMultimap.class)
                    .join();
            return map;
        } catch (Throwable e) {
            throw new RuntimeException(e.toString());
        }
    }

    @Override
    protected CopycatServer createCopycatServer(Address address) {
        CopycatServer server = CopycatServer.builder(address, members)
                .withTransport(new LocalTransport(registry))
                .withStorage(Storage.builder()
                                     .withStorageLevel(StorageLevel.MEMORY)
                                     .withDirectory(testDir + "/" + address.port())
                                     .build())
                .withStateMachine(ResourceManagerState::new)
                .withSerializer(serializer.clone())
                .withHeartbeatInterval(Duration.ofMillis(25))
                .withElectionTimeout(Duration.ofMillis(50))
                .withSessionTimeout(Duration.ofMillis(100))
                .build();
        copycatServers.add(server);
        return server;    }

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

    /**
     * Byte array comparator implementation.
     */
    private class ByteArrayComparator implements Comparator<byte[]> {

        @Override
        public int compare(byte[] o1, byte[] o2) {
            if (Arrays.equals(o1, o2)) {
                return 0;
            } else {
                for (int i = 0; i < o1.length && i < o2.length; i++) {
                    if (o1[i] < o2[i]) {
                        return -1;
                    } else if (o1[i] > o2[i]) {
                        return 1;
                    }
                }
                return o1.length > o2.length ? 1 : -1;
            }
        }
    }

    /**
     * Entry comparator, uses both key and value to determine equality,
     * for comparison falls back to the default string comparator.
     */
    private class EntryComparator
            implements Comparator<Map.Entry<String, byte[]>> {

        @Override
        public int compare(Map.Entry<String, byte[]> o1,
                           Map.Entry<String, byte[]> o2) {
            if (o1 == null || o1.getKey() == null || o2 == null ||
                    o2.getKey() == null) {
                throw new IllegalArgumentException();
            }
            if (o1.getKey().equals(o2.getKey()) &&
                    Arrays.equals(o1.getValue(), o2.getValue())) {
                return 0;
            } else {
                return o1.getKey().compareTo(o2.getKey());
            }
        }
    }
}
