{ inputs, lib, config, pkgs, ... }:
# let
#   unstable = import inputs.nixpkgs-unstable { system = "x86_64-linux"; config.allowUnfree = true; };
# in
{
  options.hyprhome = {
    enable = lib.mkEnableOption "Enable hyprland home config";
    homePackages = lib.mkOption {
        default = [];
        description = "Add any additional packages desired. Merged with hyprland defaults.";
    };
  };

  config = lib.mkIf config.hyprhome.enable {
    wayland.windowManager.hyprland.enable = true; # enable Hyprland
    # wayland.windowManager.hyprland.package = null; # enable Hyprland
    # wayland.windowManager.hyprland.portalPackage = null; # enable Hyprland
    wayland.windowManager.hyprland.settings = {
      "$mod" = "Super";
      "$terminal" = "ghostty";
      "$fileManager" = "nautilus";
      "$menu" = "nwg-drawer";
      # Autostart
      exec-once =
        [
          ###Start dbus ###
          # Starting it early may help with app launch times
          "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP"
          "systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP"
          # Utils
          "blueman-applet"
          "hypridle"
          "lxqt-policykit-agent"
          "nm-applet --indicator"
          "sleep 5 && syncthingtray --wait" # sleep added otherwise it would error...
          "swaybg -i ~/.config/hypr/va_background.png"
          "swaylock -C ~/.config/swaylock/boot-config"
          "swaync"
          "waybar"
          # GUI Applications
          "firefox --new-tab https://vasion.okta.com --new-tab https://github.com/PrinterLogic --new-tab https://claude.ai"
          "flatpak run org.signal.Signal"
          "flatpak run com.slack.Slack"
          "ghostty"
          "keepassxc"
          # set gsettings
          # "dconf write /org/gnome/desktop/interface/cursor-theme \"'catppuccin-macchiato-lavender-cursors'\""
          # "dconf write /org/gnome/desktop/interface/cursor-size 24"
          # "dconf write /org/gnome/desktop/interface/icon-theme \"'Papirus-Dark'\""
          # "dconf write /org/gnome/desktop/interface/gtk-theme \"'catppuccin-macchiato-lavender-compact+rimless'\""
          # "hyprctl setcursor catppuccin-macchiato-lavender-cursors 24"
        ];
      input = {
        repeat_rate = 50;
        repeat_delay = 350;
        touchpad = {
          natural_scroll = true;
        };
        follow_mouse = 0; # cursor movement will change focus
        float_switch_override_focus = 0;
      };
      bezier = [
        "easeout, 0, 0.55, 0.45, 1"
      ];
      animation = [
        "workspaces, 1, 1, easeout"
      ];
      gesture = [
        "3, horizontal, workspace"
      ];
      general = {
        gaps_in = 3;
        gaps_out = 5;
        border_size = 3;
        "col.active_border" = "rgba(7e5fddff) rgba(ff5100ff) 60deg";
      };
      decoration = {
        rounding = 12;
        inactive_opacity = 0.9;
        dim_inactive = true;
        dim_strength = 0.1;
        blur = {
          enabled = true;
          passes = 1;
          size = 10;
        };
        shadow.enabled = false;
      };
      bind =
        [
          "$mod, Q, killactive"
          "$mod Shift, Q, exit"
          "$mod, W, exec, firefox"
          "$mod, D, exec, $menu"
          "$mod, T, exec, $fileManager"
          "$mod, code:36, exec, $terminal" # Enter code
          "$mod, Space, togglefloating"
          # Toggle floating / tiled focus
          "$mod Shift, Space, exec, hyprctl dispatch focuswindow $(if [[ $(hyprctl activewindow -j | jq .\"floating\") == \"true\" ]]; then echo \"tiled\"; else echo \"floating\"; fi;)"
          "$mod, F, fullscreen, 0"
          "$mod, Tab, cyclenext"
          "$mod Shift, Tab, swapnext"
          "$mod, left, movefocus, l"
          "$mod, right, movefocus, r"
          "$mod, up, movefocus, u"
          "$mod, down, movefocus, d"
          "$mod Shift, left, movewindow, l"
          "$mod Shift, right, movewindow, r"
          "$mod Shift, up, movewindow, u"
          "$mod Shift, down, movewindow, d"
          # Colemak-DH binds
          "$mod, N, movefocus, l"
          "$mod, O, movefocus, r"
          "$mod, E, movefocus, u"
          "$mod, I, movefocus, d"
          "$mod Shift, N, movewindow, l"
          "$mod Shift, O, movewindow, r"
          "$mod Shift, E, movewindow, u"
          "$mod Shift, I, movewindow, d"
          # Disabled laptop keyboard
          "$mod SHIFT, K, exec, hyprctl keyword 'device[at-translated-set-2-keyboard]:enabled' 'false' && notify-send 'Laptop keyboard disabled' -i nix-snowflake"
          # Reload config
          "$mod SHIFT, R, exec, hyprctl reload && notify-send 'Hypr Config Reloaded' -i nix-snowflake"
          # Scratch pad workspace
          "$mod, minus, togglespecialworkspace, scratch"
          "$mod SHIFT, minus, movetoworkspacesilent, special:scratch"
          # Music workspace
          "$mod, M, togglespecialworkspace, music"
          # "$mod SHIFT, M, movetoworkspacesilent, special:music"
          "$mod Shift, M, exec, ~/.config/hypr/scripts/music_setup.sh"
          # "$mod Control_R, M, exec, ~/.config/hypr/scripts/music_setup.sh"
          # Screenshots
          "$mod, P, exec, ~/.config/hypr/scripts/screenshot.sh clipboard"
          "$mod SHIFT, P, exec, ~/.config/hypr/scripts/screenshot.sh"
          # Color picker
          "$mod, C, exec, color=$(hyprpicker) && echo $color | wl-copy && notify-send \"Copied $color to clipboard\""
          # Toggle notification drawer
          "$mod CONTROL, N, exec, swaync-client -t -sw"
        ]
        ++ (
          # workspaces
          # binds $mod + [shift +] {1..9} to [move to] workspace {1..9}
          builtins.concatLists (builtins.genList (i:
              let ws = i + 1;
              in [
                "$mod, code:1${toString i}, workspace, ${toString ws}"
                "$mod SHIFT, code:1${toString i}, movetoworkspacesilent, ${toString ws}"
              ]
            )
            9)
        );
      bindm = [
        "$mod, mouse:272, movewindow" # LMB to move window
        "$mod, mouse:273, resizewindow" # RMB to move window
      ];
      bindel = [
        # Brightness / Volume Controls
        # Chromebook has the printed symbols for these actions, but are really just fn keys
        ", XF86MonBrightnessDown, exec, brightnessctl s 10%-"
        ", XF86MonBrightnessUp, exec, brightnessctl s 10%+"
        ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
        ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
        ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"
        ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
      ];
      # Lid switch binds
      bindl = [
        # trigger when the switch is turning on
        ", switch:on:Lid Switch, exec, hyprctl keyword monitor 'eDP-1, disable'"

        # trigger when the switch is turning off
        ", switch:off:Lid Switch, exec, hyprctl keyword monitor 'eDP-1, 2560x1600@165, 0x0, 1.00'"
      ];
      windowrulev2 = [

        # float keepass windows, put main window in scratch
        "float, class:^(org.keepassxc.KeePassXC)$"
        "workspace special:scratch silent, class:^(org.keepassxc.KeePassXC)$"
        "workspace special:scratch silent, class:^(org.signal.Signal)$"
        
        # Firefox to workspace 2
        "workspace 2 silent, class:^(firefox)$"
        
        # Slack to workspace 3
        "workspace 3 silent, class:^(com.slack.Slack)$"
        
        # Zoom to workspace 4
        "workspace 4 silent, class:^(zoom)$" 
        "fullscreen, class:^(zoom)$, title:^(Meeting)$" 
        # Float all other zoom windows (not meetings)
        "float, class:^(zoom)$, title:!^(Meeting)$"        
      ];

      monitor = [
        "eDP-1, 2560x1600@165, 0x0, 1.00"
        # At home monitor setup, 144 for hdmi bandwidth
        "desc:LG Electronics LG ULTRAGEAR+ 406NTJJ6B876, 3840x2160@144, auto, 1, vrr, 1"
        # Work monitor over USBC
        "eDP-2, 3440x1440@99.98Hz, auto, 1, vrr, 1"
        "eDP-3, 3440x1440@99.98Hz, auto, 1, vrr, 1"
        # Auto tile new unspecified monitors to the right, in preferred resolution
        ", preferred, auto-right, 1"
      ];
      cursor = {
        no_hardware_cursors = true;
        # allow_dumb_copy = true;
      };
      misc = {
        # Revert to true when nvidia damage tracking works
        vfr = 0;
        force_default_wallpaper = 0;
        disable_hyprland_logo = true;
      };
      render = {
        direct_scanout = 0;
      };
      ##
      ## delete when nvidia damage tracking works (debug & opengl)
      ##
      debug = {
        damage_tracking = 0;
      };
      opengl = {
        nvidia_anti_flicker = 0;
        # force_introspection = 2;
      };
    };
    # import variables
    wayland.windowManager.hyprland.systemd.variables = ["--all"];

    home.pointerCursor = {
      gtk.enable = true;
      hyprcursor.enable = true;
      x11.enable = true;
      hyprcursor.size = 32;
      name = "Bibata-Modern-Classic";
      package = pkgs.bibata-cursors;
      size = 32;
    };
    # home.sessionVariables = {
    # };
    home.packages = with pkgs; lib.lists.flatten [
      [
        ### hyprland packages
        swaybg
        swaylock-effects
        waybar
        wofi
        # NWG
        nwg-bar
        nwg-menu
        nwg-look
        nwg-dock-hyprland
        nwg-panel
        nwg-drawer
        nwg-launchers
        # Hypr Utils
        hyprpicker
        hyprshot
        hypridle
        # Etc
        gopsuinfo # For system stats in panel
        wl-clipboard # System clipboard
        brightnessctl
        wev
        wdisplays
        # Notifs
        libnotify
        swaynotificationcenter
        # Tray Applets
        networkmanagerapplet
        pavucontrol
        syncthingtray
        tailscale-systray
        # include portals here for flatpak
        xdg-desktop-portal-hyprland
        xdg-desktop-portal-gtk
      ]
      config.hyprhome.homePackages
    ];
    programs.cava = {
      enable = true;
      settings = {
        smoothing.noise_reduction = 55;
      };
    };
  };
}
