using System.Collections.Generic;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Webserver.Permissions;

namespace Webserver.Commands {
	[UsedImplicitly]
	public class WebTokens : ConsoleCmdAbstract {
		private static readonly Regex validNameTokenMatcher = new Regex (@"^\w+$");

		public override string[] getCommands () {
			return new[] {"webtokens"};
		}

		public override string getDescription () {
			return "Manage web tokens";
		}

		public override string getHelp () {
			return "Set/get webtoken permission levels. A level of 0 is maximum permission.\n" +
			       "Usage:\n" +
			       "   webtokens add <tokenname> <tokensecret> <level>\n" +
			       "   webtokens remove <tokenname>\n" +
			       "   webtokens list";
		}

		public override void Execute (List<string> _params, CommandSenderInfo _senderInfo) {
			if (_params.Count >= 1) {
				if (_params [0].EqualsCaseInsensitive ("add")) {
					ExecuteAdd (_params);
				} else if (_params [0].EqualsCaseInsensitive ("remove")) {
					ExecuteRemove (_params);
				} else if (_params [0].EqualsCaseInsensitive ("list")) {
					ExecuteList ();
				} else {
					SdtdConsole.Instance.Output ($"Invalid sub command \"{_params [0]}\".");
				}
			} else {
				SdtdConsole.Instance.Output ("No sub command given.");
			}
		}

		private void ExecuteAdd (List<string> _params) {
			if (_params.Count != 4) {
				SdtdConsole.Instance.Output ($"Wrong number of arguments, expected 4, found {_params.Count}.");
				return;
			}

			if (string.IsNullOrEmpty (_params [1])) {
				SdtdConsole.Instance.Output ("Argument 'tokenname' is empty.");
				return;
			}

			if (!validNameTokenMatcher.IsMatch (_params [1])) {
				SdtdConsole.Instance.Output (
					"Argument 'tokenname' may only contain characters (A-Z, a-z), digits (0-9) and underscores (_).");
				return;
			}

			if (string.IsNullOrEmpty (_params [2])) {
				SdtdConsole.Instance.Output ("Argument 'tokensecret' is empty.");
				return;
			}

			if (!validNameTokenMatcher.IsMatch (_params [2])) {
				SdtdConsole.Instance.Output (
					"Argument 'tokensecret' may only contain characters (A-Z, a-z), digits (0-9) and underscores (_).");
				return;
			}

			if (!int.TryParse (_params [3], out int level)) {
				SdtdConsole.Instance.Output ("Argument 'level' is not a valid integer.");
				return;
			}

			AdminApiTokens.Instance.AddToken (_params [1], _params [2], level);
			SdtdConsole.Instance.Output ($"Web API token with name={_params [1]} and secret={_params [2]} added with permission level of {level}.");
		}

		private void ExecuteRemove (List<string> _params) {
			if (_params.Count != 2) {
				SdtdConsole.Instance.Output ($"Wrong number of arguments, expected 2, found {_params.Count}.");
				return;
			}

			if (string.IsNullOrEmpty (_params [1])) {
				SdtdConsole.Instance.Output ("Argument 'tokenname' is empty.");
				return;
			}

			if (!validNameTokenMatcher.IsMatch (_params [1])) {
				SdtdConsole.Instance.Output (
					"Argument 'tokenname' may only contain characters (A-Z, a-z), digits (0-9) and underscores (_).");
				return;
			}

			AdminApiTokens.Instance.RemoveToken (_params [1]);
			SdtdConsole.Instance.Output ($"{_params [1]} removed from web API token permissions list.");
		}

		private void ExecuteList () {
			SdtdConsole.Instance.Output ("Defined web API token permissions:");
			SdtdConsole.Instance.Output ("  Level: Name / Secret");
			foreach ((string _, AdminApiTokens.ApiToken apiToken) in AdminApiTokens.Instance.GetTokens ()) {
				SdtdConsole.Instance.Output ($"  {apiToken.PermissionLevel,5}: {apiToken.Name} / {apiToken.Secret}");
			}
		}
	}
}