package app.furmeet.events.system.schedule.managers

import android.content.Context
import app.furmeet.events.system.helper.lastPathPart
import app.furmeet.events.system.helper.nullAndLogIfException
import java.io.File
import java.io.InputStream
import java.io.Serializable

abstract class CacheManager : Serializable {
    abstract val goesOnline: Boolean
    abstract val preloaded: Boolean
    abstract fun getStamp(file: String): String?
    abstract operator fun get(file: String): Pair<InputStream, String>?
    abstract operator fun set(file: String, requestResult: Pair<ByteArray, String>)
    abstract fun delete(file: String): Boolean
    abstract fun sanitize(): Int
    abstract val files: Set<String>
    abstract fun getFileFor(asset: String): File

    companion object {
        operator fun invoke(context: Context) =
                if (RemoteAssetsHolder.remoteAssets.onlineApp) {
                    if (RemoteAssetsHolder.remoteAssets.preloaded)
                        OnlinePreloadedCacheManager(context)
                    else
                        OnlineCacheManager(context)
                } else
                    OfflineCacheManager(context)
    }

    open fun removeGarbageFiles(): Int {
        sanitize()
        val conventionSeries = this[RemoteAssetsHolder.remoteAssets.json.lastPathPart()]?.first?.let {
            nullAndLogIfException { ConventionJsonReader.readFromInputStream(it) }
        }
        return if (conventionSeries == null) 0 else {
            val neededImages = conventionSeries.allImages.flatMap { it.values }.map { it.lastPathPart() }.distinct().toSet()
            val neededFiles = neededImages + setOf(RemoteAssetsHolder.remoteAssets.json.lastPathPart())
            val garbageFiles = files - neededFiles
            garbageFiles.forEach { delete(it) }
            garbageFiles.size
        }
    }

    abstract fun fallbackGet(file: String): Pair<InputStream, String>?
}