/// Alignment requested by a TeamSpeak spacer channel tag.
enum SpacerAlignment {
  /// Left-aligned spacer content.
  left,

  /// Right-aligned spacer content.
  right,

  /// Center-aligned spacer content.
  center,
}

/// Built-in TeamSpeak spacer separator patterns.
enum SpacerSpecialType {
  /// `___`
  solidLine,

  /// `---`
  dashLine,

  /// `...`
  dotLine,

  /// `-.-`
  dashDotLine,

  /// `-..`
  dashDotDotLine,
}

/// Parsed form of a TeamSpeak spacer channel name.
class SpacerChannelNameParseResult {
  /// Construct a spacer parse result.
  const SpacerChannelNameParseResult({
    required this.isSpacer,
    required this.isValid,
    required this.alignment,
    required this.isRepeating,
    required this.uniqueSuffix,
    required this.text,
    required this.specialType,
    required this.isBlankSpacer,
    this.reason,
  });

  /// True only when the name begins with a valid bracketed spacer tag.
  final bool isSpacer;

  /// True when the bracketed spacer tag follows the supported syntax.
  final bool isValid;

  /// Optional alignment flag. Null means the server/client default.
  final SpacerAlignment? alignment;

  /// True when `*` appears in the tag and the text should repeat.
  final bool isRepeating;

  /// The exact suffix after `Spacer` and before `]`.
  final String uniqueSuffix;

  /// The exact text after the closing `]`.
  final String text;

  /// Built-in separator type for special text values.
  final SpacerSpecialType? specialType;

  /// True for the known blank-looking right-aligned dot spacer.
  final bool isBlankSpacer;

  /// Parse error/reason for non-spacer or malformed names.
  final String? reason;
}

/// Options for formatting a TeamSpeak spacer channel name.
class SpacerChannelNameFormatOptions {
  /// Construct spacer formatting options.
  const SpacerChannelNameFormatOptions({
    this.alignment,
    this.isRepeating = false,
    this.uniqueSuffix = '',
    this.text = '',
  });

  /// Optional alignment flag. Null means omit the alignment prefix.
  final SpacerAlignment? alignment;

  /// Whether to include the repeating `*` tag flag.
  final bool isRepeating;

  /// Uniqueness suffix to place after `Spacer`.
  final String uniqueSuffix;

  /// Text to place after the closing `]`.
  final String text;
}

const _notSpacer = SpacerChannelNameParseResult(
  isSpacer: false,
  isValid: false,
  alignment: null,
  isRepeating: false,
  uniqueSuffix: '',
  text: '',
  specialType: null,
  isBlankSpacer: false,
  reason: 'not a spacer channel name',
);

/// Return true when [name] begins with a valid bracketed spacer tag.
bool isSpacerChannelName(String name) => parseSpacerChannelName(name).isSpacer;

/// Parse a TeamSpeak spacer channel name.
///
/// Supported tag form is `[?Spacer#]Text`, parsed case-insensitively.
/// `?` may be `l`, `r`, or `c`; `*` may also appear in the tag to
/// mark repeating spacer content. The suffix and text are preserved
/// exactly as written.
SpacerChannelNameParseResult parseSpacerChannelName(String name) {
  if (!name.startsWith('[')) return _notSpacer;

  final close = name.indexOf(']');
  if (close < 0) {
    return _invalidSpacerName('missing closing bracket');
  }

  final tag = name.substring(1, close);
  final text = name.substring(close + 1);
  final match = RegExp(
    r'^([lrc*]*)(spacer)(.*)$',
    caseSensitive: false,
  ).firstMatch(tag);

  if (match == null) {
    if (tag.toLowerCase().contains('spacer')) {
      return _invalidSpacerName('invalid spacer tag');
    }
    return _notSpacer;
  }

  final flags = match.group(1) ?? '';
  final uniqueSuffix = match.group(3) ?? '';
  final alignmentFlags = flags
      .toLowerCase()
      .split('')
      .where((flag) => flag == 'l' || flag == 'r' || flag == 'c')
      .toList();
  final repeatingFlags = flags.split('').where((flag) => flag == '*').length;

  if (alignmentFlags.length > 1) {
    return _invalidSpacerName('multiple alignment flags');
  }
  if (repeatingFlags > 1) {
    return _invalidSpacerName('multiple repeating flags');
  }

  final alignmentFlag = alignmentFlags.isEmpty ? null : alignmentFlags.first;
  final alignment = switch (alignmentFlag) {
    'l' => SpacerAlignment.left,
    'r' => SpacerAlignment.right,
    'c' => SpacerAlignment.center,
    _ => null,
  };
  final specialType = _specialTypeForText(text);
  return SpacerChannelNameParseResult(
    isSpacer: true,
    isValid: true,
    alignment: alignment,
    isRepeating: repeatingFlags == 1,
    uniqueSuffix: uniqueSuffix,
    text: text,
    specialType: specialType,
    isBlankSpacer: alignment == SpacerAlignment.right && text == '.',
  );
}

/// Format a TeamSpeak spacer channel name deterministically.
///
/// The output uses canonical `Spacer` casing and places `*` before
/// the alignment flag when both are present.
String formatSpacerChannelName(SpacerChannelNameFormatOptions options) {
  final repeatFlag = options.isRepeating ? '*' : '';
  final alignFlag = switch (options.alignment) {
    SpacerAlignment.left => 'l',
    SpacerAlignment.right => 'r',
    SpacerAlignment.center => 'c',
    null => '',
  };
  return '[$repeatFlag${alignFlag}Spacer${options.uniqueSuffix}]${options.text}';
}

/// Convert a channel name into display text while preserving the
/// underlying channel entity and behavior.
String channelSpacerLabel(String raw, {int repeatColumns = 32}) {
  final parsed = parseSpacerChannelName(raw);
  if (!parsed.isValid) return raw;
  if (parsed.isBlankSpacer) return '';
  if (parsed.isRepeating) {
    return _repeatSpacerText(parsed.text, repeatColumns);
  }

  return switch (parsed.specialType) {
    SpacerSpecialType.solidLine => '────────',
    SpacerSpecialType.dashLine => '╌╌╌╌╌╌╌╌',
    SpacerSpecialType.dotLine => '········',
    SpacerSpecialType.dashDotLine => '─╶─╶─╶─╶─╶─╶─╶─╶',
    SpacerSpecialType.dashDotDotLine => '─╶╶─╶╶─╶╶─╶╶',
    null => parsed.text,
  };
}

SpacerChannelNameParseResult _invalidSpacerName(String reason) {
  return SpacerChannelNameParseResult(
    isSpacer: false,
    isValid: false,
    alignment: null,
    isRepeating: false,
    uniqueSuffix: '',
    text: '',
    specialType: null,
    isBlankSpacer: false,
    reason: reason,
  );
}

SpacerSpecialType? _specialTypeForText(String text) {
  return switch (text) {
    '___' => SpacerSpecialType.solidLine,
    '---' => SpacerSpecialType.dashLine,
    '...' => SpacerSpecialType.dotLine,
    '-.-' => SpacerSpecialType.dashDotLine,
    '-..' => SpacerSpecialType.dashDotDotLine,
    _ => null,
  };
}

String _repeatSpacerText(String pattern, int repeatColumns) {
  if (pattern.isEmpty) return '────────';
  final buffer = StringBuffer();
  while (buffer.length < repeatColumns) {
    buffer.write(pattern);
  }
  return buffer.toString().substring(0, repeatColumns);
}
