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

import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.affinity.AffinityKeyMapper;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.processors.cache.distributed.GridCacheModuloAffinityFunction;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;

import static org.apache.ignite.cache.CacheMode.PARTITIONED;

/**
 * Tests affinity mapping when {@link AffinityKeyMapper} is used.
 */
public class GridAffinityMappedTest extends GridCommonAbstractTest {
    /**
     *
     */
    public GridAffinityMappedTest() {
        super(false);
    }

    /** {@inheritDoc} */
    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);

        if (igniteInstanceName.endsWith("1"))
            cfg.setCacheConfiguration(); // Empty cache configuration.
        else {
            assert igniteInstanceName.endsWith("2") || igniteInstanceName.endsWith("3");

            CacheConfiguration<Object, Object> cacheCfg = defaultCacheConfiguration();

            cacheCfg.setCacheMode(PARTITIONED);
            cacheCfg.setAffinity(new MockCacheAffinityFunction());
            cacheCfg.setAffinityMapper(new MockCacheAffinityKeyMapper());
            cacheCfg.setNodeFilter(node -> node.attribute(GridCacheModuloAffinityFunction.IDX_ATTR) != null);

            cfg.setCacheConfiguration(cacheCfg);
            cfg.setUserAttributes(F.asMap(GridCacheModuloAffinityFunction.IDX_ATTR,
                igniteInstanceName.endsWith("2") ? 0 : 1));
        }

        return cfg;
    }

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        startGrid(1);
        startGrid(2);
        startGrid(3);
    }

    /**
     * @throws IgniteCheckedException If failed.
     */
    @Test
    public void testMappedAffinity() throws IgniteCheckedException, InterruptedException {
        Ignite g1 = grid(1);
        Ignite g2 = grid(2);
        Ignite g3 = grid(3);

        ClusterNode first = g2.cluster().localNode();
        ClusterNode second = g3.cluster().localNode();

        awaitPartitionMapExchange(true, true, null);

        //When MockCacheAfinity and MockCacheAffinityKeyMapper are set to cache configuration we expect the following.
        //Key 0 is mapped to partition 0, first node.
        //Key 1 is mapped to partition 1, second node.
        //key 2 is mapped to partition 0, first node because mapper substitutes key 2 with affinity key 0.
        Map<ClusterNode, Collection<Integer>> map = g1.<Integer>affinity(DEFAULT_CACHE_NAME).mapKeysToNodes(F.asList(0));

        assertNotNull(map);
        assertEquals("Invalid map size: " + map.size(), 1, map.size());
        assertEquals(F.first(map.keySet()), first);

        UUID id1 = g1.affinity(DEFAULT_CACHE_NAME).mapKeyToNode(1).id();

        assertNotNull(id1);
        assertEquals(second.id(), id1);

        UUID id2 = g1.affinity(DEFAULT_CACHE_NAME).mapKeyToNode(2).id();

        assertNotNull(id2);
        assertEquals(first.id(), id2);
    }

    /**
     * Mock affinity implementation that ensures constant key-to-node mapping based on {@link GridCacheModuloAffinityFunction}
     * The partition selection is as follows: 0 maps to partition 0 and any other value maps to partition 1
     */
    private static class MockCacheAffinityFunction extends GridCacheModuloAffinityFunction {
        /**
         * Initializes module affinity with 2 parts and 0 backups
         */
        private MockCacheAffinityFunction() {
            super(2, 0);
        }

        /** {@inheritDoc} */
        @Override public int partition(Object key) {
            return Integer.valueOf(0) == key ? 0 : 1;
        }

        /** {@inheritDoc} */
        @Override public void reset() {
            //no-op
        }
    }

    /**
     * Mock affinity mapper implementation that substitutes values other than 0 and 1 with 0.
     */
    private static class MockCacheAffinityKeyMapper implements AffinityKeyMapper {
        /** {@inheritDoc} */
        @Override public Object affinityKey(Object key) {
            return key instanceof Integer ? ((1 == (Integer)key) ? key : 0) : key;
        }

        /** {@inheritDoc} */
        @Override public void reset() {
            // This mapper is stateless and needs no initialization logic.
        }
    }
}
