/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.math4.legacy.linear;

import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.commons.math4.legacy.core.Field;
import org.apache.commons.math4.legacy.core.dfp.Dfp;
import org.apache.commons.math4.legacy.core.dfp.DfpField;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;


@SuppressWarnings("boxing")
public class OpenIntToFieldTest {

    private Map<Integer, Dfp> javaMap = new HashMap<>();
    private DfpField field = Dfp25.getField();

    @Before
    public void setUp() {
        javaMap.put(50, Dfp25.of(100.0));
        javaMap.put(75, Dfp25.of(75.0));
        javaMap.put(25, Dfp25.of(500.0));
        javaMap.put(Integer.MAX_VALUE, Dfp25.of(Integer.MAX_VALUE));
        javaMap.put(0, Dfp25.of(-1.0));
        javaMap.put(1, Dfp25.of(0.0));
        javaMap.put(33, Dfp25.of(-0.1));
        javaMap.put(23234234, Dfp25.of(-242343.0));
        javaMap.put(23321, Dfp25.of (Integer.MIN_VALUE));
        javaMap.put(-4444, Dfp25.of(332.0));
        javaMap.put(-1, Dfp25.of(-2323.0));
        javaMap.put(Integer.MIN_VALUE, Dfp25.of(44.0));

        /* Add a few more to cause the table to rehash */
        javaMap.putAll(generate());

    }

    private Map<Integer, Dfp> generate() {
        Map<Integer, Dfp> map = new HashMap<>();
        Random r = new Random();
        double dd = 0;
        for (int i = 0; i < 2000; ++i) {
            dd = r.nextDouble();
        }
        map.put(r.nextInt(), Dfp25.of(dd));
        return map;
    }

    private OpenIntToFieldHashMap<Dfp> createFromJavaMap(Field<Dfp> field) {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field);
        for (Map.Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            map.put(mapEntry.getKey(), mapEntry.getValue());
        }
        return map;
    }

    @Test
    public void testPutAndGetWith0ExpectedSize() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field,0);
        assertPutAndGet(map);
    }

    @Test
    public void testPutAndGetWithExpectedSize() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field,500);
        assertPutAndGet(map);
    }

    @Test
    public void testPutAndGet() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field);
        assertPutAndGet(map);
    }

    private void assertPutAndGet(OpenIntToFieldHashMap<Dfp> map) {
        assertPutAndGet(map, 0, new HashSet<Integer>());
    }

    private void assertPutAndGet(OpenIntToFieldHashMap<Dfp> map, int mapSize,
            Set<Integer> keysInMap) {
        Assert.assertEquals(mapSize, map.size());
        for (Map.Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            map.put(mapEntry.getKey(), mapEntry.getValue());
            if (!keysInMap.contains(mapEntry.getKey())) {
                ++mapSize;
            }
            Assert.assertEquals(mapSize, map.size());
            Assert.assertEquals(mapEntry.getValue(), map.get(mapEntry.getKey()));
        }
    }

    @Test
    public void testPutAbsentOnExisting() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        int size = javaMap.size();
        for (Map.Entry<Integer, Dfp> mapEntry : generateAbsent().entrySet()) {
            map.put(mapEntry.getKey(), mapEntry.getValue());
            Assert.assertEquals(++size, map.size());
            Assert.assertEquals(mapEntry.getValue(), map.get(mapEntry.getKey()));
        }
    }

    @Test
    public void testPutOnExisting() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        for (Map.Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            map.put(mapEntry.getKey(), mapEntry.getValue());
            Assert.assertEquals(javaMap.size(), map.size());
            Assert.assertEquals(mapEntry.getValue(), map.get(mapEntry.getKey()));
        }
    }

    @Test
    public void testGetAbsent() {
        Map<Integer, Dfp> generated = generateAbsent();
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);

        for (Map.Entry<Integer, Dfp> mapEntry : generated.entrySet()) {
            Assert.assertTrue(field.getZero().equals(map.get(mapEntry.getKey())));
        }
    }

    @Test
    public void testGetFromEmpty() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field);
        Assert.assertEquals(field.getZero(), map.get(5));
        Assert.assertEquals(field.getZero(), map.get(0));
        Assert.assertEquals(field.getZero(), map.get(50));
    }

    @Test
    public void testRemove() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        int mapSize = javaMap.size();
        Assert.assertEquals(mapSize, map.size());
        for (Map.Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            map.remove(mapEntry.getKey());
            Assert.assertEquals(--mapSize, map.size());
            Assert.assertEquals(field.getZero(), map.get(mapEntry.getKey()));
        }

        /* Ensure that put and get still work correctly after removals */
        assertPutAndGet(map);
    }

    /* This time only remove some entries */
    @Test
    public void testRemove2() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        int mapSize = javaMap.size();
        int count = 0;
        Set<Integer> keysInMap = new HashSet<>(javaMap.keySet());
        for (Map.Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            keysInMap.remove(mapEntry.getKey());
            map.remove(mapEntry.getKey());
            Assert.assertEquals(--mapSize, map.size());
            Assert.assertEquals(field.getZero(), map.get(mapEntry.getKey()));
            if (count++ > 5) {
                break;
            }
        }

        /* Ensure that put and get still work correctly after removals */
        assertPutAndGet(map, mapSize, keysInMap);
    }

    @Test
    public void testRemoveFromEmpty() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field);
        Assert.assertEquals(field.getZero(), map.remove(50));
    }

    @Test
    public void testRemoveAbsent() {
        Map<Integer, Dfp> generated = generateAbsent();

        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        int mapSize = map.size();

        for (Map.Entry<Integer, Dfp> mapEntry : generated.entrySet()) {
            map.remove(mapEntry.getKey());
            Assert.assertEquals(mapSize, map.size());
            Assert.assertEquals(field.getZero(), map.get(mapEntry.getKey()));
        }
    }

    /**
     * Returns a map with at least 100 elements where each element is absent from javaMap.
     */
    private Map<Integer, Dfp> generateAbsent() {
        Map<Integer, Dfp> generated = new HashMap<>();
        do {
            generated.putAll(generate());
            for (Integer key : javaMap.keySet()) {
                generated.remove(key);
            }
        } while (generated.size() < 100);
        return generated;
    }

    @Test
    public void testCopy() {
        OpenIntToFieldHashMap<Dfp> copy =
            new OpenIntToFieldHashMap<>(createFromJavaMap(field));
        Assert.assertEquals(javaMap.size(), copy.size());

        for (Map.Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            Assert.assertEquals(mapEntry.getValue(), copy.get(mapEntry.getKey()));
        }
    }

    @Test
    public void testContainsKey() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        for (Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            Assert.assertTrue(map.containsKey(mapEntry.getKey()));
        }
        for (Map.Entry<Integer, Dfp> mapEntry : generateAbsent().entrySet()) {
            Assert.assertFalse(map.containsKey(mapEntry.getKey()));
        }
        for (Entry<Integer, Dfp> mapEntry : javaMap.entrySet()) {
            int key = mapEntry.getKey();
            Assert.assertTrue(map.containsKey(key));
            map.remove(key);
            Assert.assertFalse(map.containsKey(key));
        }
    }

    @Test
    public void testIterator() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        OpenIntToFieldHashMap<Dfp>.Iterator iterator = map.iterator();
        for (int i = 0; i < map.size(); ++i) {
            Assert.assertTrue(iterator.hasNext());
            iterator.advance();
            int key = iterator.key();
            Assert.assertTrue(map.containsKey(key));
            Assert.assertEquals(javaMap.get(key), map.get(key));
            Assert.assertEquals(javaMap.get(key), iterator.value());
            Assert.assertTrue(javaMap.containsKey(key));
        }
        Assert.assertFalse(iterator.hasNext());
        try {
            iterator.advance();
            Assert.fail("an exception should have been thrown");
        } catch (NoSuchElementException nsee) {
            // expected
        }
    }

    @Test
    public void testConcurrentModification() {
        OpenIntToFieldHashMap<Dfp> map = createFromJavaMap(field);
        OpenIntToFieldHashMap<Dfp>.Iterator iterator = map.iterator();
        map.put(3, Dfp25.of(3));
        try {
            iterator.advance();
            Assert.fail("an exception should have been thrown");
        } catch (ConcurrentModificationException cme) {
            // expected
        }
    }

    /**
     * Regression test for a bug in findInsertionIndex where the hashing in the second probing
     * loop was inconsistent with the first causing duplicate keys after the right sequence
     * of puts and removes.
     */
    @Test
    public void testPutKeysWithCollisions() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field);
        int key1 = -1996012590;
        Dfp value1 = Dfp25.of(1);
        map.put(key1, value1);
        int key2 = 835099822;
        map.put(key2, value1);
        int key3 = 1008859686;
        map.put(key3, value1);
        Assert.assertEquals(value1, map.get(key3));
        Assert.assertEquals(3, map.size());

        map.remove(key2);
        Dfp value2 = Dfp25.of(2);
        map.put(key3, value2);
        Assert.assertEquals(value2, map.get(key3));
        Assert.assertEquals(2, map.size());
    }

    /**
     * Similar to testPutKeysWithCollisions() but exercises the codepaths in a slightly
     * different manner.
     */
    @Test
    public void testPutKeysWithCollision2() {
        OpenIntToFieldHashMap<Dfp> map = new OpenIntToFieldHashMap<>(field);
        int key1 = 837989881;
        Dfp value1 = Dfp25.of(1);
        map.put(key1, value1);
        int key2 = 476463321;
        map.put(key2, value1);
        Assert.assertEquals(2, map.size());
        Assert.assertEquals(value1, map.get(key2));

        map.remove(key1);
        Dfp value2 = Dfp25.of(2);
        map.put(key2, value2);
        Assert.assertEquals(1, map.size());
        Assert.assertEquals(value2, map.get(key2));
    }
}
