using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
namespace Robust.Shared.Utility
{
///
/// Represents a formatted message in the form of a list of "tags".
/// Does not do any concrete formatting, simply useful as an API surface.
///
[PublicAPI]
[Serializable, NetSerializable]
public sealed partial class FormattedMessage
{
public TagList Tags => new(_tags);
private readonly List _tags;
public bool IsEmpty => _tags.Count == 0;
public FormattedMessage()
{
_tags = new List();
}
public FormattedMessage(int capacity)
{
_tags = new List(capacity);
}
public static FormattedMessage FromMarkup(string markup)
{
var msg = new FormattedMessage();
msg.AddMarkup(markup);
return msg;
}
public static FormattedMessage FromMarkupPermissive(string markup)
{
var msg = new FormattedMessage();
msg.AddMarkupPermissive(markup);
return msg;
}
///
/// Escape a string of text to be able to be formatted into markup.
///
public static string EscapeText(string text)
{
return text.Replace("\\", "\\\\").Replace("[", "\\[");
}
///
/// Remove all markup, leaving only the basic text content behind.
///
public static string RemoveMarkup(string text)
{
return FromMarkup(text).ToString();
}
///
/// Create a new FormattedMessage by copying another one.
///
/// The message to copy.
public FormattedMessage(FormattedMessage toCopy)
{
_tags = toCopy._tags.ShallowClone();
}
public void AddText(string text)
{
_tags.Add(new TagText(text));
}
public void PushColor(Color color)
{
_tags.Add(new TagColor(color));
}
public void PushNewline()
{
AddText("\n");
}
public void Pop()
{
_tags.Add(new TagPop());
}
public void AddMessage(FormattedMessage other)
{
_tags.AddRange(other.Tags);
}
public void Clear()
{
_tags.Clear();
}
/// The string without markup tags.
public override string ToString()
{
var builder = new StringBuilder();
foreach (var tag in _tags)
{
if (tag is not TagText text)
{
continue;
}
builder.Append(text.Text);
}
return builder.ToString();
}
/// The string without filtering out markup tags.
public string ToMarkup()
{
var builder = new StringBuilder();
foreach (var tag in _tags)
{
builder.Append(tag);
}
return builder.ToString();
}
[Serializable, NetSerializable]
public abstract record Tag
{
}
[Serializable, NetSerializable]
public sealed record TagText(string Text) : Tag
{
public override string ToString()
{
return Text;
}
}
[Serializable, NetSerializable]
public sealed record TagColor(Color Color) : Tag
{
public override string ToString()
{
return $"[color={Color.ToHex()}]";
}
}
[Serializable, NetSerializable]
public sealed record TagPop : Tag
{
public static readonly TagPop Instance = new();
public override string ToString()
{
return $"[/color]";
}
}
public readonly struct TagList : IReadOnlyList
{
private readonly List _tags;
public TagList(List tags)
{
_tags = tags;
}
public List.Enumerator GetEnumerator()
{
return _tags.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _tags.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _tags.GetEnumerator();
}
public int Count => _tags.Count;
public Tag this[int index] => _tags[index];
}
}
}