/*
 * 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.util.concurrent.TimeUnit;
import javax.cache.configuration.Factory;
import javax.cache.expiry.AccessedExpiryPolicy;
import javax.cache.expiry.CreatedExpiryPolicy;
import javax.cache.expiry.Duration;
import javax.cache.expiry.ExpiryPolicy;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.CachePeekMode;
import org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.internal.util.typedef.PA;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.MvccFeatureChecker;
import org.apache.ignite.testframework.junits.IgniteCacheConfigVariationsAbstractTest;
import org.junit.Ignore;
import org.junit.Test;

/**
 *
 */
@SuppressWarnings("unchecked")
public class IgniteCacheReadThroughEvictionSelfTest extends IgniteCacheConfigVariationsAbstractTest {
    /** */
    private static final int TIMEOUT = 400;

    /** */
    private static final int KEYS = 100;

    /** {@inheritDoc} */
    @Override protected void beforeTest() throws Exception {
        MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.CACHE_STORE);

        super.beforeTest();
    }

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

    /**
     * @throws Exception if failed.
     */
    @Ignore("https://issues.apache.org/jira/browse/IGNITE-11849")
    @Test
    public void testReadThroughWithExpirePolicy() throws Exception {
        MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.EXPIRATION);

        Ignite ig = testedGrid();

        CacheConfiguration<Object, Object> cc = variationConfig("expire");

        IgniteCache<Object, Object> cache = ig.createCache(cc);

        try {
            ExpiryPolicy exp = new CreatedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, TIMEOUT));

            for (int i = 0; i < KEYS; i++)
                cache.withExpiryPolicy(exp).put(key(i), value(i));

            U.sleep(TIMEOUT);

            waitEmpty(cc.getName());

            exp = new AccessedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, TIMEOUT));

            for (int i = 0; i < KEYS; i++) {
                assertEquals(value(i), cache.get(key(i)));

                cache.withExpiryPolicy(exp).get(key(i));
            }

            U.sleep(TIMEOUT);

            waitEmpty(cc.getName());

            for (int i = 0; i < KEYS; i++)
                assertEquals(value(i), cache.get(key(i)));
        }
        finally {
            destroyCacheSafe(ig, cc.getName());
        }
    }

    /**
     * @throws Exception if failed.
     */
    @Ignore("https://issues.apache.org/jira/browse/IGNITE-11849")
    @Test
    public void testReadThroughExpirePolicyConfigured() throws Exception {
        MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.EXPIRATION);

        Ignite ig = testedGrid();

        CacheConfiguration<Object, Object> cc = variationConfig("expireConfig");

        cc.setExpiryPolicyFactory(new ExpirePolicyFactory());

        IgniteCache<Object, Object> cache = ig.createCache(cc);

        try {
            for (int i = 0; i < KEYS; i++)
                cache.put(key(i), value(i));

            U.sleep(TIMEOUT);

            waitEmpty(cc.getName());

            for (int i = 0; i < KEYS; i++) {
                assertEquals(value(i), cache.get(key(i)));

                // Access expiry.
                cache.get(key(i));
            }

            U.sleep(TIMEOUT);

            waitEmpty(cc.getName());

            for (int i = 0; i < KEYS; i++)
                assertEquals(value(i), cache.get(key(i)));

            for (int i = 0; i < KEYS; i++) {
                assertEquals(value(i), cache.get(key(i)));

                // Update expiry.
                cache.put(key(i), value(i));
            }

            U.sleep(TIMEOUT);

            waitEmpty(cc.getName());

            for (int i = 0; i < KEYS; i++)
                assertEquals(value(i), cache.get(key(i)));
        }
        finally {
            destroyCacheSafe(ig, cc.getName());
        }
    }

    /**
     * @throws Exception if failed.
     */
    @Test
    public void testReadThroughEvictionPolicy() throws Exception {
        MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.EVICTION);

        Ignite ig = testedGrid();

        CacheConfiguration<Object, Object> cc = variationConfig("eviction");

        cc.setEvictionPolicy(new FifoEvictionPolicy(1));
        cc.setOnheapCacheEnabled(true);

        final IgniteCache<Object, Object> cache = ig.createCache(cc);

        try {
            for (int i = 0; i < KEYS; i++)
                cache.put(key(i), value(i));

            assertTrue(GridTestUtils.waitForCondition(new PA() {
                @Override public boolean apply() {
                    int size = cache.size(CachePeekMode.ONHEAP);
                    int offheapSize = cache.size(CachePeekMode.OFFHEAP);

                    System.out.println("Cache [onHeap=" + size + ", offHeap=" + offheapSize + ']');

                    return size <= testsCfg.gridCount();
                }
            }, 30_000));

            for (int i = 0; i < KEYS; i++)
                assertEquals(value(i), cache.get(key(i)));
        }
        finally {
            destroyCacheSafe(ig, cc.getName());
        }
    }

    /**
     * @throws Exception if failed.
     */
    @Ignore("https://issues.apache.org/jira/browse/IGNITE-11849")
    @Test
    public void testReadThroughSkipStore() throws Exception {
        Ignite ig = testedGrid();

        CacheConfiguration<Object, Object> cc = variationConfig("skipStore");

        final IgniteCache<Object, Object> cache = ig.createCache(cc);

        try {
            for (int i = 0; i < KEYS; i++) {
                cache.put(key(i), value(i));

                cache.withSkipStore().remove(key(i));
            }

            waitEmpty(cc.getName());

            for (int i = 0; i < KEYS; i++)
                assertEquals(value(i), cache.get(key(i)));
        }
        finally {
            destroyCacheSafe(ig, cc.getName());
        }
    }

    /**
     * @return Variation test configuration.
     */
    private CacheConfiguration<Object, Object> variationConfig(String suffix) {
        CacheConfiguration ccfg = testsCfg.configurationFactory().cacheConfiguration(getTestIgniteInstanceName(testedNodeIdx));

        ccfg.setName(cacheName() + "_" + suffix);

        return ccfg;
    }

    /**
     * @throws Exception if failed.
     */
    private void waitEmpty(final String name) throws Exception {
        boolean success = GridTestUtils.waitForCondition(new PA() {
            @Override public boolean apply() {
                for (Ignite g : G.allGrids()) {
                    GridCacheAdapter<Object, Object> cache = ((IgniteEx)g).context().cache().internalCache(name);

                    if (cache == null)
                        return true;

                    if (!cache.isEmpty())
                        return false;
                }

                return true;
            }
        }, getTestTimeout());

        assertTrue("Failed to wait for the cache to be empty", success);
    }

    /**
     * @param ig Ignite.
     * @param cacheName Cache name to destroy.
     * @throws IgniteCheckedException If failed.
     */
    private void destroyCacheSafe(Ignite ig, final String cacheName) throws IgniteCheckedException {
        ig.destroyCache(cacheName);

        GridTestUtils.waitForCondition(new PA() {
            @Override public boolean apply() {
                for (Ignite g : G.allGrids()) {
                    IgniteInternalCache<Object, Object> cache = ((IgniteEx)g).context().cache().cache(cacheName);

                    if (cache != null)
                        return false;
                }

                return true;
            }
        }, getTestTimeout());
    }

    /**
     *
     */
    private static class ExpirePolicyFactory implements Factory<ExpiryPolicy> {
        /** {@inheritDoc} */
        @Override public ExpiryPolicy create() {
            return new ExpiryPolicy() {
                @Override public Duration getExpiryForCreation() {
                    return new Duration(TimeUnit.MILLISECONDS, TIMEOUT);
                }

                /** {@inheritDoc} */
                @Override public Duration getExpiryForAccess() {
                    return new Duration(TimeUnit.MILLISECONDS, TIMEOUT);
                }

                /** {@inheritDoc} */
                @Override public Duration getExpiryForUpdate() {
                    return new Duration(TimeUnit.MILLISECONDS, TIMEOUT);
                }
            };
        }
    }
}
