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

import java.io.Serializable;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.ClientConfiguration;
import org.apache.ignite.configuration.ClientConnectorConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.springdata22.repository.IgniteRepository;
import org.apache.ignite.springdata22.repository.config.EnableIgniteRepositories;
import org.apache.ignite.springdata22.repository.config.RepositoryConfig;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;

import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause;
import static org.springframework.context.annotation.FilterType.ASSIGNABLE_TYPE;

/** Tests Spring Data repository cluster connection configurations. */
public class IgniteSpringDataConnectionConfigurationTest extends GridCommonAbstractTest {
    /** */
    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);

    /** */
    private static final String CACHE_NAME = "PersonCache";

    /** */
    private static final int CLI_CONN_PORT = 10810;

    /** */
    private static final String CLI_NAME = "cli-node";

    /** */
    private static final String SRV_NAME = "srv-node";

    /** */
    private static final String LOCAL_HOST = "127.0.0.1";

    /** Tests repository configuration in case {@link IgniteConfiguration} is used to access the Ignite cluster. */
    @Test
    public void testRepositoryWithIgniteConfiguration() {
        checkRepositoryConfiguration(IgniteConfigurationApplication.class, IgniteConfigRepository.class);

        assertClientNodeIsStopped();
    }

    /** Tests repository configuration in case {@link ClientConfiguration} is used to access the Ignite cluster. */
    @Test
    public void testRepositoryWithClientConfiguration() {
        checkRepositoryConfiguration(ClientConfigurationApplication.class, IgniteClientConfigRepository.class);
    }

    /** Tests repository configuration in case {@link Ignite} with non default is used to access the Ignite cluster. */
    @Test
    public void testRepositoryWithoutIgniteInstanceParameter() {
        checkRepositoryConfiguration(DefaultIgniteBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
    }

    /** Tests repository configuration in case {@link IgniteClient} with non default name is used to access the Ignite cluster. */
    @Test
    public void testRepositoryWithoutIgniteClientInstanceParameter() {
        checkRepositoryConfiguration(DefaultIgniteClientBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
    }

    /** Tests repository configuration in case {@link ClientConfiguration} with non default name is used to access the Ignite cluster. */
    @Test
    public void testRepositoryWithoutIgnitClientConfigurationParameter() {
        checkRepositoryConfiguration(DefaultIgniteClientConfigurationBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
    }

    /** Tests repository configuration in case {@link IgniteConfiguration} with non default name is used to access the Ignite cluster. */
    @Test
    public void testRepositoryWithoutIgniteConfigurationParameter() {
        checkRepositoryConfiguration(DefaultIgniteConfigurationBeanApplication.class, IgniteRepositoryWithoutExplicitIgnite.class);
    }

    /**
     * Tests repository configuration in case {@link IgniteConfiguration} that refers to existing Ignite node instance
     * used to access the Ignite cluster.
     */
    @Test
    public void testRepositoryWithExistingIgniteInstance() throws Exception {
        try (Ignite ignored = startGrid(getIgniteConfiguration(CLI_NAME, true))) {
            checkRepositoryConfiguration(IgniteConfigurationApplication.class, IgniteConfigRepository.class);

            assertNotNull(Ignition.ignite(CLI_NAME));
        }
    }

    /** Tests repository configuration in case specified cache name is invalid. */
    @Test
    public void testRepositoryWithInvalidCacheNameConfiguration() {
        try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext()) {
            ctx.register(InvalidCacheNameApplication.class);

            assertThrowsAnyCause(log,
                () -> {
                    ctx.refresh();

                    return null;
                },
                IllegalArgumentException.class,
                "Cache 'invalidCache' not found for repository interface" +
                    " org.apache.ignite.springdata.IgniteSpringDataConnectionConfigurationTest$InvalidCacheNameRepository." +
                    " Please, add a cache configuration to ignite configuration or pass autoCreateCache=true to" +
                    " org.apache.ignite.springdata22.repository.config.RepositoryConfig annotation.");
        }

        assertClientNodeIsStopped();
    }

    /** {@inheritDoc} */
    @Override protected void afterTest() throws Exception {
        super.afterTest();

        grid(SRV_NAME).cache(CACHE_NAME).clear();
    }

    /** */
    private void assertClientNodeIsStopped() {
        assertFalse(Ignition.allGrids().stream().map(Ignite::name).anyMatch(CLI_NAME::equals));
    }

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        super.beforeTestsStarted();

        startGrid(getIgniteConfiguration(SRV_NAME, false));
    }

    /**
     * Checks that repository created based on specified Spring application configuration is properly initialized and
     * got access to the Ignite cluster.
     */
    private void checkRepositoryConfiguration(
        Class<?> cfgCls,
        Class<? extends IgniteRepository<Object, Serializable>> repoCls
    ) {
        try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext()) {
            ctx.register(cfgCls);
            ctx.refresh();

            IgniteRepository<Object, Serializable> repo = ctx.getBean(repoCls);

            IgniteCache<Object, Serializable> cache = grid(SRV_NAME).cache(CACHE_NAME);

            assertEquals(0, repo.count());
            assertEquals(0, cache.size());

            int key = 0;

            repo.save(key, "1");

            assertEquals(1, repo.count());
            assertNotNull(cache.get(key));
        }
    }

    /**
     * Spring Application configuration for repository testing in case {@link IgniteConfiguration} is used
     * for accessing the cluster.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = InvalidCacheNameRepository.class))
    public static class InvalidCacheNameApplication {
        /** Ignite configuration bean. */
        @Bean
        public IgniteConfiguration igniteConfiguration() {
            return getIgniteConfiguration(CLI_NAME, true);
        }
    }

    /**
     * Spring Application configuration for repository testing in case {@link IgniteConfiguration} is used
     * for accessing the cluster.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteConfigRepository.class))
    public static class IgniteConfigurationApplication {
        /** Ignite configuration bean. */
        @Bean
        public IgniteConfiguration igniteConfiguration() {
            return getIgniteConfiguration(CLI_NAME, true);
        }
    }

    /**
     * Spring Application configuration for repository testing in case {@link ClientConfiguration} is used
     * for accessing the cluster.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteClientConfigRepository.class))
    public static class ClientConfigurationApplication {
        /** Ignite client configuration bean. */
        @Bean
        public ClientConfiguration clientConfiguration() {
            return new ClientConfiguration().setAddresses(LOCAL_HOST + ':' + CLI_CONN_PORT);
        }
    }

    /**
     * Spring Application configuration for repository testing in case if Ignite bean name was not provided
     * through {@link RepositoryConfig#igniteInstance()} ()}.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
    )
    public static class DefaultIgniteBeanApplication {
        /** Ignite bean. */
        @Bean
        public Ignite someIgnite() {
            return Ignition.start(getIgniteConfiguration("test", false));
        }
    }

    /**
     * Spring Application configuration for repository testing in case if IgniteClient bean name was not provided
     * through {@link RepositoryConfig#igniteInstance()} ()}.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
    )
    public static class DefaultIgniteClientBeanApplication {
        /** Ignite client bean. */
        @Bean
        public IgniteClient someIgnite() {
            return Ignition.startClient(new ClientConfiguration().setAddresses(LOCAL_HOST + ':' + CLI_CONN_PORT));
        }
    }

    /**
     * Spring Application configuration for repository testing in case if ClientConfiguration bean name was not provided
     * through {@link RepositoryConfig#igniteCfg()}.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
    )
    public static class DefaultIgniteClientConfigurationBeanApplication {
        /** Ignite client configuration bean. */
        @Bean
        public ClientConfiguration someCfg() {
            return new ClientConfiguration().setAddresses(LOCAL_HOST + ':' + CLI_CONN_PORT);
        }
    }

    /**
     * Spring Application configuration for repository testing in case if IgniteConfiguration bean name was not provided
     * through {@link RepositoryConfig#igniteCfg()}.
     */
    @Configuration
    @EnableIgniteRepositories(
        considerNestedRepositories = true,
        includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = IgniteRepositoryWithoutExplicitIgnite.class)
    )
    public static class DefaultIgniteConfigurationBeanApplication {
        /** Ignite client configuration bean. */
        @Bean
        public IgniteConfiguration someCfg() {
            return getIgniteConfiguration("test", false);
        }
    }

    /** Repository for testing configuration approach through default ignite beans. */
    @RepositoryConfig(cacheName = "PersonCache")
    public interface IgniteRepositoryWithoutExplicitIgnite extends IgniteRepository<Object, Serializable> {
        // No-op.
    }

    /** Repository for testing configuration approach through {@link IgniteConfiguration}. */
    @RepositoryConfig(cacheName = "PersonCache", igniteCfg = "igniteConfiguration")
    public interface IgniteConfigRepository extends IgniteRepository<Object, Serializable> {
        // No-op.
    }

    /** Repository for testing repository configuration approach through {@link ClientConfiguration}. */
    @RepositoryConfig(cacheName = "PersonCache", igniteCfg = "clientConfiguration")
    public interface IgniteClientConfigRepository extends IgniteRepository<Object, Serializable> {
        // No-op.
    }

    /** Repository for testing application behavior in case invalid cache is specified in the repository configuration. */
    @RepositoryConfig(cacheName = "invalidCache", igniteCfg = "igniteConfiguration")
    public interface InvalidCacheNameRepository extends IgniteRepository<Object, Serializable> {
        // No-op.
    }

    /** */
    private static IgniteConfiguration getIgniteConfiguration(String name, boolean clientMode) {
        return new IgniteConfiguration()
            .setIgniteInstanceName(name)
            .setClientMode(clientMode)
            .setLocalHost(LOCAL_HOST)
            .setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(IP_FINDER))
            .setClientConnectorConfiguration(new ClientConnectorConfiguration().setPort(CLI_CONN_PORT))
            .setCacheConfiguration(new CacheConfiguration<>(CACHE_NAME));
    }
}
