{ lib, config, pkgs, inputs, ... }:

let
  cfg = config.snowhawk.hyprland;
in
{
  options.snowhawk.hyprland = {
    enable = lib.mkEnableOption "hyprland";

    split-monitor-workspaces = lib.mkEnableOption "split-monitor-workspaces";

    nvidia = lib.mkEnableOption "hyprland nvidia tweaks";
  };

  config = lib.mkIf cfg.enable (lib.mkMerge [
    # Core Module
    {
      services.graphical-desktop.enable = lib.mkDefault true;

      services.displayManager = {
        enable = true;
        sddm = {
          enable = lib.mkDefault true;
          wayland.enable = lib.mkDefault true;
        };
      };

      security = {
        polkit.enable = lib.mkDefault true;
      };

      programs = {
        dconf.enable = lib.mkDefault true;
        xwayland.enable = lib.mkDefault true;
      };

      # xdg.portal = {
      #   enable = true;
      #   extraPortals = [
      #     pkgs.xdg-desktop-portal
      #     pkgs.xdg-desktop-portal-gtk
      #   ];
      # };

      programs.waybar.enable = true;

      programs.hyprland = {
        enable = true;
        withUWSM = true;
        xwayland.enable = true;
        package = inputs.hyprland.packages.${pkgs.system}.hyprland;
        portalPackage = inputs.hyprland.packages.${pkgs.system}.xdg-desktop-portal-hyprland;
      };

      services.hypridle.enable = true;
      systemd.user.services.hypridle.path = [ pkgs.brightnessctl ];

      # programs.hyprlock.enable = true;

      # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
      # xdg.portal.config.hyprland.default = lib.mkDefault [ "wlr" "gtk" ];

      services.xserver.desktopManager.runXdgAutostartIfNone = lib.mkDefault true;

      environment.variables = {
        QT_QPA_PLATFORM = "wayland;xcb";
        MOZ_ENABLE_WAYLAND = 1;
        SDL_VIDEODRIVEWR = "wayland,x11";
        _JAVA_AWT_WM_NONREPARENTING = 1;
      };

      environment.systemPackages = [
        inputs.rose-pine-hyprcursor.packages.${pkgs.system}.default
      ];
    }

    # hyprland configuration
    {
      home-manager.sharedModules = [{
        wayland.windowManager.hyprland = {
          enable = true;
          # extraConfig = builtins.readFile ../home/hypr/hyprland.conf;
          settings = {
            source = [ "${../home/hypr/rose-pine.conf}" ];

            env = [
              "XCURSOR_SIZE,24"
              "HYPRCURSOR_SIZE,24"
              "HYPRCURSOR_THEME,rose-pine-hyprcursor"
              "MOZ_ENABLE_WAYLAND,1"
            ];

            # TODO: Direct links
            "$terminal" = "kitty";
            "$fileManager" = "pcmanfm";
            "$menu" = "wofi --show drun";

            "$mainMod" = "SUPER";

            general = {
              gaps_in = 5;
              gaps_out = 5;
              border_size = 1;

              "col.active_border" = "$foam $pine 45deg";
              "col.inactive_border" = "$muted";

              resize_on_border = true;

              allow_tearing = false;

              layout = "dwindle";
            };

            # https://wiki.hyprland.org/Configuring/Variables/#decoration
            decoration = {
              rounding = 5;
              rounding_power = 2;

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

            # https://wiki.hyprland.org/Configuring/Variables/#animations
            animations = {
              enabled = "no,";

              bezier = [ "easeOutQuint,0.23,1,0.32,1" "easeInOutCubic,0.65,0.05,0.36,1" "linear,0,0,1,1" "almostLinear,0.5,0.5,0.75,1.0" "quick,0.15,0,0.1,1" ];

              # I need to tinker with these some more for llynx
              # animation = global, 1, 10, default
              # animation = border, 1, 5.39, easeOutQuint
              # animation = windows, 1, 4.79, easeOutQuint
              # animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
              # animation = windowsOut, 1, 1.49, linear, popin 87%
              # animation = windowsMove, 1, 4.79, easeOutQuint
              # animation = fadeIn, 1, 1.73, almostLinear
              # animation = fadeOut, 1, 1.46, almostLinear
              # animation = fade, 1, 3.03, quick
              # animation = layers, 1, 3.81, easeOutQuint
              # animation = layersIn, 1, 4, easeOutQuint, fade
              # animation = layersOut, 1, 1.5, linear, fade
              # animation = fadeLayersIn, 1, 1.79, almostLinear
              # animation = fadeLayersOut, 1, 1.39, almostLinear
              # animation = workspaces, 1, 1.94, almostLinear, fade
              # animation = workspacesIn, 1, 1.21, almostLinear, fade
              # animation = workspacesOut, 1, 1.94, almostLinear, fade
            };

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

            # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
            master = {
              new_status = "master";
            };

            # https://wiki.hyprland.org/Configuring/Variables/#misc
            misc = {
              force_default_wallpaper = -1;
              disable_hyprland_logo = false;
            };

            cursor = {
              inactive_timeout = 5;
            };

            # https://wiki.hyprland.org/Configuring/Variables/#input
            input = {
              kb_layout = "us";
              kb_variant = "";
              kb_model = "";
              kb_options = "";
              kb_rules = "";

              follow_mouse = 1;
              sensitivity = 0;

              numlock_by_default = true;

              touchpad = {
                natural_scroll = true;
                clickfinger_behavior = true;
              };
            };

            # https://wiki.hyprland.org/Configuring/Variables/#gestures
            gestures = {
              workspace_swipe = true;
              workspace_swipe_distance = 50;
            };

            plugin = {
              split-monitor-workspaces = lib.mkIf cfg.split-monitor-workspaces {
                count = 10;
                keep_focused = 10;
                enable_notifications = 0;
                enable_persistent_workspaces = 0;
              };
            };

            windowrulev2 = [
              # Ignore maximize requests from apps. You'll probably like this.
              "suppressevent maximize, class:.*"
              # Fix some dragging issues with XWayland
              "nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0"
            ];

            bindm = [
              # Move/resize windows with mainMod + LMB/RMB and dragging
              "$mainMod, mouse:272, movewindow"
              "$mainMod, mouse:273, resizewindow"
            ];

            bindel = [
              # Laptop multimedia keys for volume and LCD brightness
              ",XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"
              ",XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
              ",XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
              ",XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
              ",XF86MonBrightnessUp, exec, brightnessctl s 10%+"
              ",XF86MonBrightnessDown, exec, brightnessctl s 10%-"
            ];

            bindl = [
              # Requires playerctl
              ", XF86AudioNext, exec, playerctl next"
              ", XF86AudioPause, exec, playerctl play-pause"
              ", XF86AudioPlay, exec, playerctl play-pause"
              ", XF86AudioPrev, exec, playerctl previous"
            ];

            bind = [
              "$mainMod, Q, exec, $terminal"
              "$mainMod, C, killactive,"
              "$mainMod CTRL SHIFT, M, exit,"
              "$mainMod, E, exec, $fileManager"
              "$mainMod, V, togglefloating,"
              "$mainMod, R, exec, $menu"
              "$mainMod, P, pseudo, # dwindle"
              "$mainMod, J, togglesplit, # dwindle"

              "$mainMod SHIFT, minus, exec, bash -c \"XDG_CURRENT_DESKTOP=sway flameshot gui\""
              "$mainMod, n, exec, swaync-client -t"

              # moving focus
              "$mainMod, left, movefocus, l"
              "$mainMod, right, movefocus, r"
              "$mainMod, up, movefocus, u"
              "$mainMod, down, movefocus, d"

              # scratchpad
              "$mainMod, S, togglespecialworkspace, magic"
              "$mainMod SHIFT, S, movetoworkspace, special:magic"
            ] ++ (
              # workspaces
              # binds $mod + [shift +] {1..9} to [move to] workspace {1..9}
              builtins.concatLists (builtins.genList
                (i:
                  let ws = i + 1;
                  in [
                    "$mainMod, code:1${toString i}, ${lib.optionalString cfg.split-monitor-workspaces "split-"}workspace, ${toString ws}"
                    "$mainMod SHIFT, code:1${toString i}, ${lib.optionalString cfg.split-monitor-workspaces "split-"}movetoworkspace, ${toString ws}"
                  ]
                )
                9)
            );
          };

          package = null;
          portalPackage = null;
        };
      }];
    }

    # split-monitor-workspaces
    (lib.mkIf cfg.split-monitor-workspaces {
      home-manager.sharedModules = [{
        wayland.windowManager.hyprland = {
          settings.bind = [
            "$mainMod SHIFT, comma, split-changemonitor, -1"
            "$mainMod SHIFT, period, split-changemonitor, +1"
          ];
          plugins = [
            inputs.split-monitor-workspaces.packages.${pkgs.system}.split-monitor-workspaces
          ];
        };
      }];
    })

    # useful desktop stuff
    {
      environment.systemPackages = with pkgs; [
        # Screenshotting
        grim
        slurp
        satty

        # Hardware Control
        brightnessctl

        # Desktop
        wofi
        kitty
        pipewire-controller

        # Wayland Utilities
        wdisplays
        xorg.xlsclients
        wl-clipboard
      ];
    }

    # SDDM Theme
    (
      let sddmPkg = (pkgs.sddm-astronaut.override { embeddedTheme = "purple_leaves"; });
      in {
        services.displayManager = {
          enable = lib.mkDefault true;
          sddm = {
            enable = lib.mkDefault true;
            wayland.enable = lib.mkDefault true;
            theme = "sddm-astronaut-theme";
            package = pkgs.kdePackages.sddm;
            extraPackages = with pkgs; [
              sddmPkg
              kdePackages.qtsvg
              kdePackages.qtvirtualkeyboard
              kdePackages.qtmultimedia
            ];
          };
        };

        environment.systemPackages = [ sddmPkg ];
      }
    )

    # Anyrun
    (lib.mkIf false {
      home-manager.sharedModules = [{
        imports = [
          inputs.anyrun.homeManagerModules.default
        ];

        programs.anyrun = {
          enable = true;
          config = {
            x = { fraction = 0.5; };
            y = { fraction = 0.3; };
            width = { fraction = 0.3; };
            layer = "overlay";
            showResultsImmediately = true;
            hidePluginInfo = true;
            plugins = [
              inputs.anyrun.packages.${pkgs.system}.applications
            ];
          };

          extraCss = /* css */ ''
            window {
              background: transparent;
            }
          '';
        };
      }];
    })

    ({
      home-manager.sharedModules = [{
        services.swaync = {
          enable = true;
          style = builtins.readFile "${inputs.rose-pine-swaync}/theme/rose-pine.css";
          settings = {
            positionX = "right";
            positionY = "tops";
            layer = "overlay";
            control-center-layer = "tops";
            cssPriority = "application";
            control-center-margin-top = 0;
            control-center-margin-bottom = 0;
            control-center-margin-right = 0;
            control-center-margin-left = 0;
            notification-2fa-action = true;
            notification-inline-replies = false;
            notification-icon-size = 64;
            notification-body-image-height = 100;
            notification-body-image-width = 200;
            timeout = 10;
            timeout-low = 5;
            timeout-critical = 0;
            fit-to-screen = true;
            control-center-width = 500;
            control-center-height = 600;
            notification-window-width = 500;
            keyboard-shortcuts = true;
            image-visibility = "when-available";
            transition-time = 200;
            hide-on-clear = false;
            hide-on-action = true;
            script-fail-notify = false;
          };
        };
      }];
    })

    {
      home-manager.sharedModules = [{
        services.playerctld.enable = true;
        systemd.user.services.playerctld = {
          Unit.PartOf = lib.mkForce [ "graphical-session.target" ];
          Install.WantedBy = lib.mkForce [ "graphical-session.target" ];
        };

        home.packages = with pkgs; [
          playerctl
        ];
      }];
    }

    (lib.mkIf cfg.nvidia {
      environment.variables = {
        LIBVA_DRIVER_NAME = "nvidia";
        __GLX_VENDOR_LIBRARY_NAME = "nvidia";
      };
    })
  ]);
}