class NumberSpeller {
    fun say(input: Int): String = say(input.toLong())

    fun say(input: Long): String {
        require(input >= 0) {"Input must be non-negative"}
        require(input < 1000000000000) {"Input must be less than 1000000000000"}

//        return sayHundredDelim(input.toInt()).trim()
        if (input == 0.toLong()){
            return "zero"
        }

        return when (input) {
            in 0..999 -> sayHundredDelim(inp = input).trim()
            in 1000..999999 -> sayThousands(inp = input).trim()
            in 1000000..999999999 -> sayMillions(inp = input).trim()
            in 1000000000..999999999999 -> sayBillions(inp = input).trim()
            else -> "How did you get here?"
        }
    }

    fun sayHundredDelim(inp: Long): String {
        val hundreds = inp/100
        val remainder = inp.rem(100)
        val stringBuilder = StringBuilder()
        if (hundreds.toInt() != 0) {
            stringBuilder.append(sayHundredDelim(hundreds) + " hundred ")
        }

        stringBuilder.append(
                when (remainder.toInt()){
                    0 -> ""
                    1 -> "one"
                    2 -> "two"
                    3 -> "three"
                    4 -> "four"
                    5 -> "five"
                    6 -> "six"
                    7 -> "seven"
                    8 -> "eight"
                    9 -> "nine"
                    10 -> "ten"
                    11 -> "eleven"
                    12 -> "twelve"
                    13 -> "thirteen"
                    14 -> "fourteen"
                    15 -> "fifteen"
                    16 -> "sixteen"
                    17 -> "seventeen"
                    18 -> "eighteen"
                    19 -> "nineteen"
                    20 -> "twenty"
                    in 21..29 -> "twenty-" + sayHundredDelim(remainder - 20)
                    30 -> "thirty"
                    in 31..39 -> "thirty-" + sayHundredDelim(remainder - 30)
                    40 -> "forty"
                    in 41..49 -> "forty-" + sayHundredDelim(remainder - 40)
                    50 -> "fifty"
                    in 51..59 -> "fifty-" + sayHundredDelim(remainder - 50)
                    60 -> "sixty"
                    in 61..69 -> "sixty-" + sayHundredDelim(remainder - 60)
                    70 -> "seventy"
                    in 71..79 -> "seventy-" + sayHundredDelim(remainder - 70)
                    80 -> "eighty"
                    in 81..89 -> "eighty-" + sayHundredDelim(remainder - 80)
                    90 -> "ninety"
                    in 91..99 -> "ninety-" + sayHundredDelim(remainder - 80)
                    else -> "How'd you get here?"
        })
        return String(stringBuilder)
    }

    fun sayThousands(inp: Long): String {
        if (inp == 0.toLong()){
            return ""
        }
        return sayHundredDelim(inp/1000) + " thousand " + sayHundredDelim(inp.rem(1000))
    }

    fun sayMillions(inp: Long): String {
        if (inp == 0.toLong()){
            return ""
        }
        return say(inp/1000000) + " million " + sayThousands(inp.rem(1000000))
    }

    fun sayBillions(inp: Long): String {
        return say(inp/1000000000) + " billion " + sayMillions(inp.rem(1000000000))
    }
}