package com.nisemoe.nise.osu

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

class OsuApiModels {

    @Serializable
    data class UserCountry(
        val code: String,
        val name: String
    )

    @Serializable
    data class UserStatisticsRuleset(
        val osu: UserStatistics?
    )

    @Serializable
    data class UserStatistics(
        val count_100: Long,
        val count_300: Long,
        val count_50: Long,
        val count_miss: Long,
        val country_rank: Long?,
        val global_rank: Long?,
        val pp: Double,
        val ranked_score: Long,
        val hit_accuracy: Double,
        val play_count: Long,
        val play_time: Long,
        val total_score: Long,
        val total_hits: Long
    )

    @Serializable
    data class UserExtended(
        // Documentation: https://osu.ppy.sh/docs/index.html#user
        val avatar_url: String,
        val id: Long,
        val username: String,

        // Documentation: https://osu.ppy.sh/docs/index.html#userextended
        val join_date: String?,

        val statistics: UserStatistics?,
        val statistics_rulesets: UserStatisticsRuleset?,

        val country: UserCountry?
    ) {

        fun getStatisticsEither(): UserStatistics? {
            return this.statistics ?: this.statistics_rulesets?.osu
        }

    }

    @Serializable
    data class UserBatchResponse(
        val users: List<UserExtended>
    )

    @Serializable
    data class BeatmapsetSearchResultCursor(
        val play_count: Long?,
        val id: Long?
    ) {

        override fun toString(): String {
            return "cursor[play_count]=$play_count&cursor[id]=$id"
        }

    }

    @Serializable
    data class BeatmapsetSearchResult(
        val beatmapsets: List<BeatmapsetCompact>,
        val total: Long?,
        val cursor: BeatmapsetSearchResultCursor?,
        val cursor_string: String?
    )

    @Serializable
    data class ScoreBeatmap(
        val id: Int,
        val checksum: String? = null,
        val difficulty_rating: Double?,
        val version: String?
    )

    @Serializable
    data class ScoreBeatmapset(
        val id: Int,
        val title: String?,
        val artist: String?,
        val creator: String?,
        val source: String?
    )

    @Serializable
    data class Score(
        val id: Long?,
        val best_id: Long?,
        val user_id: Long,
        val accuracy: Double,
        val mods: List<String>,
        val score: Long,
        val max_combo: Int,
        val perfect: Boolean,
        val statistics: Statistics,
        val pp: Double?,
        val rank: Grade,
        val created_at: String,
        val replay: Boolean,
        val beatmap: ScoreBeatmap?,
        val beatmapset: ScoreBeatmapset?
    )

    @Serializable
    data class Statistics(
        val count_50: Int?,
        val count_100: Int?,
        val count_300: Int?,
        val count_miss: Int?
    )

    @Serializable
    data class BeatmapScores(
        val scores: List<Score>
    )

    @Serializable
    enum class Grade {
        @SerialName("XH")
        SSH,

        @SerialName("X")
        SS,

        @SerialName("SH")
        SH,

        @SerialName("S")
        S,

        @SerialName("A")
        A,

        @SerialName("B")
        B,

        @SerialName("C")
        C,

        @SerialName("D")
        D,

        @SerialName("F")
        F
    }

    @Serializable
    data class BeatmapCompact(
        val difficulty_rating: Double,
        val id: Int,
        val mode: String,
        val version: String,
        val beatmapset_id: Long,
        val checksum: String? = null,
    )

    @Serializable
    data class BeatmapsetCompact(
        val artist: String,
        val creator: String,
        val id: Long,
        val source: String,
        val title: String,
        val beatmaps: List<BeatmapCompact>?
    )

    @Serializable
    data class Beatmap(
        val beatmapset_id: Int,
        val difficulty_rating: Double?,
        val id: Int,
        val version: String?,
        val beatmapset: BeatmapSet,
        val max_combo: Int?
    )

    @Serializable
    data class BeatmapSet(
        val artist: String?,
        val creator: String?,
        val source: String?,
        val title: String?
    )

    @Serializable
    data class ReplayResponse(
        val content: String
    )

}