MeilCli/FoodSearch

View on GitHub
features/base/src/main/kotlin/net/meilcli/foodsearch/models/RestaurantRequestModel.kt

Summary

Maintainability
A
0 mins
Test Coverage
package net.meilcli.foodsearch.models

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import net.meilcli.foodsearch.Language
import net.meilcli.foodsearch.R
import net.meilcli.foodsearch.api.gnavi.ForeignRestaurantRequestQuery
import net.meilcli.foodsearch.api.gnavi.IRestaurantRequestQuery
import net.meilcli.foodsearch.api.gnavi.Range
import net.meilcli.foodsearch.api.gnavi.RestaurantRequestQuery
import net.meilcli.foodsearch.api.gnavi.entities.*
import kotlin.reflect.KMutableProperty0

sealed class RestaurantRequestModel {

    companion object {

        private const val defaultCount = 20
        private const val defaultPage = 1

        private val defaultRange = Range.M500
    }

    private val requestQuery: IRestaurantRequestQuery

    var categories: Array<ICategory>? = null
        set(value) {
            field = value
            requestQuery.largeCategories = convertCategoryCodes<LargeCategory>(value)
            requestQuery.smallCategories = convertCategoryCodes<SmallCategory>(value)
        }

    var range: Range = defaultRange
        set(value) {
            field = value
            requestQuery.range = value
        }

    var page: Int = defaultPage
        set(value) {
            field = value
            requestQuery.page = value
        }

    var searchWords: Array<String>? = null
        set(value) {
            field = value
            requestQuery.searchWords = value
        }

    var latitude: Double?
        get() = requestQuery.latitude
        set(value) {
            requestQuery.latitude = value
        }

    var longitude: Double?
        get() = requestQuery.longitude
        set(value) {
            requestQuery.longitude = value
        }

    constructor(requestQuery: IRestaurantRequestQuery) {
        this.requestQuery = requestQuery
    }

    constructor(requestQuery: IRestaurantRequestQuery, id: String) : this(requestQuery, arrayOf(id))

    constructor(requestQuery: IRestaurantRequestQuery, ids: Array<String>) {
        this.requestQuery = requestQuery
        requestQuery.count = defaultCount
        requestQuery.ids = ids
    }

    constructor(
        requestQuery: IRestaurantRequestQuery,
        largeArea: LargeArea,
        middleArea: MiddleArea,
        smallArea: SmallArea
    ) {
        this.requestQuery = requestQuery
        requestQuery.count = defaultCount
        requestQuery.largeArea = largeArea.code
        requestQuery.middleArea = middleArea.code
        requestQuery.smallArea = smallArea.code
    }

    constructor(requestQuery: IRestaurantRequestQuery, latitude: Double, longitude: Double) {
        this.requestQuery = requestQuery
        requestQuery.count = defaultCount
        requestQuery.latitude = latitude
        requestQuery.longitude = longitude
    }

    private inline fun <reified T> convertCategoryCodes(categories: Array<ICategory>?): Array<String>? where T : ICategory {
        return categories?.asSequence()
            ?.filterIsInstance<T>()
            ?.map { it.code }
            ?.filterNotNull()
            ?.toList()
            ?.toTypedArray()
    }

    abstract fun createOptions(): List<Option>

    class Option(private val property: KMutableProperty0<Boolean>, @StringRes val description: Int, @DrawableRes val icon: Int?) {

        var value: Boolean
            get() = property.get()
            set(value) {
                property.set(value)
            }
    }

    class Japanese : RestaurantRequestModel {

        val requestQuery: RestaurantRequestQuery

        constructor(requestQuery: RestaurantRequestQuery) : super(requestQuery) {
            this.requestQuery = requestQuery
        }

        constructor(requestQuery: RestaurantRequestQuery, id: String) : super(requestQuery, id) {
            this.requestQuery = requestQuery
        }

        constructor(requestQuery: RestaurantRequestQuery, ids: Array<String>) : super(requestQuery, ids) {
            this.requestQuery = requestQuery
        }

        constructor(
            requestQuery: RestaurantRequestQuery,
            largeArea: LargeArea,
            middleArea: MiddleArea,
            smallArea: SmallArea
        ) : super(requestQuery, largeArea, middleArea, smallArea) {
            this.requestQuery = requestQuery
        }

        constructor(
            requestQuery: RestaurantRequestQuery,
            latitude: Double,
            longitude: Double
        ) : super(requestQuery, latitude = latitude, longitude = longitude) {
            this.requestQuery = requestQuery
        }

        override fun createOptions(): List<Option> {
            return listOf(
                Option(requestQuery::canLunch, R.string.option_canLunch, null),
                Option(requestQuery::canDrinkAll, R.string.option_canDrinkAll, null),
                Option(requestQuery::canEatAll, R.string.option_canEatAll, null),
                Option(requestQuery::hasLunchDesert, R.string.option_hasLunchDesert, null),
                Option(requestQuery::canNoSmoking, R.string.option_canNoSmoking, null),
                Option(requestQuery::canCreditCard, R.string.option_canCreditCard, null),
                Option(requestQuery::canElectronicMoney, R.string.option_canElectronicMoney, null),
                Option(requestQuery::canDelivery, R.string.option_canDelivery, null),
                Option(requestQuery::canReserveInWeb, R.string.option_canReserveInWeb, null),
                Option(requestQuery::isMidnightOpen, R.string.option_isMidnightOpen, null),
                Option(requestQuery::isUntilMorningOpen, R.string.option_isUntilMorningOpen, null),
                Option(requestQuery::hasPrivateRoom, R.string.option_hasPrivateRoom, null),
                Option(requestQuery::hasParking, R.string.option_hasParking, null),
                Option(requestQuery::hasPowerSupply, R.string.option_hasPowerSupply, null),
                Option(requestQuery::hasWifi, R.string.option_hasWifi, null),
                Option(requestQuery::canPet, R.string.option_canPet, null),
                Option(requestQuery::canSeeSports, R.string.option_canSeeSports, null),
                Option(requestQuery::hasDarts, R.string.option_hasDarts, null)
            )
        }
    }

    class Foreign : RestaurantRequestModel {

        val requestQuery: ForeignRestaurantRequestQuery

        constructor(requestQuery: ForeignRestaurantRequestQuery, language: Language) : super(requestQuery) {
            this.requestQuery = requestQuery
            requestQuery.language = language.toGnaviLanguage()
        }

        constructor(
            requestQuery: ForeignRestaurantRequestQuery,
            id: String,
            language: Language
        ) : super(requestQuery, id) {
            this.requestQuery = requestQuery
            requestQuery.language = language.toGnaviLanguage()
        }

        constructor(
            requestQuery: ForeignRestaurantRequestQuery,
            ids: Array<String>,
            language: Language
        ) : super(requestQuery, ids) {
            this.requestQuery = requestQuery
            requestQuery.language = language.toGnaviLanguage()
        }

        constructor(
            requestQuery: ForeignRestaurantRequestQuery,
            largeArea: LargeArea,
            middleArea: MiddleArea,
            smallArea: SmallArea,
            language: Language
        ) : super(requestQuery, largeArea, middleArea, smallArea) {
            this.requestQuery = requestQuery
            requestQuery.language = language.toGnaviLanguage()
        }

        constructor(
            requestQuery: ForeignRestaurantRequestQuery,
            latitude: Double,
            longitude: Double,
            language: Language
        ) : super(requestQuery, latitude = latitude, longitude = longitude) {
            this.requestQuery = requestQuery
            requestQuery.language = language.toGnaviLanguage()
        }

        override fun createOptions(): List<Option> {
            return listOf(
                Option(requestQuery::hasEnglishSpeakingStaff, R.string.option_hasEnglishSpeakingStaff, null),
                Option(requestQuery::hasEnglishMenu, R.string.option_hasEnglishMenu, null),
                Option(requestQuery::hasVegetarianMenu, R.string.option_hasVegetarianMenu, null),
                Option(requestQuery::hasReligiousMenu, R.string.option_hasReligiousMenu, null),
                Option(requestQuery::canCreditCard, R.string.option_canCreditCard, null),
                Option(requestQuery::hasPrivateRoom, R.string.option_hasPrivateRoom, null),
                Option(requestQuery::canNoSmoking, R.string.option_canNoSmoking, null),
                Option(requestQuery::hasWifi, R.string.option_hasWifi, null)
            )
        }
    }
}