using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
using Utf8Json;

namespace Webserver {
	public class WebCommandResult : IConsoleConnection {
		public enum ResultType {
			Full,
			ResultOnly,
			Raw
		}

		private readonly string command;
		private readonly string parameters;
		private readonly string sourceName;

		private readonly RequestContext context;
		private readonly ResultType responseType;

		public WebCommandResult (string _command, string _parameters, ResultType _responseType, RequestContext _context) {
			context = _context;
			command = _command;
			parameters = _parameters;
			responseType = _responseType;
			sourceName = _context.Connection?.Username ?? "Unauth-PermLevel-" + _context.PermissionLevel;
		}

		private static readonly byte[] jsonRawKey = JsonWriter.GetEncodedPropertyNameWithBeginObject ("resultRaw");
		
		private static readonly byte[] jsonCommandKey = JsonWriter.GetEncodedPropertyNameWithBeginObject ("command");
		private static readonly byte[] jsonParametersKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("parameters");
		private static readonly byte[] jsonResultKey = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator ("result");
		
		public void SendLines (List<string> _output) {
			StringBuilder sb = new StringBuilder ();
			foreach (string line in _output) {
				sb.AppendLine (line);
			}

			string commandOutput = sb.ToString ();

			try {
				if (responseType == ResultType.Raw) {
					WebUtils.WriteText (context.Response, commandOutput);
				} else {
					WebUtils.PrepareEnvelopedResult (out JsonWriter writer);
			
					if (responseType == ResultType.ResultOnly) {
						writer.WriteRaw (jsonRawKey);
						writer.WriteString (commandOutput);
						writer.WriteEndObject ();
					} else {
						writer.WriteRaw (jsonCommandKey);
						writer.WriteString (command);
						
						writer.WriteRaw (jsonParametersKey);
						writer.WriteString (parameters);
						
						writer.WriteRaw (jsonResultKey);
						writer.WriteString (commandOutput);
						
						writer.WriteEndObject ();
					}

					WebUtils.SendEnvelopedResult (context, ref writer);
				}
			} catch (IOException e) {
				if (e.InnerException is SocketException) {
					Log.Warning ($"[Web] Error in WebCommandResult.SendLines(): Remote host closed connection: {e.InnerException.Message}");
				} else {
					Log.Warning ($"[Web] Error (IO) in WebCommandResult.SendLines(): {e}");
				}
			} catch (Exception e) {
				Log.Warning ($"[Web] Error in WebCommandResult.SendLines(): {e}");
			} finally {
				context?.Response?.Close ();
			}
		}

		public void SendLine (string _text) {
			//throw new NotImplementedException ();
		}

		public void SendLog (string _formattedMessage, string _plainMessage, string _trace, LogType _type, DateTime _timestamp, long _uptime) {
			//throw new NotImplementedException ();
		}

		public void EnableLogLevel (LogType _type, bool _enable) {
			//throw new NotImplementedException ();
		}

		public string GetDescription () {
			return $"WebCommandResult_for_{command}_by_{sourceName}";
		}
	}
}