package net.pokeranalytics.android.model.utils

import android.content.Context
import io.realm.Realm
import io.realm.Sort
import net.pokeranalytics.android.model.realm.Location
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow

/**
 * Returns all significant parameters concatenated in a String
 * Not suitable for display
 */
private fun Session.parameterRepresentation(context: Context): String {
	var representation = ""

	this.significantFields().forEach {
		representation += this.stringForRow(it, context)
	}
	return representation

}

/**
 * Returns a list of fields used to determine which kind of session is favorite
 */
private fun Session.significantFields(): List<SessionRow> {
	when (this.type) {
		Session.Type.TOURNAMENT.ordinal -> {
			return listOf(
				SessionRow.GAME,
				SessionRow.INITIAL_BUY_IN,
				SessionRow.BANKROLL,
				SessionRow.TABLE_SIZE,
				SessionRow.TOURNAMENT_NAME,
				SessionRow.TOURNAMENT_TYPE
			)
		}
		Session.Type.CASH_GAME.ordinal -> {
			return listOf(
				SessionRow.GAME,
				SessionRow.BLINDS,
				SessionRow.BANKROLL,
				SessionRow.TABLE_SIZE
			)
		}
	}
	throw Exception("A session should always have a type: tournament or CG")
}

/**
 * A class providing convenience method to determine the favorite session of the user at a location
 */
class FavoriteSessionFinder {

	/**
	 * A counter convenience class
	 */
	class Counter(var session: Session) {

		var counter: Int = 1

		fun increment() {
			this.counter++
		}

	}

	companion object {

		private const val FAVORITE_SIGNIFICANT_SESSIONS = 15L

		/**
		 * Copies the favorite session parameters on the [newSession]
		 */
		fun copyParametersFromFavoriteSession(newSession: Session, location: Location?, context: Context) {

			val favoriteSession =
				favoriteSession(newSession.type, location, newSession.realm, context)

			favoriteSession?.let { fav ->

				newSession.limit = fav.limit
				newSession.game = fav.game
				newSession.bankroll = fav.bankroll
				newSession.tableSize = fav.tableSize

				when (newSession.type) {
					Session.Type.CASH_GAME.ordinal -> {
						newSession.cgSmallBlind = fav.cgSmallBlind
						newSession.cgBigBlind = fav.cgBigBlind
					}
					Session.Type.TOURNAMENT.ordinal -> {
						newSession.tournamentEntryFee = fav.tournamentEntryFee
					}
				}
			}
		}

		/**
		 * Determines the favorite session given a [sessionType] and an optional [location]
		 */
		fun favoriteSession(sessionType: Int, location: Location?, realm: Realm, context: Context): Session? {

			val lastSessionsQuery = realm.where(Session::class.java).isNotNull("startDate").equalTo("type", sessionType)
			if (location != null) {
				lastSessionsQuery.equalTo("location.id", location.id)
			}
			val lastSessions = lastSessionsQuery
				.sort("startDate", Sort.DESCENDING)
				.limit(FAVORITE_SIGNIFICANT_SESSIONS)
				.findAll()

			val counters = hashMapOf<String, Counter>()
			lastSessions.forEach { session ->
				val representation = session.parameterRepresentation(context)
				val counter = counters[representation]
				if (counter != null) {
					counter.increment()
				} else {
					counters[representation] = Counter(session)
				}
			}

			val sortedCounters = counters.values.sortedBy { it.counter }
			return sortedCounters.lastOrNull()?.session
		}

	}

}