/*
 * 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.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.managers.communication.GridIoMessage;
import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.lang.IgniteFuture;
import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.spi.IgniteSpiException;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
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.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;

/**
 *
 */
public abstract class IgniteCacheAbstractStopBusySelfTest extends GridCommonAbstractTest {
    /** */
    public static final int CLN_GRD = 0;

    /** */
    public static final int SRV_GRD = 1;

    /** */
    public static final String CACHE_NAME = "StopTest";

    /** */
    public final TcpDiscoveryIpFinder finder = new TcpDiscoveryVmIpFinder(true);

    /** */
    private AtomicBoolean suspended = new AtomicBoolean(false);

    /** */
    private CountDownLatch blocked;

    /** */
    protected AtomicReference<Class> bannedMsg = new AtomicReference<>();

    /**
     * @return Cache mode.
     */
    protected CacheMode cacheMode(){
        return CacheMode.PARTITIONED;
    }

    /**
     * @return Cache atomicity mode.
     */
    protected CacheAtomicityMode atomicityMode(){
        return CacheAtomicityMode.TRANSACTIONAL;
    }

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

        CacheConfiguration cacheCfg = cacheConfiguration(CACHE_NAME);

        TestTpcCommunicationSpi commSpi = new TestTpcCommunicationSpi();

        commSpi.setLocalPort(GridTestUtils.getNextCommPort(getClass()));

        commSpi.setTcpNoDelay(true);

        if (igniteInstanceName.endsWith(String.valueOf(CLN_GRD)))
            cfg.setClientMode(true);

        cacheCfg.setRebalanceMode(SYNC);

        cacheCfg.setWriteSynchronizationMode(FULL_SYNC);

        cacheCfg.setBackups(1);

        cfg.setCommunicationSpi(commSpi);

        cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(finder).setForceServerMode(true));

        cfg.setCacheConfiguration(cacheCfg);

        return cfg;
    }

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

        startGrid(SRV_GRD);

        startGrid(CLN_GRD);

        blocked = new CountDownLatch(1);

        for (int i = 0; i < 10; ++i) {
            if (clientNode().cluster().nodes().size() == 2)
                break;

            TimeUnit.MILLISECONDS.sleep(100L);
        }

        assertEquals(2, clientNode().cluster().nodes().size());
    }

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

        bannedMsg.set(null);

        afterTestsStopped();

        stopGrid(SRV_GRD);

        stopGrid(CLN_GRD);

        List<Ignite> nodes = G.allGrids();

        assertTrue("Unexpected nodes: " + nodes, nodes.isEmpty());
    }

    /**
     * @throws Exception If failed.
     */
    public void testPut() throws Exception {
        executeTest(new Callable<Integer>() {
            /** {@inheritDoc} */
            @Override public Integer call() throws Exception {
                info("Start operation.");

                Integer val = (Integer)clientCache().getAndPut(1, 999);

                info("Stop operation.");

                return val;
            }
        });
    }

    /**
     * @throws Exception If failed.
     */
    public void testRemove() throws Exception {
        executeTest(new Callable<Integer>() {
            /** {@inheritDoc} */
            @Override public Integer call() throws Exception {
                info("Start operation.");

                Integer val = (Integer)clientCache().getAndRemove(1);

                info("Stop operation.");

                return val;
            }
        });
    }

    /**
     * @throws Exception If failed.
     */
    public void testPutAsync() throws Exception {
        executeTest(new Callable<Object>() {
            /** {@inheritDoc} */
            @Override public Object call() throws Exception {
                info("Start operation.");

                IgniteFuture f = clientCache().getAndPutAsync(1, 1);

                info("Stop operation.");

                return f.get();
            }
        });
    }

    /**
     * @throws Exception If failed.
     */
    public void testGet() throws Exception {
        bannedMsg.set(GridNearSingleGetRequest.class);

        executeTest(new Callable<Integer>() {
            /** {@inheritDoc} */
            @Override public Integer call() throws Exception {
                info("Start operation.");

                Integer put = (Integer) clientCache().get(1);

                info("Stop operation.");

                return put;
            }
        });
    }

    /**
     * @throws Exception If failed.
     */
    public void testGetAll() throws Exception {
        bannedMsg.set(GridNearGetRequest.class);

        executeTest(new Callable<Integer>() {
            /** {@inheritDoc} */
            @Override public Integer call() throws Exception {
                info("Start operation.");

                Set<Integer> keys = F.asSet(1, 2, 3);

                clientCache().getAll(keys);

                info("Stop operation.");

                return null;
            }
        });
    }

    /**
     *
     * @param call Closure executing cache operation.
     * @throws Exception If failed.
     */
    private <T> void executeTest(Callable<T> call) throws Exception {
        suspended.set(true);

        IgniteInternalFuture<T> fut = GridTestUtils.runAsync(call);

        Thread stopThread = new Thread(new StopRunnable());

        blocked.await();

        stopThread.start();

        stopThread.join(10000L);

        suspended.set(false);

        assert !stopThread.isAlive();

        Exception e = null;

        try {
            fut.get();
        }
        catch (IgniteCheckedException gridException){
            e = gridException;
        }

        assertNotNull(e);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);

        e.printStackTrace(pw);

        assertTrue(sw.toString().contains("node is stopping"));
    }

    /**
     * @throws Exception If failed.
     */
    public void testPutBatch() throws Exception {
        assert !suspended.get();

        IgniteInternalFuture<Void> fut = GridTestUtils.runAsync(new Callable<Void>() {
            /** {@inheritDoc} */
            @Override public Void call() throws Exception {
                for (int i = 0; i < 1_000_000; i++)
                    clientCache().put(i, i);

                return null;
            }
        });

        Thread stopThread = new Thread(new StopRunnable());

        blocked.await();

        stopThread.start();

        stopThread.join(10000L);

        assert !stopThread.isAlive();

        Exception e = null;

        try {
            fut.get();
        }
        catch (IgniteCheckedException gridException){
            e = gridException;
        }

        assertNotNull(e);
    }

    /**
     * @return Client cache.
     */
    private Ignite clientNode() {
        return grid(CLN_GRD);
    }

    /**
     * @return Client cache.
     */
    private IgniteCache<Object, Object> clientCache() {
        return grid(CLN_GRD).cache(CACHE_NAME);
    }

    /**
     * @param cacheName Cache name.
     * @return Cache configuration.
     * @throws Exception In case of error.
     */
    @SuppressWarnings("unchecked")
    private CacheConfiguration cacheConfiguration(@NotNull String cacheName) throws Exception {
        CacheConfiguration cfg = defaultCacheConfiguration();

        cfg.setCacheMode(cacheMode());

        cfg.setAtomicityMode(atomicityMode());

        cfg.setNearConfiguration(null);

        cfg.setName(cacheName);

        return cfg;
    }

    /**
     *
     */
    private class TestTpcCommunicationSpi extends TcpCommunicationSpi {
        /** {@inheritDoc} */
        @Override public void sendMessage(ClusterNode node, Message msg, IgniteInClosure<IgniteException> ackClosure)
            throws IgniteSpiException {
            if (suspended.get()) {
                assert bannedMsg.get() != null;

                if (msg instanceof GridIoMessage
                    && ((GridIoMessage)msg).message().getClass().equals(bannedMsg.get())) {
                    blocked.countDown();

                    return;
                }
            }

            super.sendMessage(node, msg, ackClosure);
        }
    }

    /**
     *
     */
    private class StopRunnable implements Runnable {
        /** {@inheritDoc} */
        @Override public void run() {
            info("Stopping grid...");

            stopGrid(CLN_GRD, true);

            info("Grid stopped.");
        }
    }
}