#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

namespace YooAsset.Editor
{
	internal abstract class BuildPipelineViewerBase
	{
		private const int StyleWidth = 400;

		protected readonly string PackageName;
		protected readonly BuildTarget BuildTarget;
		protected readonly EBuildPipeline BuildPipeline;
		protected TemplateContainer Root;

		private TextField _buildOutputField;
		private TextField _buildVersionField;
		private PopupField<Enum> _buildModeField;
		private PopupField<Type> _encryptionField;
		private EnumField _compressionField;
		private EnumField _outputNameStyleField;
		private EnumField _copyBuildinFileOptionField;
		private TextField _copyBuildinFileTagsField;

		public BuildPipelineViewerBase(string packageName, EBuildPipeline buildPipeline, BuildTarget buildTarget, VisualElement parent)
		{
			PackageName = packageName;
			BuildTarget = buildTarget;
			BuildPipeline = buildPipeline;

			CreateView(parent);
			RefreshView();
		}
		private void CreateView(VisualElement parent)
		{
			// 加载布局文件
			var visualAsset = UxmlLoader.LoadWindowUXML<BuildPipelineViewerBase>();
			if (visualAsset == null)
				return;

			Root = visualAsset.CloneTree();
			Root.style.flexGrow = 1f;
			parent.Add(Root);

			// 输出目录
			string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
			_buildOutputField = Root.Q<TextField>("BuildOutput");
			_buildOutputField.SetValueWithoutNotify(defaultOutputRoot);
			_buildOutputField.SetEnabled(false);

			// 构建版本
			_buildVersionField = Root.Q<TextField>("BuildVersion");
			_buildVersionField.style.width = StyleWidth;
			_buildVersionField.SetValueWithoutNotify(GetDefaultPackageVersion());

			// 构建模式
			{
				var buildModeContainer = Root.Q("BuildModeContainer");
				var buildMode = AssetBundleBuilderSetting.GetPackageBuildMode(PackageName, BuildPipeline);
				var buildModeList = GetSupportBuildModes();
				int defaultIndex = buildModeList.FindIndex(x => x.Equals(buildMode));
				_buildModeField = new PopupField<Enum>(buildModeList, defaultIndex);
				_buildModeField.label = "ABB_BuildMode";
				_buildModeField.style.width = StyleWidth;
				_buildModeField.RegisterValueChangedCallback(evt =>
				{
					AssetBundleBuilderSetting.SetPackageBuildMode(PackageName, BuildPipeline, (EBuildMode)_buildModeField.value);
				});
				buildModeContainer.Add(_buildModeField);
			}

			// 加密方法
			{
				var encryptionContainer = Root.Q("EncryptionContainer");
				var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
				if (encryptionClassTypes.Count > 0)
				{
					var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionClassName(PackageName, BuildPipeline);
					int defaultIndex = encryptionClassTypes.FindIndex(x => x.FullName.Equals(encyptionClassName));
					_encryptionField = new PopupField<Type>(encryptionClassTypes, defaultIndex);
					_encryptionField.label = "ABB_Encryption";
					_encryptionField.style.width = StyleWidth;
					_encryptionField.RegisterValueChangedCallback(evt =>
					{
						AssetBundleBuilderSetting.SetPackageEncyptionClassName(PackageName, BuildPipeline, _encryptionField.value.FullName);
					});
					encryptionContainer.Add(_encryptionField);
				}
				else
				{
					_encryptionField = new PopupField<Type>();
					_encryptionField.label = "ABB_Encryption";
					_encryptionField.style.width = StyleWidth;
					encryptionContainer.Add(_encryptionField);
				}
			}

			// 压缩方式选项
			var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
			_compressionField = Root.Q<EnumField>("Compression");
			_compressionField.Init(compressOption);
			_compressionField.SetValueWithoutNotify(compressOption);
			_compressionField.style.width = StyleWidth;
			_compressionField.RegisterValueChangedCallback(evt =>
			{
				AssetBundleBuilderSetting.SetPackageCompressOption(PackageName, BuildPipeline, (ECompressOption)_compressionField.value);
			});

			// 输出文件名称样式
			var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
			_outputNameStyleField = Root.Q<EnumField>("FileNameStyle");
			_outputNameStyleField.Init(fileNameStyle);
			_outputNameStyleField.SetValueWithoutNotify(fileNameStyle);
			_outputNameStyleField.style.width = StyleWidth;
			_outputNameStyleField.RegisterValueChangedCallback(evt =>
			{
				AssetBundleBuilderSetting.SetPackageFileNameStyle(PackageName, BuildPipeline, (EFileNameStyle)_outputNameStyleField.value);
			});

			// 首包文件拷贝选项
			var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
			_copyBuildinFileOptionField = Root.Q<EnumField>("CopyBuildinFileOption");
			_copyBuildinFileOptionField.Init(buildinFileCopyOption);
			_copyBuildinFileOptionField.SetValueWithoutNotify(buildinFileCopyOption);
			_copyBuildinFileOptionField.style.width = StyleWidth;
			_copyBuildinFileOptionField.RegisterValueChangedCallback(evt =>
			{
				AssetBundleBuilderSetting.SetPackageBuildinFileCopyOption(PackageName, BuildPipeline, (EBuildinFileCopyOption)_copyBuildinFileOptionField.value);
				RefreshView();
			});

			// 首包文件拷贝参数
			var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
			_copyBuildinFileTagsField = Root.Q<TextField>("CopyBuildinFileParam");
			_copyBuildinFileTagsField.SetValueWithoutNotify(buildinFileCopyParams);
			_copyBuildinFileTagsField.RegisterValueChangedCallback(evt =>
			{
				AssetBundleBuilderSetting.SetPackageBuildinFileCopyParams(PackageName, BuildPipeline, _copyBuildinFileTagsField.value);
			});

			// 构建按钮
			var buildButton = Root.Q<Button>("Build");
			buildButton.clicked += BuildButton_clicked;

			// 本地化设置
			UIElementsLocalize.Localize(_buildOutputField);
			UIElementsLocalize.Localize(_buildVersionField);
			UIElementsLocalize.Localize(_buildModeField);
			UIElementsLocalize.Localize(_encryptionField);
			UIElementsLocalize.Localize(_compressionField);
			UIElementsLocalize.Localize(_outputNameStyleField);
			UIElementsLocalize.Localize(_copyBuildinFileOptionField);
			UIElementsLocalize.Localize(_copyBuildinFileTagsField);
			UIElementsLocalize.Localize(buildButton);
		}
		private void RefreshView()
		{
			var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
			bool tagsFiledVisible = buildinFileCopyOption == EBuildinFileCopyOption.ClearAndCopyByTags || buildinFileCopyOption == EBuildinFileCopyOption.OnlyCopyByTags;
			_copyBuildinFileTagsField.visible = tagsFiledVisible;
		}
		private void BuildButton_clicked()
		{
			var buildMode = AssetBundleBuilderSetting.GetPackageBuildMode(PackageName, BuildPipeline);
			if (EditorUtility.DisplayDialog("提示", $"通过构建模式【{buildMode}】来构建!", "Yes", "No"))
			{
				EditorTools.ClearUnityConsole();
				EditorApplication.delayCall += ExecuteBuild;
			}
			else
			{
				Debug.LogWarning("[Build] 打包已经取消");
			}
		}

		/// <summary>
		/// 执行构建任务
		/// </summary>
		protected abstract void ExecuteBuild();

		/// <summary>
		/// 获取构建管线支持的构建模式集合
		/// </summary>
		protected abstract List<Enum> GetSupportBuildModes();

		/// <summary>
		/// 获取构建版本
		/// </summary>
		protected string GetPackageVersion()
		{
			return _buildVersionField.value;
		}

		/// <summary>
		/// 创建加密类实例
		/// </summary>
		protected IEncryptionServices CreateEncryptionInstance()
		{
			var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionClassName(PackageName, BuildPipeline);
			var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
			var classType = encryptionClassTypes.Find(x => x.FullName.Equals(encyptionClassName));
			if (classType != null)
				return (IEncryptionServices)Activator.CreateInstance(classType);
			else
				return null;
		}

		private string GetDefaultPackageVersion()
		{
			int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
			return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
		}
	}
}
#endif