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

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CachePeekMode;
import org.apache.ignite.cache.store.CacheStore;
import org.apache.ignite.cache.store.CacheStoreAdapter;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.lang.IgniteBiInClosure;

import javax.cache.Cache;
import javax.cache.configuration.Factory;
import javax.cache.expiry.Duration;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CacheLoaderException;
import javax.cache.integration.CacheWriterException;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.MutableEntry;
import java.util.concurrent.TimeUnit;

/**
 * Starts up an empty node with example compute configuration.
 */
public class ExpiryExample {
    /**
     * Start up an empty node with example compute configuration.
     *
     * @param args Command line arguments, none required.
     * @throws Exception If failed.
     */
    public static void main(String[] args) throws Exception {
        Ignite ignite = Ignition.start("examples/config/example-ignite.xml");

        CacheConfiguration<Integer, Integer> cacheCfg = new CacheConfiguration<>("cache");

        cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); // Change to ATOMIC and get a different result.

        cacheCfg.setReadThrough(true);

        cacheCfg.setCacheStoreFactory(new Factory<CacheStore<Integer, Integer>>() {
            @Override public CacheStore<Integer, Integer> create() {
                return new ExampleCacheStore();
            }
        });

        cacheCfg.setExpiryPolicyFactory(new Factory<ExpiryPolicy>() {
            @Override public ExpiryPolicy create() {
                return new ExampleExpiryPolicy();
            }
        });

        IgniteCache<Integer, Integer> cache = ignite.getOrCreateCache(cacheCfg);

        cache.invoke(1, new EntryProcessor<Integer, Integer, Object>() {
            @Override public Object process(MutableEntry<Integer, Integer> e, Object... arguments) throws EntryProcessorException {
                return 1;
            }
        });

        Thread.sleep(1000);

        System.out.println(cache.localPeek(1, CachePeekMode.OFFHEAP));
    }

    /**
     *
     */
    static class ExampleExpiryPolicy implements ExpiryPolicy {

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

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

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

    /**
     *
     */
    static class ExampleCacheStore extends CacheStoreAdapter<Integer, Integer> {
        /** {@inheritDoc} */
        @Override public void loadCache(IgniteBiInClosure<Integer, Integer> clo, Object... args) {
            clo.apply(1, 1);
        }

        /** {@inheritDoc} */
        @Override public Integer load(Integer key) throws CacheLoaderException {
            return key;
        }

        /** {@inheritDoc} */
        @Override public void write(Cache.Entry<? extends Integer, ? extends Integer> entry) throws CacheWriterException {
        }

        /** {@inheritDoc} */
        @Override public void delete(Object key) throws CacheWriterException {
        }
    }
}
