/*
 * 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.collections4.keyvalue;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.*;

/**
 * Unit tests for {@link org.apache.commons.collections4.keyvalue.MultiKey}.
 *
 */
public class MultiKeyTest {

    Integer ONE = Integer.valueOf(1);
    Integer TWO = Integer.valueOf(2);
    Integer THREE = Integer.valueOf(3);
    Integer FOUR = Integer.valueOf(4);
    Integer FIVE = Integer.valueOf(5);

    //-----------------------------------------------------------------------
    @Test
    public void testConstructors() throws Exception {
        MultiKey<Integer> mk;
        mk = new MultiKey<>(ONE, TWO);
        assertTrue(Arrays.equals(new Object[] { ONE, TWO }, mk.getKeys()));

        mk = new MultiKey<>(ONE, TWO, THREE);
        assertTrue(Arrays.equals(new Object[] { ONE, TWO, THREE }, mk.getKeys()));

        mk = new MultiKey<>(ONE, TWO, THREE, FOUR);
        assertTrue(Arrays.equals(new Object[] { ONE, TWO, THREE, FOUR }, mk.getKeys()));

        mk = new MultiKey<>(ONE, TWO, THREE, FOUR, FIVE);
        assertTrue(Arrays.equals(new Object[] { ONE, TWO, THREE, FOUR, FIVE }, mk.getKeys()));

        mk = new MultiKey<>(new Integer[] { THREE, FOUR, ONE, TWO }, false);
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, TWO }, mk.getKeys()));
    }

    @Test
    public void testConstructorsByArray() throws Exception {
        MultiKey<Integer> mk;
        Integer[] keys = new Integer[] { THREE, FOUR, ONE, TWO };
        mk = new MultiKey<>(keys);
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, TWO }, mk.getKeys()));
        keys[3] = FIVE;  // no effect
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, TWO }, mk.getKeys()));

        keys = new Integer[] {};
        mk = new MultiKey<>(keys);
        assertTrue(Arrays.equals(new Object[] {}, mk.getKeys()));

        keys = new Integer[] { THREE, FOUR, ONE, TWO };
        mk = new MultiKey<>(keys, true);
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, TWO }, mk.getKeys()));
        keys[3] = FIVE;  // no effect
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, TWO }, mk.getKeys()));

        keys = new Integer[] { THREE, FOUR, ONE, TWO };
        mk = new MultiKey<>(keys, false);
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, TWO }, mk.getKeys()));
        // change key - don't do this!
        // the hashcode of the MultiKey is now broken
        keys[3] = FIVE;
        assertTrue(Arrays.equals(new Object[] { THREE, FOUR, ONE, FIVE }, mk.getKeys()));
    }

    @Test
    public void testConstructorsByArrayNull() throws Exception {
        final Integer[] keys = null;
        try {
            new MultiKey<>(keys);
            fail();
        } catch (final NullPointerException ex) {}
        try {
            new MultiKey<>(keys, true);
            fail();
        } catch (final NullPointerException ex) {}
        try {
            new MultiKey<>(keys, false);
            fail();
        } catch (final NullPointerException ex) {}
    }

    @Test
    public void testSize() {
        assertEquals(2, new MultiKey<>(ONE, TWO).size());
        assertEquals(2, new MultiKey<>(null, null).size());
        assertEquals(3, new MultiKey<>(ONE, TWO, THREE).size());
        assertEquals(3, new MultiKey<>(null, null, null).size());
        assertEquals(4, new MultiKey<>(ONE, TWO, THREE, FOUR).size());
        assertEquals(4, new MultiKey<>(null, null, null, null).size());
        assertEquals(5, new MultiKey<>(ONE, TWO, THREE, FOUR, FIVE).size());
        assertEquals(5, new MultiKey<>(null, null, null, null, null).size());

        assertEquals(0, new MultiKey<>(new Object[] {}).size());
        assertEquals(1, new MultiKey<>(new Integer[] { ONE }).size());
        assertEquals(2, new MultiKey<>(new Integer[] { ONE, TWO }).size());
        assertEquals(7, new MultiKey<>(new Integer[] { ONE, TWO, ONE, TWO, ONE, TWO, ONE }).size());
    }

    @Test
    public void testGetIndexed() {
        final MultiKey<Integer> mk = new MultiKey<>(ONE, TWO);
        assertSame(ONE, mk.getKey(0));
        assertSame(TWO, mk.getKey(1));
        try {
            mk.getKey(-1);
            fail();
        } catch (final IndexOutOfBoundsException ex) {}
        try {
            mk.getKey(2);
            fail();
        } catch (final IndexOutOfBoundsException ex) {}
    }

    @Test
    public void testGetKeysSimpleConstructor() {
        final MultiKey<Integer> mk = new MultiKey<>(ONE, TWO);
        final Object[] array = mk.getKeys();
        assertSame(ONE, array[0]);
        assertSame(TWO, array[1]);
        assertEquals(2, array.length);
    }

    @Test
    public void testGetKeysArrayConstructorCloned() {
        final Integer[] keys = new Integer[] { ONE, TWO };
        final MultiKey<Integer> mk = new MultiKey<>(keys, true);
        final Object[] array = mk.getKeys();
        assertTrue(array != keys);
        assertTrue(Arrays.equals(array, keys));
        assertSame(ONE, array[0]);
        assertSame(TWO, array[1]);
        assertEquals(2, array.length);
    }

    @Test
    public void testGetKeysArrayConstructorNonCloned() {
        final Integer[] keys = new Integer[] { ONE, TWO };
        final MultiKey<Integer> mk = new MultiKey<>(keys, false);
        final Object[] array = mk.getKeys();
        assertTrue(array != keys);  // still not equal
        assertTrue(Arrays.equals(array, keys));
        assertSame(ONE, array[0]);
        assertSame(TWO, array[1]);
        assertEquals(2, array.length);
    }

    @Test
    public void testHashCode() {
        final MultiKey<Integer> mk1 = new MultiKey<>(ONE, TWO);
        final MultiKey<Integer> mk2 = new MultiKey<>(ONE, TWO);
        final MultiKey<Object> mk3 = new MultiKey<>(ONE, "TWO");

        assertTrue(mk1.hashCode() == mk1.hashCode());
        assertTrue(mk1.hashCode() == mk2.hashCode());
        assertTrue(mk1.hashCode() != mk3.hashCode());

        final int total = (0 ^ ONE.hashCode()) ^ TWO.hashCode();
        assertEquals(total, mk1.hashCode());
    }

    @Test
    public void testEquals() {
        final MultiKey<Integer> mk1 = new MultiKey<>(ONE, TWO);
        final MultiKey<Integer> mk2 = new MultiKey<>(ONE, TWO);
        final MultiKey<Object> mk3 = new MultiKey<>(ONE, "TWO");

        assertEquals(mk1, mk1);
        assertEquals(mk1, mk2);
        assertFalse(mk1.equals(mk3));
        assertFalse(mk1.equals(""));
        assertFalse(mk1.equals(null));
    }

    static class SystemHashCodeSimulatingKey implements Serializable {

        private static final long serialVersionUID = -1736147315703444603L;
        private final String name;
        private int hashCode = 1;

        public SystemHashCodeSimulatingKey(final String name)
        {
            this.name = name;
        }

        @Override
        public boolean equals(final Object obj)
        {
            return obj instanceof SystemHashCodeSimulatingKey
                && name.equals(((SystemHashCodeSimulatingKey)obj).name);
        }

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

        private Object readResolve() {
            hashCode=2; // simulate different hashCode after deserialization in another process
            return this;
        }
    }

    @Test
    public void testEqualsAfterSerialization() throws IOException, ClassNotFoundException
    {
        SystemHashCodeSimulatingKey sysKey = new SystemHashCodeSimulatingKey("test");
        final MultiKey<?> mk = new MultiKey<Object>(ONE, sysKey);
        final Map<MultiKey<?>, Integer> map = new HashMap<>();
        map.put(mk, TWO);

        // serialize
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final ObjectOutputStream out = new ObjectOutputStream(baos);
        out.writeObject(sysKey);
        out.writeObject(map);
        out.close();

        // deserialize
        final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        final ObjectInputStream in = new ObjectInputStream(bais);
        sysKey = (SystemHashCodeSimulatingKey)in.readObject(); // simulate deserialization in another process
        final Map<?, ?> map2 = (Map<?, ?>) in.readObject();
        in.close();

        assertEquals(2, sysKey.hashCode()); // different hashCode now

        final MultiKey<?> mk2 = new MultiKey<Object>(ONE, sysKey);
        assertEquals(TWO, map2.get(mk2));
    }

    static class DerivedMultiKey<T> extends MultiKey<T> {

        private static final long serialVersionUID = 1928896152249821416L;

        public DerivedMultiKey(final T key1, final T key2) {
            super(key1, key2);
        }

        public T getFirst() {
            return getKey(0);
        }

        public T getSecond() {
            return getKey(1);
        }

    }

    @Test
    public void testEqualsAfterSerializationOfDerivedClass() throws IOException, ClassNotFoundException
    {
        final DerivedMultiKey<?> mk = new DerivedMultiKey<>("A", "B");

        // serialize
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final ObjectOutputStream out = new ObjectOutputStream(baos);
        out.writeObject(mk);
        out.close();

        // deserialize
        final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        final ObjectInputStream in = new ObjectInputStream(bais);
        final DerivedMultiKey<?> mk2 = (DerivedMultiKey<?>)in.readObject();
        in.close();

        assertEquals(mk.hashCode(), mk2.hashCode());
    }

}
