package xyz.myachin.saveto.ui.share.direct

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.widget.Toast
import androidx.documentfile.provider.DocumentFile
import xyz.myachin.saveto.R
import xyz.myachin.saveto.logic.intent.*
import xyz.myachin.saveto.settings.Settings
import xyz.myachin.saveto.ui.share.BaseShareActivity
import xyz.myachin.saveto.ui.share.FileSaveNotifier
import xyz.myachin.saveto.ui.supports.AskDirAccessActivity

open class DirectShareActivity : BaseShareActivity(), FileSaveNotifier {
    private lateinit var mime: String
    private lateinit var name: String
    private var multipleContainer: ArrayList<Intent>? = null
    private var number = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        if (intent.action == Intent.ACTION_SEND || intent.action == Intent.ACTION_SEND_MULTIPLE) {
            super.onCreate(savedInstanceState)
        } else return

        when (intent.action) {
            Intent.ACTION_SEND -> processIntent(intent)
            Intent.ACTION_SEND_MULTIPLE -> {
                extractMultipleIntent(intent)
                processMultipleIntent()
            }
        }
    }

    private fun processMultipleIntent() {
        super.processIntent(multipleContainer!![number])
    }

    private fun extractMultipleIntent(intent: Intent) {
        multipleContainer = ArrayList()
        intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM)?.forEach {
            multipleContainer?.add(Intent(intent).apply {
                action = Intent.ACTION_SEND
                putExtra(Intent.EXTRA_STREAM, it)
            })
        }
        super.addFileSaveListener(this)
    }

    override fun createDownloaderIntent(): Intent {
        return IntentCreator.forDownloader(intent!!.getStringExtra(Intent.EXTRA_TEXT)!!)
            .putExtra(EXTRA_DIRECT, true)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQUEST_NEED_DOWNLOADER_CODE -> {
                super.processOnActivityResult(requestCode, resultCode, data)
            }
            ACCESS_IMAGES_CODE, ACCESS_VIDEOS_CODE, ACCESS_DOCUMENTS_CODE, ACCESS_ARCHIVES_CODE -> {
                if (resultCode == RESULT_OK) {
                    data?.data?.run {
                        checkAccess(this)
                        return
                    }
                }
            }
            else -> finish()
        }
    }

    override fun requestTarget(intent: IncomingIntent) {
        mime = intent.mimeType
        name = intent.suggestName()

        when (intent.mimeType) {
            "text/plain",
            "text/vcard",
            "application/x-abiword",
            "application/msword",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/vnd.oasis.opendocument.presentation",
            "application/vnd.oasis.opendocument.spreadsheet",
            "application/vnd.oasis.opendocument.text",
            "application/pdf",
            "application/rtf",
            "application/vnd.ms-powerpoint",
            "application/vnd.openxmlformats-officedocument.presentationml.presentation",
            "application/vnd.visio",
            "application/vnd.ms-excel",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            -> {
                Settings.documentUri?.run {
                    if (checkAccess(this)) {
                        return
                    }
                }
                showToast(R.string.docs_summary)
                askDirAccess(ACCESS_DOCUMENTS_CODE)
            }

            "application/x-bzip",
            "application/x-bzip2",
            "application/gzip",
            "application/vnd.rar",
            "application/x-tar",
            "application/zip",
            "application/x-7z-compressed",
            -> {
                Settings.archiveUri?.run {
                    if (checkAccess(this)) return
                }
                showToast(R.string.archives_summary)
                askDirAccess(ACCESS_ARCHIVES_CODE)
            }
            else -> {
                when {
                    intent.mimeType.startsWith("video/") || intent.mimeType.startsWith("audio/") -> {
                        Settings.videoUri?.run {
                            if (checkAccess(this)) return
                        }
                        showToast(R.string.video_summary)
                        askDirAccess(ACCESS_VIDEOS_CODE)
                    }
                    intent.mimeType.startsWith("image/") -> {
                        Settings.imageUri?.run {
                            if (checkAccess(this)) {
                                return
                            }
                        }
                        showToast(R.string.images_summary)
                        askDirAccess(ACCESS_IMAGES_CODE)
                    }
                    else -> {
                        finish()
                        return
                    }
                }
            }
        }
    }

    private fun askDirAccess(accessCode: Int) {
        val askIntent = Intent(applicationContext, AskDirAccessActivity::class.java)
        startActivityForResult(askIntent.putExtra(EXTRA_DIRECTORY_ACCESS_NEED, accessCode),
            accessCode)
    }

    private fun showToast(summary: Int) {
        Toast.makeText(applicationContext,
            getString(R.string.set_dir_for, getString(summary)),
            Toast.LENGTH_LONG).show()
    }

    private fun processThis(uri: Uri) {
        super.processOnActivityResult(ACCESS_ALREADY_GIVEN,
            RESULT_OK,
            Intent().apply { data = uri })
    }

    private fun checkAccess(uri: Uri): Boolean {
        DocumentFile.fromTreeUri(applicationContext, uri)?.also { documentFile ->
            if (documentFile.isDirectory && documentFile.canWrite()) {
                documentFile.createFile(mime, name)?.run {
                    if (this.canWrite()) {
                        processThis(this.uri)
                        return true
                    }
                }
            }
        }
        return false
    }

    override fun onFileSaved() {
        number += 1
        if (multipleContainer != null && multipleContainer!!.size >= number + 1) {
            processMultipleIntent()
        } else {
            super.removeFileSaveListener()
            finish()
        }
    }
}