/* Copyright (C) Itseez3D, Inc. - All Rights Reserved
* You may not use this file except in compliance with an authorized license
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
* UNLESS REQUIRED BY APPLICABLE LAW OR AGREED BY ITSEEZ3D, INC. IN WRITING, SOFTWARE DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
* See the License for the specific language governing permissions and limitations under the License.
* Written by Itseez3D, Inc. <support@avatarsdk.com>, October 2026
*/

using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

namespace AvatarSDKMove.Editor
{
	[InitializeOnLoad]
	public static class PluginUpdateChecker
	{
		private const string CheckedThisSessionKey = "AvatarSDKMove.UpdateCheckedThisSession";
		private const string SkippedVersionKey = "AvatarSDKMove.SkippedPluginVersion";
		private const string DialogTitle = "Avatar SDK Move update";
		private const int RequestTimeoutSeconds = 15;

		static PluginUpdateChecker()
		{
			if (Application.isBatchMode || SessionState.GetBool(CheckedThisSessionKey, false))
				return;

			SessionState.SetBool(CheckedThisSessionKey, true);
			EditorApplication.delayCall += () => RequestPluginInfo(false);
		}

		[MenuItem("Avatar SDK Move/Check for Updates", priority = 12)]
		public static void CheckForUpdates()
		{
			RequestPluginInfo(true);
		}

		private static void RequestPluginInfo(bool isManualCheck)
		{
			UnityWebRequest request = UnityWebRequest.Get(AvatarSDKMoveSettings.PluginInfoUrl);
			request.timeout = RequestTimeoutSeconds;
			request.SendWebRequest().completed += _ =>
			{
				try
				{
					OnPluginInfoReceived(request, isManualCheck);
				}
				finally
				{
					request.Dispose();
				}
			};
		}

		private static void OnPluginInfoReceived(UnityWebRequest request, bool isManualCheck)
		{
			PluginInfoData info = null;
			if (request.result == UnityWebRequest.Result.Success)
			{
				try
				{
					info = JsonUtility.FromJson<PluginInfoData>(request.downloadHandler.text);
				}
				catch (ArgumentException)
				{
				}
			}

			int[] latestVersion = info == null ? null : ParseVersion(info.version);
			int[] currentVersion = ParseVersion(AvatarSDKMoveSettings.Version);

			if (latestVersion == null || currentVersion == null || !IsDownloadUrl(info.url))
			{
				if (isManualCheck)
					EditorUtility.DisplayDialog(DialogTitle, "Could not get information about the latest version of Avatar SDK Move. Please try again later.", "OK");
				return;
			}

			if (CompareVersions(latestVersion, currentVersion) <= 0)
			{
				if (isManualCheck)
					EditorUtility.DisplayDialog(DialogTitle, string.Format("You have the latest version of Avatar SDK Move: {0}.", AvatarSDKMoveSettings.Version), "OK");
				return;
			}

			if (!isManualCheck && EditorPrefs.GetString(SkippedVersionKey, string.Empty) == info.version)
				return;

			string message = string.Format("A new version of Avatar SDK Move is available: {0}\nYou have {1}.", info.version, AvatarSDKMoveSettings.Version);
			switch (EditorUtility.DisplayDialogComplex(DialogTitle, message, "Download", "Later", "Skip This Version"))
			{
				case 0:
					Application.OpenURL(info.url);
					break;
				case 2:
					EditorPrefs.SetString(SkippedVersionKey, info.version);
					break;
			}
		}

		private static bool IsDownloadUrl(string url)
		{
			return Uri.TryCreate(url, UriKind.Absolute, out Uri uri) && (uri.Scheme == Uri.UriSchemeHttps || uri.Scheme == Uri.UriSchemeHttp);
		}

		private static int[] ParseVersion(string version)
		{
			if (string.IsNullOrWhiteSpace(version))
				return null;

			string[] parts = version.Trim().Split('.');
			int[] numbers = new int[parts.Length];
			for (int i = 0; i < parts.Length; i++)
			{
				if (!int.TryParse(parts[i], out numbers[i]) || numbers[i] < 0)
					return null;
			}
			return numbers;
		}

		private static int CompareVersions(int[] a, int[] b)
		{
			for (int i = 0; i < Math.Max(a.Length, b.Length); i++)
			{
				int result = (i < a.Length ? a[i] : 0).CompareTo(i < b.Length ? b[i] : 0);
				if (result != 0)
					return result;
			}
			return 0;
		}
	}
}
