using System.Collections.Generic;
using System.Net;
using JetBrains.Annotations;
using Utf8Json;
using Webserver.Permissions;

namespace Webserver.WebAPI.APIs.Permissions {
	[UsedImplicitly]
	public class CommandPermissions : AbsRestApi {
		private const string propertyCommand = "command";
		private const string propertyPermissionLevel = "permissionLevel";
		private const string propertyIsDefault = "default";

		private static readonly byte[] jsonKeyCommand = JsonWriter.GetEncodedPropertyNameWithBeginObject (propertyCommand);
		private static readonly byte[] jsonKeyPermissionLevel = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator (propertyPermissionLevel);
		private static readonly byte[] jsonKeyIsDefault = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator (propertyIsDefault);

		private static AdminCommands CommandsInstance => GameManager.Instance.adminTools.Commands;

		protected override void HandleRestGet (RequestContext _context) {
			string id = _context.RequestPath;

			PrepareEnvelopedResult (out JsonWriter writer);
			
			if (string.IsNullOrEmpty (id)) {
				
				writer.WriteBeginArray ();
			
				bool first = true;
				
				foreach (IConsoleCommand command in SdtdConsole.Instance.GetCommands ()) {
					if (!first) {
						writer.WriteValueSeparator ();
					}

					first = false;

					AdminCommands.CommandPermission commandPermission = CommandsInstance.GetAdminToolsCommandPermission (command.GetCommands());
					bool isDefault = commandPermission.PermissionLevel == command.DefaultPermissionLevel;
					if (commandPermission.Command == "") {
						commandPermission =
							new AdminCommands.CommandPermission (command.GetCommands ()[0], commandPermission.PermissionLevel);
					}

					writeCommandJson (ref writer, commandPermission, isDefault);
				}
				
				writer.WriteEndArray ();
				
				SendEnvelopedResult (_context, ref writer);
				return;
			}

			writer.WriteRaw (WebUtils.JsonEmptyData);
			SendEnvelopedResult (_context, ref writer, HttpStatusCode.BadRequest);
		}

		private void writeCommandJson(ref JsonWriter _writer, AdminCommands.CommandPermission _commandPermission, bool _isDefault) {
			_writer.WriteRaw (jsonKeyCommand);
			_writer.WriteString (_commandPermission.Command);
			_writer.WriteRaw (jsonKeyPermissionLevel);
			_writer.WriteInt32 (_commandPermission.PermissionLevel);
			_writer.WriteRaw (jsonKeyIsDefault);
			_writer.WriteBoolean (_isDefault);
			_writer.WriteEndObject ();
		}

		protected override void HandleRestPost (RequestContext _context, IDictionary<string, object> _jsonInput, byte[] _jsonInputData) {
			string id = _context.RequestPath;

			if (string.IsNullOrEmpty (id)) {
				SendEmptyResponse (_context, HttpStatusCode.BadRequest, _jsonInputData, EApiErrorCode.NO_COMMAND);
				return;
			}

			IConsoleCommand cmd = SdtdConsole.Instance.GetCommand (id);
			if (cmd == null) {
				SendEmptyResponse (_context, HttpStatusCode.NotFound, _jsonInputData, EApiErrorCode.UNKNOWN_COMMAND);
				return;
			}

			if (!JsonCommons.TryGetJsonField (_jsonInput, propertyPermissionLevel, out int permissionLevel)) {
				SendEmptyResponse (_context, HttpStatusCode.BadRequest, _jsonInputData, EApiErrorCode.NO_OR_INVALID_PERMISSION_LEVEL);
				return;
			}

			CommandsInstance.AddCommand (cmd.GetCommands ()[0], permissionLevel);

			SendEmptyResponse (_context, HttpStatusCode.Created);
		}

		protected override void HandleRestDelete (RequestContext _context) {
			string id = _context.RequestPath;

			IConsoleCommand cmd = SdtdConsole.Instance.GetCommand (id);
			if (cmd == null || !CommandsInstance.IsPermissionDefined (cmd.GetCommands ())) {
				SendEmptyResponse (_context, HttpStatusCode.NotFound);
				return;
			}

			bool removed = CommandsInstance.RemoveCommand (cmd.GetCommands ());

			SendEmptyResponse (_context, removed ? HttpStatusCode.NoContent : HttpStatusCode.NotFound);
		}

		protected override bool AllowPostWithId => true;

		public override int[] DefaultMethodPermissionLevels () => new[] {
			AdminWebModules.MethodLevelNotSupported,
			AdminWebModules.MethodLevelInheritGlobal,
			AdminWebModules.MethodLevelInheritGlobal,
			AdminWebModules.MethodLevelNotSupported,
			AdminWebModules.MethodLevelInheritGlobal
		};
	}
}