package net.pokeranalytics.android.unitTests.filter

import net.pokeranalytics.android.components.BaseFilterInstrumentedUnitTest
import net.pokeranalytics.android.model.filter.Query
import net.pokeranalytics.android.model.filter.QueryCondition
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.FilterCondition
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow
import org.junit.Assert
import org.junit.Test
import java.util.*

class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() {

    @Test
    fun testSingleBlindNoCurrencyFilter() {

        val realm = this.mockRealm
        realm.beginTransaction()

        val currency = realm.createObject(net.pokeranalytics.android.model.realm.Currency::class.java, "1")
        currency.code = "USD"

        val b1 = realm.createObject(Bankroll::class.java, "1")
        val b2 = realm.createObject(Bankroll::class.java, "2")
        b2.currency = currency

        val s1 = Session.testInstance(100.0, false, Date(), 1, b1)
        s1.cgBigBlind = 1.0
        s1.cgSmallBlind = 0.5

        val s2 = Session.testInstance(100.0, false, Date(), 1, b1)
        s2.cgBigBlind = 1.0
        s2.cgSmallBlind = 0.5

        val s3 = Session.testInstance(100.0, false, Date(), 1, b1)
        s3.cgBigBlind = 2.0
        s3.cgSmallBlind = 1.0

        realm.commitTransaction()

        val filter = QueryCondition.AnyBlind()

        val blind = QueryCondition.AnyBlind().apply {
            listOfValues = arrayListOf(s1.blinds!!)
        }

        blind.filterSectionRow = FilterSectionRow.Blind

        val filterElement = FilterCondition(filterElementRows = arrayListOf(blind))
        filter.updateValueBy(filterElement)

        val sessions = Filter.queryOn<Session>(realm, Query(filter))

        Assert.assertEquals(2, sessions.size)
        sessions.map {
            Assert.assertTrue(arrayListOf(s1.id, s2.id).contains((it as Session).id))
        }
    }

    @Test
    fun testSingleBlindNoSmallBlindNoCurrencyFilter() {

        val realm = this.mockRealm
        realm.beginTransaction()

        val currency = realm.createObject(net.pokeranalytics.android.model.realm.Currency::class.java, "1")
        currency.code = "AUD"

        val b1 = realm.createObject(Bankroll::class.java, "1")
        val b2 = realm.createObject(Bankroll::class.java, "2")
        b2.currency = currency

        val s1 = Session.testInstance(100.0, false, Date(), 1, b1)
        s1.cgBigBlind = 1.0
        s1.cgSmallBlind = 0.5

        val s2 = Session.testInstance(100.0, false, Date(), 1, b1)
        s2.cgBigBlind = 1.0
        s2.cgSmallBlind = 0.5

        val s3 = Session.testInstance(100.0, false, Date(), 1, b1)
        s3.cgBigBlind = 2.0
        s3.cgSmallBlind = 1.0

        realm.commitTransaction()


        val filter = QueryCondition.AnyBlind()

        val blind1 = QueryCondition.AnyBlind().apply {
            listOfValues = arrayListOf(s1.blinds!!)
        }
        val blind2 = QueryCondition.AnyBlind().apply {
            listOfValues = arrayListOf(s2.blinds!!)
        }

        blind1.filterSectionRow = FilterSectionRow.Blind
        blind2.filterSectionRow = FilterSectionRow.Blind

        val filterElements = FilterCondition(filterElementRows = arrayListOf(blind1, blind2))
        filter.updateValueBy(filterElements)

        val sessions = Filter.queryOn<Session>(realm, Query(filter))

        Assert.assertEquals(2, sessions.size)
        sessions.map {
            Assert.assertTrue(arrayListOf(s1.id, s2.id).contains((it as Session).id))
        }
    }

    @Test
    fun testSingleBlindCurrencyFilter() {

        val realm = this.mockRealm
        realm.beginTransaction()

        val currency = realm.createObject(net.pokeranalytics.android.model.realm.Currency::class.java, "1")
        currency.code = "USD"

        val b1 = realm.createObject(Bankroll::class.java, "1")
        val b2 = realm.createObject(Bankroll::class.java, "2")
        b2.currency = currency

        val s1 = Session.testInstance(100.0, false, Date(), 1, b1)

        s1.cgBigBlind = 1.0
        s1.cgSmallBlind = 0.5

        val s2 = Session.testInstance(100.0, false, Date(), 1, b1)
        s2.cgBigBlind = 1.0
        s2.cgSmallBlind = 0.5

        val s3 = Session.testInstance(100.0, false, Date(), 1, b2)
        s3.cgBigBlind = 2.0
        s3.cgSmallBlind = 1.0

        realm.commitTransaction()


        val filter = QueryCondition.AnyBlind()

        val blind = QueryCondition.AnyBlind().apply {
            listOfValues = arrayListOf(s3.blinds!!)
        }

        blind.filterSectionRow = FilterSectionRow.Blind

        val filterElement = FilterCondition(filterElementRows = arrayListOf(blind))
        filter.updateValueBy(filterElement)
        val sessions = Filter.queryOn<Session>(realm, Query(filter))

        Assert.assertEquals(1, sessions.size)
        sessions.map {
            Assert.assertEquals(s3.id, (it as Session).id)
        }
    }

    @Test
    fun testMultiBlindNoCurrencyFilter() {

        val realm = this.mockRealm
        realm.beginTransaction()

        val currency = realm.createObject(net.pokeranalytics.android.model.realm.Currency::class.java, "1")
        currency.code = "AUD"

        val b1 = realm.createObject(Bankroll::class.java, "1")
        val b2 = realm.createObject(Bankroll::class.java, "2")
        b2.currency = currency

        val s1 = Session.testInstance(100.0, false, Date(), 1, b1)
        s1.cgBigBlind = 1.0
        s1.cgSmallBlind = 0.5

        val s2 = Session.testInstance(100.0, false, Date(), 1, b1)
        s2.cgBigBlind = 2.0
        s2.cgSmallBlind = 1.0

        val s3 = Session.testInstance(100.0, false, Date(), 1, b2)
        s3.cgBigBlind = 2.0
        s3.cgSmallBlind = 1.0

        realm.commitTransaction()



        val filter = QueryCondition.AnyBlind()

        val blind1 = QueryCondition.AnyBlind().apply {
            listOfValues = arrayListOf(s1.blinds!!)
        }
        val blind2 = QueryCondition.AnyBlind().apply {
            listOfValues = arrayListOf(s2.blinds!!)
        }

        blind1.filterSectionRow = FilterSectionRow.Blind
        blind2.filterSectionRow = FilterSectionRow.Blind

        val filterElement = FilterCondition(filterElementRows = arrayListOf(blind1, blind2))
        filter.updateValueBy(filterElement)

        val sessions = Filter.queryOn<Session>(realm, Query(filter))

        Assert.assertEquals(2, sessions.size)
        sessions.map {
            Assert.assertTrue(arrayListOf(s1.id, s2.id).contains((it as Session).id))
        }
    }
}