package net.taehui.twilight

import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonProperty
import java.sql.ResultSet

class JSON {
    @JsonIgnoreProperties(ignoreUnknown = true)
    data class Bmson(
        val bga: BGA = BGA(),
        val bpm_events: List<BPMEvent> = mutableListOf(),
        val info: BmsonInfo = BmsonInfo(),
        val lines: List<BarLine> = mutableListOf(),
        val mine_channels: List<SoundChannel> = mutableListOf(),
        val sound_channels: List<SoundChannel> = mutableListOf(),
        val stop_events: List<StopEvent> = mutableListOf()
    ) {
        @JsonIgnoreProperties(ignoreUnknown = true)
        data class BGA(
            val bga_events: List<BGAEvent> = mutableListOf(),
            val bga_header: List<Any> = mutableListOf(),
            val layer_events: List<BGAEvent> = mutableListOf(),
            val poor_events: List<BGAEvent> = mutableListOf()
        ) {
            @JsonIgnoreProperties(ignoreUnknown = true)
            data class BGAEvent(
                val y: Long = 0L
            )
        }

        @JsonIgnoreProperties(ignoreUnknown = true)
        data class BPMEvent(
            val bpm: Double = 0.0,
            val y: Long = 0L
        )

        @JsonIgnoreProperties(ignoreUnknown = true)
        data class BmsonInfo(
            val artist: String = "",
            val chart_name: String = "",
            val genre: String = "",
            val init_bpm: Double = 130.0,
            val judge_rank: Double = 100.0,
            val level: Long = 0L,
            val ln_type: Long = 1L,
            val mode_hint: String = "beat-7k",
            val resolution: Long = 240L,
            val subartists: List<String> = mutableListOf(),
            val subtitle: String = "",
            val title: String = "",
            val total: Double = 100.0
        )

        @JsonIgnoreProperties(ignoreUnknown = true)
        data class BarLine(
            val y: Long = 0L
        )

        @JsonIgnoreProperties(ignoreUnknown = true)
        data class SoundChannel(
            val name: String = "",
            val notes: List<Note> = mutableListOf()
        ) {
            @JsonIgnoreProperties(ignoreUnknown = true)
            data class Note(
                val damage: Double = 0.0,
                val l: Long = 0L,
                val x: Long = 0L,
                val y: Long = 0L
            )
        }

        @JsonIgnoreProperties(ignoreUnknown = true)
        data class StopEvent(
            val duration: Long,
            val y: Long
        )
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    data class BMSTable(
        val name: String = "",
        val symbol: String = "",
        val data_url: String = ""
    )

    @JsonIgnoreProperties(ignoreUnknown = true)
    data class BMSTableData(
        val md5: String = "",
        val level: String = "",
        val sha256: String = "",
    )

    @JsonIgnoreProperties(ignoreUnknown = true)
    data class N2MT(
        val message: Message = Message()
    ) {
        @JsonIgnoreProperties(ignoreUnknown = true)
        data class Message(
            val result: Result = Result()
        ) {
            @JsonIgnoreProperties(ignoreUnknown = true)
            data class Result(
                val translatedText: String = ""
            )
        }
    }

    class QwilightEstablish {
        var qwilightName = ""
        var hash = ""
        var date = ""
        var language = ""
        var amd64 = ""
        var os = ""
        var ram = ""
        var vga = ""
        var m2 = ""
        var audio = ""
        var tv = ""
        var lan = ""
    }

    class TwilightEstablish {
        var avatarID = ""
        var avatarName = ""
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TaehuiGetTotem {
        var totem = ""
        var avatarID = ""
        var avatarName = ""
        var level = 0
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TaehuiTotem {
        var avatarID = ""
        var avatarName = ""
        var level = 0
    }

    class QwilightSignIn {
        var avatarID = ""
        var avatarCipher = ""
    }

    class QwilightEnterSite {
        var siteID = ""
        var siteCipher = ""
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TwilightEnterSite {
        var siteID = ""

        @JvmField
        var isNetSite = false

        var noteID = ""
        var noteIDs: Array<String>? = null
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TwilightLevyNet {
        var siteID = ""
        var noteIDs: Array<String> = emptyArray()
        var handlerID = ""
    }

    class TwilightQuitNet {
        var handlerID = ""
        var quitNetItems: Array<Any>? = null
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TwilightCallSiteAvatar {
        var siteID = ""
        var siteHand = ""
        var situationValue = 0
        var data: Array<TwilightCallSiteAvatarItem> = emptyArray()

        @JsonIgnoreProperties(ignoreUnknown = true)
        class TwilightCallSiteAvatarItem {
            var avatarID = ""
            var avatarConfigure = 0
        }
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TwilightCallSiteNet {
        var siteID = ""
        var noteID = ""
        var noteIDs: Array<String> = emptyArray()
    }

    class QwilightSiteYell {
        var siteID = ""
        var siteYell = ""
        var target = ""
    }

    class QwilightGetSiteYells {
        var siteID = ""
        var siteYellID = 0
    }

    class QwilightSaveAsBundle {
        var bundleVariety = 0
        var bundleEntryPath = ""
        var bundleName = ""
        var etc = ""
    }

    class QwilightSetBundle {
        var bundleName = ""
        var bundleCompetence = 0
    }

    class QwilightNewSite {
        var siteName = ""
        var siteCipher = ""

        @JvmField
        var isNetSite = false
        var data: Any? = null
        var noteID = ""
        var noteIDs: Array<String> = emptyArray()
        var title = ""
        var artist = ""
        var genre = ""
        var levelText = ""
        var level = 0
        var wantLevelID = ""
        var judgmentStage = 0.0
        var hitPointsValue = 0.0
        var totalNotes = 0
        var longNotes = 0
        var autoableNotes = 0
        var trapNotes = 0
        var highestInputCount = 0
        var length = 0.0
        var bpm = 0.0
        var lowestBPM = 0.0
        var highestBPM = 0.0

        @JvmField
        var isAutoLongNote = false
        var inputMode = Component.InputMode.INPUT_MODE_5_1
        var bundleEntryPath = ""
        var allowedPostableItems = emptyArray<Int>()
    }

    class QwilightSetModeComponent {
        var siteID = ""
        var data = Any()
    }

    class QwilightSetAvatarGroup {
        var siteID = ""
        var avatarGroup = 0
    }

    class QwilightSetValidNetMode {
        var siteID = ""
        var validNetMode = 0
    }

    class QwilightSetAllowedPostableItems {
        var siteID = ""
        var allowedPostableItems = emptyArray<Int>()
    }

    class QwilightSetConfigure {
        var silentSiteCompetence = 0
        var toNotifyUbuntuCompetence = 0
        var defaultBundleCompetence = 0
        var ioCompetence = 0
        var toNotifySaveBundleCompetence = 0
    }

    class QwilightSaveBundle {
        var avatarID = ""
        var bundleName = ""
        var etc = ""
    }

    class QwilightCallIO {
        var avatarID = ""
        var handlerID = ""
        var ioMillis = 0.0
    }

    class TwilightCallIO {
        var avatarID = ""
        var handlerID = ""
        var ioMillis = 0.0
    }

    class QwilightIONot {
        var avatarID = ""
        var handlerID = ""
    }

    class QwilightCommentary {
        var noteID = ""
        var commentary = ""
    }

    class QwilightSetFavor {
        var noteID = ""
        var favor: Boolean? = null
    }

    class QwilightCallIOComponent {
        var noteID = ""
        var avatarID = ""
        var handlerID = ""

        @JvmField
        var isFailMode = false
        var data = Any()
        var ioHandlerID = ""
        var ioMillis = 0.0
        var targetIOMillis = 0.0
    }


    class QwilightCompiledIO {
        var avatarID = ""
        var handlerID = ""

        @JvmField
        var isCompiled = false
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TwilightCompiledIO {
        var avatarID = ""
        var handlerID = ""

        @JvmField
        var isCompiled = false
    }

    class QwilightLevyIO {
        var avatarIDs = emptyArray<String>()
        var handlerID = ""
        var levyingWait = 0.0
        var lastStand = 0

        @JvmField
        var isF = false
        var multiplier = 0.0
        var audioMultiplier = 0.0
        var ioMillis = 0.0
    }

    class QwilightIOPause {
        var avatarIDs = emptyArray<String>()
        var handlerID = ""

        @JvmField
        var isPaused = false
    }

    class QwilightIOQuit {
        var avatarIDs = emptyArray<String>()
        var handlerID = ""

        @JvmField
        var isBanned = false
    }

    class QwilightComment {
        var dataID = 0
        var multiplier = 0.0
        var autoMode = 0
        var noteSaltMode = 0
        var audioMultiplier = 0.0
        var faintNoteMode = 0
        var judgmentMode = 0
        var hitPointsMode = 0
        var noteMobilityMode = 0
        var longNoteMode = 0
        var inputFavorMode = 0
        var noteModifyMode = 0
        var lowestJudgmentConditionMode = 0
        var stand = 0
        var highestBand = 0
        var point = 0.0
        var salt = 0

        @JvmField
        var isPaused = false

        var inputFlags = 0
        var inputMode = Component.InputMode.INPUT_MODE_5_1
    }

    class QwilightValveComment {
        var dataID = 0
        var stand = 0
        var hitPointsMode = 0
    }

    class QwilightSetSituation {
        var situationValue = 0
        var situationText = ""
    }

    class QwilightExileAvatar {
        var siteID = ""
        var avatarID = ""
    }

    class QwilightCompiled {
        var siteID = ""
        var handlerID = ""

        @JvmField
        var isCompiled = false
    }

    class QwilightCallNet {
        var siteID = ""
        var handlerID = ""
        var avatarNetStatus = 0
        var stand = 0
        var highestBand = 0
        var point = 0.0
        var hitPoints = 0.0

        @JvmField
        var isFailed = false
        var lastJudged = 0
        var drawings: Array<Any>? = null
        var drawingComponent: Any? = null
        var multiplier = 0.0
        var title = ""
        var artist = ""
        var genre = ""
        var level = 0
        var levelText = ""
        var autoMode = 0
        var noteSaltMode = 0
        var audioMultiplier = 0.0
        var faintNoteMode = 0
        var hitPointsMode = 0
        var judgmentMode = 0
        var noteMobilityMode = 0
        var inputFavorMode = 0
        var longNoteMode = 0
        var noteModifyMode = 0
        var bpmMode = 0
        var waveMode = 0
        var setNoteMode = 0
        var lowestJudgmentConditionMode = 0
        var totalNotes = 0
        var judgmentStage = 0.0
        var hitPointsValue = 0.0
        var highestInputCount = 0
        var length = 0.0
        var bpm = 0.0
        var inputMode = Component.InputMode.INPUT_MODE_5_1
    }

    class QwilightSetNoteFile {
        var siteID = ""
        var noteID = ""
        var noteIDs = emptyArray<String>()
        var title = ""
        var artist = ""
        var genre = ""
        var levelText = ""
        var level = 0
        var wantLevelID = ""
        var judgmentStage = 0.0
        var hitPointsValue = 0.0
        var totalNotes = 0
        var longNotes = 0
        var autoableNotes = 0
        var trapNotes = 0
        var highestInputCount = 0
        var length = 0.0
        var bpm = 0.0
        var lowestBPM = 0.0
        var highestBPM = 0.0

        @JvmField
        var isAutoLongNote = false
        var inputMode = Component.InputMode.INPUT_MODE_5_1
        var bundleEntryPath = ""
    }

    class QwilightSetSiteHand {
        var siteID = ""
        var avatarID = ""
    }

    class QwilightSetSiteName {
        var siteID = ""
        var siteName = ""
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    class TwilightWwwSite {
        var siteID = ""
        var siteConfigure = 0
        var hasCipher = false
        var avatarCount = 0
    }

    class TwilightWwwTitle(var title: String, var titleColor: String)

    data class TwilightSiteYell @JsonCreator constructor(
        @JsonProperty("siteID")
        val siteID: String,
        @JsonProperty("avatarID")
        val avatarID: String,
        @JsonProperty("avatarName")
        val avatarName: String,
        @JsonProperty("date")
        val date: Long,
        @JsonProperty("siteYell")
        val siteYell: String,
        @JsonProperty("siteYellID")
        val siteYellID: Int,
        @JsonProperty("target")
        val target: String
    ) {
        constructor(siteID: String, siteYellItem: SiteYell, target: String) : this(
            siteID,
            siteYellItem.avatarID,
            siteYellItem.avatarName,
            siteYellItem.date,
            siteYellItem.siteYell,
            siteYellItem.siteYellID,
            target
        )
    }

    data class TwilightCommentSiteYell @JsonCreator constructor(
        @JsonProperty("avatarID")
        val avatarID: String,
        @JsonProperty("avatarName")
        val avatarName: String,
        @JsonProperty("artist")
        val artist: String,
        @JsonProperty("title")
        val title: String,
        @JsonProperty("genre")
        val genre: String,
        @JsonProperty("levelText")
        val levelText: String,
        @JsonProperty("level")
        val level: Int,
        @JsonProperty("stand")
        val stand: Int,
        @JsonProperty("hitPointsMode")
        val hitPointsMode: Int
    )

    data class TwilightLevelSiteYell @JsonCreator constructor(
        @JsonProperty("avatarID")
        val avatarID: String,
        @JsonProperty("avatarName")
        val avatarName: String,
        @JsonProperty("title")
        val title: String
    )

    data class TwilightAbilitySiteYell @JsonCreator constructor(
        @JsonProperty("avatarID")
        val avatarID: String,
        @JsonProperty("avatarName")
        val avatarName: String,
        @JsonProperty("inputMode")
        val inputMode: Component.InputMode,
        @JsonProperty("ability")
        val ability: Double
    )

    data class TwilightInviteSiteYell @JsonCreator constructor(
        @JsonProperty("avatarName")
        val avatarName: String,
        @JsonProperty("siteID")
        val siteID: String,
        @JsonProperty("siteName")
        val siteName: String,
    )

    data class TwilightTVSiteYell @JsonCreator constructor(
        @JsonProperty("href")
        val href: String,
        @JsonProperty("title")
        val title: String,
        @JsonProperty("text")
        val text: String,
    )

    class QwilightWwwLevel {
        var noteID = ""
        var stand = 0
        var point = 0.0
        var highestBand = 0
        var judgments = emptyArray<Int>()
        var autoMode = 0
        var noteSaltMode = 0
        var faintNoteMode = 0
        var judgmentMode = 0
        var hitPointsMode = 0
        var noteMobilityMode = 0
        var longNoteMode = 0
        var inputFavorMode = 0
        var noteModifyMode = 0
        var bpmMode = 0
        var waveMode = 0
        var setNoteMode = 0
        var lowestJudgmentConditionMode = 0
    }

    class TwilightWwwAvatarAbility(rs: ResultSet, i: Double) {
        val noteID: String
        val noteVariety: Int
        val artist: String
        val title: String
        val genre: String
        val levelText: String
        val level: Int
        val stand: Int
        val ability: Double

        init {
            noteID = rs.getString("Note_ID")
            noteVariety = rs.getInt("Note_Variety")
            artist = rs.getString("Artist")
            title = rs.getString("Title")
            genre = rs.getString("Genre")
            levelText = rs.getString("Level_Text")
            level = rs.getInt("Level")
            stand = rs.getInt("Stand")
            ability = rs.getDouble("Value") * i
        }
    }
}