/**
 * 用于下载framework jar包和framework aidl文件
 * 下载用到git中的sparse-checkout命令,请保证当前环境中的git版本支持此命令
 * 如不支持,请将git升级到最新版本2.45.1版本或最新版本
 */

import java.nio.file.Path

ext {
    getFrameworkJarPath = (gradleUserHomeDir, sdkInt) -> getFrameworkJarPathImpl(gradleUserHomeDir, sdkInt)
    runtimeExec = (cmd) -> runtimeExecImpl(cmd)
    getFrameworkAidlPath = (gradleUserHomeDir, tag) -> getFrameworkAidlPathImpl(gradleUserHomeDir, tag)
}

private static String getFrameworkJarPathImpl(File gradleUserHomeDir, String sdkInt) {
    // framework jar包下载地址
    String FRAMEWORK_JAR_URL = "https://gitcode.com/Reginer/aosp-android-jar.git"
    String FRAMEWORK_JAR_DIR_NAME = "framework-jar-$sdkInt"

    File cachesDir = new File(gradleUserHomeDir, "caches")
    File frameworkJarDir = new File(cachesDir, FRAMEWORK_JAR_DIR_NAME)
    String frameworkJarPath = Path.of(frameworkJarDir.getAbsolutePath(), "aosp-android-jar",
            "android-$sdkInt", "android.jar").toString()
    File frameworkJar = new File(frameworkJarPath)
    println("frameworkJarPath = $frameworkJarPath")
    if (frameworkJar.exists()) {
        return frameworkJarPath
    }

    if (!frameworkJarDir.exists()) {
        if (!frameworkJarDir.mkdirs()) {
            throw new RuntimeException(String.format("mkdirs error %s", frameworkJarDir))
        }
    }
    File baseDir = new File(frameworkJarDir, "aosp-android-jar")
    File gitDir = new File(baseDir, ".git")
    if (gitDir.exists()) {
        deleteDir(gitDir)
    }

    try {
        println("exec git:")
        runtimeExecImpl("git -C $frameworkJarDir clone --filter=blob:none --sparse --depth 1 -b main --single-branch --no-checkout $FRAMEWORK_JAR_URL")
        runtimeExecImpl("git -C $baseDir sparse-checkout init --no-cone")
        runtimeExecImpl("git -C $baseDir sparse-checkout set !/*")
        runtimeExecImpl("git -C $baseDir sparse-checkout add android-$sdkInt/android.jar")
        runtimeExecImpl("git -C $baseDir checkout main")
    } catch (Exception ex) {
        throw new RuntimeException(ex)
    }
    return frameworkJarPath
}

private static String getFrameworkAidlPathImpl(File gradleUserHomeDir, String tag) {
    final String PLATFORM_URL = "https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/"
    final String FRAMEWORKS_BASE_URL = "${PLATFORM_URL}frameworks/base"
    final String FRAMEWORK_AIDL_DIR_NAME = "framework-aidl_$tag"

    File cachesDir = new File(gradleUserHomeDir, "caches")
    File frameworkAidlDir = new File(cachesDir, FRAMEWORK_AIDL_DIR_NAME)

    String frameworkAidlPath = Path.of(frameworkAidlDir.getAbsolutePath(), "base",
            "core", "java").toString()
    File frameworkAidl = new File(frameworkAidlPath)

    println("frameworkAidlPath = $frameworkAidlPath")
    if (frameworkAidl.exists()) {
        return frameworkAidl
    }

    if (!frameworkAidlDir.exists()) {
        if (!frameworkAidlDir.mkdirs()) {
            throw new RuntimeException(String.format("mkdirs error %s", frameworkAidlDir))
        }
    }

    def baseDir = new File(frameworkAidlDir, "base")
    def gitDir = new File(baseDir, ".git")
    if (gitDir.exists()) {
        deleteDir(gitDir)
    }

    try {
        println("exec git:")
        runtimeExecImpl("git -C $frameworkAidlDir clone --filter=blob:none --sparse --depth 1 -b $tag --single-branch --no-checkout $FRAMEWORKS_BASE_URL")
        runtimeExecImpl("git -C $baseDir sparse-checkout init --no-cone")
        runtimeExecImpl("git -C $baseDir sparse-checkout set !/*")
        runtimeExecImpl("git -C $baseDir sparse-checkout add /core/java/**/*.aidl")
        runtimeExecImpl("git -C $baseDir checkout -b $tag $tag")
    } catch (Exception ex) {
        throw new RuntimeException(ex)
    }
    return frameworkAidlPath
}

private static void runtimeExecImpl(String cmd) throws Exception {
    println("$cmd")
    Runtime runtime = Runtime.getRuntime()
    Process process = runtime.exec(cmd)
    String result = readInputStream(process.getInputStream())
    String errorMsg = readInputStream(process.getErrorStream())
    if (process.waitFor() == 0) {
        if (!result.isEmpty()) {
            println("$result")
        }
        if (!errorMsg.isEmpty()) {
            println("$errorMsg")
        }
    } else {
        if (!result.isEmpty()) {
            println("$result")
        }
        if (!errorMsg.isEmpty()) {
            println("$errorMsg")
        }
        throw new RuntimeException("exec error")
    }
}

private static String readInputStream(InputStream input) {
    StringBuilder sb = new StringBuilder()
    try(BufferedReader br = new BufferedReader(new InputStreamReader(input))) {
        String line
        while ((line = br.readLine()) != null) {
            sb.append(line).append(System.lineSeparator())
        }
    } catch (Throwable ex) {
        ex.printStackTrace(System.err)
    }
    return sb.toString().trim()
}

private static void deleteDir(File dir) {
    if (dir.isDirectory()) {
        File[] files = dir.listFiles()
        if (files == null) {
            return
        }
        for (File file : files) {
            if (file.isFile()) {
                file.delete()
            } else {
                deleteDir(file)
            }
        }
    }
    dir.delete()
}