package com.adlerosn.brasilfurfest.schedule.managers import android.content.Context import com.adlerosn.brasilfurfest.helper.lastPathPart import org.jetbrains.anko.doAsync import org.jetbrains.anko.uiThread import java.io.Serializable import java.lang.IllegalStateException import java.net.HttpURLConnection import java.net.HttpURLConnection.HTTP_NOT_MODIFIED import java.net.HttpURLConnection.HTTP_OK import java.net.URL class UpdateChecker(context: Context): Serializable { val cacheManager = CacheManager(context).also { it.startMonitoringNeededFiles() } private val baseJsonFileName = RemoteAssets.json.lastPathPart() val hasBaseJsonCached get() = baseJsonFileName.let { cacheManager.getStamp(it) != null } fun downloadBaseJsonWithWatcher(watcher: (DownloadState, ByteArray?, Throwable?)->Any?) = downloadWithWatcher(RemoteAssets.json, watcher) fun downloadWithWatcher(httpThingToFetch: String, watcher: (DownloadState, ByteArray?, Throwable?)->Any?) = if(cacheManager.goesOnline) doAsync { try { val url = URL(httpThingToFetch) val diskIdentifier = url.toString().lastPathPart() val connection = url.openConnection() as HttpURLConnection cacheManager.getStamp(diskIdentifier)?.let { connection.setRequestProperty("If-Modified-Since", it) } connection.useCaches = false connection.connectTimeout = 3000 connection.readTimeout = 5000 connection.allowUserInteraction = false connection.doOutput = false connection.requestMethod = "GET" uiThread { watcher(DownloadState.CONNECTING, null, null) } connection.connect() try { val resCode = connection.responseCode when (resCode) { HTTP_OK -> { uiThread { watcher(DownloadState.CACHE_MISS, null, null) } val lastModified = connection.headerFields["last-modified"]?.firstOrNull() val data = connection.inputStream.buffered().readBytes() cacheManager[diskIdentifier] = Pair(data, lastModified ?: "") uiThread { watcher(DownloadState.SUCCESS, data, null) } } HTTP_NOT_MODIFIED -> { uiThread { watcher(DownloadState.CACHE_HIT, null, null) } val bytes = cacheManager[diskIdentifier]?.first?.readBytes() uiThread { watcher(DownloadState.SUCCESS, bytes, null) } } else -> { throw IllegalStateException("Server replied with code $resCode. Expected either $HTTP_OK or $HTTP_NOT_MODIFIED.") } } } catch (t: Throwable) { uiThread { watcher(DownloadState.ERROR, null, t) } } finally { connection.disconnect() } } catch (t: Throwable) { uiThread { watcher(DownloadState.ERROR, null, t) } } } else doAsync { uiThread { watcher(DownloadState.CONNECTING, null, null) watcher(DownloadState.CACHE_HIT, null, null) watcher(DownloadState.SUCCESS, cacheManager[httpThingToFetch.lastPathPart()]!!.first.readBytes(), null) } } enum class DownloadState{ CONNECTING, CACHE_MISS, CACHE_HIT, ERROR, SUCCESS } }