using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
#if UNITY_2019_2_OR_NEWER
namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
    /// 
    /// Moves our SDK Unity Plugin from under the Assets folder to the Unity Package Manager.
    /// 
    public static class AppLovinPluginMigrationHelper
    {
        private const string ApplovinRegistryName = "AppLovin MAX Unity";
        private const string ApplovinRegistryUrl = "https://unity.packages.applovin.com/";
        private static readonly List AppLovinRegistryScopes = new List() {"com.applovin.mediation.ads", "com.applovin.mediation.adapters", "com.applovin.mediation.dsp"};
        private const string OpenUpmRegistryName = "package.openupm.com";
        private const string OpenUpmRegistryUrl = "https://package.openupm.com";
        private static readonly List OpenUpmRegistryScopes = new List() {"com.google.external-dependency-manager"};
        private static List betaNetworkPluginFilePaths = new List();
        /// 
        /// Attempts to move the Unity plugin to UPM by adding the AppLovin scoped registry and dependencies to the manifest.
        /// 
        /// The Unity Plugin data for our sdk and mediation adapters.
        /// Whether to delete the EDM folder under "Assets"
        internal static void MigrateToUnityPackageManager(PluginData pluginData, bool deleteExternalDependencyManager)
        {
            MaxSdkLogger.UserDebug("Moving AppLovin Unity Plugin to package manager");
            if (deleteExternalDependencyManager)
            {
                DeleteExternalDependencyManager();
            }
            var appLovinManifest = AppLovinUpmManifest.Load();
            MigrateAdapters(pluginData, appLovinManifest);
            MigratePlugin(pluginData, appLovinManifest);
            appLovinManifest.Save();
            AppLovinUpmPackageManager.ResolvePackageManager();
            DeletePluginFiles();
        }
        /// 
        /// Add all currently installed networks to the manifest.
        /// 
        internal static void MigrateAdapters(PluginData pluginData, AppLovinUpmManifest appLovinManifest)
        {
            var allNetworks = pluginData.MediatedNetworks.Concat(pluginData.PartnerMicroSdks).ToArray();
            betaNetworkPluginFilePaths.Clear();
            // Add every currently installed network and separate it by android and iOS.
            foreach (var network in allNetworks)
            {
                var currentVersion = network.CurrentVersions != null ? network.CurrentVersions.Unity : "";
                if (string.IsNullOrEmpty(currentVersion)) continue;
                if (currentVersion.Contains("beta"))
                {
                    betaNetworkPluginFilePaths.AddRange(network.PluginFilePaths);
                    continue;
                }
                AppLovinUpmPackageManager.AddPackages(network, appLovinManifest);
            }
        }
        /// 
        /// Add the AppLovin scoped registry to the manifest if it doesn't exist. Otherwise update it.
        /// 
        private static void MigratePlugin(PluginData pluginData, AppLovinUpmManifest appLovinManifest)
        {
            appLovinManifest.AddOrUpdateRegistry(ApplovinRegistryName, ApplovinRegistryUrl, AppLovinRegistryScopes);
            appLovinManifest.AddOrUpdateRegistry(OpenUpmRegistryName, OpenUpmRegistryUrl, OpenUpmRegistryScopes);
            var appLovinVersion = pluginData.AppLovinMax.LatestVersions.Unity;
            appLovinManifest.AddPackageDependency(AppLovinUpmPackageManager.PackageNamePrefixAppLovin, appLovinVersion);
        }
        #region Utility
        /// 
        /// Delete the external dependency manager folder from the project.
        /// 
        private static void DeleteExternalDependencyManager()
        {
            var externalDependencyManagerPath = Path.Combine(Application.dataPath, "ExternalDependencyManager");
            FileUtil.DeleteFileOrDirectory(externalDependencyManagerPath);
            FileUtil.DeleteFileOrDirectory(externalDependencyManagerPath + ".meta");
        }
        /// 
        /// Deletes all the files in the plugin directory except the AppLovinSettings.asset file.
        /// 
        private static void DeletePluginFiles()
        {
            if (AppLovinIntegrationManager.IsPluginInPackageManager) return;
            var pluginPath = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, "MaxSdk");
            var appLovinSettingsPath = Path.Combine(pluginPath, "Resources/AppLovinSettings.asset");
            var appLovinResourcesDirectory = Path.Combine(pluginPath, "Resources");
            var appLovinSettingsTempPath = Path.Combine(Path.GetTempPath(), "AppLovinSettings.asset");
            var appLovinMediationTempPath = Path.Combine(Path.GetTempPath(), "Mediation");
            // Ensure there aren't any errors when moving the files due to the directories/files already existing.
            FileUtil.DeleteFileOrDirectory(appLovinSettingsTempPath);
            FileUtil.DeleteFileOrDirectory(appLovinMediationTempPath);
            var mediationAssetsDir = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, "MaxSdk/Mediation");
            // Move the AppLovinSettings.asset file and any beta adapters to a temporary directory.
            File.Move(appLovinSettingsPath, appLovinSettingsTempPath);
            var adapterSaved = MoveBetaAdaptersIfNeeded(mediationAssetsDir, appLovinMediationTempPath);
            // Move the meta file if the adapter was saved to save the asset labels
            if (adapterSaved)
            {
                File.Move(mediationAssetsDir, appLovinMediationTempPath + ".meta");
            }
            // Delete the plugin directory and then move the AppLovinSettings.asset and beta adapters back.
            FileUtil.DeleteFileOrDirectory(pluginPath);
            Directory.CreateDirectory(appLovinResourcesDirectory);
            File.Move(appLovinSettingsTempPath, appLovinSettingsPath);
            MoveBetaAdaptersIfNeeded(appLovinMediationTempPath, mediationAssetsDir);
            if (adapterSaved)
            {
                File.Move(appLovinMediationTempPath + ".meta", mediationAssetsDir);
            }
            FileUtil.DeleteFileOrDirectory(appLovinMediationTempPath);
        }
        /// 
        /// Moves the beta adapters from a source mediation directory to a destination mediation directory.
        /// 
        /// The directory containing the beta adapters to be moved.
        /// The target directory where the beta adapters should be moved.
        private static bool MoveBetaAdaptersIfNeeded(string sourceMediationDirectory, string destinationMediationDirectory)
        {
            if (betaNetworkPluginFilePaths.Count == 0 || !Directory.Exists(sourceMediationDirectory)) return false;
            var movedAdapter = false;
            Directory.CreateDirectory(destinationMediationDirectory);
            foreach (var pluginFilePath in betaNetworkPluginFilePaths)
            {
                var sourceDirectory = Path.Combine(sourceMediationDirectory, Path.GetFileName(pluginFilePath));
                var destinationDirectory = Path.Combine(destinationMediationDirectory, Path.GetFileName(pluginFilePath));
                if (Directory.Exists(sourceDirectory))
                {
                    Directory.Move(sourceDirectory, destinationDirectory);
                    movedAdapter = true;
                }
            }
            return movedAdapter;
        }
        #endregion
    }
}
#endif