{
  pkgs,
  lib,
  osConfig,
  config,
  ...
}:
let
  inherit (lib) mapAttrsToList mkIf hasAttr;
in
mkIf osConfig.programs.hyprland.enable {
  home.sessionVariables.ELECTRON_OZONE_PLATFORM_HINT = "auto";

  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"
        "${pkgs.keepassxc}/bin/keepassxc"
        (lib.mkIf config.services.hypridle.enable "${pkgs.hypridle}/bin/hypridle")
      ];

      general = {
        gaps_in = 3;
        gaps_out = 10;

        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)";

        # Set to true enable resizing windows by clicking and dragging on borders and gaps
        resize_on_border = false;

        # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
        allow_tearing = false;

        layout = "dwindle";
      };

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

      decoration = {
        rounding = 10;

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

        shadow = {
          enabled = true;
          range = 4;
          render_power = 3;
          color = "rgba(1a1a1aee)";
        };

        # https://wiki.hyprland.org/Configuring/Variables/#blur
        blur = {
          enabled = true;
          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}"
          "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 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;
      };

      # 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
      };

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

      bind =
        [
          "$mod, D, exec, ${pkgs.fuzzel}/bin/fuzzel"
          "$mod, E, exec, ${lib.my.getExe osConfig.modules.system.roles.desktop.filemanager}"
          "$mod, Return, exec, ${lib.my.getExe osConfig.modules.system.roles.desktop.terminal}"
          "$mod SHIFT, Q, killactive,"
          "$mod, V, togglefloating"
          "$mod SHIFT, P, exec, ${config.programs.rofi.package}/bin/rofi -show p -modi p:${pkgs.rofi-power-menu}/bin/rofi-power-menu"
          "$mod, P, exec, ${pkgs.cliphist}/bin/cliphist wipe & ${pkgs.hyprlock}/bin/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"

          # Example special workspace (scratchpad)
          "$mod, S, togglespecialworkspace, magic"
          "$mod SHIFT, S, movetoworkspace, special:magic"
          "$mod, X, fullscreen, 1"
          "$mod, F, fullscreen, 0"
          "$mod, N, exec, ${pkgs.swaynotificationcenter}/bin/swaync-client -t"
          "$mod, U, exec, ${pkgs.hyprshot}/bin/hyprshot -z -o $XDG_PICTURES_DIR/screenshots -m region"
          "$mod SHIFT, U, exec, ${pkgs.hyprshot}/bin/hyprshot -z --raw -m region | ${pkgs.satty}/bin/satty -f - --fullscreen"

          #: Brightness and Media {{{
          ",XF86MonBrightnessUp, exec, ${pkgs.brightnessctl}/bin/brightnessctl s +10%"
          ",XF86MonBrightnessDown, exec, ${pkgs.brightnessctl}/bin/brightnessctl s 10%-"
          ",XF86AudioRaiseVolume, exec, ${pkgs.pamixer}/bin/pamixer -i 5"
          ",XF86AudioLowerVolume, exec, ${pkgs.pamixer}/bin/pamixer -d 5"
          ",XF86AudioMicMute, exec, ${pkgs.pamixer}/bin/pamixer --default-source -m"
          ",XF86AudioMute, exec, ${pkgs.pamixer}/bin/pamixer -t"
          ",XF86AudioPlay, exec, ${pkgs.playerctl}/bin/playerctl play-pause"
          ",XF86AudioPause, exec, ${pkgs.playerctl}/bin/playerctl play-pause"
          ",XF86AudioNext, exec, ${pkgs.playerctl}/bin/playerctl next"
          ",XF86AudioPrev, exec, ${pkgs.playerctl}/bin/playerctl previous"
          #: }}}
        ]
        ++ (
          # workspaces
          # binds $mod + [shift +] {1..10} to [move to] workspace {1..10}
          builtins.concatLists (
            builtins.genList (
              x:
              let
                ws =
                  let
                    c = (x + 1) / 10;
                  in
                  builtins.toString (x + 1 - (c * 10));
              in
              [
                "$mod, ${ws}, workspace, ${toString (x + 1)}"
                "$mod SHIFT, ${ws}, movetoworkspace, ${toString (x + 1)}"
              ]
            ) 10
          )
        );
    };
  };
}
