{
  pkgs,
  lib,
  osConfig,
  config,
  ...
}:
let
  inherit (lib) mapAttrsToList mkIf hasAttr;
  inherit (lib.my) getExe getExe';

  roles = osConfig.modules.system.roles;
  desktop = osConfig.modules.system.roles.desktop;
in
mkIf osConfig.programs.hyprland.enable {
  home.sessionVariables.ELECTRON_OZONE_PLATFORM_HINT = "auto";

  programs.hyprlock.enable = true;
  services.swayidle.enable = true;

  wayland.windowManager.hyprland = {
    enable = true;
    systemd.variables = [ "--all" ];
    settings = {
      "$mod" = "SUPER";

      monitor = mapAttrsToList (
        name: value:
        let
          inherit (value) resX resY scale;
          posFinal = "${toString value.posX}x${toString value.posY}";
          rrFinal = if hasAttr "rr" value then "@${toString value.rr}" else "";
        in
        "${name}, ${toString resX}x${toString resY}${rrFinal}, ${posFinal}, ${toString scale}"
      ) osConfig.modules.system.outputs;

      exec-once = [
        "${config.services.kdeconnect.package}/bin/kdeconnect-indicator"
        "${getExe' pkgs.gnome-keyring "gnome-keyring-daemon"}"
      ];

      general = {
        gaps_in = 3;
        gaps_out = 3;

        border_size = 2;

        # https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
        "col.active_border" = "rgba(33ccffee) rgba(00ff99ee) 45deg";
        "col.inactive_border" = "rgba(595959aa)";

        # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
        allow_tearing = false;
        hover_icon_on_border = true;
        resize_on_border = true;
        layout = "dwindle";
        snap = {
          enabled = true;
        };
      };

      input = {
        numlock_by_default = true;
        kb_options = "compose:caps";
        kb_layout = osConfig.console.keyMap;
        touchpad = {
          natural_scroll = true;
        };
      };

      decoration = {
        rounding = 10;

        # Change transparency of focused and unfocused windows
        active_opacity = 1.0;
        inactive_opacity = 1.0;

        shadow = {
          enabled = roles.portable.enable;
          range = 4;
          render_power = 3;
          color = "rgba(1a1a1aee)";
        };

        # https://wiki.hyprland.org/Configuring/Variables/#blur
        blur = {
          enabled = roles.portable.enable;
          size = 3;
          passes = 1;

          vibrancy = 0.1696;
        };
      };
      windowrulev2 =
        let
          mkRegexList = list: "^(${(lib.strings.concatStringsSep "|" list)})$";
          floatReg = mkRegexList [
            "com.nextcloud.desktopclient.nextcloud"
            "soffice"
            "xdg-desktop-portal-gtk"
          ];
        in
        [
          "float,initialClass:${floatReg}"
          "float,initialTitle:^(KeePassXC - Passkey credentials)$"
          "bordercolor rgb(e50000) rgb(ff8d00) rgb(ffee00) rgb(028121) rgb(004cff) rgb(770088), fullscreen:1"
          "focusonactivate, title:${mkRegexList [ "Firefox" ]}"
          "workspace 2,initialClass:${mkRegexList [ "firefox" ]}"
          "workspace 3,initialClass:${mkRegexList [ "obsidian" ]}"
          "workspace silent 4,initialClass:${mkRegexList [ "steam" ]}"
          "workspace 5,initialClass:${mkRegexList [ "lollypop" ]}"

          "fullscreen, class:gamescope"
          # Fixes: Nextcloud Client having a variable size depending on open tiled windows
          "size 30% 50%, initialClass:com.nextcloud.desktopclient.nextcloud"
          # Fixes: Nextcloud Client closing instantly because the cursor is not on the app
          "noinitialfocus, initialClass:com.nextcloud.desktopclient.nextcloud"
        ];
      # https://wiki.hyprland.org/Configuring/Variables/#animations
      animations = {

        enabled = true;

        # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more

        bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";

        animation = [
          "windows, 1, 7, myBezier"
          "windowsOut, 1, 7, default, popin 80%"
          "border, 1, 10, default"
          "borderangle, 1, 8, default"
          "fade, 1, 7, default"
          "workspaces, 1, 6, default"
          "specialWorkspace, 1, 6, default, slidevert"
        ];
      };

      # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
      dwindle = {
        pseudotile = true;
        preserve_split = true;
      };

      gestures = {
        workspace_swipe = true;
      };
      group = {

        "col.border_active" = "0xff601393";

        groupbar = {
          "col.active" = "0x66601393";
          "col.inactive" = "0xff340851";
        };
      };
      # https://wiki.hyprland.org/Configuring/Variables/#misc
      misc = {
        force_default_wallpaper = 0;
        disable_hyprland_logo = false;
        focus_on_activate = false; # Open windows without focusing them
        new_window_takes_over_fullscreen = 2; # When a new window opens, the current fullscreen window returns to its tiled state
        key_press_enables_dpms = true;
        mouse_move_enables_dpms = true;
        disable_autoreload = true;
        vfr = true;
        enable_swallow = true;
        swallow_regex = "^foot$";
      };

      bindm = [ "$mod,mouse:272,movewindow" ];

      bind =
        let
          copy = getExe' pkgs.wl-clipboard "wl-copy";
          cliphist = getExe pkgs.cliphist;
        in
        [
          "$mod, D, exec, ${getExe osConfig.modules.system.roles.desktop.runner.package}"
          "$mod, E, exec, ${getExe osConfig.modules.system.roles.desktop.filemanager}"
          "$mod, Return, exec, ${getExe osConfig.modules.system.roles.desktop.terminal}"
          "$mod SHIFT, Q, killactive,"
          "$mod, V, togglefloating"
          "$mod SHIFT, P, exec, ${getExe pkgs.scripts.powerMenu}"
          "$mod, P, exec, ${cliphist} wipe & ${getExe pkgs.hyprlock}"
          "$mod SHIFT, C, exec, hyprctl reload"
          "$mod SHIFT, space, togglefloating"
          "$mod, left, movefocus, l"
          "$mod, right, movefocus, r"
          "$mod, up, movefocus, u"
          "$mod, down, movefocus, d"
          "CTRL, G, togglegroup"
          "ALT, Tab, changegroupactive"
          # Example special workspace (scratchpad)
          "$mod, W, togglespecialworkspace, magic"
          "$mod SHIFT, W, movetoworkspace, special:magic"
          "$mod, X, fullscreen, 1"
          "$mod, F, fullscreen, 0"
          "$mod, U, exec, ${pkgs.hyprshot}/bin/hyprshot -o ${config.xdg.userDirs.pictures}/screenshots -m region"
          "$mod SHIFT, U, exec, ${pkgs.hyprshot}/bin/hyprshot --raw -m region | ${getExe pkgs.satty} -f - --fullscreen  --copy-command ${copy}"
          "$mod, S, exec, ${cliphist} list | ${desktop.runner.dmenu}  | ${cliphist} decode |  ${copy}"

          #: Brightness and Media {{{
          ",XF86MonBrightnessUp, exec, ${getExe pkgs.brightnessctl} s +10%"
          ",XF86MonBrightnessDown, exec, ${getExe pkgs.brightnessctl} s 10%-"
          ",XF86AudioRaiseVolume, exec, ${getExe pkgs.pamixer} -u && ${getExe pkgs.pamixer} -i 5"
          ",XF86AudioLowerVolume, exec, ${getExe pkgs.pamixer} -u && ${getExe pkgs.pamixer} -d 5"
          ",XF86AudioMicMute, exec, ${getExe pkgs.pamixer} --default-source -m"
          ",XF86AudioMute, exec, ${getExe pkgs.pamixer} -t"
          ",XF86AudioPlay, exec, ${getExe pkgs.playerctl} play-pause"
          ",XF86AudioPause, exec, ${getExe pkgs.playerctl} play-pause"
          ",XF86AudioNext, exec, ${getExe pkgs.playerctl} next"
          ",XF86AudioPrev, exec, ${getExe pkgs.playerctl} previous"
          #: }}}

          # Workspaces
          "$mod, code:10, workspace, 1"
          "$mod, code:11, workspace, 2"
          "$mod, code:12, workspace, 3"
          "$mod, code:13, workspace, 4"
          "$mod, code:14, workspace, 5"
          "$mod, code:15, workspace, 6"
          "$mod, code:16, workspace, 7"
          "$mod, code:17, workspace, 8"
          "$mod, code:18, workspace, 9"
          "$mod, code:19, workspace, 10"

          # Send to Workspaces
          "$mod SHIFT, code:10, movetoworkspace, 1"
          "$mod SHIFT, code:11, movetoworkspace, 2"
          "$mod SHIFT, code:12, movetoworkspace, 3"
          "$mod SHIFT, code:13, movetoworkspace, 4"
          "$mod SHIFT, code:14, movetoworkspace, 5"
          "$mod SHIFT, code:15, movetoworkspace, 6"
          "$mod SHIFT, code:16, movetoworkspace, 7"
          "$mod SHIFT, code:17, movetoworkspace, 8"
          "$mod SHIFT, code:18, movetoworkspace, 9"
          "$mod SHIFT, code:19, movetoworkspace, 10"
        ];
    };
  };
}