package org.kishore.backends.ignite;

import java.util.Collections;
import java.util.List;

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.CacheMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
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.TransactionConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;

public class IgniteClient {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
			
		System.out.println(" cache set beginning " );
		  DataRegionConfiguration dr = new DataRegionConfiguration();
		    dr.setPersistenceEnabled(true);
		    dr.setMaxSize(10l*1024*1024*1024);
		    DataStorageConfiguration ds = new DataStorageConfiguration();
		    ds.setDefaultDataRegionConfiguration(dr);
		    ds.setPageSize(4096);
		    IgniteConfiguration serverConfig = new IgniteConfiguration()

		        .setIgniteInstanceName("nitin-instance")
		        .setDataStorageConfiguration(ds)
		        .setDiscoverySpi(
		            new TcpDiscoverySpi().setIpFinder(

		            new TcpDiscoveryVmIpFinder().setAddresses(Collections
		                .singleton("127.0.0.1:47500..47502"))

		            ));

		    serverConfig.setTransactionConfiguration(new TransactionConfiguration());
		    System.out.println("cache started in" );
		    Ignite ignite = Ignition.start(serverConfig);
		    ignite.active(true);
		    System.out.println("cache started" );
		    
		    // ALL caches are already created
		    CacheConfiguration<Long, Ignite_DSAttributeStore> cacheCfg =
		        new CacheConfiguration<>("Ignite_DSAttributeStore");

		    cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
		    cacheCfg
		        .setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
		    cacheCfg.setIndexedTypes(Long.class, Ignite_DSAttributeStore.class);
		    cacheCfg.setCacheMode(CacheMode.LOCAL);
		    IgniteCache<Long, Ignite_DSAttributeStore> cache = ignite
		        .getOrCreateCache(cacheCfg);
		    //this.cache = cache;
		    System.out.println(" cache set " +cache );
		    CacheConfiguration<Long, Ignite_DN> cacheCfgDN =
		        new CacheConfiguration<>("dn");

		    cacheCfgDN.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
		    cacheCfgDN
		        .setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
		    cacheCfgDN.setCacheMode(CacheMode.LOCAL);
		    cacheCfgDN.setIndexedTypes(Long.class, Ignite_DN.class);
		    IgniteCache<Long, Ignite_DN> cacheDN = ignite.getOrCreateCache(cacheCfgDN);

/*		    IgniteCache<Long, Ignite_DN> cacheDN = ignite
		        .cache("dn");

		    System.out.println("cache "+cacheDN.get(10L).getRdn() );*/

		    
			 CacheConfiguration<Long, Ignite_ObjectClass> 
	         cacheCfgIndex = null;
	        cacheCfgIndex = new CacheConfiguration<>("objectclass");
	        cacheCfgIndex.setIndexedTypes(Long.class, Ignite_ObjectClass.class);
	        cacheCfgIndex.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
	        cacheCfgIndex
	          .setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
	        cacheCfgIndex.setCacheMode(CacheMode.LOCAL);
	        ignite.getOrCreateCache(cacheCfgIndex);
	        System.out.println(" befire query ");

	        // DATA is already pushed in from other client
/*		    String s = "SELECT st.entryID,st.attrName,st.attrValue, st.attrsType " 
		    		+ "FROM \"Ignite_DSAttributeStore\".IGNITE_DSATTRIBUTESTORE st "
		    		+"INNER JOIN \"dn\".Ignite_DN dn "
		    		+" ON dn.entryID = st.entryID "
		    		+" INNER JOIN \"objectclass\".IGNITE_OBJECTCLASS at1 "
		    		+" ON dn.entryID = at1.entryID "
		    		+" WHERE (at1.attrValue = 'person') AND "
		    		+ "( dn.parentDN like 'dc=ignite,%')"
		    		+"  AND st.attrKind IN ('u','o') order by st.entryID ";
		    
		    
		    System.out.println("before explain");
		    String s1 = "EXPLAIN SELECT store.entryID,store.attrName,store.attrValue, store.attrsType FROM \"dn\".Ignite_DN dn, Ignite_DSAttributeStore store WHERE dn.entryID in (" 
		+"(SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'subentry' )"
		+"UNION "  
		+"(SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'ldapsubentry' )" 
												  +")"
  +" AND ( dn.parentDN like 'dc=ignite,%' OR   ( dn.rdn='dc=ignite' and dn.parentDN=',' ) )"
  +"AND dn.entryID = store.entryID AND store.attrKind IN ('u','o') order by store.entryID";
	String s1 = "SELECT store.entryID,store.attrName,store.attrValue, store.attrsType FROM \"dn\".Ignite_DN dn, \"Ignite_DSAttributeStore\".Ignite_DSAttributeStore store WHERE dn.entryID in (" 
		+"(SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'subentry' )"
		+"UNION "  
		+"(SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'ldapsubentry' )" 
												  +")"
  +" AND ( dn.parentDN like 'dc=ignite,%')"
  +"AND dn.entryID = store.entryID AND store.attrKind IN ('u','o') order by store.entryID";
	
	String s3 ="SELECT f.entryID,f.attrName,f.attrValue, f.attrsType "
+"FROM "
+"( select st.entryID,st.attrName,st.attrValue, st.attrsType from " 

+"(" 
   +"SELECT entryID as entryID FROM \"objectclass\".IGNITE_OBJECTCLASS WHERE attrValue = 'person' "  
   +" UNION " 
   +" SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'ldapsubentry' " 
+" ) t" 
  +" INNER JOIN \"Ignite_DSAttributeStore\".IGNITE_DSATTRIBUTESTORE st ON st.entryID = t.entryID " 			
+" ) f "
+ "INNER JOIN "

+ " ( "
+" SELECT entryID from \"dn\".Ignite_DN where parentDN like 'dc=ignite,%' "
 +")  "
+" dnt"
     
+ " ON f.entryID = dnt.entryID"
+ " order by f.entryID";
	
	String s4 = "SELECT f.entryID,f.attrName,f.attrValue, f.attrsType FROM "
			+"( select st.entryID,st.attrName,st.attrValue, st.attrsType from (  (SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'subentry' )  UNION  (SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass at1 WHERE at1.attrValue = 'person' )  ) t INNER JOIN \"Ignite_DSAttributeStore\".IGNITE_DSATTRIBUTESTORE st ON st.entryID = t.entryID  WHERE st.attrKind IN ('u','o')  ) f  INNER JOIN  (  SELECT entryID from \"dn\".Ignite_DN where parentDN like 'dc=ignite,%' )   " 
			+" dnt ON f.entryID = dnt.entryID order by f.entryID ";

		    												  
		    //QueryCursor<List<?>> topMostEntry = cacheDN.query(new SqlFieldsQuery(
			  //      s4).setEnforceJoinOrder(true));
		    //List<List<?>> lst =  topMostEntry.getAll();
			  //  System.out.println(" done "+lst.size());
*/	
    final String query1 = "SELECT "
            + "f.entryID,f.attrName,f.attrValue, "
            + "f.attrsType "
            + "FROM "
            +"( select st.entryID,st.attrName,st.attrValue, st.attrsType from "
            +"(SELECT at1.entryID FROM \"objectclass\".Ignite_ObjectClass"
                + " at1 WHERE "
                + " at1.attrValue= ? )  t"
            +" INNER JOIN \"Ignite_DSAttributeStore\".IGNITE_DSATTRIBUTESTORE st ON st.entryID = t.entryID "
            + " WHERE st.attrKind IN ('u','o') "
            +" ) f "
            + " INNER JOIN "
            + " ( "
            +" SELECT entryID from \"dn\".Ignite_DN where parentDN like ? "
             +")  "
            +" dnt"
            + " ON f.entryID = dnt.entryID"
            + " order by f.entryID";

        String queryWithType = query1;
        QueryCursor<List<?>> cursor = cache.query(new SqlFieldsQuery(
            "EXPLAIN "+queryWithType).setEnforceJoinOrder(true).setArgs("person", "dc=ignite,%"));/*, base
            .rdn().toString(), reverseDN(base.getParent())));*/
        System.out.println("EXPLAIN SUBTREE "+cursor.getAll() );

        cursor = cache.query(new SqlFieldsQuery(
            queryWithType).setEnforceJoinOrder(true).setArgs("person", "dc=ignite,%"));
        long start = System.currentTimeMillis();
        List<List<?>> lst = cursor.getAll();
        for (List<?> result: lst) {
        	result.get(0);
        }
        System.out.println("TOTAL "+lst.size() );
        long end = System.currentTimeMillis();
        System.out.println(" total time taken "+(end - start));
	}

}
