package net.pokeranalytics.android

import android.app.Application
import com.crashlytics.android.Crashlytics
import io.fabric.sdk.android.Fabric
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmResults
import io.realm.kotlin.where
import net.pokeranalytics.android.model.Limit
import net.pokeranalytics.android.model.realm.Bankroll
import net.pokeranalytics.android.model.realm.Game
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.utils.Seed
import net.pokeranalytics.android.util.PokerAnalyticsLogs
import timber.log.Timber
import java.util.*


class PokerAnalyticsApplication : Application() {

	var sessions: RealmResults<Session>? = null

//    private val listener: OrderedRealmCollectionChangeListener<RealmResults<Session>> =
//        OrderedRealmCollectionChangeListener() { realmResults: RealmResults<Session>, changeSet: OrderedCollectionChangeSet ->
//
//            if (changeSet == null) {
//                return@OrderedRealmCollectionChangeListener
//            }
//
//            val realm: Realm = Realm.getDefaultInstance()
//
//            val deletedSessions = realm.where(Session::class.java).`in`("id", changeSet.deletions.toTypedArray()).findAll()
//            deletedSessions.forEach { it.cleanup() }
//
//    }

	override fun onCreate() {
		super.onCreate()

		// Realm
		Realm.init(this)
		val realmConfiguration = RealmConfiguration.Builder()
			.name(Realm.DEFAULT_REALM_NAME)
			.deleteRealmIfMigrationNeeded()
			.initialData(Seed(this))
			.build()
		Realm.setDefaultConfiguration(realmConfiguration)

		val realm: Realm = Realm.getDefaultInstance()
		// Add observer on session time frame changes
		this.sessions = realm.where(Session::class.java).findAll() // monitor session deletions
//		this.endedSessions?.addChangeListener { _, changeSet ->
		/*
		val deletedSessions =
			realm.where(Session::class.java).`in`("id", changeSet.deletions.toTypedArray()).findAll()
		deletedSessions.forEach { it.cleanup() }
		*/
//		}

		if (BuildConfig.DEBUG) {
			// Logs
			Timber.plant(PokerAnalyticsLogs())
		} else {
			Fabric.with(this, Crashlytics())
		}

		if (BuildConfig.DEBUG) {
			this.createFakeSessions() // debug
		}

	}
//
//	private fun createFakeStats() {
//
//		val buyinList = arrayListOf(100.0, 200.0, 300.0, 500.0, 1000.0, 2000.0)
//		val resultsList = arrayListOf(
//			-2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0, 2500.0
//		)
//
//		val commitFrequency = 100
//
//		Thread() {
//
//			try {
//
//				val realm = Realm.getDefaultInstance()
//
//				// Test endedSessions
//				val pstats = realm.where<ComputableResult>().findAll()
//				if (pstats.size < 10) {
//
//					val numberOfSessions = 2000
//					Timber.d("*** Start creating ${numberOfSessions} fake computables...")
//
//					val s = Date()
//
//					realm.beginTransaction()
//
//					for (index in 0..numberOfSessions) {
//
//						if (index % commitFrequency == 0) {
//							Timber.d("****** committing at ${index} computables...")
//							realm.commitTransaction()
//							realm.beginTransaction()
//						}
//
//						val ps = realm.createObject(ComputableResult::class.java)
//						ps.ratedBuyin = buyinList.random()
//						ps.ratedNet = resultsList.random()
//
//					}
//
//					realm.commitTransaction()
//
//					val e = Date()
//					val duration = (e.time - s.time) / 1000.0
//					Timber.d("*** ended in ${duration} seconds")
//
//				}
//
//				realm.close()
//
//			} catch (e: Exception) {
//				Timber.e(e)
//			}
//
//		}.start()
//
//	}

	private fun createFakeSessions() {

		val buyinList = arrayListOf(100.0, 200.0, 300.0, 500.0, 1000.0, 2000.0)
		val resultsList = arrayListOf(
			-2500.0, -2000.0, -1500.0, -1000.0, -500.0, 200.0, 1000.0, 1500.0, 2500.0
		)

		val commitFrequency = 100

		Thread() {

			try {

				val realm = Realm.getDefaultInstance()
				val games = realm.where<Game>().findAll()
				val bankroll = realm.where<Bankroll>().findAll().firstOrNull()

				// Test endedSessions
				val sessions = realm.where<Session>().findAll()
				if (sessions.size < 10) {

					val numberOfSessions = 2000
					Timber.d("*** Start creating ${numberOfSessions} fake computables...")

					val s = Date()

					realm.beginTransaction()

					for (index in 0..numberOfSessions) {

						if (index % commitFrequency == 0) {
							Timber.d("****** committing at ${index} computables...")
							realm.commitTransaction()
							realm.beginTransaction()
						}

						val session = Session.newInstance(realm, false, bankroll)

						val calendar = Calendar.getInstance()
						calendar.set(
							(2016..2018).random(),
							(0..11).random(),
							(0..28).random(),
							(0..23).random(),
							(0..59).random()
						)

						val startDate = calendar.time
						calendar.add(Calendar.HOUR_OF_DAY, (2..12).random())
						calendar.add(Calendar.MINUTE, (0..59).random())
						val endDate = calendar.time

						session.startDate = startDate
						session.endDate = endDate
						session.creationDate = startDate

						session.limit = Limit.values().random().ordinal
						session.game = games.random()

						session.result?.let { result ->
							result.buyin = buyinList.random()
							result.netResult = resultsList.random()
						}

					}

					realm.commitTransaction()

					val e = Date()
					val duration = (e.time - s.time) / 1000.0
					Timber.d("*** ended in ${duration} seconds")

				}

				realm.close()

			} catch (e: Exception) {
				Timber.e(e)
			}

		}.start()

	}

}