package net.pokeranalytics.android.model.migrations

import io.realm.DynamicRealm
import io.realm.RealmMigration
import timber.log.Timber


class PokerAnalyticsMigration : RealmMigration {

	override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {

        // DynamicRealm exposes an editable schema
        val schema = realm.schema

        var currentVersion = oldVersion.toInt()
        Timber.d("*** migrate from $oldVersion to $newVersion")

        // Migrate to version 1
        if (currentVersion == 0) {
            Timber.d("*** Running migration 1")

            schema.get("Filter")?.addField("entityType", Int::class.java)?.setNullable("entityType", true)
            schema.get("FilterElement")?.let {
                it.setNullable("filterName", true)
                it.setNullable("sectionName", true)
            }
            schema.get("FilterElementBlind")?.renameField("code", "currencyCode")
            currentVersion++
        }

        // Migrate to version 2
        if (currentVersion == 1) {
            Timber.d("*** Running migration ${currentVersion + 1}")
            schema.rename("FilterElement", "FilterCondition")

            schema.get("Filter")?.renameField("filterElements", "filterConditions")

            schema.get("SessionSet")?.let {
                it.addField("id", String::class.java).setRequired("id", true)
                it.addPrimaryKey("id")
            }
            currentVersion++
        }

        // Migrate to version 3
        if (currentVersion == 2) {
            Timber.d("*** Running migration ${currentVersion + 1}")
            schema.rename("Report", "ReportSetup")

            schema.get("Filter")?.removeField("entityType")

            schema.get("Session")?.let {
                it.addField("blinds", String::class.java).transform {

                }
            }

            schema.get("FilterCondition")?.let {
                it.removeField("blindValues")
                it.removeField("numericValues")

                it.addField("operator", Integer::class.java)
                it.addField("intValue", Integer::class.java)
                it.addRealmListField("intValues", Integer::class.java)
                it.addField("doubleValue", Double::class.java).setNullable("doubleValue", true)
                it.addRealmListField("doubleValues", Double::class.java)
                if (it.isRequired("doubleValues")) {
                    it.setRequired("doubleValues", false)
                }
                it.addField("stringValue", String::class.java)
            }

            schema.get("ComputableResult")?.removeField("sessionSet")

            schema.get("Bankroll")?.addField("initialValue", Double::class.java)

            currentVersion++
        }

        // Migrate to version 4
        if (currentVersion == 3) {
            Timber.d("*** Running migration ${currentVersion + 1}")

            schema.get("Result")?.addField("numberOfRebuy", Double::class.java)?.setNullable("numberOfRebuy", true)
            currentVersion++
        }

        // Migrate to version 5
        if (currentVersion == 4) {
            Timber.d("*** Running migration ${currentVersion + 1}")
            schema.get("Bankroll")?.removeField("transactions")
            currentVersion++
        }

        // Migrate to version 6
        if (currentVersion == 5) {
            Timber.d("*** Running migration ${currentVersion + 1}")
            schema.get("Transaction")?.let {
                it.addField("dayOfWeek", Integer::class.java)
                it.addField("month", Integer::class.java)
                it.addField("year", Integer::class.java)
                it.addField("dayOfMonth", Integer::class.java)
            }

            val cfEntry = schema.create("CustomFieldEntry")?.let {
                it.addField("id", String::class.java).setRequired("id", true)
                it.addPrimaryKey("id")
                it.addField("value", String::class.java).setNullable("value", false)
                it.addField("order", Integer::class.java).setNullable("order", false)
//                    it.addRealmObjectField("customField", it).setNullable("customField", false)
                it.addField("numericValue", Double::class.java).setNullable("numericValue", true)
            }

            cfEntry?.let { customFieldEntrySchema ->
                schema.get("CustomField")?.let {
                    it.addField("type", Integer::class.java).setNullable("type", false)
                    it.addField("duplicateValue", Boolean::class.java)
                    it.addField("sortCondition", Integer::class.java).setRequired("sortCondition", true)
                    it.addRealmListField("entries", customFieldEntrySchema)
                }

                schema.get("Session")?.let {
                    it.addField("startDateHourMinuteComponent", Double::class.java)
                        .setNullable("startDateHourMinuteComponent", true)
                    it.addField("endDateHourMinuteComponent", Double::class.java)
                        .setNullable("endDateHourMinuteComponent", true)
                    it.addRealmListField("customFieldEntries", customFieldEntrySchema)
                }

            }

            schema.get("ReportSetup")?.let {
                it.addRealmListField("statIds", Int::class.java).setNullable("statIds", true)
                it.addRealmListField("criteriaCustomFieldIds", String::class.java)
                it.addRealmListField("criteriaIds", Int::class.java).setNullable("criteriaIds", true)
                it.removeField("filters")
                schema.get("Filter")?.let { filterSchema ->
                    it.addRealmObjectField("filter", filterSchema)
                }
            }

            schema.get("Filter")?.addField("filterableTypeUniqueIdentifier", Integer::class.java)
            schema.get("Filter")?.addField("useCount", Int::class.java)
            schema.get("Filter")?.removeField("usageCount")
            currentVersion++
        }
    }

	override fun equals(other: Any?): Boolean {
		return other is RealmMigration
	}

	override fun hashCode(): Int {
		return RealmMigration::javaClass.hashCode()
	}
}