context: using ACE.Entity;
  using ACE.Entity.Enum;
  using ACE.Server.Entity;
  using ACE.Server.Managers;
  using ACE.Server.Network;
  using ACE.Server.WorldObjects;
  
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text.RegularExpressions;
  
  namespace ACE.Server.Command
  {
      /// <summary>
      /// Command handler sanity preserving parameter parsing
      /// </summary>
      public class CommandParameterHelpers
      {
          /// <summary>
          /// Types of parameter values
          /// </summary>
          public enum ACECommandParameterType
          {
              /// <summary>
              /// don't use this one
              /// </summary>
              Invalid,
              /// <summary>
              /// normal coordinates, example: 37.3s,67w<para/>
              /// output is of type ACE.Entity.Position
              /// </summary>
              Location,
              /// <summary>
              /// a character name of an online player, example: the fat bastard<para/>
              /// output is of type ACE.Server.WorldObjects.Player<para/>
              /// only one of OnlinePlayerName or OnlinePlayerNameOrIid or PlayerName parameter can be used for one command<para/>
              /// must be the first parameter
              /// </summary>
              OnlinePlayerName,
              /// <summary>
              /// a character name of an online player, example: the fat bastard or a decimal iid, example: 1342177281<para/>
              /// output is of type ACE.Server.WorldObjects.Player<para/>
              /// only one of OnlinePlayerName or OnlinePlayerNameOrIid or PlayerName parameter can be used for one command<para/>
              /// must be the first parameter
              /// </summary>
              OnlinePlayerNameOrIid,
              /// <summary>
              /// a decimal or hexadecimal iid of an online player, examples: 1342177292 or 0x5000000C<para/>
              /// output is of type ACE.Server.WorldObjects.Player<para/>
              /// </summary>
              OnlinePlayerIid,
              /// <summary>
              /// a character name, example: the fat bastard<para/>
              /// output is of type string<para/>
              /// only one of OnlinePlayerName or OnlinePlayerNameOrIid or PlayerName parameter can be used for one command<para/>
              /// must be the first parameter
              /// </summary>
              PlayerName,
              /// <summary>
              /// a url, example: http://someserver.net:4321/?get=blah <para/>
              /// output is of type System.Uri
              /// </summary>
              Uri,
              /// <summary>
              /// a number, example: 01231242<para/>
              /// output is of type ulong: 1231242
              /// </summary>
              ULong,
              /// <summary>
              /// a number, example: -01231242<para/>
              /// output is of type long: -1231242
              /// </summary>
              Long,
              /// <summary>
              /// a number, example: 01231242<para/>
              /// output is of type long: 1231242
              /// </summary>
              PositiveLong,
              /// <summary>
              /// some text enclosed in double quotes, example: "the problem is solved"<para/>
              /// Note:  To accept this kind of parameter IncludeRaw must be true for the command handler attribute decoration and RawIncluded argument must be true for the call to ResolveACEParameters
              /// </summary>
              DoubleQuoteEnclosedText,
              /// <summary>
              /// some text preceeded by a comma, example (the part after char): /hug my girl, char, the reasons are plenty!<para/>
              /// Note: To accept this kind of parameter IncludeRaw must be true for the command handler attribute decoration and RawIncluded argument must be true for the call to ResolveACEParameters<para/>
              /// limit 1 per command, may not include commas
              /// </summary>
              CommaPrefixedText,
              /// <summary>
              /// a word, example: boat<para/>
              /// output is of type string<para/>
              /// word may be one or more of case insensitive a-z, 0-9, and underscore<para/>
              /// </summary>
              SimpleWord,
              /// <summary>
              /// an element of an enum<para/>
              /// output is of enum type you supply as PossibleValues<para/>
              /// set the PossibleValues object to the type of enum<para/>
              /// </summary>
              Enum,
          }
          /// <summary>
          /// A player supplied parameter
          /// </summary>
          public class ACECommandParameter
          {
              /// <summary>
              /// The type of the parameter value
              /// </summary>
              public ACECommandParameterType Type { get; set; } = ACECommandParameterType.Invalid;
              /// <summary>
              /// The value to use upon missing or invalid supplied parameter
              /// </summary>
              public object DefaultValue { get; set; } = null;
              /// <summary>
              /// If this parameter is required
              /// </summary>
              public bool Required { get; set; } = false;
              /// <summary>
              /// The resultant parsed Value (or the default value)
              /// </summary>
              public object Value { get; set; } = null;
              public Position AsPosition => (Position)Value;
              public Player AsPlayer => (Player)Value;
              public ulong AsULong => (ulong)Value;
              public long AsLong => (long)Value;
              public long AsInt => (int)Value;
              public string AsString => (string)Value;
              public Uri AsUri => (Uri)Value;
              /// <summary>
              /// The parameter either wasn't supplied or was invalid (doesn't parse, player doesn't exist, etc.)
              /// </summary>
              public bool Defaulted { get; set; } = true;
              /// <summary>
              /// The broadcast message to send to the session when the parameter is required and didn't parse or wasn't supplied.
              /// </summary>
              public string ErrorMessage { get; set; } = null;
              /// <summary>
              /// Automatically assigned during GetParameters procedure
              /// </summary>
              public int ParameterNo { get; set; } = -1;
              /// <summary>
              /// if the type is enum set this to the enum that the parameter should be part of
              /// </summary>
              public Type PossibleValues { get; set; } = null;
          }
          /// <summary>
          /// Resolve the parameters supplied by the player into usable values.
          /// </summary>
          /// <param name="session">the session of the player who sent the command</param>
          /// <param name="aceParsedParameters">the collection of parameters supplied by the default parameter parser</param>
          /// <param name="parameters">the resolution details for every parameter</param>
          /// <param name="rawIncluded">whether or not the raw unparsed command line minus the command name was included as the first parameter</param>
          /// <returns>the parameters were successfully resolved or not</returns>
          public static bool ResolveACEParameters(Session session, IEnumerable<string> aceParsedParameters, IEnumerable<ACECommandParameter> parameters, bool rawIncluded = false)
          {
              string parameterBlob = "";
              if (rawIncluded)
              {
                  parameterBlob = aceParsedParameters.First();
              }
              else
              {
                  parameterBlob = aceParsedParameters.Count() > 0 ? aceParsedParameters.Aggregate((a, b) => a + " " + b).Trim(new char[] { ' ', ',' }) : string.Empty;
              }
              int commaCount = parameterBlob.Count(x => x == ',');
  
              List<ACECommandParameter> acps = parameters.ToList();
              for (int i = acps.Count - 1; i > -1; i--)
              {
                  ACECommandParameter acp = acps[i];
                  acp.ParameterNo = i + 1;
                  if (parameterBlob.Length > 0)
                  {
                      try
                      {
                          switch (acp.Type)
                          {
                              case ACECommandParameterType.PositiveLong:
                                  Match match4 = Regex.Match(parameterBlob, @"(-?\d+)$", RegexOptions.IgnoreCase);
                                  if (match4.Success)
                                  {
                                      if (!long.TryParse(match4.Groups[1].Value, out long val))
                                      {
                                          return false;
                                      }
                                      if (val <= 0)
                                      {
                                          return false;
                                      }
                                      acp.Value = val;
                                      acp.Defaulted = false;
                                      parameterBlob = (match4.Groups[1].Index == 0) ? string.Empty : parameterBlob.Substring(0, match4.Groups[1].Index).Trim(new char[] { ' ' });
                                  }
                                  break;
                              case ACECommandParameterType.Long:
                                  Match match3 = Regex.Match(parameterBlob, @"(-?\d+)$", RegexOptions.IgnoreCase);
                                  if (match3.Success)
                                  {
  
gt:                                     if (!long.TryParse(match3.Groups[1].Value, out long val))