import 'dart:io';

/// Supported window managers
enum WindowManager {
  hyprland,
  sway,
  unknown;

  @override
  String toString() {
    return switch (this) {
      WindowManager.hyprland => 'Hyprland',
      WindowManager.sway => 'Sway',
      WindowManager.unknown => 'Unknown',
    };
  }
}

/// Singleton class for detecting the current window manager at runtime
class WindowManagerDetector {
  static WindowManagerDetector? _instance;
  static WindowManagerDetector get instance => _instance ??= WindowManagerDetector._();
  
  WindowManagerDetector._();

  WindowManager? _detectedWindowManager;

  /// Detect the current window manager based on environment variables
  WindowManager detect() {
    if (_detectedWindowManager != null) {
      return _detectedWindowManager!;
    }

    final env = Platform.environment;

    // Check for Hyprland signature
    if (env.containsKey('HYPRLAND_INSTANCE_SIGNATURE') && env['HYPRLAND_INSTANCE_SIGNATURE']!.isNotEmpty) {
      _detectedWindowManager = WindowManager.hyprland;
      return _detectedWindowManager!;
    }

    // Check for Sway socket
    if (env.containsKey('SWAYSOCK') && env['SWAYSOCK']!.isNotEmpty) {
      _detectedWindowManager = WindowManager.sway;
      return _detectedWindowManager!;
    }

    // Fallback: Try to detect by checking running processes
    _detectedWindowManager = _detectByProcess();
    return _detectedWindowManager!;
  }

  /// Fallback detection by checking running processes
  WindowManager _detectByProcess() {
    try {
      // Check if hyprctl is available and working
      final hyprResult = Process.runSync('which', ['hyprctl']);
      if (hyprResult.exitCode == 0) {
        final hyprTest = Process.runSync('hyprctl', ['version']);
        if (hyprTest.exitCode == 0) {
          return WindowManager.hyprland;
        }
      }

      // Check if swaymsg is available and working
      final swayResult = Process.runSync('which', ['swaymsg']);
      if (swayResult.exitCode == 0) {
        final swayTest = Process.runSync('swaymsg', ['-t', 'get_version']);
        if (swayTest.exitCode == 0) {
          return WindowManager.sway;
        }
      }
    } catch (e) {
      // Ignore errors in fallback detection
    }

    return WindowManager.unknown;
  }

  /// Get information about the detected window manager
  Map<String, dynamic> getDetectionInfo() {
    final windowManager = detect();
    final env = Platform.environment;

    return {
      'detected_window_manager': windowManager.toString(),
      'detection_method': _getDetectionMethod(),
      'environment_variables': {
        'HYPRLAND_INSTANCE_SIGNATURE': env['HYPRLAND_INSTANCE_SIGNATURE'],
        'SWAYSOCK': env['SWAYSOCK'],
        'WAYLAND_DISPLAY': env['WAYLAND_DISPLAY'],
        'XDG_CURRENT_DESKTOP': env['XDG_CURRENT_DESKTOP'],
        'XDG_SESSION_TYPE': env['XDG_SESSION_TYPE'],
      },
    };
  }

  String _getDetectionMethod() {
    final env = Platform.environment;
    
    if (env.containsKey('HYPRLAND_INSTANCE_SIGNATURE') && env['HYPRLAND_INSTANCE_SIGNATURE']!.isNotEmpty) {
      return 'HYPRLAND_INSTANCE_SIGNATURE environment variable';
    }
    
    if (env.containsKey('SWAYSOCK') && env['SWAYSOCK']!.isNotEmpty) {
      return 'SWAYSOCK environment variable';
    }
    
    return 'Process detection fallback';
  }

  /// Reset detection (useful for testing)
  void reset() {
    _detectedWindowManager = null;
  }

  /// Check if the window manager supports visual enhancements
  bool supportsVisualEnhancements(WindowManager windowManager) {
    return switch (windowManager) {
      WindowManager.hyprland => true,
      WindowManager.sway => false, // As requested: no visual enhancements for Sway
      WindowManager.unknown => false,
    };
  }

  /// Check if the window manager supports idle monitoring
  bool supportsIdleMonitoring(WindowManager windowManager) {
    return switch (windowManager) {
      WindowManager.hyprland => true,
      WindowManager.sway => true,
      WindowManager.unknown => false,
    };
  }

  /// Check if the window manager supports activity detection
  bool supportsActivityDetection(WindowManager windowManager) {
    return switch (windowManager) {
      WindowManager.hyprland => true,
      WindowManager.sway => true,
      WindowManager.unknown => false,
    };
  }
}