/*
 * 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 org.apache.tools.ant.filters.ReplaceTokens

// !!!
// Increment this when making changes to any of the native
// dependencies.
// !!!
final def CACHE_REVISION = 31

final def externalDir = new File("$projectDir/external")
final def downloadsDir = new File("$externalDir/downloads")
final def revisionFile = new File("$buildDir/external_cache_revision.txt")

final def getDownloadFileName = { final URL src ->
    final def i = src.file.lastIndexOf('/')
    return src.file.substring(i + 1)
}

final def isCacheOutOfDate = { final Integer revision ->
    if (!revisionFile.exists()) {
        return true
    } else {
        final def content = revisionFile.text
        return !content.isInteger() || content as Integer != revision
    }
}

task createNativeDepsDirectories {
    buildDir.mkdirs()
    downloadsDir.mkdirs()
    externalDir.mkdirs()
}

task cleanNative(type: Delete) {
    delete externalDir
}

task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    src 'https://github.com/google/glog/archive/v0.3.5.tar.gz'
    onlyIfNewer true
    overwrite false
    dest new File(downloadsDir, 'glog-' + getDownloadFileName(src))
}

task prepareGlog(dependsOn: [downloadGlog], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from tarTree(downloadGlog.dest)
    duplicatesStrategy DuplicatesStrategy.INCLUDE
    from './overrides/glog/'
    include 'glog-0.3.5/src/**/*', 'Android.mk', 'config.h', 'build.gradle', 'CMakeLists.txt', 'ApplicationManifest.xml'
    includeEmptyDirs = false
    filesMatching('**/*.h.in') {
        filter(ReplaceTokens, tokens: [
                ac_cv_have_unistd_h: '1',
                ac_cv_have_stdint_h: '1',
                ac_cv_have_systypes_h: '1',
                ac_cv_have_inttypes_h: '1',
                ac_cv_have_libgflags: '0',
                ac_google_start_namespace: 'namespace google {',
                ac_cv_have_uint16_t: '1',
                ac_cv_have_u_int16_t: '1',
                ac_cv_have___uint16: '0',
                ac_google_end_namespace: '}',
                ac_cv_have___builtin_expect: '1',
                ac_google_namespace: 'google',
                ac_cv___attribute___noinline: '__attribute__ ((noinline))',
                ac_cv___attribute___noreturn: '__attribute__ ((noreturn))',
                ac_cv___attribute___printf_4_5: '__attribute__((__format__ (__printf__, 4, 5)))'
        ])
        it.path = (it.name - '.in')
    }
    into "$externalDir/glog"
}

task finalizeGlog(dependsOn: [prepareGlog], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from './overrides/glog/'
    include 'logging.cc'
    includeEmptyDirs = false
    into "$externalDir/glog/glog-0.3.5/src/"
}

task downloadDoubleConversion(dependsOn: createNativeDepsDirectories, type: Download) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    src 'https://github.com/google/double-conversion/archive/v3.0.0.tar.gz'
    onlyIfNewer true
    overwrite false
    dest new File(downloadsDir, 'double-conversion-' + getDownloadFileName(src))
}

task prepareDoubleConversion(dependsOn: [downloadDoubleConversion], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from tarTree(downloadDoubleConversion.dest)
    from './overrides/DoubleConversion/'
    include 'double-conversion-3.0.0/**/*', 'build.gradle', 'CMakeLists.txt', 'ApplicationManifest.xml'
    includeEmptyDirs = false
    into "$externalDir/double-conversion"
}

task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    src 'https://github.com/react-native-community/boost-for-react-native/releases/download/v1.63.0-0/boost_1_63_0.tar.gz'
    onlyIfNewer true
    overwrite false
    dest new File(downloadsDir, getDownloadFileName(src))
}

task prepareBoost(dependsOn: [downloadBoost], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from tarTree(resources.gzip(downloadBoost.dest))
    include 'boost_1_63_0/boost/**/*.hpp', 'boost_1_63_0/boost/**/*.h', 'boost/boost/**/*.hpp', 'boost/boost/**/*.h'
    includeEmptyDirs = false
    into "$externalDir/boost"
    doLast {
        file("$externalDir/boost/boost").renameTo("$externalDir/boost/boost_1_63_0")
    }
}

task downloadLibEvent(dependsOn: [createNativeDepsDirectories], type: Download) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    src 'https://github.com/libevent/libevent/releases/download/release-2.1.11-stable/libevent-2.1.11-stable.tar.gz'
    onlyIfNewer true
    overwrite false
    dest new File(downloadsDir, 'libevent-' + getDownloadFileName(src))
}

task prepareLibEvent1(dependsOn: [downloadLibEvent], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from tarTree(downloadLibEvent.dest)
    from './overrides/LibEvent/'
    include 'libevent-2.1.11-stable/**/*', 'build.gradle', 'ApplicationManifest.xml'
    includeEmptyDirs = false
    into "$externalDir/LibEvent"
}

task prepareLibEvent2(dependsOn: [prepareLibEvent1], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from './overrides/LibEvent/'
    include 'event-config.h'
    includeEmptyDirs = false
    into "$externalDir/LibEvent/libevent-2.1.11-stable/include/event2/"
}

task finalizeLibEvent(dependsOn: [prepareLibEvent2], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from './overrides/LibEvent/'
    include 'CMakeLists.txt'
    into "$externalDir/LibEvent/libevent-2.1.11-stable/"
}

task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    src 'https://github.com/facebook/folly/archive/v2020.02.17.00.tar.gz'
    onlyIfNewer true
    overwrite false
    dest new File(downloadsDir, 'folly-' + getDownloadFileName(src))
}

task prepareFolly(dependsOn: [downloadFolly, prepareBoost, prepareDoubleConversion, finalizeGlog, finalizeLibEvent], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from tarTree(downloadFolly.dest)
    from './overrides/Folly/'
    include 'folly-2020.02.17.00/folly/**/*', 'build.gradle', 'CMakeLists.txt', 'ApplicationManifest.xml'
    eachFile { it.path = it.path - "folly-2020.02.17.00/" }
    includeEmptyDirs = false
    into "$externalDir/folly/"
}

task finalizeFollyWithDemangle(dependsOn: [prepareFolly], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from './overrides/Folly/'
    include 'Demangle.h'
    into "$externalDir/folly/folly/detail/"
}

// Fix template issue with newest NDK
task finalizeFollyWithFileUtil(dependsOn: [prepareFolly], type: Copy) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    from './overrides/Folly/'
    include 'FileUtil.cpp'
    into "$externalDir/folly/folly/"
}

task finalizeFolly(dependsOn: [finalizeFollyWithDemangle, finalizeFollyWithFileUtil]) {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
}

task writeCacheRevision(dependsOn: [finalizeFolly]) {
    doLast {
        buildDir.mkdirs()
        revisionFile.text = CACHE_REVISION.toString()
    }
}

task prepareAllLibs() {
    onlyIf { isCacheOutOfDate(CACHE_REVISION) }
    dependsOn writeCacheRevision
}
