package ch.dissem.yaep.domain

enum class Animal(symbol: String) : ItemClass<Animal> {
    ZEBRA("🦓"),
    OCTOPUS("🐙"),
    GOAT("🐐"),
    SLOTH("🦥"),
    DOG("🐕"),
    SNAIL("🐌"),
    ANT("🐜");

    override val symbols: Array<String> = arrayOf(symbol)

    override val companion
        get() = Animal

    companion object : ItemClassCompanion<Animal> {
        override val items: List<Animal> = entries
    }
}

enum class Nationality(symbol: String) : ItemClass<Nationality> {
    ENGLAND("🇬🇧"),
    UKRAINE("🇺🇦"),
    SPAIN("🇪🇸"),
    NORWAY("🇳🇴"),
    JAPAN("🇯🇵"),
    SWITZERLAND("🇨🇭"),
    CANADA("🇨🇦");

    override val symbols: Array<String> = arrayOf(symbol)

    override val companion
        get() = Nationality

    companion object : ItemClassCompanion<Nationality> {
        override val items: List<Nationality> = entries
    }
}

enum class Drink(symbol: String) : ItemClass<Drink> {
    MILK("🥛"),
    WINE("🍷"),
    COCKTAIL("🍸"),
    COFFEE("☕"),
    TEA("🍵"),
    BEER("🍺"),
    BEVERAGE("🧃");

    override val symbols: Array<String> = arrayOf(symbol)

    override val companion
        get() = Drink

    companion object : ItemClassCompanion<Drink> {
        override val items: List<Drink> = entries
    }
}

enum class Profession(symbol: String) : ItemClass<Profession> {
    ASTRONAUT("\u200D\uD83D\uDE80"),
    HEALTH_WORKER("\u200D⚕\uFE0F"),
    FARMER("\u200D\uD83C\uDF3E"),
    ROCK_STAR("\u200D\uD83C\uDFA4"),
    SCIENTIST("\u200D\uD83D\uDD2C"),
    SOFTWARE_DEV("\u200D\uD83D\uDCBB"),
    FIREFIGHTER("\u200D\uD83D\uDE92"),
    TEACHER("\u200D\uD83C\uDFEB");

    override val symbols: Array<String> = idic(symbol)

    override val companion
        get() = Profession

    companion object : ItemClassCompanion<Profession> {
        override val items: List<Profession> = entries
    }
}

enum class Fruit(symbol: String) : ItemClass<Fruit> {
    GRAPES("🍇"),
    WATERMELON("🍉"),
    LEMON("🍋"),
    BANANA("🍌"),
    PINEAPPLE("🍍"),
    CHERRIES("🍒"),
    STRAWBERRY("🍓"),
    KIWI("🥝"),
    PEAR("🍐"),
    MANGO("🥭");

    override val symbols: Array<String> = arrayOf(symbol)

    override val companion
        get() = Fruit

    companion object : ItemClassCompanion<Fruit> {
        override val items: List<Fruit> = entries
    }
}

enum class Dessert(symbol: String) : ItemClass<Dessert> {
    ICE_CREAM("🍨"),
    DOUGHNUT("🍩"),
    COOKIE("🍪"),
    CAKE("🍰"),
    CUPCAKE("🧁"),
    PIE("🥧"),
    CHOCOLATE("🍫"),
    LOLLIPOP("🍭"),
    CUSTARD("🍮");

    override val symbols: Array<String> = arrayOf(symbol)

    override val companion
        get() = Dessert

    companion object : ItemClassCompanion<Dessert> {
        override val items: List<Dessert> = entries
    }
}

enum class Transportation(symbol: String) : ItemClass<Transportation> {
    BICYCLE("🚲"),
    MOTOR_SCOOTER("🛵"),
    SKATEBOARD("🛹"),
    TAXI("🚕"),
    LOCOMOTIVE("🚂"),
    TRAM_CAR("🚋"),
    BUS("🚌");

    override val symbols: Array<String> = arrayOf(symbol)

    override val companion
        get() = Transportation

    companion object : ItemClassCompanion<Transportation> {
        override val items: List<Transportation> = entries
    }
}

private val GENDERS = arrayOf("\uD83E\uDDD1", "\uD83D\uDC68", "\uD83D\uDC69")
private val SKIN_TONES =
    arrayOf("\uD83C\uDFFB", "\uD83C\uDFFC", "\uD83C\uDFFD", "\uD83C\uDFFE", "\uD83C\uDFFF")

private fun idic(symbol: String): Array<String> = Array(GENDERS.size * SKIN_TONES.size) { i ->
    val g = GENDERS[i % GENDERS.size]
    val t = SKIN_TONES[i / GENDERS.size]
    g + t + symbol
}

sealed interface ItemClass<out SELF : ItemClass<SELF>> {
    val symbols: Array<String>

    val companion: ItemClassCompanion<SELF>

    companion object {
        val classes: List<ItemClassCompanion<*>> = listOf(
            Animal,
            Nationality,
            Drink,
            Profession,
            Fruit,
            Dessert,
            Transportation
        )

        fun randomClasses(n: Int): List<ItemClassCompanion<*>> {
            return classes.shuffled().take(n)
        }
    }
}

sealed interface ItemClassCompanion<out C : ItemClass<C>> {
    val items: List<C>

    fun randomItems(n: Int): List<C> {
        return items.shuffled().take(n)
    }
}
