package net.pokeranalytics.android.model.filter

import android.content.Context
import io.realm.RealmQuery
import net.pokeranalytics.android.R
import net.pokeranalytics.android.util.NULL_TEXT

fun List<Query>.mapFirstCondition() : List<QueryCondition> {
	return this.map { it.conditions.first() }
}

class Query {

	constructor(vararg elements: QueryCondition) {
		if (elements.size > 0) {
			this.add(elements.asList())
		}
	}

	private val _conditions: MutableList<QueryCondition> = mutableListOf()
	val conditions: List<QueryCondition>
		get() {
			return this._conditions
		}

	fun add(vararg elements: QueryCondition) {
		if (elements.size > 0) {
			this.add(elements.asList())
		}
	}

	fun add(queryCondition: QueryCondition) {
		this._conditions.add(queryCondition)
	}

	fun remove(queryCondition: QueryCondition) {
		this._conditions.remove(queryCondition)
	}

	fun add(queryConditions: List<QueryCondition>) {
		this._conditions.addAll(queryConditions)
	}

    val defaultName: String
        get() {
            return when (this._conditions.size) {
                0 -> NULL_TEXT
                else -> this._conditions.joinToString("") { it.id.joinToString("") }
            }
        }

	fun getName(context: Context): String {
		return when (this._conditions.size) {
			0 -> context.getString(R.string.all_sessions) // @todo should be dependant of the underlying type, ie. Session, Transaction...
			else -> this._conditions.joinToString(" : ") { it.getDisplayName(context) }
		}
	}

	inline fun <reified T : Filterable> queryWith(query: RealmQuery<T>): RealmQuery<T> {
		var realmQuery = query

        val queryFromTime = this.conditions.filter {
            it is QueryCondition.StartedFromTime
        }.firstOrNull()
        val queryToTime = this.conditions.filter {
            it is QueryCondition.EndedToTime
        }.firstOrNull()

        this.conditions.forEach {
            if (it is QueryCondition.StartedFromTime) {
                realmQuery = it.queryWith(realmQuery, queryToTime)
            } else if (it is QueryCondition.EndedToTime) {
                realmQuery = it.queryWith(realmQuery, queryFromTime)
            } else {
                realmQuery = it.queryWith(realmQuery)
            }
		}

//        println("<<<<<< ${realmQuery.description}")
        val queryLast = this.conditions.filter {
            it is QueryCondition.Last
        }.firstOrNull()
        queryLast?.let {qc ->
            (qc as QueryCondition.Last).singleValue?.let {
                return realmQuery.limit(it.toLong())
            }
        }
        return realmQuery
	}

	fun merge(query: Query) : Query {
		this.add(query.conditions)
		return this
	}

}