// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace Microsoft.AspNetCore.Razor.Language
{
	public abstract class RazorDiagnostic : IEquatable<RazorDiagnostic>, IFormattable
	{
		internal static readonly RazorDiagnostic[] EmptyArray = Array.Empty<RazorDiagnostic>();
		internal static readonly object[] EmptyArgs = Array.Empty<object>();

		public abstract string Id { get; }

		public abstract RazorDiagnosticSeverity Severity { get; }

		public abstract SourceSpan Span { get; }

		public abstract string GetMessage( IFormatProvider formatProvider );

		public string GetMessage() => GetMessage( null );

		public abstract bool Equals( RazorDiagnostic other );

		public abstract override int GetHashCode();

		public static RazorDiagnostic Create( RazorDiagnosticDescriptor descriptor, SourceSpan span )
		{
			if ( descriptor == null )
			{
				throw new ArgumentNullException( nameof( descriptor ) );
			}

			return new DefaultRazorDiagnostic( descriptor, span, EmptyArgs );
		}

		public static RazorDiagnostic Create( RazorDiagnosticDescriptor descriptor, SourceSpan span, params object[] args )
		{
			if ( descriptor == null )
			{
				throw new ArgumentNullException( nameof( descriptor ) );
			}

			return new DefaultRazorDiagnostic( descriptor, span, args );
		}

		public override string ToString()
		{
			return ((IFormattable)this).ToString( null, null );
		}

		public override bool Equals( object obj )
		{
			var other = obj as RazorDiagnostic;
			return other == null ? false : Equals( other );
		}

		string IFormattable.ToString( string ignore, IFormatProvider formatProvider )
		{
			// Our indices are 0-based, but we we want to print them as 1-based.
			return $"{Span.FilePath}({Span.LineIndex + 1},{Span.CharacterIndex + 1}): {Severity} {Id}: {GetMessage( formatProvider )}";
		}
	}
}
