import java.nio.file.Files
import java.nio.file.Paths

buildscript {
  // Simple helper that allows the root project to override versions declared by this library.
  ext.safeExtGet = { prop, fallback ->
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
  }

  repositories {
    google()
    mavenCentral()
  }

  dependencies {
    classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', '1.6.10')}")
  }
}
apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'com.google.firebase.crashlytics'

def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
apply from: expoModulesCorePlugin
applyKotlinExpoModulesCorePlugin()
useDefaultAndroidSdkVersions()

apply plugin: 'com.facebook.react'

react {
  def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath()

  entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim())
  reactNativeDir = new File(projectRoot, "../../react-native-lab/react-native/packages/react-native")
  codegenDir = new File(projectRoot, "../../react-native-lab/react-native/packages/react-native-codegen")

  // Expo Go does not require JS bundling from build, we set all variants as debuggableVariants
  debuggableVariants = ["mobileDebug", "mobileRelease", "questDebug", "questRelease"]

  cliFile = new File(["node", "--print", "require.resolve('@expo/cli')"].execute(null, rootDir).text.trim())
  bundleCommand = "export:embed"

  /* Autolinking */
  autolinkLibrariesWithApp()
}

android {
  namespace "host.exp.exponent"

  buildFeatures {
    buildConfig true
  }

  defaultConfig {
    applicationId 'host.exp.exponent'
    versionCode 227
    versionName '54.0.4'

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    // Deprecated. Used by net.openid:appauth
    manifestPlaceholders = [
        'appAuthRedirectScheme': 'host.exp.exponent',
        'appLabel': '@string/versioned_app_name'
    ]
  }

  flavorDimensions += "device"
  productFlavors {
    quest { dimension "device" }
    mobile { dimension "device" }
  }

  signingConfigs {
    debug {
      storeFile file('../debug.keystore')
    }
    release {
      storeFile file(System.getenv("ANDROID_KEYSTORE_PATH") ?: "release-key.jks")
      storePassword System.getenv("ANDROID_KEYSTORE_PASSWORD")
      keyAlias System.getenv("ANDROID_KEY_ALIAS")
      keyPassword System.getenv("ANDROID_KEY_PASSWORD")
    }
  }
  buildTypes {
    debug {
      debuggable true
      firebaseCrashlytics {
        nativeSymbolUploadEnabled false
      }
    }
    release {
      minifyEnabled true
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      consumerProguardFiles 'proguard-rules.pro'
      if (!System.getenv("ANDROID_UNSIGNED")) {
        signingConfig signingConfigs.release
      }
      def shouldUploadCrashlytics = System.getenv("EAS_BUILD") != null
      firebaseCrashlytics {
        nativeSymbolUploadEnabled shouldUploadCrashlytics
      }
    }
  }

  applicationVariants.all { variant ->
    if (variant.buildType.name == 'release') {
      variant.buildType.firebaseCrashlytics.unstrippedNativeLibsDir = file("${buildDir}/intermediates/merged_native_libs/${variant.name}/merge${variant.name.capitalize()}NativeLibs/out/lib")
    }
  }


  lintOptions {
    abortOnError false
  }
  packagingOptions {
    // libfbjni.so is prebuilt library shared between all ABIs
    pickFirst "lib/**/libfbjni.so"
    // AGP will give priority of libc++_shared coming from App modules.
    pickFirst "**/libc++_shared.so"
  }
  androidResources {
    ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~'
  }
}

// [BEGIN] Applying namespace for 3rd party vendor modules
import com.android.build.api.variant.AndroidComponentsExtension
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import com.android.build.gradle.LibraryExtension
import org.w3c.dom.Element

// Based on RNGP's AgpConfiguratorPlugin
class AgpConfiguratorPlugin implements Plugin<Project> {
  @Override
  void apply(Project project) {
    configureBuildConfigFieldsForLibraries(project)
    configureNamespaceForLibraries(project)
  }

  // Make sure buildConfig is turned on for all the 3rd party libraries
  private void configureBuildConfigFieldsForLibraries(Project project) {
    project.rootProject.allprojects { subproject ->
      subproject.plugins.withId("com.android.library") {
        AndroidComponentsExtension ext = subproject.extensions.getByType(AndroidComponentsExtension)
        ext.finalizeDsl { androidComponentProperties ->
          buildFeatures.buildConfig = true
        }
      }
    }
  }

  // Ensure namespace is specified for all the 3rd party libraries
  private void configureNamespaceForLibraries(Project project) {
    project.rootProject.allprojects { subproject ->
      subproject.plugins.withId("com.android.library") {
        AndroidComponentsExtension ext = subproject.extensions.getByType(AndroidComponentsExtension)
        ext.finalizeDsl { androidComponentProperties ->
          if (androidComponentProperties.namespace == null) {
            LibraryExtension android = subproject.extensions.getByType(LibraryExtension)
            def manifestFile = android.sourceSets.getByName("main").manifest.srcFile

             if (manifestFile.exists()) {
               def packageName = getPackageNameFromManifest(manifestFile);
               androidComponentProperties.namespace = packageName
             }
          }
        }
      }
    }
  }

  private String getPackageNameFromManifest(File manifestFile) {
    try {
      // Use XmlPullParser to parse the AndroidManifest.xml
      def xmlFactory = XmlPullParserFactory.newInstance()
      def xmlParser = xmlFactory.newPullParser()

      // Open the manifest file for parsing
      def manifestReader = new FileReader(manifestFile)
      xmlParser.setInput(manifestReader)

      String packageName = null

      // Iterate through the XML elements
      while (xmlParser.getEventType() != XmlPullParser.END_DOCUMENT) {
        if (xmlParser.getEventType() == XmlPullParser.START_TAG) {
          if (xmlParser.getName() == "manifest") {
            // Read the package attribute
            packageName = xmlParser.getAttributeValue(null, "package")
            break
          }
        }
        xmlParser.next()
      }

      return packageName
    } catch (Exception e) {
      return null
    }
  }
}
// [END] Applying namespace for 3rd party vendor modules

// we need to apply this plugin here instead of inside expoview
// for it to be applied when running the clean task as well
apply plugin: AgpConfiguratorPlugin

dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar'])

  implementation "org.jetbrains.kotlin:kotlin-stdlib:${safeExtGet('kotlinVersion', '1.9.22')}"

  // Our dependencies
  implementation ('androidx.appcompat:appcompat:1.6.1')

  // Our dependencies for toggling edge-to-edge support
  implementation 'androidx.activity:activity:1.10.1'
  implementation 'androidx.activity:activity-ktx:1.10.1'
  implementation 'androidx.core:core-splashscreen:1.0.1'

  // Our dependencies from ExpoView
  // DON'T ADD ANYTHING HERE THAT ISN'T IN EXPOVIEW. ONLY COPY THINGS FROM EXPOVIEW TO HERE.
  compileOnly 'org.glassfish:javax.annotation:3.1.1'
  implementation 'com.jakewharton:butterknife:10.2.1'
  implementation 'de.greenrobot:eventbus:2.4.0'

  implementation 'com.squareup.picasso:picasso:2.5.2'
  implementation 'com.google.android.gms:play-services-analytics:16.0.1'
  implementation 'com.google.android.gms:play-services-maps:18.0.0'
  implementation 'com.google.android.gms:play-services-auth:15.0.1'
  implementation 'com.google.android.gms:play-services-location:15.0.1'
  debugImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
  // debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
  implementation 'com.facebook.device.yearclass:yearclass:2.1.0'
  implementation 'commons-io:commons-io:1.4'
  implementation 'com.airbnb.android:lottie:6.5.2'
  implementation 'me.leolin:ShortcutBadger:1.1.4@aar'
  implementation 'com.vanniktech:android-image-cropper:4.6.0'
  implementation 'commons-codec:commons-codec:1.10'
  implementation 'com.google.zxing:core:3.3.3'
  implementation 'net.openid:appauth:0.4.1'
  implementation "androidx.exifinterface:exifinterface:1.3.3"
  implementation 'com.squareup.okio:okio:1.9.0'
  implementation 'com.facebook.soloader:soloader:0.12.1'
  implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'

  // expo-file-system
  implementation 'com.squareup.okhttp3:okhttp:3.10.0'
  implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0'

  // Testing
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
  androidTestImplementation 'androidx.test:runner:1.4.0'
  androidTestImplementation "androidx.annotation:annotation:1.3.0"
  androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.0'
  androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
//  androidTestImplementation 'com.azimolabs.conditionwatcher:conditionwatcher:0.2'

  androidTestImplementation 'junit:junit:4.13.2'
  androidTestImplementation 'org.mockito:mockito-core:1.10.19'
  testImplementation 'org.robolectric:robolectric:4.10'
  androidTestImplementation 'androidx.test:runner:1.4.0'
  androidTestImplementation 'androidx.test:rules:1.4.0'

  testImplementation 'androidx.test:runner:1.4.0'
  testImplementation 'androidx.test:rules:1.4.0'
  testImplementation 'junit:junit:4.13.2'
  testImplementation 'org.mockito:mockito-core:1.10.19'

  implementation(project(':expoview'))

  implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
}

// This has to be down here for some reason
apply plugin: 'com.google.gms.google-services'

def ensureCrashlyticsDir = tasks.register('ensureCrashlyticsDir') {
  doLast {
    Files.createDirectories(Paths.get("${buildDir}/intermediates/merged_native_libs/mobileRelease/mergeMobileReleaseNativeLibs/out/lib"))
    Files.createDirectories(Paths.get("${buildDir}/intermediates/merged_native_libs/questRelease/mergeQuestReleaseNativeLibs/out/lib"))
  }
}
preBuild.dependsOn(ensureCrashlyticsDir)

afterEvaluate {
  // Overrides the react-native enforcing from RNGP
  rootProject.allprojects { eachProject ->
    eachProject.configurations.all { configuration ->
      configuration.resolutionStrategy.dependencySubstitution {
        substitute(module("com.facebook.react:react-native"))
          .using(project(":packages:react-native:ReactAndroid"))
          .because("Building React Native from source")
        substitute(module("com.facebook.react:react-native:+"))
          .using(project(":packages:react-native:ReactAndroid"))
          .because("Building React Native from source")
        substitute(module("com.facebook.react:react-android"))
          .using(project(":packages:react-native:ReactAndroid"))
          .because("Building React Native from source")
        substitute(module("com.facebook.react:hermes-android"))
          .using(project(":packages:react-native:ReactAndroid:hermes-engine"))
          .because("Building React Native from source")
      }
    }
  }
}
