buildscript {
    def androidDir = "${buildscript.sourceFile.getParent()}/../"
    apply(from: "${androidDir}/autolink.gradle")
    apply(from: "${androidDir}/dependencies.gradle")
    apply(from: "${androidDir}/manifest.gradle")
}

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

// `react-native run-android` is hard-coded to look for the output APK at a very
// specific location. See
// https://github.com/react-native-community/cli/blob/6cf12b00c02aca6d4bc843446394331d71a9749e/packages/platform-android/src/commands/runAndroid/index.ts#L180
buildDir = "${rootDir}/${name}/build"

def reactNativePath = file(findNodeModulesPath("react-native", rootDir))

apply(plugin: "com.facebook.react")

react {
    reactNativeDir = reactNativePath
        codegenDir = file(findNodeModulesPath("@react-native/codegen", reactNativePath))
}

// We don't want the React plugin to bundle.
tasks.whenTaskAdded { task ->
    // The task name can be found in `react-native-gradle-plugin`:
    // https://github.com/facebook/react-native/blob/0.71-stable/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt#L54
    if (task.name.startsWith("createBundle") && task.name.endsWith("JsAndAssets")) {
        task.enabled = false
    }
}

repositories {
    maven {
        url = uri("${reactNativePath}/android")
    }

    mavenCentral()
    google()

    // https://github.com/AzureAD/microsoft-authentication-library-for-android#step-1-declare-dependency-on-msal
    maven {
        url = uri("https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1")
    }
}

apply(from: "${projectDir}/../../test-app.gradle")
applyTestAppModule(project)

project.ext.react = [
    abiSplit             : false,
    appName              : getAppName(),
    applicationId        : getApplicationId(),
    architectures        : getArchitectures(project),
    bundleInRelease      : false,
    enableCamera         : !getSingleAppMode(),
    enableHermes         : true,
    enableNewArchitecture: enableNewArchitecture,
]

project.ext.signingConfigs = getSigningConfigs()

android {
    namespace = "com.microsoft.reacttestapp"

    compileSdkVersion = project.ext.compileSdkVersion

    if (project.hasProperty("ndkVersion")) {
        ndkVersion = project.ext.ndkVersion
    }

    buildFeatures {
        prefab = true
    }

    kotlinOptions {
        allWarningsAsErrors = true
    }

    defaultConfig {
        applicationId = project.ext.react.applicationId
        minSdkVersion = project.ext.minSdkVersion
        targetSdkVersion = project.ext.targetSdkVersion
        versionCode = project.ext.getVersionCode()
        versionName = project.ext.getVersionName()

        def singleApp = getSingleAppMode()
        buildConfigField("String", "REACTAPP_SINGLE_APP", singleApp ? "\"${singleApp}\"" : "null")

        buildConfigField("boolean", "REACTAPP_USE_FABRIC", enableNewArchitecture.toString())
        buildConfigField("boolean", "REACTAPP_USE_BRIDGELESS", enableBridgeless.toString())

        manifestPlaceholders = [
            rntaEnableCamera: project.ext.react.enableCamera ? "1000000" : "1"
        ]

        resValue("string", "app_name", project.ext.react.appName)

        def cppStd = "-std=c++20"
        def cmakeMakeProgram = System.getenv("CMAKE_MAKE_PROGRAM")

        if (enableNewArchitecture) {
            def cmakeArgs = [
                "-DANDROID_STL=c++_shared",
                "-DPROJECT_BUILD_DIR=${buildDir}",
                "-DREACT_ANDROID_DIR=${reactNativePath}/ReactAndroid",
            ]
            if (cmakeMakeProgram != null) {
                cmakeArgs.add("-DCMAKE_MAKE_PROGRAM=${cmakeMakeProgram}")
            }

            externalNativeBuild {
                cmake {
                    arguments(*cmakeArgs)
                    cppFlags(cppStd, "-frtti", "-fexceptions", "-DWITH_INSPECTOR=1")
                }
            }
            if (!project.ext.react.abiSplit) {
                ndk {
                    abiFilters(*project.ext.react.architectures)
                }
            }
        } else {
            def cmakeArgs = [
                "-DANDROID_STL=c++_shared",
                "-DREACT_COMMON_DIR=${reactNativePath}/ReactCommon",
                "-DREACT_JNILIBS_DIR=${buildDir}/outputs/jniLibs",
            ]
            if (cmakeMakeProgram != null) {
                cmakeArgs.add("-DCMAKE_MAKE_PROGRAM=${cmakeMakeProgram}")
            }

            externalNativeBuild {
                cmake {
                    arguments(*cmakeArgs)
                    cppFlags(cppStd, "-Wall", "-Werror", "-frtti", "-fexceptions", "-DWITH_INSPECTOR=1")
                }
            }
        }
    }

    externalNativeBuild {
        cmake {
            path = "${projectDir}/src/main/jni/CMakeLists.txt"
        }
    }

    lintOptions {
        lintConfig = file("lint.xml")
    }

    packagingOptions {
        pickFirst("lib/armeabi-v7a/libc++_shared.so")
        pickFirst("lib/arm64-v8a/libc++_shared.so")
        pickFirst("lib/x86_64/libc++_shared.so")
        pickFirst("lib/x86/libc++_shared.so")
    }

    project.ext.signingConfigs.each { name, config ->
        def signingConfig = signingConfigs.findByName(name) ?: signingConfigs.create(name)
        signingConfig.keyAlias = config["keyAlias"]
        signingConfig.keyPassword = config["keyPassword"]
        signingConfig.storeFile = config["storeFile"]
        signingConfig.storePassword = config["storePassword"]

        def buildType = buildTypes.findByName(name) ?: buildTypes.create(name)
        buildType.signingConfig = signingConfigs[name]
    }
    if (buildTypes.release.signingConfig == null) {
        logger.warn("Signing config for 'release' build type not found; reusing debug config")
        buildTypes.release.signingConfig = signingConfigs.debug
    }

    sourceSets {
        main.java.srcDirs += [
            project.ext.react.enableCamera ? "src/camera/java" : "src/no-camera/java",

            !enableNewArchitecture
                ? "src/old-arch/java"
                : reactNativeVersion >= v(0, 81, 0)
                    ? "src/new-arch-0.81/java"
                    : "src/new-arch-0.73/java",

            "src/devserverhelper-0.75/java",
            "src/reactactivitydelegate-0.75/java",
            "src/reactapplication-0.76/java",
            "src/reacthost-0.76/java",
        ]
    }

    splits {
        abi {
            reset()
            enable = project.ext.react.abiSplit
            universalApk = false
            include(*project.ext.react.architectures)
        }
    }
}

dependencies {
    implementation project(":support")

    implementation("com.facebook.react:hermes-android")
    implementation("com.facebook.react:react-android")

    implementation(libraries.androidAppCompat)
    implementation(libraries.androidCoreKotlinExtensions)
    implementation(libraries.androidRecyclerView)
    implementation(libraries.materialComponents)

    if (project.ext.react.enableCamera) {
        implementation(libraries.androidCamera)
        implementation(libraries.androidCameraMlKitVision)
        implementation(libraries.mlKitBarcodeScanning)
    }

    // https://github.com/facebook/react-native/blob/b0c0bb45911434ea654ba7e2feff4686061eba7a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt#L162
    autolinkingInfo(buildDir).each { path, info ->
        info.configurations.each { configuration ->
            add(configuration, project(path))
        }
    }
}

// `@react-native-community/cli` currently requires this function to be defined.
// See https://github.com/react-native-community/cli/blob/a87fb9014635fe84ab19a1a88d6ecbbc530eb4e2/packages/platform-android/native_modules.gradle#L497
def isNewArchitectureEnabled() {
    return isFabricEnabled(project)
}
