package net.pokeranalytics.android.model.filter

import io.realm.RealmModel
import io.realm.RealmResults
import net.pokeranalytics.android.exceptions.PokerAnalyticsException
import net.pokeranalytics.android.model.realm.*

/**
 * We want to be able to store filters in the database:
 * - filters can be a combination of sub filters
 * - filters can be applied to different type of objects: Sessions, Hands, Transactions...
 * - filters can be applied to a list of different type of objects (feed)
 *
 * A queryWith is described by the following:
 * - a data type: Session, Hands...
 * - a field: table size of a Session
 * - an operator: equal, >=, <...
 * - a value: an id, a number, a date...
 *
 * We can decide to have a collection of [operator, value] for a field
 *
 * Combination:
 * - multiple datatype filters should be handled as 'OR'
 * - multiple field filters should be handled as 'AND'
 * - multiple '=' filters as 'OR'
 * - multiple 'Greater than', 'less than' as 'AND'
 * - multiple numericValues as 'OR'
 *
 * Also:
 * A queryWith should be able to be converted into a Realm query
 *
 */

class UnmanagedFilterField(message: String) : Exception(message) {

}

/**
 * Companion-level Interface to indicate an RealmObject class can be filtered and to provide all the fieldNames (eg: parameter's path) needed to be query on.
 */
interface Filterable : RealmModel {

	/**
	 * return the path of the parameter used in the [QueryCondition] related to this entity
	 */
//    fun fieldNameForQueryType(queryCondition: QueryCondition) : String?

}

inline fun <reified T : Filterable> RealmResults<T>.filter(query: Query) : RealmResults<T> {
	return query.queryWith(this.where()).findAll()
}

class FilterHelper {

	companion object {

		inline fun <reified T : Filterable > fieldNameForQueryType(queryCondition: Class< out QueryCondition>): String? {

			val fieldName = when (T::class.java) {
				Session::class.java -> Session.fieldNameForQueryType(queryCondition)
				ComputableResult::class.java -> ComputableResult.fieldNameForQueryType(queryCondition)
				SessionSet::class.java -> SessionSet.fieldNameForQueryType(queryCondition)
				Transaction::class.java -> Transaction.fieldNameForQueryType(queryCondition)
				Result::class.java -> Result.fieldNameForQueryType(queryCondition)
				else -> {
                    null
//					throw UnmanagedFilterField("Filterable type fields are not defined for class ${T::class}")
				}
			}

            return fieldName

/*
			fieldName?.let {
				return fieldName
			} ?: run {
				throw PokerAnalyticsException.MissingFieldNameForQueryCondition(queryCondition.name)
			}
*/

		}

	}

}



//
//fun MutableList<Filterable>.queryWith(queryWith: FilterCondition) : List<Filterable> {
//
//    return this.queryWith { f ->
//        return@queryWith true
//    }
//}


// doesnt compile: Class "FilterableRealmObject" must contain at least 1 persistable field.

//class FilterableRealmObject : RealmObject(), Filterable {
//
//}