import Foundation

extension GameType {

    var gameClass: GameClass {
        switch self {
        case .rufEichel, .rufBlatt, .rufSchelln, .hochzeit:
            return .ruf
        case .bettel:
            return .bettel
        case .wenz, .geier:
            return .wenz
        case .soloEichel, .soloBlatt, .soloHerz, .soloSchelln:
            return .solo
        }
    }

    enum GameClass: String {
        case none = "none"
        case ruf = "ruf"
        case hochzeit = "hochzeit"
        case bettel = "bettel"
        case wenz = "wenz"
        case geier = "geier"
        case solo = "solo"

        var cost: Int {
            switch self {
            case .none: return 0
            case .ruf: return 5
            case .hochzeit: return 10
            case .bettel: return 15
            case .wenz, .geier, .solo: return 20
            }
        }

        @discardableResult
        mutating func increase() -> Bool {
            switch self {
            case .none:
                self = .ruf
            case .ruf:
                self = .bettel
            case .hochzeit:
                self = .bettel
            case .bettel:
                self = .wenz
            case .wenz, .geier:
                self = .solo
            case .solo:
                return false
            }
            return true
        }

        func increased() -> GameClass? {
            switch self {
            case .none:
                return .ruf
            case .ruf:
                return .bettel
            case .hochzeit:
                return .bettel
            case .bettel:
                return .wenz
            case .wenz, .geier:
                return .solo
            case .solo:
                return nil
            }
        }

        var allowsWedding: Bool {
            switch self {
            case .none, .ruf:
                return true
            default:
                return false
            }
        }

        func allows(game: GameType) -> Bool {
            availableGames.contains(game)
        }

        var availableGames: [GameType] {
            switch self {
            case .none, .ruf:
                return GameType.allCases
            case .hochzeit, .bettel:
                return [.bettel, .wenz, .geier, .soloEichel, .soloBlatt, .soloHerz, .soloSchelln]
            case .wenz, .geier:
                return [.wenz, .geier, .soloEichel, .soloBlatt, .soloHerz, .soloSchelln]
            case .solo:
                return [.soloEichel, .soloBlatt, .soloHerz, .soloSchelln]
            }
        }

        var availableClasses: [GameClass] {
            switch self {
            case .none, .ruf:
                return [.ruf, .bettel, .wenz, .geier, .solo]
            case .hochzeit, .bettel:
                return [.bettel, .wenz, .geier, .solo]
            case .wenz, .geier:
                return [.wenz, .geier, .solo]
            case .solo:
                return [.solo]
            }
        }

        var classesWhenOutbidding: [GameClass] {
            increased()?.availableClasses ?? []
        }
    }
}

extension GameType.GameClass: Comparable {

    static func < (lhs: GameType.GameClass, rhs: GameType.GameClass) -> Bool {
        lhs.rawValue < rhs.rawValue
    }
}

extension GameType.GameClass: GameConvertible {

    var id: GameId {
        rawValue
    }
}
