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

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.cluster.ClusterState;
import org.apache.ignite.compatibility.testframework.junits.Dependency;
import org.apache.ignite.configuration.BinaryConfiguration;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.WALMode;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.lang.IgniteInClosure;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;


/**
 * Tests that upgrade version on persisted inline index is successfull.
 */
@RunWith(Parameterized.class)
public class InlineIndexCompatibilityTest extends IgnitePersistenceCompatibilityAbstractTest {
    /** */
    private static final String TEST_CACHE_NAME = InlineIndexCompatibilityTest.class.getSimpleName();

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

    /** Index to test. */
    private static final String INDEX_NAME = "intval1_val_intval2";

    /** Index to test with configured inline size. */
    private static final String INDEX_SIZED_NAME = "intval1_val_intval2_sized";

    /** Parametrized run param: Ignite version. */
    @Parameterized.Parameter(0)
    public String igniteVer;

    /** Parametrized run param: Inline size is configured by user. */
    @Parameterized.Parameter(1)
    public boolean cfgInlineSize;

    /** Test run configurations: Ignite version, Inline size configuration. */
    @Parameterized.Parameters(name = "ver={0}, cfgInlineSize={1}")
    public static Collection<Object[]> runConfig() {
        return Arrays.asList(new Object[][] {
            /** 2.6.0 is a last version where POJO inlining isn't enabled. */
            {"2.6.0", false},
            {"2.6.0", true},

            {"2.7.0", false},
            {"2.7.0", true},

            {"2.7.6", false},
            {"2.7.6", true},

            {"2.8.0", false},
            {"2.8.0", true},

            {"2.8.1", false},
            {"2.8.1", true},

            {"2.9.0", false},
            {"2.9.0", true},

            {"2.9.1", false},
            {"2.9.1", true}
        });
    }

    /** */
    @Test
    public void testQueryOldInlinedIndex() throws Exception {
        PostStartupClosure closure = cfgInlineSize ? new PostStartupClosureSized() : new PostStartupClosure();
        String idxName = cfgInlineSize ? INDEX_SIZED_NAME : INDEX_NAME;

        doTestStartupWithOldVersion(igniteVer, closure, idxName);
    }

    /** {@inheritDoc} */
    @Override @NotNull protected Collection<Dependency> getDependencies(String igniteVer) {
        Collection<Dependency> dependencies = super.getDependencies(igniteVer);

        if ("2.6.0".equals(igniteVer))
            dependencies.add(new Dependency("h2", "com.h2database", "h2", "1.4.195", false));

        dependencies.add(new Dependency("indexing", "ignite-indexing", false));

        return dependencies;
    }

    /** {@inheritDoc} */
    @Override protected Set<String> getExcluded(String ver, Collection<Dependency> dependencies) {
        Set<String> excluded = super.getExcluded(ver, dependencies);

        if ("2.6.0".equals(ver))
            excluded.add("h2");

        return excluded;
    }

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

        cfg.setPeerClassLoadingEnabled(false);

        cfg.setDataStorageConfiguration(
            new DataStorageConfiguration()
                .setDefaultDataRegionConfiguration(
                    new DataRegionConfiguration()
                        .setPersistenceEnabled(true)
                        .setMaxSize(DataStorageConfiguration.DFLT_DATA_REGION_INITIAL_SIZE)
                )
                // Disable WAL to skip filling index with reading WAL. Instead just start on previous persisted files.
                .setWalMode(WALMode.NONE));

        cfg.setBinaryConfiguration(
            new BinaryConfiguration()
                .setCompactFooter(true)
        );

        return cfg;
    }

    /**
     * Tests opportunity to read data from previous Ignite DB version.
     *
     * @param igniteVer 3-digits version of ignite
     * @throws Exception If failed.
     */
    protected void doTestStartupWithOldVersion(String igniteVer, PostStartupClosure closure, String idxName) throws Exception {
        try {
            startGrid(1, igniteVer,
                new PersistenceBasicCompatibilityTest.ConfigurationClosure(true),
                closure);

            stopAllGrids();

            IgniteEx ignite = startGrid(0);

            assertEquals(1, ignite.context().discovery().topologyVersion());

            ignite.cluster().state(ClusterState.ACTIVE);

            validateResultingCacheData(ignite.cache(TEST_CACHE_NAME), idxName);
        }
        finally {
            stopAllGrids();
        }
    }

    /**
     * Asserts cache contained all expected values as it was saved before.
     *
     * @param cache Cache to check.
     * @param idxName Name of index to check.
     */
    private void validateResultingCacheData(IgniteCache<Object, Object> cache, String idxName) {
        validateRandomRow(cache, idxName);
        validateRandomRange(cache, idxName);
    }

    /** */
    private void validateRandomRow(IgniteCache<Object, Object> cache, String idxName) {
        int val = new Random().nextInt(ROWS_CNT);

        // Select by quering complex index.
        SqlFieldsQuery qry = new SqlFieldsQuery(
            "SELECT * FROM \"" + TEST_CACHE_NAME + "\".EntityValueValue v " +
                "WHERE v.intVal1 = ? and v.val = ? and v.intVal2 = ?;")
            .setArgs(val, new EntityValue(val + 2), val + 1);

        checkIndexUsed(cache, qry, idxName);

        List<List<?>> result = cache.query(qry).getAll();

        assertTrue(result.size() == 1);

        List<?> row = result.get(0);

        assertTrue(row.get(0).equals(new EntityValue(val + 2)));
        assertTrue(row.get(1).equals(val));
        assertTrue(row.get(2).equals(val + 1));
    }

    /** */
    private void validateRandomRange(IgniteCache<Object, Object> cache, String idxName) {
        int pivot = new Random().nextInt(ROWS_CNT);

        // Select by quering complex index.
        SqlFieldsQuery qry = new SqlFieldsQuery(
            "SELECT * FROM \"" + TEST_CACHE_NAME + "\".EntityValueValue v " +
                "WHERE v.intVal1 > ? and v.val > ? and v.intVal2 > ? " +
                "ORDER BY v.val, v.intVal1, v.intVal2;")
            .setArgs(pivot, new EntityValue(pivot), pivot);

        checkIndexUsed(cache, qry, idxName);

        List<List<?>> result = cache.query(qry).getAll();

        // For strict comparison. There was an issues with >= comparison for some versions.
        pivot += 1;

        assertTrue(result.size() == ROWS_CNT - pivot);

        for (int i = 0; i < ROWS_CNT - pivot; i++) {
            List<?> row = result.get(i);

            assertTrue(row.get(0).equals(new EntityValue(pivot + i + 2)));
            assertTrue(row.get(1).equals(pivot + i));
            assertTrue(row.get(2).equals(pivot + i + 1));
        }
    }

    /** */
    private void checkIndexUsed(IgniteCache<?, ?> cache, SqlFieldsQuery qry, String idxName) {
        assertTrue("Query does not use index.", queryPlan(cache, qry).toLowerCase().contains(idxName.toLowerCase()));
    }

    /** */
    public static class PostStartupClosure implements IgniteInClosure<Ignite> {
        /** {@inheritDoc} */
        @Override public void apply(Ignite ignite) {
            ignite.active(true);

            CacheConfiguration<Object, Object> cacheCfg = new CacheConfiguration<>();
            cacheCfg.setName(TEST_CACHE_NAME);
            cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
            cacheCfg.setBackups(1);

            cacheCfg.setIndexedTypes(Integer.class, EntityValueValue.class);

            IgniteCache<Object, Object> cache = ignite.createCache(cacheCfg);

            saveCacheData(cache);

            ignite.active(false);

            try {
                Thread.sleep(1_000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        /**
         * Create a complex index (int, pojo, int). Check that middle POJO object is correctly available from inline.
         *
         * @param cache to be filled with data. Results may be validated in {@link #validateResultingCacheData(IgniteCache, String)}.
         */
        protected void saveCacheData(IgniteCache<Object, Object> cache) {
            for (int i = 0; i < ROWS_CNT; i++)
                cache.put(i, new EntityValueValue(new EntityValue(i + 2), i, i + 1));

            // Create index (int, pojo, int).
            cache.query(new SqlFieldsQuery(
                    "CREATE INDEX " + INDEX_NAME + " ON \"" + TEST_CACHE_NAME + "\".EntityValueValue " +
                    "(intVal1, val, intVal2)")).getAll();
        }
    }

    /** */
    public static class PostStartupClosureSized extends PostStartupClosure {
        /** {@inheritDoc} */
        @Override protected void saveCacheData(IgniteCache<Object, Object> cache) {
            for (int i = 0; i < ROWS_CNT; i++)
                cache.put(i, new EntityValueValue(new EntityValue(i + 2), i, i + 1));

            // Create index (int, pojo, int) with configured inline size.
            cache.query(new SqlFieldsQuery(
                "CREATE INDEX " + INDEX_SIZED_NAME + " ON \"" + TEST_CACHE_NAME + "\".EntityValueValue " +
                    "(intVal1, val, intVal2) " +
                    "INLINE_SIZE 100")).getAll();
        }
    }

    /** POJO object aimed to be inlined. */
    public static class EntityValue {
        /** */
        private final int val;

        /** */
        public EntityValue(int val) {
            this.val = val;
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return "EV[value=" + val + "]";
        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return val;
        }

        /** {@inheritDoc} */
        @Override public boolean equals(Object other) {
            return val == ((EntityValue) other).val;
        }
    }

    /** Represents a cache value with 3 fields (POJO, int, int). */
    public static class EntityValueValue {
        /** */
        @QuerySqlField
        private final EntityValue val;

        /** */
        @QuerySqlField
        private final int intVal1;

        /** */
        @QuerySqlField
        private final int intVal2;

        /** */
        public EntityValueValue(EntityValue val, int val1, int val2) {
            this.val = val;
            intVal1 = val1;
            intVal2 = val2;
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return "EVV[value=" + val + "]";
        }
    }
}
