#if UNITY_EDITOR
namespace NiAkaDev.EzMirror.Editor
{
    using System.Collections.Generic;
    using System.Text;

    internal sealed class EzMirrorValidationReport
    {
        private readonly List<EzMirrorValidationIssue> errors = new List<EzMirrorValidationIssue>();
        private readonly List<EzMirrorValidationIssue> warnings = new List<EzMirrorValidationIssue>();
        private readonly List<string> details = new List<string>();

        internal bool Success => errors.Count == 0;
        internal EzMirrorValidationIssue[] Errors => errors.ToArray();
        internal EzMirrorValidationIssue[] Warnings => warnings.ToArray();
        internal string[] Details => details.ToArray();

        internal void AddError(string code, string message)
        {
            errors.Add(new EzMirrorValidationIssue(code, message));
        }

        internal void AddWarning(string code, string message)
        {
            warnings.Add(new EzMirrorValidationIssue(code, message));
        }

        internal void AddDetail(string message)
        {
            details.Add(message);
        }

        internal bool HasIssueCode(string code)
        {
            return ContainsCode(errors, code);
        }

        internal bool HasWarningCode(string code)
        {
            return ContainsCode(warnings, code);
        }

        internal string ToLogString()
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine(Success ? "[EzMirror] 検証に成功しました。" : "[EzMirror] 検証に失敗しました。");
            AppendIssues(builder, "Errors", errors);
            AppendIssues(builder, "Warnings", warnings);
            if (details.Count > 0)
            {
                builder.AppendLine("Details:");
                for (int i = 0; i < details.Count; i++)
                    builder.AppendLine("- " + details[i]);
            }
            return builder.ToString();
        }

        private static bool ContainsCode(List<EzMirrorValidationIssue> issues, string code)
        {
            for (int i = 0; i < issues.Count; i++)
            {
                if (issues[i].Code == code)
                    return true;
            }
            return false;
        }

        private static void AppendIssues(
            StringBuilder builder,
            string label,
            List<EzMirrorValidationIssue> issues
        )
        {
            if (issues.Count == 0)
                return;
            builder.AppendLine(label + ":");
            for (int i = 0; i < issues.Count; i++)
                builder.AppendLine("- " + issues[i].Code + ": " + issues[i].Message);
        }
    }

    internal readonly struct EzMirrorValidationIssue
    {
        internal EzMirrorValidationIssue(string code, string message)
        {
            Code = code;
            Message = message;
        }

        internal string Code { get; }
        internal string Message { get; }
    }
}
#endif
