package net.pokeranalytics.android.ui.view.rowrepresentable

import android.content.Context
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.Criteria
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.filter.mapFirstCondition
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType

sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable {
    object CashOrTournament: FilterSectionRow(R.string.cash_or_tournament)
    object LiveOrOnline: FilterSectionRow(R.string.live_or_online)
    object Game: FilterSectionRow(R.string.games)
    object LimitType: FilterSectionRow(R.string.limits)
    object TableSize: FilterSectionRow(R.string.table_sizes)
    object DynamicDate: FilterSectionRow(R.string.dynamic_date)
    object FixedDate: FilterSectionRow(R.string.fixed_date)
    object Duration: FilterSectionRow(R.string.duration)
    object Year: FilterSectionRow(R.string.year)
    object WeekdayOrWeekend: FilterSectionRow(R.string.weekdays_or_weekend)
    object DayOfWeek: FilterSectionRow(R.string.day_of_the_week)
    object MonthOfYear: FilterSectionRow(R.string.month_of_the_year)
    object SessionDuration: FilterSectionRow(R.string.session_duration)
    object TimeFrameRange: FilterSectionRow(R.string.hour_slot)
    object Sessions: FilterSectionRow(R.string.sessions)
    object Blind: FilterSectionRow(R.string.blinds)
    object CashRebuyCount: FilterSectionRow(R.string.rebuy_count)
    object TournamentType: FilterSectionRow(R.string.tournament_types)
    object TournamentName: FilterSectionRow(R.string.tournament_name)
    object TournamentFeature: FilterSectionRow(R.string.tournament_feature)
    object CompletionPercentage: FilterSectionRow(R.string.tournament_completion_percentage_interval)
    object TournamentFinalPosition: FilterSectionRow(R.string.final_position)
    object TournamentNumberOfPlayer: FilterSectionRow(R.string.players_count)
    object TournamentRebuyCount: FilterSectionRow(R.string.rebuy_count)
    object TournamentEntryFee: FilterSectionRow(R.string.buyin)
    object MultiTabling: FilterSectionRow(R.string.number_of_tables)
    object Value: FilterSectionRow(R.string.value)
    object Location: FilterSectionRow(R.string.locations)
    object Bankroll: FilterSectionRow(R.string.bankrolls)
    object NumberOfPlayers: FilterSectionRow(R.string.number_of_players)
    object MultiPlayer: FilterSectionRow(R.string.multiplayer)
    object NumberOfRebuy: FilterSectionRow(R.string.number_of_buyins)
    object TransactionType: FilterSectionRow(R.string.operation_types)

    data class CustomField(var customField:net.pokeranalytics.android.model.realm.CustomField): FilterSectionRow(customField.resId) {
        override val name = this.customField::class.simpleName ?: throw PokerAnalyticsException.FilterElementUnknownName
    }

	private enum class SelectionType {
		SINGLE,
		MULTIPLE,
	}

	override val viewType: Int = RowViewType.HEADER_TITLE.ordinal

    open val name = this::class.simpleName ?: throw PokerAnalyticsException.FilterElementUnknownName

    override fun getDisplayName(context: Context): String {
        when (this) {
            is CustomField -> {
                return customField.name
            }
        }
        return name
    }

    val allowMultiSelection: Boolean
		get() = (this.selectionType == SelectionType.MULTIPLE)

	val filterElements: List<RowRepresentable>
		get() {

			val data = arrayListOf<RowRepresentable>().apply {
				this.addAll(
					when (this@FilterSectionRow) {

						// General
						CashOrTournament -> Criteria.SessionTypes.queryConditions.mapFirstCondition()
						LiveOrOnline -> Criteria.BankrollTypes.queryConditions.mapFirstCondition()
						Game -> Criteria.Games.queryConditions.mapFirstCondition()
						LimitType -> Criteria.Limits.queryConditions.mapFirstCondition()
                        TableSize -> Criteria.TableSizes.queryConditions.mapFirstCondition()
						// Date
						DynamicDate -> arrayListOf(
							QueryCondition.IsToday,
							QueryCondition.WasYesterday,
							QueryCondition.WasTodayAndYesterday,
							QueryCondition.DuringThisWeek,
							QueryCondition.DuringThisMonth,
							QueryCondition.DuringThisYear
						)
						FixedDate -> arrayListOf(QueryCondition.StartedFromDate(), QueryCondition.EndedToDate())
						Duration -> arrayListOf(QueryCondition.PastDay())
                        WeekdayOrWeekend -> arrayListOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd)
                        Year -> Criteria.Years.queryConditions.mapFirstCondition()
                        DayOfWeek -> Criteria.DaysOfWeek.queryConditions.mapFirstCondition()
                        MonthOfYear -> Criteria.MonthsOfYear.queryConditions.mapFirstCondition()

						// Duration
						SessionDuration -> QueryCondition.moreOrLess<QueryCondition.Duration>()
						TimeFrameRange -> arrayListOf(QueryCondition.StartedFromTime(), QueryCondition.EndedToTime())

						// Sessions
						//Sessions -> arrayListOf(QueryCondition.LastGame(), QueryCondition.LastSession())

						// Cash
                        Blind -> Criteria.Blinds.queryConditions.mapFirstCondition()
//						CashRebuyCount -> QueryCondition.moreOrLess<QueryCondition.Rebuy>()

						// Tournament
						TournamentType -> Criteria.TournamentTypes.queryConditions.mapFirstCondition()
//						CompletionPercentage ->  arrayListOf()

						TournamentFinalPosition -> QueryCondition.moreOrLess<QueryCondition.TournamentFinalPosition>()
						TournamentNumberOfPlayer -> QueryCondition.moreOrLess<QueryCondition.TournamentNumberOfPlayer>()
						TournamentEntryFee -> Criteria.TournamentFees.queryConditions.mapFirstCondition()
						TournamentName -> Criteria.TournamentNames.queryConditions.mapFirstCondition()
						TournamentFeature -> Criteria.TournamentFeatures.queryConditions.mapFirstCondition()
						Location -> Criteria.Locations.queryConditions.mapFirstCondition()
						Bankroll -> Criteria.Bankrolls.queryConditions.mapFirstCondition()
						MultiTabling -> QueryCondition.moreOrLess<QueryCondition.NumberOfTable>()
						//NumberOfPlayers -> QueryCondition.moreOrLess<QueryCondition.TournamentNumberOfPlayer>()
                        NumberOfRebuy -> QueryCondition.moreOrLess<QueryCondition.NumberOfRebuy>()
//						MultiPlayer -> arrayListOf()

						Value -> arrayListOf<QueryCondition>().apply {
                            addAll(QueryCondition.moreOrLess<QueryCondition.NetAmountWon>())
                            addAll(QueryCondition.moreOrLess<QueryCondition.NetAmountLost>())
                        }
                        TransactionType -> Criteria.TransactionTypes.queryConditions.mapFirstCondition()
                        is CustomField -> {
	                        val cf = this@FilterSectionRow.customField
                            if (cf.isListType) {
                                Criteria.ListCustomFields(cf.id).queryConditions.mapFirstCondition()
                            } else if (cf.isAmountType) {
                                QueryCondition.moreOrLess<QueryCondition.CustomFieldAmountQuery>().apply {
                                    this.forEach {
                                        it.customFieldId = cf.id
                                    }
                                }
                            } else {
                                QueryCondition.moreOrLess<QueryCondition.CustomFieldNumberQuery>().apply {
                                    this.forEach {
                                        it.customFieldId = cf.id
                                    }
                                }
                            }
                        }
                        else -> arrayListOf()
					}.apply {
						this.forEach {
							it.filterSectionRow = this@FilterSectionRow
						}
					}
				)
			}

			// Add the section row only if we have data for this section
			if (data.isNotEmpty()) {
				data.add(0, this@FilterSectionRow)
			}

			return data
		}

	private val selectionType: SelectionType
		get() {
			return when (this) {
				CashOrTournament, DynamicDate, LiveOrOnline, Sessions -> SelectionType.SINGLE
				else -> SelectionType.MULTIPLE
			}
		}

	val exclusiveWith: List<FilterSectionRow>?
		get() {
			return when (this) {
				DynamicDate -> arrayListOf(FixedDate)
				FixedDate -> arrayListOf(DynamicDate)
				else -> null
			}
		}

}
