

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


#if UNITY_2021_3_OR_NEWER || UNITY_2022_3_OR_NEWER
public class AndroidAdKitPostBuildProcessor : IPostGenerateGradleAndroidProject
{
    const string ANDROID_DARO_PLUGIN_VERSION = "1.0.11";
    const string DARO_APP_KEY_FILE = "android-daro-key.txt";
    const string TAG = "AndroidAdKitPostBuildProcessor::";

    public int callbackOrder
    {
        get
        {
            return 5000; // Hive SDK 샘플 빌더와 순서 겹치지 않게
        }
    }

    void IPostGenerateGradleAndroidProject.OnPostGenerateGradleAndroidProject(string path)
    {
#if UNITY_ANDROID        
        UnityEngine.Debug.Log(TAG + "AndroidAdKitPostBuildProcessor");
        resolveBaseBuildGradle(path);
        resolveLauncherBuildGradle(path);

        copyDaroAppKey(path);
#endif        
    }

    private void resolveLauncherBuildGradle(string path)
    {
        string launcherPath = path + "/../launcher/";
        string launcherBuildGradle = launcherPath + "build.gradle";
        string tmpBuildGradle = launcherPath + "tmpBuild.gradle";

        // 1. 파일 존재 여부 체크
        if (!File.Exists(launcherBuildGradle))
        {
            UnityEngine.Debug.Log("launcher's build.gradle is not exist");
            return;
        }

        // 2. 파일 읽기
        IEnumerable<string> lines = null;
        try
        {
            lines = File.ReadAllLines(launcherBuildGradle);
        }
        catch (Exception ex)
        {
            UnityEngine.Debug.Log(String.Format("Unable to read lines {0} ({1})", launcherBuildGradle, ex.ToString()));
            return; // 파일 읽기 실패 시 중단
        }

        // 3. 임시 파일에 쓰기
        using (StreamWriter writer = File.CreateText(tmpBuildGradle))
        {
            bool applicationPluginFound = false;
            const string applicationPluginLine = "apply plugin: 'com.android.application'";
            const string pluginToAdd = "apply plugin: 'so.daro.a'";

            // 4. 라인별로 처리 및 플러그인 삽입 위치 확인
            foreach (var line in lines)
            {
                writer.WriteLine(line);

                // 'com.android.application' 라인을 찾았고,
                // 'so.daro.a' 플러그인이 아직 추가되지 않았다면
                if (!applicationPluginFound && line.Contains(applicationPluginLine))
                {
                    applicationPluginFound = true; // 플러그인 라인을 찾았음을 표시

                    // 중복 체크 함수를 사용하여 플러그인이 이미 있는지 확인
                    // (주의: checkDuplicateHiveSetting 구현은 제공되지 않았으므로 가정하고 사용합니다.)
                    if (!checkDuplicateHiveSetting(launcherBuildGradle, pluginToAdd))
                    {
                        // 해당 라인 바로 다음에 새 플러그인 추가
                        writer.WriteLine(pluginToAdd);
                    }
                }
            }
        } // using 블록을 사용하여 writer를 자동으로 닫고 자원을 해제합니다.

        // 5. 파일 교체
        File.Delete(launcherBuildGradle);
        File.Move(tmpBuildGradle, launcherBuildGradle);
        
        UnityEngine.Debug.Log($"Successfully resolved {launcherBuildGradle}.");
    }

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

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

        var lines = File.ReadAllLines(baseBuildGradle);
        var outputLines = new List<string>();

        bool hasBuildscriptBlock = false;
        bool hasDaroClasspath = false;
        bool insideBuildscript = false;
        bool insideDependencies = false;

        for (int i = 0; i < lines.Length; i++)
        {
            string line = lines[i].Trim();

            // Detect buildscript block start
            if (line.StartsWith("buildscript"))
            {
                hasBuildscriptBlock = true;
                insideBuildscript = true;
            }

            if (insideBuildscript && line.StartsWith("dependencies"))
            {
                insideDependencies = true;
            }

            // Check if classpath exists
            if (insideDependencies && line.Contains("classpath 'so.daro:daro-plugin:" + ANDROID_DARO_PLUGIN_VERSION + "'"))
            {
                hasDaroClasspath = true;
            }

            // Detect end of buildscript block
            if (insideBuildscript && line.Contains("}"))
            {
                if (insideDependencies)
                {
                    insideDependencies = false;
                }
                else
                {
                    insideBuildscript = false;
                }
            }

            outputLines.Add(lines[i]);
        }

        // 수정이 필요한 경우만 처리
        if (!hasBuildscriptBlock)
        {
            // buildscript 블록 전체를 plugins 블록 위에 추가
            var modifiedLines = new List<string>();

            bool buildscriptInserted = false;

            for (int i = 0; i < outputLines.Count; i++)
            {
                string line = outputLines[i];

                if (!buildscriptInserted && line.TrimStart().StartsWith("plugins"))
                {
                    modifiedLines.Add("// Add WeMake");
                    modifiedLines.Add("buildscript {");
                    modifiedLines.Add("    repositories {");
                    modifiedLines.Add("        google()");
                    modifiedLines.Add("        mavenCentral()");
                    modifiedLines.Add("    }");
                    modifiedLines.Add("    dependencies {");
                    modifiedLines.Add("        classpath 'so.daro:daro-plugin:" + ANDROID_DARO_PLUGIN_VERSION + "'");
                    modifiedLines.Add("    }");
                    modifiedLines.Add("}");
                    modifiedLines.Add(""); // 빈 줄
                    buildscriptInserted = true;
                }

                modifiedLines.Add(line);
            }

            outputLines = modifiedLines;
        }
        else if (!hasDaroClasspath)
        {
            // buildscript 블록은 있지만 classpath가 없다면, dependencies 안에 추가
            var modifiedLines = new List<string>();
            bool inserted = false;

            for (int i = 0; i < outputLines.Count; i++)
            {
                string line = outputLines[i];

                modifiedLines.Add(line);

                if (!inserted && line.Trim().StartsWith("dependencies") && outputLines[i + 1].Trim().StartsWith("{"))
                {
                    // 다음 줄에서 삽입
                    modifiedLines.Add("        // Add WeMake");
                    modifiedLines.Add("        classpath 'so.daro:daro-plugin:" + ANDROID_DARO_PLUGIN_VERSION + "'");
                    inserted = true;
                }
            }

            outputLines = modifiedLines;
        }
        else
        {
            // 둘 다 있으면 아무것도 안 함 (패스)
            UnityEngine.Debug.Log("Gradle file already contains buildscript and daro-plugin classpath. Skipping modification.");
            return;
        }

        // 파일 저장
        File.WriteAllLines(tmpBuildGradle, outputLines);
        File.Delete(baseBuildGradle);
        File.Move(tmpBuildGradle, baseBuildGradle);
    }

    private void copyDaroAppKey(string path) {

        string launcherPath = path + "/../launcher/" + DARO_APP_KEY_FILE;
        string txtFile = Application.dataPath + "/HIVEAdKit/Plugins/Android/" + DARO_APP_KEY_FILE;

        if (File.Exists(txtFile))
        {
            File.Copy(txtFile, launcherPath, true);
        }
        else
        {
            Debug.Log(TAG + DARO_APP_KEY_FILE + " 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)
        {
            Debug.Log(String.Format("Unable to read lines {0} ({1})", fileName, ex.ToString()));
            isDuplicate = false;
        }

        return isDuplicate;
    }
}
#endif