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

let
  cfg = config.sydnix.users.crumb.niri;
in {
  options.sydnix.users.crumb.niri = {
    enable = lib.mkEnableOption "Niri, à la crumb";
    wallpaper = lib.mkOption {
      type = lib.types.nullOr lib.types.path;
      default = config.stylix.image;
    };
    # xwayland-satellite implements rootless Xwayland in a separate application,
    # without the host compositor's involvement. It makes X11 windows appear as
    # normal windows, just like a native Xwayland integration. While it is still
    # somewhat experimental, it handles a lot of applications correctly, like
    # Steam, games and Discord.
    xwayland-satellite.enable =
      lib.mkEnableOption "xwayland-satellite starting with Niri"
        // { default = true; };
  };

  config = lib.mkIf cfg.enable {
    stylix.targets.swaylock.enable = true;

    services.polkit-gnome.enable = true;

    systemd.user.services.xwayland-satellite =
      lib.mkIf cfg.xwayland-satellite.enable {
        Service.ExecStart =
          ["${pkgs.xwayland-satellite}/bin/xwayland-satellite"];
        Unit.After = ["niri.service"];
        Unit.PartOf = ["niri.service"];
      };

    programs.niri = {
      # Activates some Nixpkgs patches to help run Electron applications under
      # Wayland.
      settings = {
        environment."NIXOS_OZONE_WL" = "1";
        environment."DISPLAY" = ":0";

        spawn-at-startup =
          [{ command = [ "${pkgs.swaynotificationcenter}/bin/swaync" ]; }]
          ++ lib.optional
            (! builtins.isNull cfg.wallpaper)
            { command = [ "${pkgs.wbg}/bin/wbg" "${cfg.wallpaper}" ]; };
        input = {
          keyboard.xkb = {
            layout = "us";
            options = "ctrl:swapcaps,compose:menu";
          };
          mouse = {
            accel-speed = -0.5;
            accel-profile = "flat";
          };
          focus-follows-mouse.enable = true;
        };
        outputs."DP-1" = {
          mode.width = 2560;
          mode.height = 1440;
          mode.refresh = 143.912;
          scale = 1;
        };
        layout = {
          gaps = 8;
          # center-focused-column = "always";
          center-focused-column = "never";
          preset-column-widths = [ 
            { proportion = 1.0 / 3.0; }
            { proportion = 1.0 / 2.0; }
            { proportion = 2.0 / 3.0; }
          ];
          default-column-width.proportion = 0.5;
          # default-column-width.proportion = {};
          focus-ring = {
            enable = false;
            width = 2;
          };
          border = {
            enable = true;
            width = 2;
            # Override Niri's Stylix integration.  Default uses Crystal Blue; we
            # override it with Old White.
            active.color = config.lib.stylix.colors.withHashtag.base06;
          };
          shadow = {
            enable = true;
            softness = 30;
            spread = 5;
            offset.x = 5;
            offset.y = 5;
          };
          tab-indicator = {
            place-within-column = true;
            position = "top";
            # active.color = config.lib.stylix.colors.withHashtag.blue;
            inactive.color = config.lib.stylix.colors.withHashtag.base01;
            width = 8;
            corner-radius = 2.0;
            gaps-between-tabs = 10;
          };
        };
        prefer-no-csd = true;
        screenshot-path = "~/Pictures/Screenshots/%Y-%m-%d %H-%M-%S.png";
        cursor = {
          theme = "default";
          size = 24;
        };
        window-rules = [
          { # Set red borders to indicate that a window is being captured.
            matches = [
              { is-window-cast-target = true; }
            ];
            focus-ring = {
              enable = true;
              width = 2;
              active.color = "#f38ba8";
              inactive.color = "#7d0d2d";
            };
            border = {
              width = 2;
              inactive.color = "#7d0d2d";
              active.color = "#7d0d2d";
            };
            shadow = {
              color = "#7d0d2d70";
              softness = 30;
              spread = 10;
              offset.x = 0;
              offset.y = 0;
            };
            tab-indicator = {
              active.color = "#f38ba8";
              inactive.color = "#7d0d2d";
            };
          }
          { # Block private DMs from screencast...
            matches = [
              { title = "Element \\|"; }
              { title = "^Discord \\| @"; }
            ];
            excludes = [
              # ... except when explicitly targeting the window.
              { is-window-cast-target = true; }
            ];
            block-out-from = "screen-capture";
          }
          {
            # This regular expression is intentionally made as specific as
            # possible, since this is the default config, and we want no false
            # positives.  You can get away with just app-id="wezterm" if you
            # want.
            matches = [
              { app-id = "^org\\.wezfurlong\\.wezterm$"; }
            ];
            default-column-width = {};
          }
          {
            # Open the Firefox picture-in-picture player as floating by default.
            matches = [
              { app-id = "firefox$"; title = "^Picture-in-Picture$"; }
            ];
            open-floating = true;
          }
          { # Start terminals with low width.
            matches = [
              { app-id = "com\\.mitchellh\\.ghostty"; }
              { title = "^\\*eshell\\*"; }
            ];
            default-column-width.proportion = 1.0 / 3.0;
          }
          {
            # Enable rounded corners for all windows.
            geometry-corner-radius =
              let r = 8.0;
              in {
                bottom-left = r;
                top-left = r;
                bottom-right = r;
                top-right = r;
              };
            clip-to-geometry = true;
          }
        ];
        binds = {
          "Mod+Q".action.close-window = [];
          "Mod+Shift+Q".action.quit = [];
          "Mod+Ctrl+L".action.spawn = ["${pkgs.swaylock}/bin/swaylock"];
          "Mod+D".action.spawn = ["${pkgs.fuzzel}/bin/fuzzel"];
          "Mod+Shift+Slash".action.show-hotkey-overlay = [];

          # Powers off the monitors.  They will be powered back on upon any
          # keyboard/mouse input.
          "Mod+Shift+P".action.power-off-monitors = []; 

          "Mod+I".action.set-dynamic-cast-window = [];
          "Mod+Shift+I".action.set-dynamic-cast-monitor = [];
          "Mod+Ctrl+I".action.clear-dynamic-cast-target = [];

          "Mod+BracketLeft".action.consume-or-expel-window-left = [];
          "Mod+BracketRight".action.consume-or-expel-window-right = [];
          "Mod+Comma".action.consume-window-into-column = [];
          "Mod+Period".action.expel-window-from-column = [];

          "Mod+Minus".action.set-column-width = ["-10%"];
          "Mod+Equal".action.set-column-width = ["+10%"];

          "Mod+Shift+Minus".action.set-window-height = ["-10%"];
          "Mod+Shift+Equal".action.set-window-height = ["+10%"];

          "Mod+C".action.center-column = [];
          "Mod+M".action.maximize-column = [];
          "Mod+Shift+M".action.fullscreen-window = [];
          "Mod+Ctrl+M".action.toggle-windowed-fullscreen = [];

          "Mod+Shift+S".action.screenshot = [];
          "Print".action.screenshot-screen = [];
          "Mod+Print".action.screenshot-window = [];

          "Mod+X".action.spawn = [
            "emacsclient-or-emacs"
            "-ce"
            "(eshell t)"
          ];

          "Mod+Shift+F".action.toggle-window-floating = []; 
          "Mod+F".action.switch-focus-between-floating-and-tiling = [];
          "Mod+Shift+T".action.toggle-column-tabbed-display = []; 

          "Alt+Tab".action.focus-window-previous = [];

          "Mod+H".action.focus-column-left = [];
          "Mod+J".action.focus-window-down = [];
          "Mod+K".action.focus-window-up = [];
          "Mod+L".action.focus-column-right = [];

          "Mod+Shift+H".action.move-column-left = []; 
          "Mod+Shift+J".action.move-window-down = []; 
          "Mod+Shift+K".action.move-window-up = []; 
          "Mod+Shift+L".action.move-column-right = []; 
            
          "Mod+1".action.focus-workspace = [1];
          "Mod+2".action.focus-workspace = [2];
          "Mod+3".action.focus-workspace = [3];
          "Mod+4".action.focus-workspace = [4];
          "Mod+5".action.focus-workspace = [5];
          "Mod+6".action.focus-workspace = [6];
          "Mod+7".action.focus-workspace = [7];
          "Mod+8".action.focus-workspace = [8];
          "Mod+9".action.focus-workspace = [9];
          "Mod+Shift+1".action.move-column-to-workspace = [1];
          "Mod+Shift+2".action.move-column-to-workspace = [2];
          "Mod+Shift+3".action.move-column-to-workspace = [3];
          "Mod+Shift+4".action.move-column-to-workspace = [4];
          "Mod+Shift+5".action.move-column-to-workspace = [5];
          "Mod+Shift+6".action.move-column-to-workspace = [6];
          "Mod+Shift+7".action.move-column-to-workspace = [7];
          "Mod+Shift+8".action.move-column-to-workspace = [8];
          "Mod+Shift+9".action.move-column-to-workspace = [9];

          "Mod+Shift+R".action.switch-preset-window-height = [];
          "Mod+Ctrl+R".action.reset-window-height = [];

          "XF86AudioRaiseVolume".action.spawn =
            ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"];
          "XF86AudioLowerVolume".action.spawn =
            ["wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"];
        };
      };
    };
  };
}

