package training.ignite;

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.affinity.AffinityKeyMapped;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
import org.jetbrains.annotations.NotNull;

import java.io.Serializable;
import java.util.List;


class Order implements Serializable {
    @QuerySqlField
    Integer id;

    @QuerySqlField Integer customerId;

    @QuerySqlField String product;

    public Order(Integer id, Integer customerId, String product) {
        this.id = id;
        this.customerId = customerId;
        this.product = product;
    }

    public Integer getCustomerId() {
        return customerId;
    }

    public Integer getId() {
        return id;
    }

    public String getProduct() {
        return product;
    }
}


public class JoinQueryTest {
    public static final String ORDER_CACHE = "orderCache";
    public static void main(String[] args) {
        try (Ignite ignite = Ignition.start()) {
            IgniteCache<Integer, Order> orderCache = ignite.getOrCreateCache(ordersCacheConfig());
            initializeCaches(orderCache);
            testJoinQuery(orderCache);
        }
    }
    public static void testJoinQuery(IgniteCache<Integer, Order> orderCache) {
        String query = "SELECT DISTINCT C.id, C.product, O.id FROM   \n" +
                "   (select id, product FROM \"orderCache\".\"ORDER\" WHERE id IN ( 1, 2)) C \n" +
                "LEFT JOIN \n" +
                "   (select id, product FROM \"orderCache\".\"ORDER\" WHERE  id IN (3, 2)) O \n" +
                "ON\n" +
                " C.id = O.id";

        checkQuery(query, orderCache , 3);
    }
    private static void checkQuery(String sql, IgniteCache<Integer, Order> cache, int expSize) {
        List<List<?>> res = cache.query(new SqlFieldsQuery(sql)).getAll();
        for ( List<?> row: res) {
            System.out.println(row);
        }
        System.out.println("Size of actual output " + res.size());
        if (expSize != res.size()) {
            System.out.println("Expected size " + expSize + " is not equal to Actual size " + res.size());
        }
        else {
            System.out.println("Join working as expected.");
        }
    }
    public static void initializeCaches(IgniteCache<Integer, Order> orderCache){
        Order o1 = new Order(1, 1, "Laptop");
        Order o2 = new Order(2, 2, "Keyboard");
        Order o3 = new Order(3, 3, "Speaker");
        Order o4 = new Order(4, 2, "Mouse");
        Order o5 = new Order(5, 1, "Monitor");

        orderCache.put(o1.getId(), o1);
        orderCache.put(o2.getId(), o2);
        orderCache.put(o3.getId(), o3);
        orderCache.put(o4.getId(), o4);
        orderCache.put(o5.getId(), o5);
        System.out.println("Order cache initialized");
    }
    @NotNull
    public static CacheConfiguration<Integer, Order> ordersCacheConfig() {
        CacheConfiguration<Integer, Order> orderCacheCfg =
                new CacheConfiguration<>(ORDER_CACHE);
        orderCacheCfg.setCacheMode(CacheMode.PARTITIONED); // Default.
        orderCacheCfg.setBackups(1);
        orderCacheCfg.setIndexedTypes(Integer.class, Order.class);
        return orderCacheCfg;
    }
}
