/*
  KeePass Password Safe - The Open-Source Password Manager
  Copyright (C) 2003-2025 Dominik Reichl <dominik.reichl@t-online.de>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;

using KeePass.Ecas;
using KeePass.Resources;
using KeePass.UI;

using KeePassLib;
using KeePassLib.Cryptography.PasswordGenerator;
using KeePassLib.Utility;

namespace KeePass.App.Configuration
{
	[Flags]
	internal enum AceSections
	{
		None = 0,
		TriggerSystem = 0x1,
		UrlOverride = 0x2,
		UrlSchemeOverrides = 0x4,
		PasswordGenerator = 0x8
		// HelpUrl = 0x10
	}

	public sealed partial class AppConfigEx
	{
		internal static AceSections GetEnabledNonEnforcedSections()
		{
			AppConfigEx cfg = Program.Config;
			AceApplication aceApp = cfg.Application;
			AceIntegration aceInt = cfg.Integration;
			AcePasswordGenerator acePG = cfg.PasswordGenerator;

			AceSections s = AceSections.None;

			EcasTriggerSystem ets = aceApp.TriggerSystem;
			if(ets.Enabled)
			{
				foreach(EcasTrigger t in ets.TriggerCollection)
				{
					if(!t.Enabled) continue;

					if(!IsOptionEnforced(aceApp, "TriggerSystem"))
						s |= AceSections.TriggerSystem;
					break;
				}
			}

			if(!string.IsNullOrEmpty(aceInt.UrlOverride) && aceInt.UrlOverrideEnabled &&
				!IsOptionEnforced(aceInt, "UrlOverride"))
				s |= AceSections.UrlOverride;

			bool bHasUso = false;
			if(aceInt.UrlSchemeOverrides.BuiltInOverridesEnabled != 0UL)
				bHasUso = true;
			else
			{
				foreach(AceUrlSchemeOverride o in aceInt.UrlSchemeOverrides.CustomOverrides)
				{
					if(o.Enabled) { bHasUso = true; break; }
				}
			}
			if(bHasUso && !IsOptionEnforced(aceInt, "UrlSchemeOverrides"))
				s |= AceSections.UrlSchemeOverrides;

			if(acePG.ProfilesEnabled)
			{
				if(!acePG.AutoGeneratedPasswordsProfile.Equals(new PwProfile()) &&
					!IsOptionEnforced(acePG, "AutoGeneratedPasswordsProfile"))
					s |= AceSections.PasswordGenerator;
				else if((acePG.UserProfiles.Count != 0) &&
					!IsOptionEnforced(acePG, "UserProfiles"))
					s |= AceSections.PasswordGenerator;
			}

			// if(!string.IsNullOrEmpty(aceApp.HelpUrl) && !IsOptionEnforced(
			//	aceApp, "HelpUrl"))
			//	s |= AceSections.HelpUrl;

			return s;
		}

		internal static void DisableSections(AceSections s)
		{
			if(s == AceSections.None) return;

			AppConfigEx cfg = Program.Config;
			AceApplication aceApp = cfg.Application;
			AceIntegration aceInt = cfg.Integration;

			string strMsg = KPRes.ItemsDisabled + MessageService.NewParagraph;
			string strNL = MessageService.NewLine;

			if((s & AceSections.TriggerSystem) != AceSections.None)
			{
				aceApp.TriggerSystem.Enabled = false;

				strMsg += "* " + KPRes.Triggers + "." + strNL;
			}

			if((s & AceSections.UrlOverride) != AceSections.None)
			{
				aceInt.UrlOverrideEnabled = false;

				strMsg += "* " + KPRes.UrlOverride + " (" + KPRes.All + ")." + strNL;
			}

			if((s & AceSections.UrlSchemeOverrides) != AceSections.None)
			{
				aceInt.UrlSchemeOverrides.BuiltInOverridesEnabled = 0;
				foreach(AceUrlSchemeOverride o in aceInt.UrlSchemeOverrides.CustomOverrides)
					o.Enabled = false;

				strMsg += "* " + KPRes.UrlOverrides + " (" + KPRes.Scheme + ")." + strNL;
			}

			if((s & AceSections.PasswordGenerator) != AceSections.None)
			{
				cfg.PasswordGenerator.ProfilesEnabled = false;

				strMsg += "* " + KPRes.PwGenProfiles + "." + strNL;
			}

			// if((s & AceSections.HelpUrl) != AceSections.None)
			// {
			//	aceApp.HelpUrl = string.Empty;
			//	strMsg += "* " + KPRes.UrlOverride + " 'HelpUrl'." + strNL;
			// }

			// Save, such that newly started KeePass instances do not
			// show the disablement message box again
			AppConfigSerializer.Save();

			strMsg += strNL + KPRes.ItemsCheckEnable;

			VistaTaskDialog dlg = new VistaTaskDialog();
			dlg.Content = strMsg;
			dlg.DefaultButtonID = (int)DialogResult.Cancel;
			dlg.EnableHyperlinks = true;
			dlg.FooterText = VistaTaskDialog.CreateLink("h", KPRes.MoreInfo);
			dlg.SetFooterIcon(VtdIcon.Information);
			dlg.SetIcon(VtdIcon.Warning);
			dlg.WindowTitle = PwDefs.ShortProductName;
			dlg.AddButton((int)DialogResult.Cancel, KPRes.Ok, null);

			dlg.LinkClicked += delegate(object sender, LinkClickedEventArgs e)
			{
				string str = ((e != null) ? e.LinkText : null);
				if(string.Equals(str, "h", StrUtil.CaseIgnoreCmp))
					AppHelp.ShowHelp(AppDefs.HelpTopics.Configuration,
						AppDefs.HelpTopics.ConfigurationEnableEnf);
				else { Debug.Assert(false); }
			};

			if(!dlg.ShowDialog()) MessageService.ShowWarning(strMsg);
		}

		private static List<AecItem> GetSectionItems(AceSections s, AppConfigEx cfg)
		{
			AceApplication aceApp = cfg.Application;
			AceIntegration aceInt = cfg.Integration;
			AcePasswordGenerator acePG = cfg.PasswordGenerator;

			List<AecItem> l = new List<AecItem>();

			if((s & AceSections.TriggerSystem) != AceSections.None)
				l.Add(new AecItem(aceApp, "TriggerSystem", true));

			if((s & AceSections.UrlOverride) != AceSections.None)
			{
				l.Add(new AecItem(aceInt, "UrlOverride", true));
				l.Add(new AecItem(aceInt, "UrlOverrideEnabled", true));
			}

			if((s & AceSections.UrlSchemeOverrides) != AceSections.None)
				l.Add(new AecItem(aceInt, "UrlSchemeOverrides", true));

			if((s & AceSections.PasswordGenerator) != AceSections.None)
			{
				l.Add(new AecItem(acePG, "ProfilesEnabled", true));
				l.Add(new AecItem(acePG, "AutoGeneratedPasswordsProfile", true));
				l.Add(new AecItem(acePG, "UserProfiles", true));
			}

			// if((s & AceSections.HelpUrl) != AceSections.None)
			//	l.Add(new AecItem(aceApp, "HelpUrl", true));

			return l;
		}

		private static void MoveSectionsToPrimary(AceSections s, AppConfigEx cfgValues)
		{
			AceApplication aceAppF = cfgValues.Application;
			AceApplication aceAppT = Program.Config.Application;
			AceIntegration aceIntF = cfgValues.Integration;
			AceIntegration aceIntT = Program.Config.Integration;
			AcePasswordGenerator acePGF = cfgValues.PasswordGenerator;
			AcePasswordGenerator acePGT = Program.Config.PasswordGenerator;

			if((s & AceSections.TriggerSystem) != AceSections.None)
			{
				aceAppT.TriggerSystem.Enabled = aceAppF.TriggerSystem.Enabled;
				aceAppT.TriggerSystem.TriggerCollection = aceAppF.TriggerSystem.TriggerCollection;
				// Do not change events
			}

			if((s & AceSections.UrlOverride) != AceSections.None)
			{
				aceIntT.UrlOverride = aceIntF.UrlOverride;
				aceIntT.UrlOverrideEnabled = aceIntF.UrlOverrideEnabled;
			}

			if((s & AceSections.UrlSchemeOverrides) != AceSections.None)
				aceIntT.UrlSchemeOverrides = aceIntF.UrlSchemeOverrides;

			if((s & AceSections.PasswordGenerator) != AceSections.None)
			{
				acePGT.ProfilesEnabled = acePGF.ProfilesEnabled;
				acePGT.AutoGeneratedPasswordsProfile = acePGF.AutoGeneratedPasswordsProfile;
				acePGT.UserProfiles = acePGF.UserProfiles;
			}

			// if((s & AceSections.HelpUrl) != AceSections.None)
			//	aceAppT.HelpUrl = aceAppF.HelpUrl;

			ClearXmlPathCache();
		}

		internal static bool EnforceSections(AceSections s, AppConfigEx cfgValues,
			bool bConfirm, bool bAllowElevate, Form fParent, object oSender)
		{
			if(s == AceSections.None) { Debug.Assert(false); return true; }
			if(cfgValues == null) { Debug.Assert(false); return false; }

			Debug.Assert((fParent == null) == (oSender == null));
			Debug.Assert((oSender == null) || (oSender is Button));
			Button btnSender = (oSender as Button); // Do not disable generic Control

			bool bSenderE = false;
			if(btnSender != null)
			{
				bSenderE = btnSender.Enabled;
				Debug.Assert(bSenderE);
				btnSender.Enabled = false; // Avoid problems due to double-click
			}

			try
			{
				if(bConfirm && !AppEnforcedConfig.ConfirmSavingItems(fParent))
					return false;

				List<AecItem> l = GetSectionItems(s, cfgValues);
				if(!AppEnforcedConfig.Modify(l, cfgValues, bAllowElevate))
					return false;

				MoveSectionsToPrimary(s, cfgValues);
			}
			finally
			{
				if(btnSender != null) btnSender.Enabled = bSenderE;
			}

			return true;
		}
	}
}
