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

import android.text.InputType
import io.realm.RealmResults
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.TournamentType
import net.pokeranalytics.android.model.extensions.SessionState
import net.pokeranalytics.android.model.extensions.getState
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.extensions.round


enum class SessionRow : RowRepresentable {

	PRIZE,
	CASHED_OUT,
	NET_RESULT,
	INITIAL_BUY_IN,
	BUY_IN,
	POSITION,
	PLAYERS,
	TIPS,

	GAME,
	BLINDS,
	LOCATION,
	BANKROLL,
	TABLE_SIZE,
	TOURNAMENT_TYPE,
	TOURNAMENT_NAME,
	TOURNAMENT_FEATURE,
	START_DATE,
	END_DATE,

	BREAK_TIME,
	COMMENT;

	companion object {
		/**
		 * Return the rows to display for the current session state
		 */
		fun getRows(session: Session): List<RowRepresentable> {
			when (session.type) {
				Session.Type.TOURNAMENT.ordinal -> {
					return when (session.getState()) {
						SessionState.PENDING, SessionState.PLANNED -> {
							arrayListOf(
								GAME,
								INITIAL_BUY_IN,
								LOCATION,
								BANKROLL,
								TABLE_SIZE,
								TOURNAMENT_TYPE,
								TOURNAMENT_NAME,
								TOURNAMENT_FEATURE,
								START_DATE,
								END_DATE
							)
						}
						SessionState.STARTED, SessionState.PAUSED, SessionState.FINISHED -> {
							arrayListOf(
								PRIZE,
								BUY_IN,
								POSITION,
								PLAYERS,
								TIPS,
								SeparatorRow(),
								GAME,
								INITIAL_BUY_IN,
								LOCATION,
								BANKROLL,
								TABLE_SIZE,
								TOURNAMENT_TYPE,
								TOURNAMENT_NAME,
								TOURNAMENT_FEATURE,
								SeparatorRow(),
								START_DATE,
								END_DATE,
								BREAK_TIME,
								COMMENT
							)
						}
					}
				}
				Session.Type.CASH_GAME.ordinal -> {
					when (session.getState()) {
						SessionState.PENDING, SessionState.PLANNED -> {
							return arrayListOf(GAME, BLINDS, LOCATION, BANKROLL, TABLE_SIZE, START_DATE, END_DATE)
						}
						SessionState.STARTED, SessionState.PAUSED, SessionState.FINISHED -> {

							val fields = mutableListOf<RowRepresentable>()
							when {
								session.hasBuyin -> fields.addAll(listOf(CASHED_OUT, BUY_IN, TIPS))
								session.hasNetResult -> fields.add(NET_RESULT)
								session.isLive -> fields.addAll(listOf(CASHED_OUT, BUY_IN, TIPS))
								else -> fields.add(NET_RESULT)
							}
							fields.add(SeparatorRow())
							fields.addAll(listOf(
									GAME,
									BLINDS,
									LOCATION,
									BANKROLL,
									TABLE_SIZE,
									START_DATE,
									END_DATE,
									BREAK_TIME,
									COMMENT
								)
							)
							return fields
						}
					}
				}
			}
			return arrayListOf()
		}
	}

	override val resId: Int?
		get() {
			return when (this) {
				NET_RESULT -> R.string.net_result
				PRIZE -> R.string.prize
				POSITION -> R.string.position
				PLAYERS -> R.string.players
				CASHED_OUT -> R.string.cashed_out
				INITIAL_BUY_IN -> R.string.initial_stack
				BUY_IN -> R.string.buyin
				TIPS -> R.string.tips
				GAME -> R.string.game
				BLINDS -> R.string.blinds
				LOCATION -> R.string.location
				BANKROLL -> R.string.bankroll
				TABLE_SIZE -> R.string.table_size
				TOURNAMENT_TYPE -> R.string.tournament_type
				TOURNAMENT_NAME -> R.string.tournament_name
				TOURNAMENT_FEATURE -> R.string.tournament_feature
				START_DATE -> R.string.start_date
				END_DATE -> R.string.end_date
				BREAK_TIME -> R.string.break_time
				COMMENT -> R.string.comment
			}
		}

	override val viewType: Int
		get() {
			return when (this) {
				NET_RESULT, PRIZE, POSITION, PLAYERS, CASHED_OUT, INITIAL_BUY_IN, BUY_IN, TIPS,
				GAME, BLINDS, LOCATION, BANKROLL, TABLE_SIZE, COMMENT,
				TOURNAMENT_TYPE, TOURNAMENT_NAME, TOURNAMENT_FEATURE, START_DATE, END_DATE, BREAK_TIME -> RowViewType.TITLE_VALUE.ordinal
			}
		}

	override val bottomSheetType: BottomSheetType
		get() {
			return when (this) {
				NET_RESULT, CASHED_OUT, INITIAL_BUY_IN, BREAK_TIME, POSITION, PLAYERS, PRIZE -> BottomSheetType.NUMERIC_TEXT
				BUY_IN, TIPS -> BottomSheetType.SUM
				BLINDS -> BottomSheetType.DOUBLE_EDIT_TEXT
				GAME -> BottomSheetType.LIST_GAME
				TOURNAMENT_TYPE -> BottomSheetType.LIST_STATIC
				LOCATION, BANKROLL, TOURNAMENT_NAME -> BottomSheetType.LIST
				TOURNAMENT_FEATURE -> BottomSheetType.MULTI_SELECTION
				TABLE_SIZE -> BottomSheetType.GRID
				COMMENT -> BottomSheetType.EDIT_TEXT_MULTI_LINES
				else -> BottomSheetType.NONE
			}
		}


	override fun editingDescriptors(map: Map<String, Any?>): ArrayList<RowRepresentableEditDescriptor>? {
		return when (this) {
			BLINDS -> {
				val sb: String? by map
				val bb: String? by map
				arrayListOf(
					RowRepresentableEditDescriptor(
						sb, R.string.smallblind, InputType.TYPE_CLASS_NUMBER
								or InputType.TYPE_NUMBER_FLAG_DECIMAL
					),
					RowRepresentableEditDescriptor(
						bb, R.string.bigblind, InputType.TYPE_CLASS_NUMBER
								or InputType.TYPE_NUMBER_FLAG_DECIMAL
					)
				)
			}
			BUY_IN -> {
				val bb: Double? by map
				val fee: Double? by map
				val ratedBuyin: Double? by map
				val data = arrayListOf<RowRepresentableEditDescriptor>()
				if (bb != null) {
					data.add(RowRepresentableEditDescriptor(100.0 * (bb ?: 0.0)))
					data.add(RowRepresentableEditDescriptor(200.0 * (bb ?: 0.0)))
				} else if (fee != null) {
					data.add(RowRepresentableEditDescriptor((fee ?: 0.0) * 1.0))
					data.add(RowRepresentableEditDescriptor((fee ?: 0.0) * 2.0))
				} else {
					data.add(RowRepresentableEditDescriptor(0))
					data.add(RowRepresentableEditDescriptor(0))
				}

				data.add(RowRepresentableEditDescriptor(ratedBuyin))
				data.add(
					RowRepresentableEditDescriptor(
						inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
					)
				)
				data.add(
					RowRepresentableEditDescriptor(
						inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
					)
				)
				data
			}
			CASHED_OUT, PRIZE, NET_RESULT -> {
				val defaultValue: Double? by map
				arrayListOf(
					RowRepresentableEditDescriptor(
						defaultValue,
						inputType = InputType.TYPE_CLASS_NUMBER
								or InputType.TYPE_NUMBER_FLAG_DECIMAL
								or InputType.TYPE_NUMBER_FLAG_SIGNED
					)
				)
			}
			COMMENT -> {
				val defaultValue: String? by map
				arrayListOf(RowRepresentableEditDescriptor(defaultValue, R.string.comment))
			}
			BREAK_TIME -> {
				arrayListOf(
					RowRepresentableEditDescriptor(
						hint = R.string.in_minutes, inputType = InputType.TYPE_CLASS_NUMBER
					)
				)
			}
			GAME -> {
				val limit: Int? by map
				val defaultValue: Any? by map
				val data: RealmResults<RowRepresentable>? by map
				arrayListOf(
					RowRepresentableEditDescriptor(limit),
					RowRepresentableEditDescriptor(defaultValue, data = data)
				)
			}
			INITIAL_BUY_IN -> {
				val defaultValue: Double? by map
				arrayListOf(
					RowRepresentableEditDescriptor(defaultValue?.round(), inputType = InputType.TYPE_CLASS_NUMBER)
				)
			}
			BANKROLL, LOCATION, TOURNAMENT_FEATURE, TOURNAMENT_NAME -> {
				val defaultValue: Any? by map
				val data: RealmResults<RowRepresentable>? by map
				arrayListOf(
					RowRepresentableEditDescriptor(defaultValue, data = data)
				)
			}
			PLAYERS -> {
				val defaultValue: Int? by map
				arrayListOf(
					RowRepresentableEditDescriptor(
						defaultValue?.toString(),
						inputType = InputType.TYPE_CLASS_NUMBER
					)
				)
			}
			POSITION -> {
				val defaultValue: Int? by map
				arrayListOf(
					RowRepresentableEditDescriptor(
						defaultValue,
						inputType = InputType.TYPE_CLASS_NUMBER
					)
				)
			}
			TABLE_SIZE -> {
				val defaultValue: Int? by map
				arrayListOf(RowRepresentableEditDescriptor(defaultValue))
			}
			TIPS -> {
				val sb: String? by map
				val bb: String? by map
				val tips: Double? by map

				// Disable the buttons with value = 0, add current value & set the 2 edit texts
				arrayListOf(
					RowRepresentableEditDescriptor(sb ?: 0.0),
					RowRepresentableEditDescriptor(bb ?: 0.0),
					RowRepresentableEditDescriptor(tips ?: 0.0),
					RowRepresentableEditDescriptor("", inputType = InputType.TYPE_CLASS_NUMBER),
					RowRepresentableEditDescriptor("", inputType = InputType.TYPE_CLASS_NUMBER)
				)
			}
			TOURNAMENT_TYPE -> {
				val defaultValue: Any? by map
				arrayListOf(
					RowRepresentableEditDescriptor(defaultValue, staticData = TournamentType.values().map {
						it
					})
				)
			}
			else -> null
		}
	}

}