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

with lib;
let
  cfg = config.modules.desktop.hyprland;
  hyprpkgs = inputs.hyprland.packages.${system};
in {
  options.modules.desktop.hyprland = {
    enable = mkEnableOption "Enable hyprland, a dynamic tiling wayland compositor based on wlroots that doesn't sacrifice on its looks";
    package = mkOption {
      type = types.package;
      default = hyprpkgs.hyprland;
      example = "pkgs.hyprland";
    };
    portalPackage = mkOption {
      type = types.package;
      default = hyprpkgs.xdg-desktop-portal-hyprland;
      example = "pkgs.xdg-desktop-portal-hyprland";
    };
  };

  config = mkIf cfg.enable {
    services.displayManager.sessionPackages = [ cfg.package ];
    xdg.portal = {
      enable = true;
      extraPortals = [ pkgs.xdg-desktop-portal-gtk cfg.portalPackage ];
      config = {
        common = {
          default = [ "hyprland" "gtk" ];
        };
      };
    };
    hm.wayland.windowManager.hyprland = {
      enable = true;
      xwayland.enable = true;
      package = cfg.package;

      systemd.variables = [ "--all" ];

      settings = {
        source = [];

        "$mod" = "SUPER";
        bindm = [ # "bind mouse"
          # move/resize windows with mod + lmb/rmb and dragging
          "$mod, mouse:272, movewindow"
          "$mod, mouse:273, resizewindow"
        ];
        bindel = [ # "bind held & locked"
          ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 10%+"
          ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 10%-"

          ", XF86MonBrightnessUp, exec, ${lib.getExe pkgs.brightnessctl} -c backlight s +5%"
          ", XF86MonBrightnessDown, exec, ${lib.getExe pkgs.brightnessctl} -c backlight s 5%-"
        ];
        bindl = [ # "bind locked"
          ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
          ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"

          ", XF86AudioPlay, exec, ${lib.getExe pkgs.playerctl} play-pause"
          ", XF86AudioStop, exec, ${lib.getExe pkgs.playerctl} stop"
          ", XF86AudioPrev, exec, ${lib.getExe pkgs.playerctl} previous"
          ", XF86AudioNext, exec, ${lib.getExe pkgs.playerctl} next"
        ];
        bindr = [ # "bind released"
          "SUPER, Super_L, exec, ${lib.getExe pkgs.nwg-drawer}"
        ];
        bind = [
          "$mod, R, exec, ${lib.getExe pkgs.rofi-wayland} -show run"
          ", print, exec, ${lib.getExe pkgs.grimblast} --freeze copy area"
          "$mod, T, exec, ${lib.getExe pkgs.wezterm}"

          "$mod, Q, killactive, "
          "$mod, V, togglefloating, "
          "$mod, P, pseudo, " # dwindle
          "$mod, J, togglesplit, " # dwindle

          # move focus with mod + arrow keys
          "$mod, left, movefocus, l"
          "$mod, right, movefocus, r"
          "$mod, up, movefocus, u"
          "$mod, down, movefocus, d"

          # scroll through workspaces with mod + scroll
          "$mod, mouse_down, workspace, e+1"
          "$mod, mouse_up, workspace, e-1"
        ] ++ (
          # 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)
        );

        input = {
          kb_layout = "us";

          follow_mouse = 1;

          sensitivity = 0; # -1.0 - 1.0, 0 means no modification
        };

        monitor= [
          "DVI-D-1, 1920x1080@60, 0x0,    1"
          "DP-2,    1920x1080@60, 1920x0, 1"
        ];  

        exec-once = [ "${lib.getExe pkgs.networkmanagerapplet}" ];

        env = [
          "XCURSOR_THEME,${config.modules.desktop.themes.cursorTheme.name}"
          "XCURSOR_SIZE,24"
        ];

        general = {
          gaps_in = 6;
          gaps_out = 6;
          border_size = 2;
          no_border_on_floating = true;

          layout = "dwindle";

          resize_on_border = true;	
        };

        windowrulev2 = [
          # common popups
          "float, class:org.gnome.FileRoller"
          "center, class:org.gnome.FileRoller"
          "size 1100 730, class:org.gnome.FileRoller"
          "float, class:org.gnome.Loupe"
          "center, class:org.gnome.Loupe"
          "size 1100 730, class:org.gnome.Loupe"
          "float, initialTitle:^Open Folder$"
          "center, initialTitle:^Open Folder$"
          "size 1100 730, initialTitle:^Open Folder$"
          "float, initialTitle:^Open File$"
          "center, initialTitle:^Open File$"
          "size 1100 730, initialTitle:^Open File$"
          "float, initialTitle:^Open Files$"
          "center, initialTitle:^Open Files$"
          "size 1100 730, initialTitle:^Open Files$"
          "float, initialTitle:^Save As$"
          "center, initialTitle:^Save As$"
          "size 1100 730, initialTitle:^Save As$"
          "float, initialTitle:^Select a file to open$"
          "center, initialTitle:^Select a file to open$"
          "size 1100 730, initialTitle:^Select a file to open$"

          "float, class:\.exe$"

          # fix focus
          "stayfocused, class:^pinentry-"
          "stayfocused, class:^polkit-"
          "stayfocused, class:^rofi-"

          # workspace moving
          "workspace 1, class:^firefox"
          "workspace 2, class:code-url-handler"
          "workspace 4, class:vesktop"
        ];

        layerrule = [
          "animation slide, notifications"
          "animation slide, waybar"
        ];

        blurls = [
          "gtk-layer-shell" # nwg-drawer
          "waybar"
        ];

        decoration = {
          rounding = 10;

          blur = {
            enabled = true;
            size = 4;
            passes = 2;
            #popups = true;
          };

          drop_shadow = false;
          #shadow_range = 4;
          #shadow_render_power = 3;
        };

        animations = {
          enabled = true;

          bezier = [
            "outCubic, 0.33, 1, 0.68, 1"
            "outExpo, 0.16, 1, 0.3, 1"
          ];

          animation = [
            "windows, 1, 5, outExpo, popin"
            "windowsOut, 1, 5, outCubic, popin 80%"
            "border, 1, 2, outExpo"
            "fade, 1, 3, outCubic"
            "workspaces, 1, 6, outExpo"
          ];
        };

        dwindle = {
          pseudotile = "yes"; # master swtich for pseudotiling. enabling is mod + P in the keybinds section
          preserve_split = "yes";
        };

        master = {
          new_is_master = true;
        };

        misc = {
          force_default_wallpaper = 0;
          disable_splash_rendering = true;
          disable_hyprland_logo = true;
        };
      };
      
      extraConfig = ''
        general {
          col.active_border=$pink
          col.inactive_border=$surface0
        }
        decoration {
          col.shadow=$surface0
          col.shadow_inactive=$surface0
        }
        misc {
          background_color=$crust
        }
      '';
    };
  };
}
