{
  # Snowfall Lib provides a customized `lib` instance with access to your flake's library
  # as well as the libraries available from your flake's inputs.
  lib,
  # An instance of `pkgs` with your overlays and packages applied is also available.
  pkgs,
  # You also have access to your flake's inputs.
  inputs,

  # Additional metadata is provided by Snowfall Lib.
  namespace, # The namespace used for your flake, defaulting to "internal" if not set.
  system, # The system architecture for this host (eg. `x86_64-linux`).
  target, # The Snowfall Lib target for this system (eg. `x86_64-iso`).
  format, # A normalized name for the system target (eg. `iso`).
  virtual, # A boolean to determine whether this system is a virtual target using nixos-generators.
  systems, # An attribute map of your defined hosts.

  # All other arguments come from the module system.
  config,
  ...
}:

let
  cfg = config.modules.hyprland;
  inherit (inputs.nix-colors.colorschemes.${builtins.toString config.modules.desktop.colorscheme})
    palette
    ;
in
{
  options.modules.hyprland = with lib.frajul; {
    enable = mkBoolOpt false "Enable or disable the hyprland window manager.";
  };

  imports = [ inputs.hyprland.homeManagerModules.default ];

  config = lib.mkIf cfg.enable {
    modules.desktop.addons = {
      waybar.enable = true;
      wofi.enable = true;
      mako.enable = true;
      hyprlock.enable = true;
      wlogout.enable = true;
    };

    home.packages = with pkgs; [
      # hyprpicker # TODO
      # hyprcursor # TODO
      brightnessctl
      # grimblast
      frajul.hyprshot-gui
    ];

    # services.hypridle = {
    #   enable = true;
    #   settings = {
    #     general = {
    #       after_sleep_cmd = "hyprctl dispatch dpms on";
    #       ignore_dbus_inhibit = false;
    #       lock_cmd = "hyprlock";
    #     };

    #     listener = [
    #       {
    #         timeout = 300; # 5min
    #         on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor.
    #         on-resume = "brightnessctl -r"; # monitor backlight restore.
    #       }

    #       {
    #         timeout = 360; # 6min
    #         on-timeout = "hyprlock"; # lock screen when timeout has passed
    #       }

    #       {
    #         timeout = 600; # 10min
    #         on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
    #         on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has fired.
    #       }
    #     ];
    #   };
    # };

    # services.hypridle.enable = true; # can be configured

    services.network-manager-applet.enable = true;

    wayland.windowManager.hyprland = {
      # Whether to enable Hyprland wayland compositor
      enable = true;
      package = inputs.hyprland.packages."${pkgs.system}".hyprland; # does only work with nixos-unstable

      # The hyprland package to use (simplifies use of plugins)
      # package = inputs.hyprland.packages.${pkgs.system}.hyprland;
      # Whether to enable XWayland
      xwayland.enable = true;

      # Optional
      # Whether to enable hyprland-session.target on hyprland startup
      systemd.enable = true;
      # Make PATH available to systemd services
      systemd.variables = [ "--all" ];

      plugins = [
        inputs.hyprland-plugins.packages.${pkgs.system}.hyprbars # does only work with nixos-unstable
        # hyprlandPlugins.hyprbars
      ];

      settings = {
        "$mod" = "SUPER";

        # Monitors
        monitor = ",preferred,auto,auto";

        # Autostart
        exec-once = [ "firefox" ];

        # Look and Feel
        general = {
          gaps_in = 5;
          gaps_out = 5;

          layout = "dwindle";

          "col.active_border" = "0xff${palette.base0C} 0xff${palette.base0D} 270deg";
          "col.inactive_border" = "0xff${palette.base00}";
        };

        decoration = {
          # power saving
          blur.enabled = false;
          # power saving
          drop_shadow = false;
        };

        # Dwindle layout
        dwindle = {
          pseudotile = true; # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
          preserve_split = true; # You probably want this
          no_gaps_when_only = 2; # with border
        };

        # Master layout
        master = {
          new_status = "slave";
          no_gaps_when_only = 2; # with border
          mfact = 0.5; # Do not make master bigger
        };

        misc = {
          # disable auto polling for config file changes
          disable_autoreload = true;

          force_default_wallpaper = 0;

          # we do, in fact, want direct scanout
          # no_direct_scanout = false;
          vfr = true; # power saving
        };

        # Input
        input = {
          kb_layout = "de";
          natural_scroll = false;
          follow_mouse = 1;
        };

        # Window rules
        windowrulev2 = [
          "suppressevent maximize, class:.*"
          "workspace 1, class:firefox"
          "workspace 9, class:nheko"
          "workspace 9, class:org.telegram.desktop"
          "workspace 10, class:thunderbird"
          "float, class:qalculate-gtk"
          "tile, class:MATLAB, title:MATLAB"
        ];

        # Workspace rules
        workspace = [
          "1, monitor:HDMI-A-1"
          "2, monitor:HDMI-A-1"
          "3, monitor:HDMI-A-1"
          "4, monitor:HDMI-A-1"
          "5, monitor:HDMI-A-1"
          "6, monitor:eDP-1"
          "7, monitor:eDP-1"
          "8, monitor:eDP-1"
          "9, monitor:eDP-1"
          "10, monitor:eDP-1"
        ];

        # Mouse binds
        bindm = [
          "$mod, mouse:272, movewindow" # leftclick
          "$mod, mouse:273, resizewindow" # rightclick
        ];

        # binds
        bind = [
          # compositor commands
          "$mod, Space, focuswindow, floating"
          "$mod SHIFT, Space, togglefloating,"
          "$mod, F, fullscreen,"
          "$mod, X, killactive,"

          "$mod, O, togglesplit," # dwindle

          # opening applications
          "$mod, D, exec, wofi --show drun,run"
          "$mod, E, exec, pcmanfm"
          "$mod, Return, exec, kitty"
          "$mod, B, exec, firefox"
          "$mod, C, exec, qalculate-gtk"

          # other commands
          "$mod SHIFT, E, exec, wlogout -p layer-shell"
          "$mod, Escape, exec, wlogout -p layer-shell"
          "$mod, TAB, exec, hyprlock"
          "$mod SHIFT, R, exec, hyprctl reload"
          ", Print, exec, hyprshot-gui"

          # "$mod SHIFT, E, exec, pkill Hyprland"
          # "$mod, G, togglegroup,"
          # "$mod SHIFT, N, changegroupactive, f"
          # "$mod SHIFT, P, changegroupactive, b"
          # "$mod ALT, ,resizeactive,"

          # media keys
          ", XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"
          ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
          ", XF86AudioPlay, exec, playerctl play-pause"
          ", XF86AudioPause, exec, playerctl pause"
          ", XF86AudioStop, exec, playerctl stop"
          ", XF86AudioNext, exec, playerctl next"
          ", XF86AudioPrev, exec, playerctl previous"
          ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
          ", XF86MonBrightnessUp, exec, brightnessctl --class backlight set 5%+"
          ", XF86MonBrightnessDown, exec, brightnessctl --class backlight set 5%-"

          # move focus
          "$mod, left, movefocus, l"
          "$mod, H, movefocus, l"
          "$mod, right, movefocus, r"
          "$mod, L, movefocus, r"
          "$mod, up, movefocus, u"
          "$mod, K, movefocus, u"
          "$mod, down, movefocus, d"
          "$mod, J, movefocus, d"

          # move window
          "$mod SHIFT, left, movewindow, l"
          "$mod SHIFT, H, movewindow, l"
          "$mod SHIFT, right, movewindow, r"
          "$mod SHIFT, L, movewindow, r"
          "$mod SHIFT, up, movewindow, u"
          "$mod SHIFT, K, movewindow, u"
          "$mod SHIFT, down, movewindow, d"
          "$mod SHIFT, J, movewindow, d"

          # Switch workspaces with mainMod + [0-9]
          "$mod, 1, workspace, 1"
          "$mod, 2, workspace, 2"
          "$mod, 3, workspace, 3"
          "$mod, 4, workspace, 4"
          "$mod, 5, workspace, 5"
          "$mod, 6, workspace, 6"
          "$mod, 7, workspace, 7"
          "$mod, 8, workspace, 8"
          "$mod, 9, workspace, 9"
          "$mod, 0, workspace, 10"

          # Move active window to a workspace with mainMod + SHIFT + [0-9]
          "$mod SHIFT, 1, movetoworkspace, 1"
          "$mod SHIFT, 2, movetoworkspace, 2"
          "$mod SHIFT, 3, movetoworkspace, 3"
          "$mod SHIFT, 4, movetoworkspace, 4"
          "$mod SHIFT, 5, movetoworkspace, 5"
          "$mod SHIFT, 6, movetoworkspace, 6"
          "$mod SHIFT, 7, movetoworkspace, 7"
          "$mod SHIFT, 8, movetoworkspace, 8"
          "$mod SHIFT, 9, movetoworkspace, 9"
          "$mod SHIFT, 0, movetoworkspace, 10"

          # Move active window to a workspace without following with mainMod + CTRL + [0-9]
          "$mod CTRL, 1, movetoworkspacesilent, 1"
          "$mod CTRL, 2, movetoworkspacesilent, 2"
          "$mod CTRL, 3, movetoworkspacesilent, 3"
          "$mod CTRL, 4, movetoworkspacesilent, 4"
          "$mod CTRL, 5, movetoworkspacesilent, 5"
          "$mod CTRL, 6, movetoworkspacesilent, 6"
          "$mod CTRL, 7, movetoworkspacesilent, 7"
          "$mod CTRL, 8, movetoworkspacesilent, 8"
          "$mod CTRL, 9, movetoworkspacesilent, 9"
          "$mod CTRL, 0, movetoworkspacesilent, 10"
        ];

        plugin = {
          hyprbars = {
            bar_text_size = 10;
            bar_height = 16;
            bar_text_font = "Ubuntu Nerd Font";
            bar_precedence_over_border = true;
            bar_color = "rgb(${palette.base01})";

            hyprbars-button = [ "rgb(${palette.base03}), 14, 󰖭, hyprctl dispatch killactive" ];
          };
        };
      };
    };
  };
}
