package app.revanced.patches.youtube.misc.links

import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_33_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

@Suppress("unused")
val bypassURLRedirectsPatch = bytecodePatch(
    name = "Bypass URL redirects",
    description = "Adds an option to bypass URL redirects and open the original URL directly.",
) {
    dependsOn(
        sharedExtensionPatch,
        settingsPatch,
        addResourcesPatch,
        versionCheckPatch,
    )

    compatibleWith(
        "com.google.android.youtube"(
            "18.38.44",
            "18.49.37",
            "19.16.39",
            "19.25.37",
            "19.34.42",
        ),
    )

    val abUriParserMatch by abUriParserFingerprint()
    val abUriParserLegacyMatch by abUriParserLegacyFingerprint()
    val httpUriParserMatch by httpUriParserFingerprint()
    val httpUriParserLegacyMatch by httpUriParserLegacyFingerprint()

    execute {
        addResources("youtube", "misc.links.bypassURLRedirectsPatch")

        PreferenceScreen.MISC.addPreferences(
            SwitchPreference("revanced_bypass_url_redirects"),
        )

        val matches = if (is_19_33_or_greater) {
            arrayOf(
                abUriParserMatch,
                httpUriParserMatch,
            )
        } else {
            arrayOf(
                abUriParserLegacyMatch,
                httpUriParserLegacyMatch,
            )
        }

        matches.forEach {
            it.mutableMethod.apply {
                val insertIndex = findUriParseIndex()
                val uriStringRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC

                replaceInstruction(
                    insertIndex,
                    "invoke-static {v$uriStringRegister}," +
                        "Lapp/revanced/extension/youtube/patches/BypassURLRedirectsPatch;" +
                        "->" +
                        "parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;",
                )
            }
        }
    }
}

internal fun Method.findUriParseIndex() = indexOfFirstInstruction {
    val reference = getReference<MethodReference>()
    reference?.returnType == "Landroid/net/Uri;" && reference.name == "parse"
}
