import 'exception.dart';
import 'format_exception.dart';

/// Exception thrown when the end tag does not match the open tag.
class XmlTagException extends XmlException with XmlFormatException {
  /// Creates a new XmlTagException.
  XmlTagException(
    super.message, {
    this.expectedName,
    this.actualName,
    this.buffer,
    this.position,
  });

  /// Creates a new XmlTagException where [expectedName] was expected, but
  /// instead we found [actualName].
  factory XmlTagException.mismatchClosingTag(
    String expectedName,
    String actualName, {
    String? buffer,
    int? position,
  }) => XmlTagException(
    'Expected </$expectedName>, but found </$actualName>',
    expectedName: expectedName,
    actualName: actualName,
    buffer: buffer,
    position: position,
  );

  /// Creates a new XmlTagException for an unexpected closing tag.
  factory XmlTagException.unexpectedClosingTag(
    String actualName, {
    String? buffer,
    int? position,
  }) => XmlTagException(
    'Unexpected </$actualName>',
    actualName: actualName,
    buffer: buffer,
    position: position,
  );

  /// Creates a new XmlTagException for a missing closing tag.
  factory XmlTagException.missingClosingTag(
    String expectedName, {
    String? buffer,
    int? position,
  }) => XmlTagException(
    'Missing </$expectedName>',
    expectedName: expectedName,
    buffer: buffer,
    position: position,
  );

  /// Ensure that the expected tag matches the actual one.
  static void checkClosingTag(
    String expectedName,
    String actualName, {
    String? buffer,
    int? position,
  }) {
    if (expectedName != actualName) {
      throw XmlTagException.mismatchClosingTag(
        expectedName,
        actualName,
        buffer: buffer,
        position: position,
      );
    }
  }

  /// The tag name that was expected, or `null`.
  final String? expectedName;

  /// The tag name that was found, or `null`.
  final String? actualName;

  @override
  String? buffer;

  @override
  int? position;

  @override
  String toString() => 'XmlTagException: $message$locationString';
}
