package com.kdanmobile.reader.copyfile

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import android.content.Context
import com.kdanmobile.reader.event.EventBroadcaster
import com.kdanmobile.reader.event.EventManager
import com.kdanmobile.reader.thumb.FileUtil
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File

class CopyFileViewModel(applicationContext: Context,
                        info: CopyFileInfo,
                        private val eventManager: EventManager<Event> = EventManager()
): ViewModel(), EventBroadcaster<CopyFileViewModel.Event> by eventManager {

    sealed class Event {
        data class Success(val filePath: String?): Event()
        data class Failed(val filePath: String?, val e: Throwable): Event()
    }

    val copyProgressLiveData: LiveData<Int>
        get() = mCopyProgressLiveData

    private val mCopyProgressLiveData = MutableLiveData<Int>().apply { value = 0 }

    private var copyFileDisposable: Disposable? = null
    private var dstFilePath: String? = null
    private var hasCompleteCopy = false

    init {
        if (!info.shouldCopyFile) {
            onCopySuccess()
        } else {
            val source = if (!info.filePath.isNullOrEmpty()) {
                FilePathSource(info.filePath!!)
            } else if (info.isActionView && null != info.uri) {
                FileUriSource(applicationContext, info.uri)
            } else {
                null
            }
            val fullFileSize = Math.max(1, source?.getFileSize() ?: 1)
            val task = CopyFileTask()
            task.setCopyMode(CopyFileTask.Mode.CREATE_NEW_FILE)
            task.setTargetFolder(FileUtil.getKdanPDFReaderFolder())
            dstFilePath = task.generateUniqueFilePath(source)

            copyFileDisposable = task.copyFile(source)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe({
                        val progress = Math.min(100, (it * 100.0 / fullFileSize).toInt())
                        onCopyProgressUpdate(progress)
                    }, {
                        onCopyFailed(it)
                    }, {
                        onCopySuccess()
                    })
        }
    }

    private fun onCopyFailed(e: Throwable) {
        if (!hasCompleteCopy) {
            deleteDstFile()
            eventManager.send(Event.Failed(dstFilePath, e))
        }
    }

    private fun onCopySuccess() {
        hasCompleteCopy = true
        eventManager.send(Event.Success(dstFilePath))
    }

    private fun onCopyProgressUpdate(progress: Int) {
        mCopyProgressLiveData.postValue(progress)
    }

    private fun deleteDstFile() {
        dstFilePath?.apply {
            val file = File(this)
            if (file.exists()) {
                file.delete()
            }
        }
    }

    override fun onCleared() {
        if (copyFileDisposable?.isDisposed == false) {
            copyFileDisposable?.dispose()
        }
        if (!hasCompleteCopy) {
            deleteDstFile()
        }
        super.onCleared()
    }
}