{
  # 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;
in
{
  options.modules.hyprland = {
    enable = lib.mkOption { default = false; };
  };

  # imports = [ (ib.mkIf inputs.hyprland.homeManagerModules.default) ];

  config = lib.mkIf cfg.enable {

    services.dunst.enable = true;

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

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

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

        # 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, SPC, 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, hyprlock"
          "$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,"

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