import 'package:flutter/material.dart';

import '../design/chanora_tokens.dart';
import '../l10n/generated/app_localizations.dart';

enum ConnectionPhase {
  /// App is disconnected, no error.
  idle,

  /// Connecting to server.
  connecting,

  /// Connected but still synchronizing snapshot.
  synchronizing,

  /// Connected and ready.
  connected,

  /// Connection lost, auto-reconnecting.
  reconnecting,

  /// Explicitly disconnected by user.
  disconnected,
}

extension ConnectionPhaseState on ConnectionPhase {
  bool get isServerReachable =>
      this == ConnectionPhase.connected ||
      this == ConnectionPhase.synchronizing ||
      this == ConnectionPhase.reconnecting;

  bool get canOpenChat =>
      this == ConnectionPhase.connected ||
      this == ConnectionPhase.synchronizing;

  bool get canDisconnect => canOpenChat;

  bool shouldShowSnapshotLoading({required bool hasSnapshot}) =>
      isServerReachable && !hasSnapshot;

  bool canOpenChatWithSnapshot({required bool hasSnapshot}) =>
      canOpenChat && hasSnapshot;

  ConnectionTokens tokens(ColorScheme colorScheme) {
    switch (this) {
      case ConnectionPhase.idle:
      case ConnectionPhase.disconnected:
        return ConnectionTokens.disconnected(colorScheme);
      case ConnectionPhase.connecting:
        return ConnectionTokens.connecting(colorScheme);
      case ConnectionPhase.synchronizing:
        return ConnectionTokens.synchronizing(colorScheme);
      case ConnectionPhase.connected:
        return ConnectionTokens.connected(colorScheme);
      case ConnectionPhase.reconnecting:
        return ConnectionTokens.reconnecting(colorScheme);
    }
  }
}

ConnectionPhase phaseAfterConnectedEvent(
  ConnectionPhase phase, {
  required bool hasSnapshot,
}) {
  return phase == ConnectionPhase.connected && hasSnapshot
      ? ConnectionPhase.connected
      : ConnectionPhase.synchronizing;
}

String connectionStatusText({
  required ConnectionPhase phase,
  required AppL10n l10n,
  String? serverName,
  String? lostReason,
  int? reconnectAttempt,
  int? reconnectDelay,
}) {
  switch (phase) {
    case ConnectionPhase.idle:
      return l10n.statusIdle;
    case ConnectionPhase.connecting:
      return l10n.statusConnecting;
    case ConnectionPhase.synchronizing:
      return 'Synchronizing...';
    case ConnectionPhase.connected:
      return l10n.statusConnected(serverName ?? '');
    case ConnectionPhase.reconnecting:
      return reconnectAttempt != null
          ? l10n.statusReconnecting(reconnectAttempt, reconnectDelay ?? 0)
          : l10n.statusConnectionLost(lostReason ?? '');
    case ConnectionPhase.disconnected:
      return l10n.statusIdle;
  }
}

ConnectionPhase phaseAfterSnapshotApplied(ConnectionPhase phase) {
  return phase == ConnectionPhase.synchronizing
      ? ConnectionPhase.connected
      : phase;
}
