package com.marvinelsen.willow.cedict

import com.marvinelsen.cedict.api.CedictParser
import com.marvinelsen.chinese.transliteration.TransliterationSystem
import com.marvinelsen.chinese.transliteration.Zhuyin
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.Json
import java.sql.DriverManager
import java.util.zip.GZIPInputStream

const val JDBC_CONNECTION_STRING = "jdbc:sqlite:dictionary.db"

@Suppress("MagicNumber", "LongMethod", "MaximumLineLength", "MaxLineLength")
fun main() {
    val connection = DriverManager.getConnection(JDBC_CONNECTION_STRING).apply {
        autoCommit = false
    }

    val statement = connection.createStatement()
    statement.executeUpdate(
        """
        CREATE TABLE IF NOT EXISTS cedict(
            id INTEGER PRIMARY KEY,
            traditional TEXT NOT NULL,
            simplified TEXT NOT NULL,
            pinyin_with_tone_marks TEXT NOT NULL,
            pinyin_with_tone_numbers TEXT NOT NULL,
            zhuyin TEXT NOT NULL,
            definitions JSON NOT NULL,
            character_count INTEGER NOT NULL,
            CONSTRAINT character_count_gte CHECK(character_count > 0)
        );
        """.trimIndent()
    )
    statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_traditional ON cedict (traditional)")
    statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_simplified ON cedict (simplified)")
    statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_character_count ON cedict (character_count)")

    val cedictParser = CedictParser.instance
    val cedictEntries =
        cedictParser.parseCedict(
            GZIPInputStream(object {}.javaClass.getResourceAsStream("/data/cedict_1_0_ts_utf-8_mdbg.txt.gz")!!)
        )

    val insertStatement =
        connection.prepareStatement(
            "INSERT OR IGNORE INTO cedict(traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, definitions, character_count) VALUES(?,?,?,?,?,?,?)"
        )
    for (entry in cedictEntries) {
        try {
            insertStatement.setString(1, entry.traditional)
            insertStatement.setString(2, entry.simplified)
            insertStatement.setString(
                3,
                entry.pinyinSyllables.joinToString(
                    separator = " "
                ) { it.format(TransliterationSystem.PINYIN_WITH_TONE_MARKS) }
            )
            insertStatement.setString(
                4,
                entry.pinyinSyllables.joinToString(
                    separator = " "
                ) { it.format(TransliterationSystem.PINYIN_WITH_TONE_NUMBERS) }
            )
            insertStatement.setString(
                5,
                entry.pinyinSyllables.joinToString(
                    separator = Zhuyin.SEPARATOR
                ) { it.format(TransliterationSystem.ZHUYIN) }
            )
            insertStatement.setString(
                6,
                Json.encodeToString(
                    ListSerializer(ListSerializer(String.serializer())),
                    entry.definitions.map { it.glosses }
                )
            )
            insertStatement.setInt(7, entry.traditional.length)
        } catch (_: Exception) {
            // no-op
        }

        insertStatement.addBatch()
    }

    insertStatement.executeBatch()
    connection.commit()

    insertStatement.close()
    statement.close()
    connection.close()
}
