package xyz.myachin.saveto.ui.share

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import xyz.myachin.saveto.R
import xyz.myachin.saveto.logic.files.FileSaver
import xyz.myachin.saveto.logic.intent.*
import xyz.myachin.saveto.ui.supports.NeedDownloaderActivity
import java.io.File

abstract class BaseShareActivity : Activity() {
    private val fileSaver by lazy { FileSaver(applicationContext) }
    private var listener: FileSaveNotifier? = null
    private lateinit var incomingIntent: IncomingIntent
    protected var tmpFile: File? = null
        private set

    protected fun addFileSaveListener(notifier: FileSaveNotifier) {
        listener = notifier
    }

    protected fun removeFileSaveListener() {
        listener = null
    }

    abstract fun createDownloaderIntent(): Intent

    abstract fun requestTarget(intent: IncomingIntent)

    protected fun processIntent(intent: Intent) {
        incomingIntent = IncomingIntent(intent)

        when (incomingIntent.recognizeIntent()) {

            IncomingIntent.FilterResult.NOT_FOR_ME -> {
                finish()
                return
            }
            IncomingIntent.FilterResult.URL -> {
                processNeedDownloader(createDownloaderIntent())
            }

            IncomingIntent.FilterResult.TEXT -> {
                requestTarget(incomingIntent)
            }

            IncomingIntent.FilterResult.FILE_OK -> {
                tmpFile = fileSaver.createBinTempFile(incomingIntent)
                removeSource()
                if (tmpFile == null) {
                    finish()
                    return
                }
                requestTarget(incomingIntent)
            }

            IncomingIntent.FilterResult.FILE_DAMAGED -> {
                tmpFile = fileSaver.createBinTempFile(incomingIntent, true)
                if (tmpFile == null) {
                    finish()
                    return
                }
                requestTarget(incomingIntent)
            }
        }
    }

    private fun removeSource() {
        Thread {
            if (incomingIntent.removeFileId > -1L) {
                startActivity(IntentCreator.removeFileIdForDownloader(incomingIntent.removeFileId))
            }
        }.start()
    }

    private fun processNeedDownloader(intent: Intent) {
        try {
            startActivity(intent)
            finish()
        } catch (_: ActivityNotFoundException) {
            startActivityForResult(
                Intent(
                    applicationContext,
                    NeedDownloaderActivity::class.java
                ).apply {
                    action = ACTION_NEED_DOWNLOAD
                }, REQUEST_NEED_DOWNLOADER_CODE
            )
        }
    }

    override fun onDestroy() {
        cacheDir?.list()?.map { File(cacheDir, it).delete() }
        super.onDestroy()
    }

    protected fun processOnActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            REQUEST_NEED_DOWNLOADER_CODE -> {
                when (resultCode) {
                    RESULT_OK -> {
                        try {
                            startActivity(data)
                        } catch (_: ActivityNotFoundException) {
                            Toast.makeText(
                                applicationContext,
                                R.string.cannot_find_market,
                                Toast.LENGTH_SHORT
                            ).show()
                        }
                    }
                    RESULT_CANCELED -> {
                        if (data?.getBooleanExtra(EXTRA_SAVE_URL_AS_TEXT, false) == true) {
                            requestTarget(incomingIntent)
                        }
                    }
                }
            }
            ACCESS_ALREADY_GIVEN -> writeFile(data!!.data!!)
        }
        finish()
    }

    private fun writeFile(target: Uri) {
        if (tmpFile != null) {
            fileSaver.saveBinFile(tmpFile!!, target)
        } else {
            fileSaver.saveTextFile(incomingIntent.text, target)
        }
        listener?.onFileSaved()
    }

}