//import java.util
//import javax.cache.Cache
import javax.cache.configuration.FactoryBuilder
import javax.cache.expiry.{CreatedExpiryPolicy, Duration}

//import grizzled.slf4j.Logging
//import org.apache.ignite.cache.eviction.lru.LruEvictionPolicy
//import org.apache.ignite.cache.store.CacheStoreAdapter
import org.apache.ignite.cache.{CacheAtomicityMode, CacheMode}
import org.apache.ignite.{Ignite, IgniteCache}
import org.apache.ignite.configuration._
//import org.apache.ignite.lang.IgniteBiInClosure
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder

import scala.collection.JavaConverters._
//import scala.reflect.ClassTag


object IgniteConfigGenerator {

  def getRegionConfig(name: String, sizeInMegs : Long) : DataRegionConfiguration = {
    (new DataRegionConfiguration)
      .setName(name)
      .setInitialSize(sizeInMegs * 1024 * 1024)
      .setMaxSize(sizeInMegs * 1024 * 1024)
      .setPersistenceEnabled(false)
      .setPageEvictionMode(DataPageEvictionMode.RANDOM_LRU)
      .setMetricsEnabled(true)
      .setEvictionThreshold(.9)
  }

  def basicIgniteConfig(hostname: String, discoveryPort: Int, commPort: Int, commPortRange: Int): IgniteConfiguration = {

    val spi: TcpDiscoverySpi = new TcpDiscoverySpi
    val ipFinder: TcpDiscoveryVmIpFinder = new TcpDiscoveryVmIpFinder
    val ipFinderAddresses = List(s"$hostname:$discoveryPort..${discoveryPort+9}")

    ipFinder.setAddresses(ipFinderAddresses.asJavaCollection)
    spi.setIpFinder(ipFinder)

    // Even though this is a client it binds to a TCP port like a server, for running in IDE force
    // to a different port from the materializer.   This does not matter in a container where there are no port conflict issues
    val tcpSpi = new TcpCommunicationSpi()
    tcpSpi.setLocalPort(commPort)
    tcpSpi.setLocalPortRange(commPortRange)


    val igniteConfig: IgniteConfiguration = new IgniteConfiguration
    igniteConfig.setDiscoverySpi(spi).setCommunicationSpi(tcpSpi)
      .setPeerClassLoadingEnabled(false)

    val refDataConfig : DataRegionConfiguration = getRegionConfig("RefData", 21L)

    // Setting the data region configuration.
    val  storageCfg : DataStorageConfiguration = new DataStorageConfiguration
    storageCfg.getDefaultDataRegionConfiguration.setMaxSize(10 * 1024 * 1024)  // we want to manage all memory, so make the unused default very small
    storageCfg.setDataRegionConfigurations(refDataConfig)

    igniteConfig.setDataStorageConfiguration(storageCfg)
  }

  def initCache[Int, String]
    (ignite: Ignite,
    cacheName: java.lang.String,
    persistenceEnabled : Boolean,
    memRegion: Option[String] = None
  ): IgniteCache[Int, String] = {

    val cfg = new CacheConfiguration[Int, String]

    cfg.setName(cacheName)
      .setCacheMode(CacheMode.PARTITIONED)
      .setAtomicityMode(CacheAtomicityMode.ATOMIC)
      .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ETERNAL)) // never throw away data
      .setStatisticsEnabled(true)

    cfg.setIndexedTypes(classOf[java.lang.Integer], classOf[java.lang.String])

    if (persistenceEnabled) {
      val cacheFactory = FactoryBuilder.factoryOf("CacheJdbcPlacebo")
      cfg.setCacheStoreFactory(cacheFactory)
        .setReadThrough(true)
    }

    memRegion.foreach(rg => cfg.setDataRegionName(rg.asInstanceOf[java.lang.String]))
    ignite.getOrCreateCache(cfg)
  }

}
