using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Build.AnalyzeRules;
using UnityEditor.AddressableAssets.Settings;

namespace Blindflug.MemoryManagement.Editor
{
	public sealed class CheckAddressNameTooLong : AnalyzeRule
	{
		public override bool CanFix => true;
		public override string ruleName => "Check Address Name Too Long";

		private List<AnalyzeResult> _analyzeResults;
		private List<string> _resultsGUIDs;
		private HashSet<string> _duplicates;

		public override List<AnalyzeResult> RefreshAnalysis(AddressableAssetSettings settings)
		{
			ClearAnalysis();
			_analyzeResults = new List<AnalyzeResult>();
			_resultsGUIDs = new List<string>();

			for (var i = 0; i < settings.groups.Count; i++)
			{
				AddressableAssetGroup group = settings.groups[i];
				foreach (AddressableAssetEntry entry in group.entries)
				{
					if (entry.address.Length > 32)
					{
						_analyzeResults.Add(
							new AnalyzeResult
							{
								resultName = $"{group.Name}{kDelimiter}{entry.address}",
								severity = MessageType.Warning
							});
						_resultsGUIDs.Add(entry.guid);
					}
				}
			}

			if (_analyzeResults.Count <= 0)
			{
				_analyzeResults.Add(new AnalyzeResult
				{
					resultName = "No issues found",
					severity = MessageType.Info
				});
			}
			return _analyzeResults;
		}

		public override void FixIssues(AddressableAssetSettings settings)
		{
			if (_resultsGUIDs == null)
			{
				RefreshAnalysis(settings);
			}

			if (_resultsGUIDs.Count <= 0)
			{
				return;
			}

			_duplicates = new HashSet<string>();
			for (var i = 0; i < _resultsGUIDs.Count; i++)
			{
				AddressableAssetEntry entry = settings.FindAssetEntry(_resultsGUIDs[i]);
				entry.address = entry.address.Substring(entry.address.Length - 32, 30);
				var index = 0;
				string address = entry.address;
				while (_duplicates.Add(address) == false)
				{
					address = entry.address + index.ToString("D2");
					index++;
				}

				entry.address = address;
			}
		}

		[InitializeOnLoad]
		class RegisterCheckAddressNameTooLong
		{
			static RegisterCheckAddressNameTooLong()
			{
				AnalyzeSystem.RegisterNewRule<CheckAddressNameTooLong>();
			}
		}
	}
}