{
  # 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 = [ (ib.mkIf inputs.hyprland.homeManagerModules.default) ];

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

    # services.dunst.enable = true;

    home.packages = with pkgs; [
      # wofi
      xfce.thunar
      # hyprpicker # TODO
      # hyprcursor # TODO
      brightnessctl
      grimblast
    ];

    xdg.configFile = {
      "hypr/launch".source = ./launch;
      # "hypr/hyprland.conf".source = ./hyprland.conf;
      "hypr/colors.conf" = {
        text = ''
          general {
            col.active_border = 0xff${palette.base0C} 0xff${palette.base0D} 270deg
            col.inactive_border = 0xff${palette.base00}
          }
        '';
      };
    };

    # services.copyq.enable = true;

    # programs.hyprlock.enable = true;
    # programs.hyprlock.settings = {
    #   general = {
    #     disable_loading_bar = true;
    #     hide_cursor = true;
    #     ignore_empty_input = true;
    #   };

    #   background = [
    #     {
    #       path = "screenshot";
    #       blur_passes = 3;
    #       blur_size = 8;
    #     }
    #   ];

    #   input-field = [
    #     {
    #       size = "200, 50";
    #       position = "0, -80";
    #       monitor = "";
    #       dots_center = true;
    #       fade_on_empty = false;
    #       font_color = "rgb(202, 211, 245)";
    #       inner_color = "rgb(91, 96, 120)";
    #       outer_color = "rgb(24, 25, 38)";
    #       outline_thickness = 5;
    #       placeholder_text = "Password...";
    #       shadow_passes = 2;
    #     }
    #   ];
    # };

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

    # programs.waybar = {
    #   enable = true;
    #   systemd.enable = true;
    #   style = builtins.readFile ./style.css;
    #   settings.mainBar = builtins.fromJSON (builtins.readFile ./waybar-config.json);
    #   # settings = {
    #   #   mainBar = {
    #   #     layer = "top";
    #   #     position = "bottom";
    #   #     height = 30;
    #   #     output = [
    #   #       "eDP-1"
    #   #       "HDMI-A-1"
    #   #     ];
    #   #     modules-left = [
    #   #       "hyprland/workspaces"
    #   #       "hyprland/submap"
    #   #     ];
    #   #     modules-center = [ "hyprland/window" ];
    #   #     modules-right = [
    #   #       # "mpd"
    #   #       # "idle_inhibitor"
    #   #       "pulseaudio"
    #   #       # "network"
    #   #       "power-profiles-daemon"
    #   #       "cpu"
    #   #       "memory"
    #   #       # "temperature"
    #   #       # "backlight"
    #   #       # "keyboard-state"
    #   #       "battery"
    #   #       # "battery#bat2"
    #   #       "clock"
    #   #       "tray"
    #   #     ];

    #   #     # "sway/workspaces" = {
    #   #     #   disable-scroll = true;
    #   #     #   all-outputs = true;
    #   #     # };
    #   #   };
    #   # };
    # };

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

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

    wayland.windowManager.hyprland = {
      # Whether to enable Hyprland wayland compositor
      enable = true;
      # 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;

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

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

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

        # Environment Variables
        ###
        env = "XDG_CURRENT_DESKTOP,Hyprland";
        # env = "XCURSOR_SIZE,24";
        # env = "HYPRCURSOR_SIZE,24";

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

          # 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 = "master";
        };

        decoration = {
          # power saving
          # blur = {
          #   enable = 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
        };

        # Master layout
        master = {
          new_is_master = false;
          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";
        };

        # 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"
        ];

        # 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, togglefloating,"
          "$mod, F, fullscreen,"
          "$mod, X, killactive,"

          "$mod, R, togglesplit," # dwindle
          "$mod, P, pseudo," # dwindle

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

          # other commands
          "$mod, Escape, exec, wlogout -p layer-shell"
          "$mod, TAB, exec, gtklock"
          "$mod SHIFT, R, exec, hyprctl reload"
          ", Print, exec, grimblast --notify copysave area"

          # "$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"
        ];
      };
    };
  };
}