/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import groovy.json.JsonSlurper
import org.apache.tools.ant.filters.ReplaceTokens

// read the React-Native version of local app
def parseAppRnVersion() {
   def inputFile = new File(rootDir, '../node_modules/react-native/package.json')
   def json = new JsonSlurper().parseText(inputFile.text)
   return json.version as String
}

def (appRnMajorVersion, appRnMinorVersion, appRnPatchVersion) = parseAppRnVersion().tokenize('.')

buildscript {
  if (project == rootProject) {
    repositories {
      google()
      jcenter()
      maven {
        url "https://plugins.gradle.org/m2/"
      }
    }
    dependencies {
      classpath "com.android.tools.build:gradle:3.5.3"
    }
  }
}

apply plugin: "com.android.library"

def safeExtGet(prop, fallback) {
    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}

android {
  compileSdkVersion safeExtGet('PyTorchCore_compileSdkVersion', Integer.parseInt(appRnMinorVersion) < 68 ? 30 : 31)
  buildToolsVersion safeExtGet('PyTorchCore_buildToolsVersion', Integer.parseInt(appRnMinorVersion) < 68 ? '30.0.2' : '31.0.0')
  defaultConfig {
    minSdkVersion safeExtGet('PyTorchCore_minSdkVersion', 21)
    targetSdkVersion safeExtGet('PyTorchCore_targetSdkVersion', 30)
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    packagingOptions {
      pickFirst '**/*.so'
    }
    externalNativeBuild {
      cmake {
        cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID"
        abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
        arguments '-DANDROID_STL=c++_shared', "-DNODE_MODULES_DIR=${rootDir}/../node_modules", "-DREACT_NATIVE_MINOR_VERSION=${appRnMinorVersion}"
      }
    }
  }

  buildTypes {
    release {
      minifyEnabled false
    }
  }
  lintOptions {
   disable 'GradleCompatible'
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  externalNativeBuild {
    cmake {
      path "CMakeLists.txt"
    }
  }

  // Exclude META-INF/MANIFEST.MF otherwise the Detox build will fail with
  // message "More than one file was found with OS independent path 'META-INF/MANIFEST.MF'."
  // A potential solution would be upgrading the Gradle version as mentioned
  // in the following Stack Overflow comment:
  // https://stackoverflow.com/questions/58745742/error-duplicate-entry-meta-inf-manifest-mf
  packagingOptions {
    excludes = ["**/libc++_shared.so","**/libreactnativeutilsjni.so",'META-INF/MANIFEST.MF']
  }

  configurations {
    extractHeaders
    extractJNI
    extractForNativeBuild
  }
}

repositories {
    mavenCentral()
    mavenLocal()
    maven {
        // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
        url("$rootDir/../node_modules/react-native/android")
    }
    google()
    jcenter()
}

dependencies {
  def pytorchLiteVersion = '1.12.2'
  implementation "org.pytorch:pytorch_android_lite:${pytorchLiteVersion}"

  //noinspection GradleDynamicVersion
  api "com.facebook.react:react-native:+"  // From node_modules

  //noinspection GradleDynamicVersion
  extractHeaders("com.facebook.fbjni:fbjni:+:headers")
  //noinspection GradleDynamicVersion
  extractJNI("com.facebook.fbjni:fbjni:+")

  def nodeModules = "${rootDir}/../node_modules"

  // For now we use the release version of the jni library
  // we will look back on this once we figure out how to
  // get the buildType duing configuration stage
  def buildType = "release"

  if (Integer.parseInt(appRnMinorVersion) < 69) {
      def rnAAR = fileTree("${nodeModules}/react-native/android").matching({ it.include "**/**/*.aar" }).singleFile
      extractJNI(files(rnAAR))
  } else {
      // React Native 0.69
      def rnAarMatcher = "**/react-native/**/*${buildType}.aar"
      def rnAAR = fileTree("${nodeModules}/react-native/android").matching({ it.include rnAarMatcher }).singleFile
      extractJNI(files(rnAAR))
  }

  extractForNativeBuild("org.pytorch:pytorch_android_lite:${pytorchLiteVersion}")

  implementation "androidx.appcompat:appcompat:1.2.0"
  implementation "com.android.support.constraint:constraint-layout:2.0.4"
  implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"

  implementation "androidx.cardview:cardview:1.0.0"
  implementation 'com.android.support:support-annotations:28.0.0'
  testImplementation 'junit:junit:4.12'
  testImplementation 'org.json:json:20140107'
  testImplementation 'org.mockito:mockito-core:1.10.19'

  androidTestImplementation 'junit:junit:4.12'
  androidTestImplementation 'androidx.test:core:1.3.0'
  androidTestImplementation 'androidx.test:runner:1.3.0'
  androidTestImplementation 'androidx.test:rules:1.3.0'
  androidTestImplementation 'com.facebook.soloader:soloader:0.9.0'

  def cameraxVersion = "1.1.0-alpha05"
  implementation "androidx.camera:camera-core:${cameraxVersion}"
  implementation "androidx.camera:camera-camera2:${cameraxVersion}"
  implementation "androidx.camera:camera-lifecycle:${cameraxVersion}"
  implementation "androidx.camera:camera-view:1.0.0-alpha25"

  implementation "androidx.constraintlayout:constraintlayout:2.0.4"
}

// fbjni
// https://github.com/facebookincubator/fbjni/blob/master/docs/android_setup.md

task extractAARHeaders {
  doLast {
    configurations.extractHeaders.files.each {
      def file = it.absoluteFile
      copy {
        from zipTree(file)
        into "$buildDir/$file.name"
        include "**/*.h"
      }
    }
  }
}

task extractJNIFiles {
  doLast {
    configurations.extractJNI.files.each {
      def file = it.absoluteFile

      copy {
        from zipTree(file)
        into "$buildDir/$file.name"
        include "jni/**/*"
      }
    }
  }
}

task extractAARForNativeBuild {
    doLast {
        configurations.extractForNativeBuild.files.each {
            def file = it.absoluteFile
            copy {
                from zipTree(file)
                into "$buildDir/$file.name"
                include "headers/**"
                include "jni/**"
            }
        }
    }
}

def configureCMakeTaskName = Integer.parseInt(appRnMinorVersion) < 68 ? "externalNativeBuild" : "configureCMake"
tasks.whenTaskAdded { task ->
  if (task.name.contains(configureCMakeTaskName)) {
    task.dependsOn(extractAARHeaders)
    task.dependsOn(extractJNIFiles)
    task.dependsOn(extractAARForNativeBuild)
  }
}
