package org.amnezia.vpn

import android.Manifest
import android.content.Intent
import android.content.Intent.ACTION_SEND
import android.content.Intent.ACTION_VIEW
import android.content.Intent.CATEGORY_DEFAULT
import android.content.Intent.EXTRA_TEXT
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.os.Bundle
import android.os.Process
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
import java.io.BufferedReader
import java.io.IOException
import org.amnezia.vpn.util.Log

private const val TAG = "ImportConfigActivity"

const val ACTION_IMPORT_CONFIG = "org.amnezia.vpn.IMPORT_CONFIG"
const val EXTRA_CONFIG = "CONFIG"

class ImportConfigActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "Create Import Config Activity: $intent")
        intent?.let(::readConfig)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        Log.d(TAG, "onNewIntent: $intent")
        intent?.let(::readConfig)
    }

    private fun readConfig(intent: Intent) {
        when (intent.action) {
            ACTION_SEND -> {
                Log.d(TAG, "Process SEND action, type: ${intent.type}")
                when (intent.type) {
                    "application/octet-stream" -> {
                        intent.getUriCompat()?.let { uri ->
                            checkPermissions(
                                uri,
                                onSuccess = ::processUri,
                                onFail = ::finish
                            )
                        }
                        return
                    }

                    "text/plain" -> intent.getStringExtra(EXTRA_TEXT)?.let(::startMainActivity)
                }
            }

            ACTION_VIEW -> {
                Log.d(TAG, "Process VIEW action, scheme: ${intent.scheme}")
                when (intent.scheme) {
                    "file", "content" -> {
                        intent.data?.let { uri ->
                            checkPermissions(
                                uri,
                                onSuccess = ::processUri,
                                onFail = ::finish
                            )
                        }
                        return
                    }

                    "vpn" -> intent.data?.toString()?.let(::startMainActivity)
                }

            }
        }
        finish()
    }

    private fun checkPermissions(uri: Uri, onSuccess: (Uri) -> Unit, onFail: () -> Unit) {
        if (checkUriReadPermission(uri) == PackageManager.PERMISSION_GRANTED) {
            onSuccess(uri)
        } else {
            val requestPermissionLauncher =
                registerForActivityResult(RequestPermission()) { isGranted ->
                    if (isGranted) onSuccess(uri)
                    else {
                        Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
                        onFail()
                    }
                }
            requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
        }
    }

    private fun checkUriReadPermission(uri: Uri) = checkUriPermission(
        uri,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        null,
        Process.myPid(),
        Process.myUid(),
        Intent.FLAG_GRANT_READ_URI_PERMISSION
    )

    private fun processUri(uri: Uri) {
        try {
            contentResolver.openInputStream(uri)?.use {
                it.bufferedReader().use(BufferedReader::readText).let(::startMainActivity)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            finish()
        }
    }

    private fun Intent.getUriCompat(): Uri? =
        if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
            getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
        } else {
            @Suppress("DEPRECATION")
            getParcelableExtra(Intent.EXTRA_STREAM)
        }

    private fun startMainActivity(config: String) {
        if (config.isNotBlank()) {
            Log.d(TAG, "startMainActivity")
            Intent(applicationContext, AmneziaActivity::class.java).apply {
                action = ACTION_IMPORT_CONFIG
                addCategory(CATEGORY_DEFAULT)
                putExtra(EXTRA_CONFIG, config)
                flags = FLAG_ACTIVITY_NEW_TASK
            }.also {
                startActivity(it)
            }
        }
    }
}
