/**
 * @file    ExternalDependencyLoader.cs
 * 
 * @author  jschoi
 * @date    2024~
 * @copyright Copyright © Com2uS Platform Corporation. All Right Reserved.
 * @defgroup Hive.Unity.Editor
 * @{
 * @brief HIVE External Dependency 로컬 경로 동기화 <br/><br/>
 */

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.ComponentModel;
using System.Reflection;
using System.Xml;
using System.Linq;

namespace Hive.Unity.Editor
{    
    using ExternalDependencyDictionary = Dictionary<ExternalDependencyType, bool>;
    using ExternalDependencySerializableDictionary = SerializableDictionary<string, bool>;

    [InitializeOnLoad]
    public class ExternalDependencyLoader
    {
        static ExternalDependencyLoader()
        {
            // Hive Sample 빌드 프로젝트가 아닌 경우만 동기화
            if(!ExternalDependencyUtil.isSampleBuild())
            {
                // HiveSDK 버전 업데이트로 더이상 사용하지 않는 '디펜던시 xml'이나 '기타 설정 파일' 제거
                removeDeprecatedFiles();              

                // HiveSDK 업데이트 한 경우
                // - HiveSDKSettingsDependencies.xml에 설정된 HiveSDK 버전 업데이트
                // - HiveSDKSettingsDependencies.xml가 없는 경우 TempHiveSDK{Platform}SettingsDependencies.xml(디폴트 파일)의 HiveSDK 버전 업데이트
                updateHiveDependenciesXmlVersion();
            }
        }

        private enum ExternalDependencySupportPlatform
        {
            Android,
            iOS,
        }

        // 파일 삭제 (HiveSDK 업데이트 과정에서 더이상 사용하지 않는 파일 포함)
        private static void removeDeprecatedFiles()
        {
            HiveLogger.Log(String.Format("[ExternalDependencyLoader] removeDeprecatedFiles"));

            // (1) ExternalDependencyType에서 제거된 미사용 **Dependencies.xml 제거 (+ 구버전 셋팅 저장 세이브 파일(HiveEditorSettings.txt) 제거)
            string[] removeFileList = {"../ProjectSettings/HiveEditorSettings.txt",     // 23.0.0 업데이트 시 Hive Dependenices 저장 유도 팝업 노출 시간 저장된 파일 제거, (해당 팝업을 23.4.0 부터 사용하지 않음)
                                        "Hive_SDK_v4/Dependencies/HIVESDK_MarketFacebookCloudDependencies.xml",     // 24.2.0, Facebook Cloud 관련 디펜던시 파일 제거 
                                        "Hive_SDK_v4/Dependencies/HIVESDK_ProviderFacebookCloudDependencies.xml",
                                        "Hive_SDK_v4/Dependencies/HIVESDK_PushFacebookCloudA2uDependencies.xml",
                                        "Hive_SDK_v4/Dependencies/HIVESDK_DefaultDependencies.xml",
                                        "Hive_SDK_v4/Dependencies/HIVESDKDependencies.xml",
                                        "Hive_SDK_v4/Editor/HIVESDK_MarketFacebookCloudDependencies.xml",
                                        "Hive_SDK_v4/Editor/HIVESDK_PushFacebookCloudA2uDependencies.xml",
                                        "Hive_SDK_v4/Editor/HIVESDK_ProviderFacebookCloudDependencies.xml",
                                        "Hive_SDK_v4/Editor/HIVESDK_DefaultDependencies.xml",
                                        "Hive_SDK_v4/Editor/HIVESDKDependencies.xml",
                                        "Hive_SDK_v4/Editor/TempHiveSDKSettingsDependencies.xml",
                                        "Hive_SDK_v4/Editor/JenkinsAndroidSnapshotDependencies.xml" };

            foreach (string removeFile in removeFileList)
            {
                string path = Path.Combine(Application.dataPath, removeFile);

                if (File.Exists(path))
                {
                    try
                    {
                        File.Delete(path);
                        HiveLogger.Log(String.Format("[ExternalDependencyLoader] removeDeprecatedFiles, path : " + path));
                    }
                    catch (Exception e)
                    {
                        HiveLogger.Log(String.Format("[ExternalDependencyLoader] removeDeprecatedFiles, File.Delete({0}) Exception. \n {1}", path, e.ToString()));
                    }
                }
            }

            // (2) HiveSDKSettingsDependencies.xml 사용으로 미사용하게된 **Dependencies.xml 제거 (ExternalDependenciesType에 정의된)
            DirectoryInfo editorDirInfo = new DirectoryInfo(ExternalDependencyConst.editorPath);
            DirectoryInfo dependenciesDirInfo = new DirectoryInfo(ExternalDependencyConst.dependenciesPath);

            foreach (ExternalDependencyType t in Enum.GetValues(typeof(ExternalDependencyType)))
            {
                if (Directory.Exists(ExternalDependencyConst.editorPath))
                {
                    foreach (FileInfo f in editorDirInfo.GetFiles())
                    {
                        if (f.Name.Contains(ExternalDependencyUtil.getEnumDescription(t) + "Dependencies.xml"))
                        {
                            HiveLogger.Log(String.Format("[ExternalDependencyLoader] removeFile (/Editor path), remove : ~" + ExternalDependencyUtil.getEnumDescription(t) + "Dependencies.xml"));
                            f.Delete(); // .xml 및 .meta 제거
                        }
                    }
                }
                if (Directory.Exists(ExternalDependencyConst.dependenciesPath))
                {
                    foreach (FileInfo f in dependenciesDirInfo.GetFiles())
                    {
                        if (f.Name.Contains(ExternalDependencyUtil.getEnumDescription(t) + "Dependencies.xml"))
                        {
                            HiveLogger.Log(String.Format("[ExternalDependencyLoader] removeFile (/Dependencies path), remove : ~" + ExternalDependencyUtil.getEnumDescription(t) + "Dependencies.xml"));
                            f.Delete(); // .xml 및 .meta 제거
                        }
                    }
                }
            }
        }

        // HiveSDK Unity 패키지 업데이트 시 디펜던시 파일 내 적용된 HiveSDK 버전 업데이트 (HiveSDK v4 25.2.0)
        private static void updateHiveDependenciesXmlVersion() {

            // 개발자가 직접 저장한 디펜던시 파일 존재 여부에 따라 관리할 디펜던시 파일을 확인
            if (File.Exists(ExternalDependencyConst.hiveDependenciesXmlPath))
            {
                // 개발자가 디펜던시를 저장해서 사용하고 있으며 && Hive Unity 패키지를 업데이트한 상황

                // Save 상태를 불러와 현재 HiveSDK 버전으로 업데이트
                ExternalDependencyDictionary androidDependency = ExternalDependencyDictionaryManager.LoadExternalDependencyDictionary(ExternalDependencyDictionaryManager.SupportOSType.Android);
                ExternalDependencyDictionary iosDependency = ExternalDependencyDictionaryManager.LoadExternalDependencyDictionary(ExternalDependencyDictionaryManager.SupportOSType.iOS);
                Dictionary<ExternalDependencyDictionaryManager.SupportOSType, Dictionary<ExternalDependencyType, bool>> osDependency = new Dictionary<ExternalDependencyDictionaryManager.SupportOSType, Dictionary<ExternalDependencyType, bool>>();
                osDependency[ExternalDependencyDictionaryManager.SupportOSType.Android] = androidDependency;
                osDependency[ExternalDependencyDictionaryManager.SupportOSType.iOS] = iosDependency;
                ExternalDependencyDictionaryManager.createHiveSDKSettingsDependenciesXmlFile(osDependency);

                // 디폴트 디펜던시 제거
                //  - (Assets/Hive_SDK_v4/Editor/TempHiveSDKAndroidSettingsDependencies.xml)
                //  - (Assets/Hive_SDK_v4/Editor/TempHiveSDKiOSSettingsDependencies.xml)
                // 해당 파일을 제거하면서 업데이트를 1회성으로 진행 (잦은 반복처리 하지 않도록)
                if (File.Exists(ExternalDependencyConst.hiveAndroidDependenciesTempXmlPath))
                    File.Delete(ExternalDependencyConst.hiveAndroidDependenciesTempXmlPath);
                if (File.Exists(ExternalDependencyConst.hiveiOSDependenciesTempXmlPath))
                    File.Delete(ExternalDependencyConst.hiveiOSDependenciesTempXmlPath);
            }
            else
            {
                // 버전 업데이트
                //   - (Assets/Hive_SDK_v4/Editor/TempHiveSDKAndroidSettingsDependencies.xml)
                //   - (Assets/Hive_SDK_v4/Editor/TempHiveSDKiOSSettingsDependencies.xml)
                makeTempAndroidDependencyXml();
                makeTempiOSDependencyXml();
            }
        }

        private static void makeTempAndroidDependencyXml()
        {
            if(File.Exists(ExternalDependencyConst.hiveDependenciesXmlPath))
            {
                // 개발자가 직접 저장한 디펜던시 파일이 존재하는 경우는 생성하지 않음
                return;
            }
            if(File.Exists(ExternalDependencyConst.hiveAndroidVersionJsonPath) == false)
            {
                // Android 버전 정보 파일이 없는 경우 생성하지 않음
                return;
            }

            // Hive SDK 버전
            string hiveVersion = ExternalDependencyConst.getAndroidDependencyVersion();
            string dependencyFilePath = ExternalDependencyConst.hiveAndroidDependenciesTempXmlPath;

            // 기존 파일 체크
            if (File.Exists(dependencyFilePath))
            {
                using (StreamReader sr = new StreamReader(dependencyFilePath))
                {
                    string firstLine = sr.ReadLine()?.Trim();
                    if (!string.IsNullOrEmpty(firstLine) && firstLine == $"<!--{hiveVersion}-->")
                    {
                        // 버전 동일하면 재생성하지 않고 종료
                        Debug.Log("XML 파일 버전 동일, 재생성하지 않음: " + dependencyFilePath);
                        return;
                    }
                }

                // 버전이 다르면 기존 파일 삭제
                File.Delete(dependencyFilePath);
            }           

            // Android 패키지 목록
            string[] androidPackages = new string[]
            {
                "com.com2us.android.hive:hive-authv4-provider-google-signin",
                "com.com2us.android.hive:hive-authv4-provider-google-playgames",
                "com.com2us.android.hive:hive-authv4-provider-facebook",
                "com.com2us.android.hive:hive-authv4-provider-apple-signin",
                "com.com2us.android.hive:hive-authv4-provider-line",
                "com.com2us.android.hive:hive-authv4-provider-hive-membership",
                "com.com2us.android.hive:hive-promotion",
                "com.com2us.android.hive:hive-promotion-google-inappreview",
                "com.com2us.android.hive:hive-authv4-device-management",
                "com.com2us.android.hive:hive-authv4-adult-confirm",
                "com.com2us.android.hive:hive-authv4-google-recaptcha",
                "com.com2us.android.hive:hive-hercules",
                "com.com2us.android.hive:hive-authv4-google-inappupdate",
                "com.com2us.android.hive:hive-datastore",
                "com.com2us.android.hive:hive-analytics-consent-mode",
                "com.com2us.android.hive:hive-push-google-fcm",
                "com.com2us.android.hive:hive-iapv4-market-google",
                "com.com2us.android.hive:hive-iapv4-market-hivestore",
                "com.com2us.android.hive:youtube-helper:1.0.1",
                "com.android.installreferrer:installreferrer:2.2",
                "com.com2us.android.hive:hive-sdk",
                "com.com2us.android.hive:hive-plugin-java"
            };

            // XML 생성
            XmlDocument doc = new XmlDocument();

            // 최상단 버전 주석
            doc.AppendChild(doc.CreateComment(hiveVersion));

            // 기존 주석 추가
            doc.AppendChild(doc.CreateComment("HiveSDK Unity Package Default Example TempHiveSDKAndroidSettingsDependencies.xml"));
            doc.AppendChild(doc.CreateComment("Please save Hive Dependencies options"));

            // <dependencies>
            XmlElement dependenciesElem = doc.CreateElement("dependencies");
            doc.AppendChild(dependenciesElem);

            // <androidPackages>
            XmlElement androidPackagesElem = doc.CreateElement("androidPackages");
            dependenciesElem.AppendChild(androidPackagesElem);

            // <repositories>
            XmlElement repositoriesElem = doc.CreateElement("repositories");
            androidPackagesElem.AppendChild(repositoriesElem);

            XmlElement repo1 = doc.CreateElement("repository");
            repo1.InnerText = "https://repo.maven.apache.org/maven2";
            repositoriesElem.AppendChild(repo1);

            XmlElement repo2 = doc.CreateElement("repository");
            repo2.InnerText = "https://jcenter.bintray.com";
            repositoriesElem.AppendChild(repo2);

            // <androidPackage> 항목 추가
            foreach (var packageSpec in androidPackages)
            {
                XmlElement packageElem = doc.CreateElement("androidPackage");

                // 고정 버전 패키지
                if (packageSpec.EndsWith("youtube-helper:1.0.1") || packageSpec.EndsWith("installreferrer:2.2"))
                {
                    packageElem.SetAttribute("spec", packageSpec);
                }
                else
                {
                    packageElem.SetAttribute("spec", $"{packageSpec}:{hiveVersion}");
                }

                androidPackagesElem.AppendChild(packageElem);
            }

            // XML 저장
            doc.Save(dependencyFilePath);
        }

        private static void makeTempiOSDependencyXml()
        {
            if(File.Exists(ExternalDependencyConst.hiveDependenciesXmlPath))
            {
                // 개발자가 직접 저장한 디펜던시 파일이 존재하는 경우는 생성하지 않음
                return;
            }
            if(File.Exists(ExternalDependencyConst.hiveiOSVersionJsonPath) == false)
            {
                // iOS 버전 정보 파일이 없는 경우 생성하지 않음
                return;
            }

            string dependencyFilePath = ExternalDependencyConst.hiveiOSDependenciesTempXmlPath;

            // Hive SDK iOS 버전
            string hiveVersion = ExternalDependencyConst.getiOSDependencyVersion();

            // 기존 파일 체크
            if (File.Exists(dependencyFilePath))
            {
                using (StreamReader sr = new StreamReader(dependencyFilePath))
                {
                    string firstLine = sr.ReadLine()?.Trim();
                    if (!string.IsNullOrEmpty(firstLine) && firstLine == $"<!--{hiveVersion}-->")
                    {
                        Debug.Log("iOS XML 파일 버전 동일, 재생성하지 않음: " + dependencyFilePath);
                        return;
                    }
                }

                // 버전이 다르면 기존 파일 삭제
                File.Delete(dependencyFilePath);
                Debug.Log("기존 iOS XML 파일 삭제: " + dependencyFilePath);
            }

            // iOS Pod 목록
            string[] iosPods = new string[]
            {
                "HiveAuthV4ProviderGoogle",
                "HiveAuthV4ProviderFacebook",
                "HiveAuthV4ProviderAppleGameCenter",
                "HiveAuthV4ProviderAppleSignIn",
                "HiveAuthV4ProviderLine",
                "HiveAuthV4ProviderHive",
                "HivePromotion",
                "HiveDeviceManagement",
                "HiveAdultConfirm",
                "HiveGoogleRecaptcha",
                "HerculesSwift",
                "HiveDataStore",
                "HiveAnalyticsConsentMode",
                "HiveIAPV4",
                "HiveExtensions",
                "HiveSDKUnityPlugin"
            };

            // XML 생성
            XmlDocument doc = new XmlDocument();

            // 최상단 버전 주석
            doc.AppendChild(doc.CreateComment(hiveVersion));

            // 기존 주석 추가
            doc.AppendChild(doc.CreateComment("HiveSDK Unity Package Default Example TempHiveSDKiOSSettingsDependencies.xml"));
            doc.AppendChild(doc.CreateComment("Please save Hive Dependencies options"));

            // <dependencies> 루트
            XmlElement dependenciesElem = doc.CreateElement("dependencies");
            doc.AppendChild(dependenciesElem);

            // <iosPods>
            XmlElement iosPodsElem = doc.CreateElement("iosPods");
            dependenciesElem.AppendChild(iosPodsElem);

            // <sources>
            XmlElement sourcesElem = doc.CreateElement("sources");
            iosPodsElem.AppendChild(sourcesElem);

            XmlElement source1 = doc.CreateElement("source");
            source1.InnerText = "https://github.com/Com2uSPlatformCorp/Hercules-iOS.git";
            sourcesElem.AppendChild(source1);

            XmlElement source2 = doc.CreateElement("source");
            source2.InnerText = "https://github.com/Com2uSPlatformCorp/HiveSDK-iOS.git";
            sourcesElem.AppendChild(source2);

            // <iosPod> 항목 추가
            foreach (var podName in iosPods)
            {
                XmlElement podElem = doc.CreateElement("iosPod");
                podElem.SetAttribute("name", podName);
                podElem.SetAttribute("version", hiveVersion);
                iosPodsElem.AppendChild(podElem);
            }

            // XML 저장
            doc.Save(dependencyFilePath);
        }
    }
}
