

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Android;
using UnityEditorInternal;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Globalization;

using Hive.Unity.Editor;


#if UNITY_2018_1_OR_NEWER // PreProc [1]
public class AndroidPostBuildProcessor : IPostGenerateGradleAndroidProject
{
    private string Android_Huawei_Agconnect_Version = "1.7.3.300";
    private string Android_Huawei_Gradle_Tool_Version = "7.1.3";
    private Version currentVersion = null;

    public int callbackOrder
    {
        get
        {
            return 999;
        }
    }

    void IPostGenerateGradleAndroidProject.OnPostGenerateGradleAndroidProject(string path)
    {
        // PostProcess 과정에선 Unity 런타임이 아니여서 new Version(Application.unityVersion) 로 버전 획득 불가
        currentVersion = GetCurrentUnityCoreVersion(InternalEditorUtility.GetFullUnityVersion()); 

        resolveGradleProperties(path);

    #if UNITY_2019_3_OR_NEWER // PreProc [1-1] OnPostGenerateGradleAndroidProject
        resolveBaseBuildGradle(path); // for huawei
        resolveLauncherBuildGradle(path);
    #endif // PreProc [1-1] OnPostGenerateGradleAndroidProject(end)
    #if UNITY_2020_1_OR_NEWER // PreProc [1-2] OnPostGenerateGradleAndroidProject
        resolveMainBuildGradle(path);
    #endif // PreProc [1-2] OnPostGenerateGradleAndroidProject(end)

        // resolve targetSDKversion 31, JDK 11 issue
        // https://developers.google.com/ar/develop/unity-arf/android-12-build
        resolveMainBuildGradleTargetSDK31(path);
        resolveUnityResourcesBuildGradleTargetSDK31(path);
        copyToGoogleServicesJson(path);
        resolveSettingsGradle(path);
    }

    private void resolveGradleProperties(string path)
    {
    #if UNITY_2022_2_OR_NEWER
        // 2022.2.1f1 이상에서 androidX 라이브러리를 못찾는 이슈가 있어 프로젝트 레벨의 gradle.properties 에 android.useAndroidX=true를 쓸수 있도록 경로 수정
        string gradlePropertiesPath = path + "/../gradle.properties";
    #else
        string gradlePropertiesPath = path + "/gradle.properties";
    #endif

        string[] lines = {
                "android.useAndroidX = true",
                "android.enableJetifier = true"
            };

        using (StreamWriter sw = File.AppendText(gradlePropertiesPath))
        {
            sw.WriteLine(Environment.NewLine);
            foreach (string line in lines){
                sw.WriteLine(line);
            }
        }
    }

    /*
    * Resolve launcher's build.gradle (#GCPSDK4-99)
    * - unity 2019.3에서 launcher, unityLibrary 로 프로젝트가 분리
    * - unityLibrary's build.gradle은 기존 mainTemplate.gradle로 커스텀할 수 있으나, launcher's build.gradle은 커스텀할 수 없는 이슈 존재
    */
    private void resolveLauncherBuildGradle(string path)
    {    
        string launcherPath = path + "/../launcher/";
        string launcherBuildGradle = launcherPath + "build.gradle";
        string tmpBuildGradle = launcherPath + "tmpBuild.gradle";
        string basePath = path + "/..";

        if (!File.Exists(launcherBuildGradle))
        {
            HiveLogger.Log("launcher's build.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(launcherBuildGradle);
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", launcherBuildGradle, ex.ToString()));
        }

        StreamWriter writer = File.CreateText(tmpBuildGradle);
            
        IEnumerator ienum = lines.GetEnumerator();
        while(ienum.MoveNext())
        {
            string line = (string)ienum.Current;

            // resolve targetSDKversion 31, JDK 11 issue
            // https://developers.google.com/ar/develop/unity-arf/android-12-build
    #if UNITY_2021_3_OR_NEWER // PreProc [1-1] resolveLauncherBuildGradle
            if(IsAtLeast(currentVersion, 2021, 3, 41))
            {
                // nothing to do
            }
            else
            {
                if(line.Contains("compileSdkVersion 31"))
                {
                    line = "compileSdkVersion 30 // Add Hive for targetSDKversion 31 issue";
                }
                else if(line.Contains("buildToolsVersion \'31"))
                {
                    line = "buildToolsVersion \'30.0.3\' // Add Hive for targetSDKversion 31 issue";
                }
            }
    #else
            if(line.Contains("compileSdkVersion 31"))
            {
                line = "compileSdkVersion 30 // Add Hive for targetSDKversion 31 issue";
            }
            else if(line.Contains("buildToolsVersion \'31"))
            {
                line = "buildToolsVersion \'30.0.3\' // Add Hive for targetSDKversion 31 issue";
            }
    #endif // // PreProc [1-1] resolveLauncherBuildGradle(end)

            // Android 16 support 16KB Page Size App Build (#GCPSDK4-2232)
            // https://developer.android.com/guide/practices/page-sizes?hl=ko#groovy
    #if (UNITY_2021_3_OR_NEWER && !UNITY_2022_1_OR_NEWER) || UNITY_2022_3_OR_NEWER // PreProc [1-2] resolveLauncherBuildGradle
            if(line.Contains("defaultConfig") && needUseLegacyPackaging(basePath))
            {
                string tmpLine = "";
                tmpLine = "    packagingOptions {\n";
                tmpLine += "        jniLibs {\n";
                tmpLine += "            useLegacyPackaging true\n";
                tmpLine += "        }\n";
                tmpLine += "    }\n";

                line = tmpLine + line;
            }
    #endif // PreProc [1-2] resolveLauncherBuildGradle(end)

            writer.WriteLine(line);
        }

        // google firebase apply plugin
        bool useFirebase = ExternalDependencyDictionaryManager.isUseDependency(ExternalDependencyDictionaryManager.SupportOSType.Android, ExternalDependencyType.Firebase);
        if(useFirebase) {
            if(!checkDuplicateHiveSetting(launcherBuildGradle, "apply plugin: 'com.google.gms.google-services")) {
                writer.WriteLine("apply plugin: 'com.google.gms.google-services'");
            }
        } else {
            HiveLogger.Log("firebase dependecies is not exist");
        }

        // huawei apply plugin
        bool useHuawei = ExternalDependencyDictionaryManager.isUseDependency(ExternalDependencyDictionaryManager.SupportOSType.Android, ExternalDependencyType.Huawei);
        if (useHuawei) {
            if(!checkDuplicateHiveSetting(launcherBuildGradle, "apply plugin: 'com.huawei.agconnect")) {
                writer.WriteLine("apply plugin: 'com.huawei.agconnect'");
            }
            copyToHuaweiServicesJson(path); // huawei

        } else {
            HiveLogger.Log("huawei dependecies is not exist");
        }

        writer.Flush();
        writer.Close();

        File.Delete(launcherBuildGradle);
        File.Move(tmpBuildGradle, launcherBuildGradle);

    }

    /*
    * Resolve launcher's build.gradle (#GCPTAM-391)
    * - unity 2020.1에서 aaptOptions STREAMING_ASSETS 예약어가 사라짐
    */
    private void resolveMainBuildGradle(string path)
    {    
        string mainPath = path + "/../unityLibrary/";
        string mainBuildGradle = mainPath + "build.gradle";
        string tmpBuildGradle = mainPath + "tmpBuild.gradle";

        if (!File.Exists(mainBuildGradle))
        {
            HiveLogger.Log("main's build.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(mainBuildGradle);
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", mainBuildGradle, ex.ToString()));
            return;
        }

        StreamWriter writer = File.CreateText(tmpBuildGradle);
            
        IEnumerator ienum = lines.GetEnumerator();
        while(ienum.MoveNext())
        {
            string line = (string)ienum.Current;

            // Find and Replace '**STREAMING_ASSETS**'
            if(line.Contains("**STREAMING_ASSETS**")) {
                writer.WriteLine("noCompress = ['.ress', '.resource', '.obb'] + unityStreamingAssets.tokenize(', ')");
            } else {
                writer.WriteLine(line);
            }
        }
        writer.Flush();
        writer.Close();

        File.Delete(mainBuildGradle);
        File.Move(tmpBuildGradle, mainBuildGradle);

    }

    private void resolveMainBuildGradleTargetSDK31(string path)
    {    
        string mainPath = path + "/../unityLibrary/";
        string mainBuildGradle = mainPath + "build.gradle";
        string tmpBuildGradle = mainPath + "tmpBuild.gradle";

        if (!File.Exists(mainBuildGradle))
        {
            HiveLogger.Log("main's build.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(mainBuildGradle);
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", mainBuildGradle, ex.ToString()));
            return;
        }

        StreamWriter writer = File.CreateText(tmpBuildGradle);
            
        IEnumerator ienum = lines.GetEnumerator();
        while(ienum.MoveNext())
        {
            string line = (string)ienum.Current;

            #if UNITY_2022_2_OR_NEWER
            //
            #else
            if(line.Contains("compileSdkVersion 31")) {
                line = "compileSdkVersion 30 // Add Hive for targetSDKversion 31 issue";
            } else if(line.Contains("buildToolsVersion \'31")){
                line = "buildToolsVersion \'30.0.3\' // Add Hive for targetSDKversion 31 issue";
            }
            #endif

            writer.WriteLine(line);  
        }
        writer.Flush();
        writer.Close();

        File.Delete(mainBuildGradle);
        File.Move(tmpBuildGradle, mainBuildGradle);

    }

    private void resolveUnityResourcesBuildGradleTargetSDK31(string path){
        
        string mainPath = path + "/../unityLibrary/unity-android-resources/";
        string mainBuildGradle = mainPath + "build.gradle";
        string tmpBuildGradle = mainPath + "tmpBuild.gradle";

        if (!File.Exists(mainBuildGradle))
        {
            HiveLogger.Log("main's build.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(mainBuildGradle);
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", mainBuildGradle, ex.ToString()));
            return;
        }

        StreamWriter writer = File.CreateText(tmpBuildGradle);
            
        IEnumerator ienum = lines.GetEnumerator();
        while(ienum.MoveNext())
        {
            string line = (string)ienum.Current;
            
    #if UNITY_2022_2_OR_NEWER // PreProc [1-1] resolveUnityResourcesBuildGradleTargetSDK31
            //
    #else
            if(line.Contains("compileSdkVersion 31")) {
                line = "compileSdkVersion 30 // Add Hive for targetSDKversion 31 issue";
            } else if(line.Contains("buildToolsVersion \'31")){
                line = "buildToolsVersion \'30.0.3\' // Add Hive for targetSDKversion 31 issue";
            }
    #endif // PreProc [1-1] resolveUnityResourcesBuildGradleTargetSDK31(end)

            writer.WriteLine(line);  
        }
        writer.Flush();
        writer.Close();

        File.Delete(mainBuildGradle);
        File.Move(tmpBuildGradle, mainBuildGradle);

    }

    private void resolveBaseBuildGradle(string path)
    {    
        string basePath = path + "/../";
        string baseBuildGradle = basePath + "build.gradle";
        string tmpBuildGradle = basePath + "tmpBuild.gradle";

        if (!File.Exists(baseBuildGradle))
        {
            HiveLogger.Log("main's build.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        bool alreadyHiveAdded = false;
        
        try
        {
            lines = File.ReadAllLines(baseBuildGradle);
    #if UNITY_2022_2_OR_NEWER // PreProc [1-1] resolveBaseBuildGradle
            foreach (string line in lines)
            {
                if(line.Contains("Add HIVE")) {
                    HiveLogger.Log("already hive settings added");
                    alreadyHiveAdded = true;
                    break;
                }
            }
    #elif UNITY_2021_3_OR_NEWER
            if(IsAtLeast(currentVersion, 2021, 3, 41))
            {
                foreach (string line in lines)
                {
                    if(line.Contains("Add HIVE")) {
                        HiveLogger.Log("already hive settings added");
                        alreadyHiveAdded = true;
                        break;
                    }
                }
            }
    #endif // PreProc [1-1] resolveBaseBuildGradle(end)
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", baseBuildGradle, ex.ToString()));
            return;
        }

        StreamWriter writer = File.CreateText(tmpBuildGradle);
            
        IEnumerator ienum = lines.GetEnumerator();
        while(ienum.MoveNext())
        {
            string line = (string)ienum.Current;

    #if UNITY_2021_3_OR_NEWER // PreProc [1-2] resolveBaseBuildGradle
            if(IsAtLeast(currentVersion, 2021, 3, 41))
            {
                if(line.Contains("plugins"))
                {
                    writer.WriteLine(line);
                    if(!alreadyHiveAdded) {
                        writer.WriteLine("    // Add HIVE");
                        writer.WriteLine("    id 'org.jetbrains.kotlin.android' version '1.5.20' apply false");
                        writer.WriteLine("    id 'com.google.gms.google-services' version '4.4.0' apply false");
                    }
                }
                else
                {
                    writer.WriteLine(line);
                }
            }
            else
            {
                if(line.Contains("jcenter()"))
                {
                    writer.WriteLine("jcenter()");
                    writer.WriteLine("// Add HIVE");
                    writer.WriteLine("maven { url 'https://developer.huawei.com/repo/' }");
                }
                else
                {
                    writer.WriteLine(line);
                }
            }
    #else
            if(line.Contains("jcenter()"))
            {
                writer.WriteLine("jcenter()");
                writer.WriteLine("// Add HIVE");
                writer.WriteLine("maven { url 'https://developer.huawei.com/repo/' }");
            }
            else
            {
                writer.WriteLine(line);
            }
    #endif // PreProc [1-2] resolveBaseBuildGradle(end)
        }
        writer.Flush();
        writer.Close();

        File.Delete(baseBuildGradle);
        File.Move(tmpBuildGradle, baseBuildGradle);

    #if UNITY_2021_3_OR_NEWER // PreProc [1-3] resolveBaseBuildGradle
        if(IsAtLeast(currentVersion, 2021, 3, 41))
        {
            bool useHuawei = ExternalDependencyDictionaryManager.isUseDependency(ExternalDependencyDictionaryManager.SupportOSType.Android, ExternalDependencyType.Huawei);
            if (useHuawei)
            {
                includeHuaweiBaseBuildGradle(path);
                includeHuaweiSettingsGradle(path);       
            }
        }
    #endif // PreProc [1-3] resolveBaseBuildGradle(end)
    }

    private void includeHuaweiBaseBuildGradle(string path) {
        string basePath = path + "/../";
        string baseBuildGradle = basePath + "build.gradle";
        string tmpBuildGradle = basePath + "tmpBuild.gradle";
        bool alreadyHuaweiAdded = false;

        if (!File.Exists(baseBuildGradle))
        {
            HiveLogger.Log("includeHuaweiToBaseBuildGradle, main's build.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(baseBuildGradle);
            foreach (string line in lines)
            {
                if(line.Contains("com.huawei.agconnect:agcp")) {
                    HiveLogger.Log("already huawei settings added");
                    alreadyHuaweiAdded = true;
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("includeHuaweiToBaseBuildGradle, Unable to read lines {0} ({1})", baseBuildGradle, ex.ToString()));
            return;
        }

        // 상위 gradle 파일 읽기에 이상이 없는 경우
        // Huawei 설정 추가 진행
        StreamWriter writer = File.CreateText(tmpBuildGradle);
        IEnumerator ienum = lines.GetEnumerator();
        bool alreadySet = false;

        if(alreadyHuaweiAdded) {

            while(ienum.MoveNext()) {
                string line = (string)ienum.Current;

                // 상위 gradle에 buildscript 내용이 있는 경우
                // Huawei agconnect 설정만 추가
                if(line.Contains("com.huawei.agconnect:agcp")) {
                    string agconnectInfo = "        classpath 'com.huawei.agconnect:agcp:";
                    agconnectInfo += Android_Huawei_Agconnect_Version;
                    agconnectInfo += "'";
                    writer.WriteLine(agconnectInfo);

                    alreadySet = true;
                } else {
                    writer.WriteLine(line);
                }
            }
        } else {

            while(ienum.MoveNext()) {
                string line = (string)ienum.Current;

                // 상위 gradle에 buildscript 내용이 있는 경우
                // Huawei agconnect 설정만 추가
                if(line.Contains("com.android.tools.build:gradle")) {
                    writer.WriteLine(line);
                    writer.WriteLine("        // Add Hive(for Huawei)");
                    string agconnectInfo = "        classpath 'com.huawei.agconnect:agcp:";
                    agconnectInfo += Android_Huawei_Agconnect_Version;
                    agconnectInfo += "'";
                    writer.WriteLine(agconnectInfo);

                    alreadySet = true;
                } else {
                    writer.WriteLine(line);
                }
            }

            // 상위 gradle에 buildscript 내용이 애초 없었던 상태
            if(!alreadySet) {
                writer.Flush();
                writer.Close();     // tmpBuildGradle 삭제를 위해 Close 처리 (OS(ex : Windows)에 따라 Close 처리 안할 경우 파일 접근 불가)
                File.Delete(tmpBuildGradle);

                writer = File.CreateText(tmpBuildGradle);
                ienum = lines.GetEnumerator();

                while(ienum.MoveNext()) {
                    string line = (string)ienum.Current;

                    if(line.Contains("plugins")) {
                        writer.WriteLine("// Add Hive(for Huawei)");
                        writer.WriteLine("buildscript {");
                        writer.WriteLine("    dependencies {");

                        string gradleToolInfo = "        classpath 'com.android.tools.build:gradle:";
                        gradleToolInfo += Android_Huawei_Gradle_Tool_Version;
                        gradleToolInfo += "'";
                        writer.WriteLine(gradleToolInfo);

                        string agconnectInfo = "        classpath 'com.huawei.agconnect:agcp:";
                        agconnectInfo += Android_Huawei_Agconnect_Version;
                        agconnectInfo += "'";
                        writer.WriteLine(agconnectInfo);
                        
                        writer.WriteLine("    }");
                        writer.WriteLine("}");
                        writer.WriteLine("\n");

                        writer.WriteLine(line);

                        alreadySet = true;
                    }
                    else {
                        writer.WriteLine(line);
                    }
                } 
            }
        }

        writer.Flush();
        writer.Close();

        File.Delete(baseBuildGradle);
        File.Move(tmpBuildGradle, baseBuildGradle);
    }

    private void includeHuaweiSettingsGradle(string path) {
        string basePath = path + "/../";
        string baseSettingsGradle = basePath + "settings.gradle";
        string tmpSettingsGradle = basePath + "tmpBuild.gradle";
        int settingsNumHuawei = 0;

        if (!File.Exists(baseSettingsGradle))
        {
            HiveLogger.Log("includeHuaweiSettingsGradle, main's settings.gradle is not exist");
            return;
        }

        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(baseSettingsGradle);
            foreach (string line in lines)
            {
                if(line.Contains("developer.huawei.com/repo")) {
                    HiveLogger.Log("already huawei settings(developer.huawei.com/repo) added : " + ++settingsNumHuawei);
                }
            }
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("includeHuaweiSettingsGradle, Unable to read lines {0} ({1})", baseSettingsGradle, ex.ToString()));
            return;
        }

        // 상위 settings.gradle 파일 읽기에 이상이 없는 경우
        // Huawei 설정 추가 진행
        StreamWriter writer = File.CreateText(tmpSettingsGradle);
        IEnumerator ienum = lines.GetEnumerator();
        bool isPluginManagement = false;

        if(settingsNumHuawei == 1) {
            while(ienum.MoveNext()) {
                string line = (string)ienum.Current;

                if(line.Contains("pluginManagement")) {
                    isPluginManagement = true;
                }

                if(isPluginManagement && line.Contains("repositories")) {
                    writer.WriteLine(line);
                    writer.WriteLine("        // Add Hive(for Huawei)");
                    writer.WriteLine("        maven { url 'https://developer.huawei.com/repo/' }");

                    isPluginManagement = false;
                } else {
                    writer.WriteLine(line);
                }
            }
        }

        writer.Flush();
        writer.Close();

        File.Delete(baseSettingsGradle);
        File.Move(tmpSettingsGradle, baseSettingsGradle);
    }

    private void resolveSettingsGradle(string path)
    {
        HiveLogger.Log("AndroidPostBuildProcessor, resolveSettingsGradle");

        string settingsGradle = path + "/../settings.gradle";
        string tmpSettingsGradle = path + "/../tmpSettings.gradle";

        if (!File.Exists(settingsGradle)) {
            HiveLogger.Log("settings.gradle is not exist");
            return;
        }

        // 1. Xiaomi 사용 시 credentials 정보 추가
        #if UNITY_2021_3_OR_NEWER // PreProc [resolveSettingsGradle - 1] resolveSettingsGradle
        if(IsAtLeast(currentVersion, 2021, 3, 41))
        {
            bool useXiaomi = ExternalDependencyDictionaryManager.isUseDependency(ExternalDependencyDictionaryManager.SupportOSType.Android, ExternalDependencyType.Xiaomi);
            if (useXiaomi)
            {
                IEnumerable<string> lines = null;
                bool alreadyXiaomiAdded = false;
                try
                {
                    lines = File.ReadAllLines(settingsGradle);
                    foreach(string line in lines) {
                        if(line.Contains("username") && line.Contains("\'mi-gamesdk\'"))
                        {
                            alreadyXiaomiAdded = true;
                            break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", settingsGradle, ex.ToString()));
                }

                if(!alreadyXiaomiAdded)
                {
                    StreamWriter writer = File.CreateText(tmpSettingsGradle);   
                    IEnumerator ienum = lines.GetEnumerator();

                    while(ienum.MoveNext())
                    {
                        string line = (string)ienum.Current;

                        if(line.Contains("repos.xiaomi.com")) {
                            HiveLogger.Log("AndroidPostBuildProcessor, process-1, to add xiaomi settings");

                            string tmpLine = line;
                            tmpLine += "\n";
                            tmpLine += "            credentials {\n";
                            tmpLine += "                username \'mi-gamesdk\'\n";
                            tmpLine += "                password \'AKCp8mYeLuhuaGj6bK1XK7t2w4CsPuGwg6GpQdZ9cat7K59y5sD7Tx3dHjJcFrBGj3TQ4vi7g\'\n";  // 노출되어도 무방한 정보
                            tmpLine += "            }\n";

                            line = tmpLine;
                        }
                        writer.WriteLine(line);
                    }

                    writer.Flush();
                    writer.Close();

                    File.Delete(settingsGradle);
                    File.Move(tmpSettingsGradle, settingsGradle);
                }
            }
        }
        #endif // PreProc [resolveSettingsGradle - 1] resolveSettingsGradle(end)
    }

    private void copyToGoogleServicesJson(string path) {

        string launcherPath = path + "/../launcher/google-services.json";
        string jsonFile = Application.dataPath + "/google-services.json";

        if (File.Exists(jsonFile)) {
            File.Copy(jsonFile, launcherPath, true);
        } else {
            HiveLogger.Log("google-services.json is not exist");
            return;
        }
    }

    private void copyToHuaweiServicesJson(string path) {

        string launcherPath = path + "/../launcher/agconnect-services.json";
        string jsonFile = Application.dataPath + "/agconnect-services.json";

        if (File.Exists(jsonFile)) {
            File.Copy(jsonFile, launcherPath, true);
        } else {
            HiveLogger.Log("agconnect-services.json is not exist");
            return;
        }
    }

    private bool checkDuplicateHiveSetting(string fileName, string checkStr) {
        IEnumerable<string> lines = null;
        bool isDuplicate = false;
        try
        {
            lines = File.ReadAllLines(fileName);
            foreach (string line in lines)
            {
                if(line.Contains(checkStr)) {
                    isDuplicate = true;
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            HiveLogger.Log(String.Format("Unable to read lines {0} ({1})", fileName, ex.ToString()));
            isDuplicate = false;
        }

        return isDuplicate;
    }

    private bool needUseLegacyPackaging(string basePath)
    {
        string gradleWrapperPath = Path.Combine(basePath, "gradle/wrapper/gradle-wrapper.properties");
        if(!File.Exists(gradleWrapperPath))
        {
            HiveLogger.Log("[AndroidPostBuildProcessor] needUseLegacyPackaging, gradle-wrapper.properties not exists.");
            return false;
        }

        string[] lines = File.ReadAllLines(gradleWrapperPath);
        string gradleVersion = null;

        foreach (var line in lines)
        {
            if (line.StartsWith("distributionUrl"))
            {
                // 형태 : distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
                var match = Regex.Match(line, @"gradle-(\d+\.\d+(\.\d+)?)-");
                if (match.Success)
                {
                    gradleVersion = match.Groups[1].Value; // "8.11.1" 또는 "8.5" (3자리 또는 2자리)
                }
                break;
            }
        }

        if (string.IsNullOrEmpty(gradleVersion))
        {
            HiveLogger.Log("[AndroidPostBuildProcessor] needUseLegacyPackaging, Gradle parsing failed.");
            return false;
        }
        HiveLogger.Log($"[AndroidPostBuildProcessor] needUseLegacyPackaging, Gradle version: {gradleVersion}");

        // 기준 Gradle 버전 (8.5.1)
        Version threshold = new Version(8, 5, 1);
        Version current;

        try
        {
            current = new Version(gradleVersion);
        }
        catch
        {
            HiveLogger.Log("[AndroidPostBuildProcessor] needUseLegacyPackaging, Gradle get Version object failed.");
            return false;
        }

        if (current < threshold)
        {
            HiveLogger.Log("[AndroidPostBuildProcessor] needUseLegacyPackaging, using under Gradle 8.5.1, need to set");
            return true;
        }
        HiveLogger.Log("[AndroidPostBuildProcessor] needUseLegacyPackaging, using above Gradle 8.5.1, not need to set");
        return false;
    }

    /// <summary>
    /// "2021.3.28f1" → core: 2021.3.28, channel: "f", channelNum: 1
    /// "6000.0.10b3" → core: 6000.0.10, channel: "b", channelNum: 3
    /// "2021.3.0"    → core: 2021.3.0,  channel: null, channelNum: 0
    /// </summary>
    private static bool TryParseUnityVersion(
        string full,
        out Version core,
        out string channel,
        out int channelNum)
    {
        core = new Version(0, 0, 0);
        channel = null;
        channelNum = 0;

        if (string.IsNullOrEmpty(full)) return false;

        // 1) 숫자 코어(major.minor.patch) 추출
        //    2021.3.28f1  →  2021.3.28
        var coreMatch = Regex.Match(full, @"^\s*(\d+)\.(\d+)\.(\d+)");
        if (!coreMatch.Success) return false;

        int maj = int.Parse(coreMatch.Groups[1].Value);
        int min = int.Parse(coreMatch.Groups[2].Value);
        int pat = int.Parse(coreMatch.Groups[3].Value);
        core = new Version(maj, min, pat);

        // 2) 채널/번호 (옵션) 추출: f1/p2/b3/a13 …
        var tailMatch = Regex.Match(full, @"[abfp](\d+)", RegexOptions.IgnoreCase);
        if (tailMatch.Success)
        {
            channel = full[tailMatch.Index].ToString().ToLower(); // 'a','b','f','p'
            _ = int.TryParse(tailMatch.Groups[1].Value, out channelNum);
        }

        return true;
    }

    /// <summary> System.Version 기반 안전 비교 (빌드/수정 번호 없이 3요소 비교) </summary>
    private static bool IsAtLeast(Version v, int maj, int min, int pat)
    {
        var target = new Version(maj, min, pat);
        return v.CompareTo(target) >= 0;
    }

    private static Version GetCurrentUnityCoreVersion(string fullVersionSting)
    {
        if (!TryParseUnityVersion(fullVersionSting, out var core, out var channel, out var channelNum))
        {
            Debug.LogWarning($"[Post] Unity version parse failed: '{fullVersionSting}'");
            return null;
        }
        // ex : 2022.3.38f1
        // core : 2022.3.38, channel : f, channelNum : 1

        return core;
    }
}
#endif // PreProc [1](end)