// Adapted from https://raw.githubusercontent.com/facebook/react-native/d16ff3bd8b92fa84a9007bf5ebedd8153e4c089d/react.gradle

import java.nio.file.Paths;

def config = project.hasProperty("react") ? project.react : [];
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"

// because elvis operator
def elvisFile(thing) {
  return thing ? file(thing) : null;
}

void runBefore(String dependentTaskName, Task task) {
  Task dependentTask = tasks.findByPath(dependentTaskName);
  if (dependentTask != null) {
    dependentTask.dependsOn task
  }
}

android.buildTypes.each { buildType ->
  // to prevent incorrect long value restoration from strings.xml we need to wrap it with double quotes
  // https://github.com/microsoft/cordova-plugin-code-push/issues/264
  buildType.resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
}

gradle.projectsEvaluated {
  android.libraryVariants.all { variant ->
    def nodeModulesPath;
    if (config.root) {
      nodeModulesPath = Paths.get(config.root, "/node_modules");
    } else if (project.hasProperty('nodeModulesPath')) {
      nodeModulesPath = project.nodeModulesPath
    } else {
      nodeModulesPath = "../../node_modules";
    }

    def targetName = variant.name.capitalize()
    def targetPath = variant.dirName

    def jsBundleDir;
    def resourcesDir;
    def jsBundleFile;

    // Additional node commandline arguments
    def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
    def extraPackagerArgs = config.extraPackagerArgs ?: []

    // Make this task run right after the bundle task
    def generateBundledResourcesHash;

    if (variant.hasProperty("bundleJsAndAssets")) {
      def reactBundleTask = variant.bundleJsAndAssets
      jsBundleDir = reactBundleTask.generatedAssetsFolders[0].absolutePath
      resourcesDir = reactBundleTask.generatedResFolders[0].absolutePath
      jsBundleFile = file("$jsBundleDir/$bundleAssetName")

      generateBundledResourcesHash = tasks.create(
        name: "generateBundledResourcesHash${targetName}",
        type: Exec) {
        commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir)

        enabled config."bundleIn${targetName}" ||
          config."bundleIn${variant.buildType.name.capitalize()}" ?:
          targetName.toLowerCase().contains("release")
      }

      runBefore("merge${targetName}Resources", generateBundledResourcesHash)
      runBefore("merge${targetName}Assets", generateBundledResourcesHash)
    } else {
      def jsBundleDirConfigName = "jsBundleDir${targetName}"
      jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
        file("$buildDir/intermediates/assets/${targetPath}")

      def resourcesDirConfigName = "resourcesDir${targetName}"
      resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
        file("$buildDir/intermediates/res/merged/${targetPath}")

      // In case version of 'Android Plugin for Gradle'' is lower than 1.3.0
      // '$buildDir' has slightly different structure - 'merged' folder
      // does not exists so '${targetPath}' folder contains directly in 'res' folder.
      if (!resourcesDir.exists() && file("$buildDir/intermediates/res/${targetPath}").exists()) {
        resourcesDir = file("$buildDir/intermediates/res/${targetPath}")
      }

      jsBundleFile = file("$jsBundleDir/$bundleAssetName")

      def resourcesMapTempFileName = "CodePushResourcesMap-" + java.util.UUID.randomUUID().toString().substring(0,8) + ".json"

      generateBundledResourcesHash = tasks.create(
        name: "generateBundledResourcesHash${targetName}",
        type: Exec) {
        commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir, resourcesMapTempFileName)
      }

      // Make this task run right before the bundle task
      def recordFilesBeforeBundleCommand = tasks.create(
        name: "recordFilesBeforeBundleCommand${targetName}",
        type: Exec) {
        commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/react-native-code-push/scripts/recordFilesBeforeBundleCommand.js", resourcesDir, resourcesMapTempFileName)
      }

      recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Resources")
      recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Assets")
      runBefore("bundle${targetName}JsAndAssets", recordFilesBeforeBundleCommand)

      // We need to generate and record the resources map, but we use it to generate the bundle hash
      generateBundledResourcesHash.dependsOn("recordFilesBeforeBundleCommand${targetName}")
    }

    generateBundledResourcesHash.dependsOn("bundle${targetName}JsAndAssets")
    runBefore("processArmeabi-v7a${targetName}Resources", generateBundledResourcesHash)
    runBefore("processX86${targetName}Resources", generateBundledResourcesHash)
    runBefore("processUniversal${targetName}Resources", generateBundledResourcesHash)
    runBefore("process${targetName}Resources", generateBundledResourcesHash)
  }
}
