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

import io.realm.Realm
import io.realm.RealmResults
import io.realm.Sort
import io.realm.kotlin.where
import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.TableSize
import net.pokeranalytics.android.model.realm.Game
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import java.text.DateFormatSymbols
import java.util.*
import kotlin.collections.ArrayList

/*
			GAME -> {
				val games = realm.copyFromRealm(LiveData.GAME.items(realm) as RealmResults<Game>)
				games.forEach {
					rows.add(FilterElement.Game(game = it))
				}
			}
 */
enum class FilterSubcategoryRow : RowRepresentable {

	// General
	CASH_TOURNAMENT,
	LIVE_ONLINE,
	GAME,
	LIMIT_TYPE,
	TABLE_SIZE,

	// Date
	DYNAMIC_DATE,
	FIXED_DATE,
	DURATION,
	YEAR,
	WEEKDAYS_OR_WEEKEND,
	DAY_OF_WEEK,
	MONTH_OF_YEAR,

	// Duration
	SESSION_DURATION,
	RANGE,

	// Sessions
	// -

	// Cash
	BLINDS,
	CASH_RE_BUY_COUNT,

	// Tournament
	TOURNAMENT_TYPE,
	COMPLETION_PERCENTAGE,
	PLACE,
	PLAYERS_COUNT,
	TOURNAMENT_RE_BUY_COUNT,
	BUY_IN,

	// Online
	MULTI_TABLING,

	// Result
	VALUE,

	// Transaction types
	// -

	// Location
	LOCATION,

	// Bankroll
	BANKROLL,

	// Players
	NUMBER_OF_PLAYERS,
	MULTI_PLAYER;

	enum class Type {
		SINGLE,
		MULTIPLE,
	}

	override val resId: Int?
		get() {
			return when (this) {
				CASH_TOURNAMENT -> net.pokeranalytics.android.R.string.cash_or_tournament
				LIVE_ONLINE -> net.pokeranalytics.android.R.string.live_or_online
				GAME -> net.pokeranalytics.android.R.string.game
				LIMIT_TYPE -> net.pokeranalytics.android.R.string.type_de_limite
				TABLE_SIZE -> net.pokeranalytics.android.R.string.table_size

				DYNAMIC_DATE -> net.pokeranalytics.android.R.string.dynamic_date
				FIXED_DATE -> net.pokeranalytics.android.R.string.fixed_date
				DURATION -> net.pokeranalytics.android.R.string.duration
				YEAR -> net.pokeranalytics.android.R.string.year
				WEEKDAYS_OR_WEEKEND -> net.pokeranalytics.android.R.string.weekdays_or_weekend
				DAY_OF_WEEK -> net.pokeranalytics.android.R.string.day_of_the_week
				MONTH_OF_YEAR -> net.pokeranalytics.android.R.string.month_of_the_year

				SESSION_DURATION -> net.pokeranalytics.android.R.string.session_duration
				RANGE -> net.pokeranalytics.android.R.string.hour_slot

				BLINDS -> net.pokeranalytics.android.R.string.blinds
				CASH_RE_BUY_COUNT -> net.pokeranalytics.android.R.string.rebuy_count

				TOURNAMENT_TYPE -> net.pokeranalytics.android.R.string.tournament_type
				COMPLETION_PERCENTAGE -> net.pokeranalytics.android.R.string.tournament_completion_percentage_interval
				PLACE -> net.pokeranalytics.android.R.string.place
				PLAYERS_COUNT -> net.pokeranalytics.android.R.string.players_count
				TOURNAMENT_RE_BUY_COUNT -> net.pokeranalytics.android.R.string.rebuy_count
				BUY_IN -> net.pokeranalytics.android.R.string.buyin

				MULTI_TABLING -> net.pokeranalytics.android.R.string.multi_tabling

				VALUE -> net.pokeranalytics.android.R.string.value

				LOCATION -> net.pokeranalytics.android.R.string.location

				BANKROLL -> net.pokeranalytics.android.R.string.bankroll

				NUMBER_OF_PLAYERS -> net.pokeranalytics.android.R.string.number_of_players
				MULTI_PLAYER -> net.pokeranalytics.android.R.string.multiplayer
			}
		}

	override val viewType: Int = RowViewType.HEADER_TITLE.ordinal

	/**
	 * Return the type of the selection
	 */
	fun getType(): Type {
		return when (this) {
			GAME, LIMIT_TYPE -> Type.MULTIPLE
			FIXED_DATE, YEAR, WEEKDAYS_OR_WEEKEND, DAY_OF_WEEK, MONTH_OF_YEAR -> Type.MULTIPLE
			else -> Type.SINGLE
		}
	}

	/**
	 * Returns the filter rows
	 */
	fun getFilterRows(realm: Realm): ArrayList<RowRepresentable> {
		val rows = ArrayList<RowRepresentable>()
		when (this) {

			// General
			CASH_TOURNAMENT -> rows.addAll(arrayListOf(FilterRow.CASH_GAME, FilterRow.TOURNAMENT))
			LIVE_ONLINE -> rows.addAll(arrayListOf(FilterRow.LIVE, FilterRow.ONLINE))
			GAME -> {
				val games = realm.copyFromRealm(LiveData.GAME.items(realm) as RealmResults<Game>)
				rows.addAll(games)
			}
			LIMIT_TYPE -> rows.addAll(Limit.values())
			TABLE_SIZE -> {
				val sessions = realm.where<Session>().sort("tableSize").distinct("tableSize").findAll()
				for (session in sessions) {
					session.tableSize?.let {
						rows.add(TableSize(it, RowViewType.TITLE_CHECK.ordinal))
					}
				}
			}

			// Date
			DYNAMIC_DATE -> rows.addAll(
				arrayListOf(
					FilterRow.TODAY, FilterRow.YESTERDAY, FilterRow.TODAY_AND_YESTERDAY, FilterRow.CURRENT_WEEK,
					FilterRow.CURRENT_MONTH, FilterRow.CURRENT_YEAR
				)
			)
			FIXED_DATE -> {
				rows.addAll(arrayListOf(FilterRow.FROM, FilterRow.TO))
			}
			DURATION -> rows.addAll(arrayListOf(FilterRow.PAST_DAYS))
			YEAR -> {

				//TODO: Maybe move this code

				val calendar = Calendar.getInstance()
				val sessions = realm.where<Session>().sort("endDate", Sort.DESCENDING).findAll()
				val years = ArrayList<Int>()

				for (session in sessions) {
					session.endDate?.let {
						calendar.time = it
						val year = calendar.get(Calendar.YEAR)
						if (!years.contains(year)) {
							years.add(year)
						}
					}
				}

				for (year in years) {
					rows.add(CustomizableRowRepresentable(customViewType = RowViewType.TITLE_CHECK, title = year.toString(), isSelectable = true))
				}

			}
			WEEKDAYS_OR_WEEKEND -> rows.addAll(arrayListOf(FilterRow.WEEKDAYS, FilterRow.WEEKEND))
			DAY_OF_WEEK -> {
				val dfs = DateFormatSymbols.getInstance(Locale.getDefault())
				for (day in dfs.weekdays) {
					if (day.isNotEmpty()) {
						rows.add(CustomizableRowRepresentable(customViewType = RowViewType.TITLE_CHECK, title = day, isSelectable = true))
					}
				}
			}
			MONTH_OF_YEAR -> {
				val dfs = DateFormatSymbols.getInstance(Locale.getDefault())
				for (month in dfs.months) {
					if (month.isNotEmpty()) {
						rows.add(CustomizableRowRepresentable(customViewType = RowViewType.TITLE_CHECK, title = month, isSelectable = true))
					}
				}
			}


			else -> rows.addAll(arrayListOf())
		}
		return rows
	}

}