/*
 * 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.ignite.internal.processors.cache;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
import org.apache.ignite.configuration.CacheConfiguration;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;

/**
 * Data types coverage for basic cache operations.
 */
@RunWith(Parameterized.class)
@SuppressWarnings("ZeroLengthArrayAllocation")
public class GridCacheDataTypesCoverageTest extends AbstractDataTypesCoverageTest {
    /** @inheritDoc */
    @Before
    @Override public void init() throws Exception {
        super.init();
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testByteDataType() throws Exception {
        checkBasicCacheOperations(
            Byte.MIN_VALUE,
            Byte.MAX_VALUE,
            (byte)0,
            (byte)1);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testShortDataType() throws Exception {
        checkBasicCacheOperations(
            Short.MIN_VALUE,
            Short.MAX_VALUE,
            (short)0,
            (short)1);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testIntegerDataType() throws Exception {
        checkBasicCacheOperations(
            Integer.MIN_VALUE,
            Integer.MAX_VALUE,
            0,
            1);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testLongDataType() throws Exception {
        checkBasicCacheOperations(
            Long.MIN_VALUE,
            Long.MAX_VALUE,
            0L,
            1L);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testFloatDataType() throws Exception {
        checkBasicCacheOperations(
            Float.MIN_VALUE,
            Float.MAX_VALUE,
            Float.NaN,
            Float.NEGATIVE_INFINITY,
            Float.POSITIVE_INFINITY,
            0F,
            0.0F,
            1F,
            1.1F);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testDoubleDataType() throws Exception {
        checkBasicCacheOperations(
            Double.MIN_VALUE,
            Double.MAX_VALUE,
            Double.NaN,
            Double.NEGATIVE_INFINITY,
            Double.POSITIVE_INFINITY,
            0D,
            0.0D,
            1D,
            1.1D);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testBooleanDataType() throws Exception {
        checkBasicCacheOperations(
            Boolean.TRUE,
            Boolean.FALSE);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCharacterDataType() throws Exception {
        checkBasicCacheOperations(
            'a',
            'A');
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testStringDataType() throws Exception {
        checkBasicCacheOperations(
            "aAbB",
            "");
    }

    /**
     * @throws Exception If failed.
     */
    @Ignore("https://issues.apache.org/jira/browse/IGNITE-12314")
    @Test
    public void testByteArrayDataType() throws Exception {
        checkBasicCacheOperations(
            new Byte[] {},
            new Byte[] {1, 2, 3},
            new byte[] {3, 2, 1});
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testObjectArrayDataType() throws Exception {
        checkBasicCacheOperations(
            new Object[] {},
            new Object[] {"String", Boolean.TRUE, 'A', 1},
            new Object[] {
                "String",
                new ObjectBasedOnPrimitives(123, 123.123, true)});
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testListDataType() throws Exception {
        checkBasicCacheOperations(
            new ArrayList<>(),
            (Serializable)Collections.singletonList("Aaa"),
            (Serializable)Arrays.asList("String", Boolean.TRUE, 'A', 1));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testSetDataType() throws Exception {
        checkBasicCacheOperations(
            new HashSet<>(),
            (Serializable)Collections.singleton("Aaa"),
            new HashSet<>(Arrays.asList("String", Boolean.TRUE, 'A', 1)));
    }

    /**
     * @throws Exception If failed.
     */
    @Ignore("https://issues.apache.org/jira/browse/IGNITE-12315")
    @Test
    public void testQueueDataType() throws Exception {
        ArrayBlockingQueue<Integer> queueToCheck = new ArrayBlockingQueue<>(5);
        queueToCheck.addAll(Arrays.asList(1, 2, 3));

        checkBasicCacheOperations(
            new LinkedList<>(),
            new LinkedList<>(Arrays.asList("Aaa", "Bbb")),
            queueToCheck);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testObjectBasedOnPrimitivesDataType() throws Exception {
        checkBasicCacheOperations(
            new ObjectBasedOnPrimitives(0, 0.0, false),
            new ObjectBasedOnPrimitives(123, 123.123, true));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testObjectBasedOnPrimitivesAndCollectionsDataType() throws Exception {
        checkBasicCacheOperations(
            new ObjectBasedOnPrimitivesAndCollections(0,
                Collections.emptyList(),
                new boolean[] {}),
            new ObjectBasedOnPrimitivesAndCollections(123,
                Arrays.asList(1.0, 0.0),
                new boolean[] {true, false}));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testObjectBasedOnPrimitivesAndCollectionsAndNestedObjectsDataType() throws Exception {
        checkBasicCacheOperations(
            new ObjectBasedOnPrimitivesCollectionsAndNestedObject(0,
                Collections.emptyList(),
                new ObjectBasedOnPrimitivesAndCollections(
                    0,
                    Collections.emptyList(),
                    new boolean[] {})),
            new ObjectBasedOnPrimitivesCollectionsAndNestedObject(-1,
                Collections.singletonList(0.0),
                new ObjectBasedOnPrimitivesAndCollections(
                    Integer.MAX_VALUE,
                    new ArrayList<>(Collections.singleton(22.2)),
                    new boolean[] {true, false, true})));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testDateDataType() throws Exception {
        checkBasicCacheOperations(
            new Date(),
            new Date(Long.MIN_VALUE),
            new Date(Long.MAX_VALUE));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testSqlDateDataType() throws Exception {
        checkBasicCacheOperations(
            new java.sql.Date(Long.MIN_VALUE),
            new java.sql.Date(Long.MAX_VALUE));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testCalendarDataType() throws Exception {
        checkBasicCacheOperations(new GregorianCalendar());
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testInstantDataType() throws Exception {
        checkBasicCacheOperations(
            Instant.now(),
            Instant.ofEpochMilli(Long.MIN_VALUE),
            Instant.ofEpochMilli(Long.MAX_VALUE));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testLocalDateDataType() throws Exception {
        checkBasicCacheOperations(
            LocalDate.of(2015, 2, 20),
            LocalDate.now().plusDays(1));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testLocalDateTimeDataType() throws Exception {
        checkBasicCacheOperations(
            LocalDateTime.of(2015, 2, 20, 9, 4, 30),
            LocalDateTime.now().plusDays(1));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testLocalTimeDataType() throws Exception {
        checkBasicCacheOperations(
            LocalTime.of(9, 4, 40),
            LocalTime.now());
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testBigIntegerDataType() throws Exception {
        checkBasicCacheOperations(
            new BigInteger("1"),
            BigInteger.ONE,
            BigInteger.ZERO,
            new BigInteger("123456789"));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testBigDecimalDataType() throws Exception {
        checkBasicCacheOperations(
            new BigDecimal(123.123),
            BigDecimal.ONE,
            BigDecimal.ZERO,
            BigDecimal.valueOf(123456789, 0),
            BigDecimal.valueOf(123456789, 1),
            BigDecimal.valueOf(123456789, 2),
            BigDecimal.valueOf(123456789, 3));
    }

    /**
     * Verification that following cache methods works correctly:
     *
     * <ul>
     * <li>put</li>
     * <li>putAll</li>
     * <li>remove</li>
     * <li>removeAll</li>
     * <li>get</li>
     * <li>getAll</li>
     * </ul>
     *
     * @param valsToCheck Array of values to check.
     */
    @SuppressWarnings("unchecked")
    protected void checkBasicCacheOperations(Serializable... valsToCheck) throws Exception {
        assert valsToCheck.length > 0;

        // In case of BigDecimal, cache internally changes bitLength of BigDecimal's intValue,
        // so that EqualsBuilder.reflectionEquals returns false.
        // As a result in case of BigDecimal data type Objects.equals is used.
        // Same is about BigInteger.
        BiFunction<Object, Object, Boolean> equalsProcessor =
            valsToCheck[0] instanceof BigDecimal || valsToCheck[0] instanceof BigInteger ?
                Objects::equals :
                (lhs, rhs) -> EqualsBuilder.reflectionEquals(
                    lhs, rhs, false, lhs.getClass(), true);

        String cacheName = "cache" + UUID.randomUUID();

        IgniteCache<Object, Object> cache = grid(new Random().nextInt(NODES_CNT)).createCache(
            new CacheConfiguration<>()
                .setName(cacheName)
                .setAtomicityMode(atomicityMode)
                .setCacheMode(cacheMode)
                .setExpiryPolicyFactory(ttlFactory)
                .setBackups(backups)
                .setEvictionPolicyFactory(evictionFactory)
                .setOnheapCacheEnabled(evictionFactory != null || onheapCacheEnabled)
                .setWriteSynchronizationMode(writeSyncMode)
                .setAffinity(new RendezvousAffinityFunction(false, PARTITIONS_CNT)));

        Map<Serializable, Serializable> keyValMap = new HashMap<>();

        for (int i = 0; i < valsToCheck.length; i++)
            keyValMap.put(valsToCheck[i], valsToCheck[valsToCheck.length - i - 1]);

        for (Map.Entry<Serializable, Serializable> keyValEntry : keyValMap.entrySet()) {
            // Put.
            cache.put(keyValEntry.getKey(), keyValEntry.getValue());

            Serializable clonedKey = SerializationUtils.clone(keyValEntry.getKey());

            if (writeSyncMode == CacheWriteSynchronizationMode.FULL_ASYNC &&
                !waitForCondition(() -> cache.get(clonedKey) != null, TIMEOUT_FOR_KEY_RETRIEVAL_IN_FULL_ASYNC_MODE))
                fail("Unable to retrieve value for key = [" + clonedKey + "].");

            // Check Put/Get.
            assertTrue(equalsProcessor.apply(keyValEntry.getValue(), cache.get(clonedKey)));

            // Remove.
            cache.remove(clonedKey);

            if (writeSyncMode == CacheWriteSynchronizationMode.FULL_ASYNC &&
                !waitForCondition(() -> cache.get(clonedKey) == null, TIMEOUT_FOR_KEY_RETRIEVAL_IN_FULL_ASYNC_MODE))
                fail("Unable to retrieve null value for key = [" + clonedKey + "] after entry removal.");

            // Check remove.
            assertNull(cache.get(clonedKey));
        }

        // PutAll
        cache.putAll(keyValMap);

        // Check putAll.
        for (Map.Entry<Serializable, Serializable> keyValEntry : keyValMap.entrySet()) {
            Serializable clonedKey = SerializationUtils.clone(keyValEntry.getKey());

            if (writeSyncMode == CacheWriteSynchronizationMode.FULL_ASYNC &&
                !waitForCondition(() -> cache.get(clonedKey) != null, TIMEOUT_FOR_KEY_RETRIEVAL_IN_FULL_ASYNC_MODE))
                fail("Unable to retrieve value for key = [" + clonedKey + "].");

            assertTrue(equalsProcessor.apply(keyValEntry.getValue(), cache.get(clonedKey)));
        }

        Set<Serializable> clonedKeySet =
            keyValMap.keySet().stream().map(SerializationUtils::clone).collect(Collectors.toSet());

        if (writeSyncMode == CacheWriteSynchronizationMode.FULL_ASYNC &&
            !waitForCondition(() -> cache.getAll(clonedKeySet) != null, TIMEOUT_FOR_KEY_RETRIEVAL_IN_FULL_ASYNC_MODE))
            fail("Unable to retrieve values value for keySet = [" + clonedKeySet + "].");

        // Check get all.
        Map<Object, Object> mapToCheck = cache.getAll(clonedKeySet);

        assertEquals(keyValMap.size(), mapToCheck.size());

        for (Map.Entry<Serializable, Serializable> keyValEntry : keyValMap.entrySet()) {
            boolean keyFound = false;
            for (Map.Entry<Object, Object> keyValEntryToCheck : mapToCheck.entrySet()) {
                if (equalsProcessor.apply(keyValEntry.getKey(), keyValEntryToCheck.getKey())) {
                    keyFound = true;

                    assertTrue(equalsProcessor.apply(keyValEntry.getValue(), keyValEntryToCheck.getValue()));

                    break;
                }
            }
            assertTrue(keyFound);
        }

        // Remove all.
        cache.removeAll(clonedKeySet);

        // Check remove all.
        for (Serializable clonedKey : clonedKeySet) {
            if (writeSyncMode == CacheWriteSynchronizationMode.FULL_ASYNC &&
                !waitForCondition(() -> cache.get(clonedKey) == null, TIMEOUT_FOR_KEY_RETRIEVAL_IN_FULL_ASYNC_MODE))
                fail("Unable to retrieve null value for key = [" + clonedKey + "] after entry removal.");

            assertNull(cache.get(clonedKey));
        }
    }
}
