package ru.yandex.featurer.utils.application

import java.io.File

import com.typesafe.config.{Config, ConfigFactory, ConfigParseOptions, ConfigResolveOptions}
import org.slf4j.LoggerFactory
import ru.yandex.featurer.utils.config.EnvironmentAwareIncluder
import ru.yandex.kungfu
import ru.yandex.kungfu.application.BaseApplicationResources

/**
 * @author avhaliullin
 */
abstract class TypesafeApplication extends
kungfu.application.Application[BaseApplicationResources]
with AbstractApp {
  /**
   * Имя ресурса с конфигом приложения,
   * <b>Нужно имплементить def'ом, не val'ом!</b>
   * Иначе все поломается из-за DelayedInit.
   * Аргументом конструктора не передать, из-за https://issues.scala-lang.org/browse/SI-4396
   *
   * @return
   */
  def configResource: String

  val config = {
    val log = LoggerFactory.getLogger(classOf[TypesafeApplication])
    val overrideConfFile = new File(getApplicationResources.getConfig.getFile.getAbsolutePath + "/application.override")

    val overrideConfig = ConfigFactory.parseFileAnySyntax(overrideConfFile)
    overrideConfig withFallback ConfigFactory.load(configResource,
      ConfigParseOptions.defaults().prependIncluder(new EnvironmentAwareIncluder(getEnvironment, getApplicationResources.getConfig.getFile)),
      ConfigResolveOptions.defaults()
    )
  }

  protected def postInit() {
    for (x <- _postInit) x()
  }

  def config(path: String): Config = config.getConfig(path)

  def doMain(args: Array[String]) {
    val log = LoggerFactory.getLogger(classOf[TypesafeApplication])
    try {
      log.info("Executing doMain in TypesafeApplication")
      for (x <- init) x()
      postInit()
    } catch {
      case e: Throwable =>
        log.error("Application init failed", e)
        throw e
    }
  }

  def main(args: Array[String]) {
    try {
      stat(args)
    } catch {
      case e: Throwable =>
        LoggerFactory.getLogger(classOf[TypesafeApplication]).error("Shutting down due to error", e)
        System.exit(1)
    }
  }
}

