package com.mime.dualscreenview.data

import com.mime.dualscreenview.common.Blog
import com.mime.dualscreenview.data.model.BookPageInfo
import com.mime.dualscreenview.data.model.BookPageInfos
import com.mime.dualscreenview.data.model.HistoryItem
import com.mime.dualscreenview.data.model.LastInfo
import com.mime.dualscreenview.data.model.ReaderConfig
import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.types.BaseRealmObject
import io.realm.kotlin.types.TypedRealmObject
import kotlin.reflect.KClass

object HistoryManager {
    val clazz : Set<KClass<out BaseRealmObject>> = setOf(LastInfo::class, HistoryItem::class, ReaderConfig::class, BookPageInfos::class, BookPageInfo::class)
    val schemaVersion : Long = 5


    val openRealm  : Realm  = Realm.open(RealmConfiguration.Builder(clazz as Set<KClass<out TypedRealmObject>>)
        .schemaVersion(schemaVersion)
        .deleteRealmIfMigrationNeeded()
        .build())

    fun save(lastInfo: LastInfo) {
        openRealm.apply{
            this.writeBlocking {
                copyToRealm(lastInfo, UpdatePolicy.ALL)
            }
        }
    }

    fun save(historyItem: HistoryItem) {
        openRealm.apply{
            this.writeBlocking {
                copyToRealm(historyItem, UpdatePolicy.ALL)
            }
        }
    }

    fun requestLastInfo(callback : (LastInfo)->Unit)  {
        openRealm.apply{

        }
    }

    fun save(config : ReaderConfig)  {
        openRealm.apply{
            this.writeBlocking {
                copyToRealm(config,UpdatePolicy.ALL)
            }
        }
    }

    fun getBookInfos(aUrl : String, callback : (BookPageInfos?)->Unit) {
        var url : String = aUrl
        openRealm.apply{
            if (url.startsWith("//")) {
                while (url.startsWith("//")) {
                    url = url.replace("//","/").trim()
                }
            }
            Blog.LOGE("aUrl >>> ${aUrl}")
            Blog.LOGE("aUrl >>> ${aUrl}")
            var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0 || bookPageUrl == $0","${url}").find()
            if (bookPageInfo != null && bookPageInfo.count() > 0) {
                Blog.LOGE("get  ${bookPageInfo}" )
                var pgs = this.query(BookPageInfos::class,"bookPageUrl == $0", bookPageInfo.first().bookPageUrl).find()
                if (pgs.size > 0) {
                    pgs.first().let {
                        Blog.LOGE("get  ${it}  , ${it?.pages}")
                        callback.invoke(this.copyFromRealm(it))
                    }
                }
            } else {
                callback.invoke(null)
            }
        }
    }

    fun getBookPageInfo(aUrl : String, callback : (BookPageInfo?)->Unit) {
        var url : String = aUrl
        openRealm.apply{
            if (url.startsWith("//")) {
                while (url.startsWith("//")) {
                    url = url.replace("//","/").trim()
                }
            }
            var result = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find()
            if (result.size > 0) {
                var bookPageInfo = result?.first()
                if (bookPageInfo != null) {
                    callback.invoke(bookPageInfo)
                }
            }
        }
    }

    fun getBooPageInfoContentsSave(aUrl : String, contents : String) {
        var url : String = aUrl
        openRealm.writeBlocking {
            Blog.LOGE("getBooPageInfoContentsSave  ${url}")
            val result = query(BookPageInfo::class).query("pathUrl == $0", "${url}").find()
            if (result.size > 0) {
                result.first().contents = contents
                copyToRealm(result.first(), UpdatePolicy.ALL)
            }
        }
    }




    fun getNextPage(aUrl : String ,callback : (BookPageInfo?)->Unit) {
        var url : String = aUrl
        openRealm.apply{
            if (url.startsWith("//")) {
                while (url.startsWith("//")) {
                    url = url.replace("//","/").trim()
                }
            }
            var bookPageInfo =
                this.query(BookPageInfo::class).query("pathUrl == $0", url).find()
            if (bookPageInfo.size > 0) {
                Blog.LOGE("getNextPage 2 => chapterNum : ${bookPageInfo.first().chapterNum}  , bookPageInfo.bookPageUrl :  ${bookPageInfo.first().bookPageUrl}" )
                var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.first().chapterNum + 1).query("bookPageUrl == $0","${bookPageInfo.first().bookPageUrl}").find()
                if(results.size > 0) {
                    results.first().let {
                        Blog.LOGE("getNextPage 2 nextBook pathUrl : ${it.pathUrl}" )
                        callback.invoke(it)
                    }
                } else {callback.invoke(null)}
            } else {callback.invoke(null)}
        }
    }

    fun getPrevPage(aUrl : String ,callback : (BookPageInfo?)->Unit) {
        var url : String = aUrl
        openRealm.apply{
            Blog.LOGE("getPrevPage  ${url}" )
            if (url.startsWith("//")) {
                while (url.startsWith("//")) {
                    url = url.replace("//","/").trim()
                }
            }
            Blog.LOGE("getPrevPage  ${url}" )
            var bookPageInfo =
                this.query(BookPageInfo::class).query("pathUrl == $0", url).find()
            Blog.LOGE("getPrevPage  ${bookPageInfo}" )
            if (bookPageInfo.size > 0) {
                Blog.LOGE("getPrevPage 2  ${bookPageInfo?.first()?.chapterNum}" )
                Blog.LOGE("getPrevPage 2  ${bookPageInfo?.first()?.bookPageUrl}" )
                var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.first().chapterNum - 1).query("bookPageUrl == $0","${bookPageInfo.first().bookPageUrl}").find()
                if(results.size > 0) {
                    results.first()?.let {
                        callback.invoke(it)
                    }
                } else {
                    callback.invoke(null)
                }
            } else {
                callback.invoke(null)
            }
        }
    }

}