package com.marvinelsen.willow

import com.marvinelsen.willow.config.Config
import com.marvinelsen.willow.domain.SqliteDictionary
import com.marvinelsen.willow.ui.controllers.DetailsController
import com.marvinelsen.willow.ui.controllers.MainController
import com.marvinelsen.willow.ui.controllers.MenuController
import com.marvinelsen.willow.ui.controllers.SearchController
import com.marvinelsen.willow.ui.controllers.SearchResultsController
import com.marvinelsen.willow.ui.services.FindCharacterService
import com.marvinelsen.willow.ui.services.FindWordsService
import com.marvinelsen.willow.ui.services.SearchService
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.Scene
import javafx.scene.image.Image
import javafx.scene.layout.BorderPane
import javafx.scene.text.Font
import javafx.stage.Stage
import javafx.util.Callback
import java.sql.DriverManager
import java.util.ResourceBundle

class WillowApplication : Application() {
    companion object {
        private const val WINDOW_TITLE = "Willow"
        private const val WINDOW_MIN_HEIGHT = 480.0
        private const val WINDOW_MIN_WIDTH = 640.0
        private const val WINDOW_WIDTH = 640.0
        private const val WINDOW_HEIGHT = 480.0

        private const val FONT_SIZE = 12.0

        private const val JDBC_CONNECTION_STRING = "jdbc:sqlite::resource:data/dictionary.db"
    }

    override fun init() {
        loadFonts()
    }

    override fun start(primaryStage: Stage) {
        val connection = DriverManager.getConnection(JDBC_CONNECTION_STRING).apply {
            autoCommit = false
        }
        val dictionary = SqliteDictionary(connection)
        val searchService = SearchService(dictionary)
        val findWordsService = FindWordsService(dictionary)
        val findCharacterService = FindCharacterService(dictionary)
        val model = Model(searchService, findWordsService, findCharacterService)
        val config = Config()
        config.load()

        val fxmlLoader = FXMLLoader()
        fxmlLoader.resources = ResourceBundle.getBundle("i18n/willow", config.locale.value)
        fxmlLoader.controllerFactory = Callback { type ->
            when (type) {
                MainController::class.java -> MainController(model)
                MenuController::class.java -> MenuController(model, config)
                DetailsController::class.java -> DetailsController(model, config)
                SearchController::class.java -> SearchController(model)
                SearchResultsController::class.java -> SearchResultsController(model, config)
                else -> error("Trying to instantiate unknown controller type $type")
            }
        }

        val root = fxmlLoader.load(javaClass.getResourceAsStream("/fxml/main.fxml")) as BorderPane

        val primaryScene = Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT)
        // primaryScene.stylesheets.add(javaClass.getResource("/css/dark.css")?.toExternalForm()!!)

        primaryStage.apply {
            title = WINDOW_TITLE
            minWidth = WINDOW_MIN_WIDTH
            minHeight = WINDOW_MIN_HEIGHT
            scene = primaryScene
            icons.add(Image(javaClass.getResourceAsStream("/img/icon.png")))
        }.show()
    }

    private fun loadFonts() {
        Font.loadFont(javaClass.getResourceAsStream("/fonts/inter.ttf"), FONT_SIZE)
        Font.loadFont(javaClass.getResourceAsStream("/fonts/tw-kai.ttf"), FONT_SIZE)
        Font.loadFont(javaClass.getResourceAsStream("/fonts/noto-sans-tc-regular.ttf"), FONT_SIZE)
        Font.loadFont(javaClass.getResourceAsStream("/fonts/noto-sans-tc-bold.ttf"), FONT_SIZE)
    }
}

@Suppress("SpreadOperator")
fun main(args: Array<String>) {
    Application.launch(WillowApplication::class.java, *args)
}
