using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;

namespace Websocket.Client.Logging.LogProviders
{
	internal static class LogMessageFormatter
	{
		public static Func<string> SimulateStructuredLogging(Func<string> messageBuilder, object[] formatParameters)
		{
			if (formatParameters != null && formatParameters.Length != 0)
			{
				return delegate
				{
					IEnumerable<string> enumerable;
					return LogMessageFormatter.FormatStructuredMessage(messageBuilder(), formatParameters, out enumerable);
				};
			}
			return messageBuilder;
		}

		private static string ReplaceFirst(object text, object search, object replace)
		{
			int num = text.IndexOf(search, StringComparison.Ordinal);
			if (num < 0)
			{
				return text;
			}
			return text.Substring(0, num) + replace + text.Substring(num + search.Length);
		}

		public static string FormatStructuredMessage(string targetMessage, object[] formatParameters, out IEnumerable<string> patternMatches)
		{
			if (formatParameters != null && formatParameters.Length != 0)
			{
				List<string> list = null;
				foreach (object obj in LogMessageFormatter.Pattern.Matches(targetMessage))
				{
					Match match = (Match)obj;
					string value = match.Groups["arg"].Value;
					int num;
					if (!int.TryParse(value, out num))
					{
						list = list ?? new List<string>(formatParameters.Length);
						int num2 = list.IndexOf(value);
						if (num2 == -1)
						{
							num2 = list.Count;
							list.Add(value);
						}
						targetMessage = LogMessageFormatter.ReplaceFirst(targetMessage, match.Value, "{" + num2.ToString() + match.Groups["format"].Value + "}");
					}
				}
				IEnumerable<string> enumerable = list;
				patternMatches = enumerable ?? Enumerable.Empty<string>();
				string text;
				try
				{
					text = string.Format(CultureInfo.InvariantCulture, targetMessage, formatParameters);
				}
				catch (FormatException ex)
				{
					throw new FormatException("The input string '" + targetMessage + "' could not be formatted using string.Format", ex);
				}
				return text;
			}
			patternMatches = Enumerable.Empty<string>();
			return targetMessage;
		}

		private static readonly Regex Pattern = new Regex("(?<!{){@?(?<arg>[^ :{}]+)(?<format>:[^}]+)?}", RegexOptions.Compiled);
	}
}
