{ flake, userName, pkgs, customUtils, lib, config, ... }@inputs:
let
  cfg = config.home-manager.users.${userName};
  xmonad = import ./xmonad pkgs.haskellPackages;
  emacsclientDesktopItem = pkgs.makeDesktopItem {
    name = "emacsclient";
    genericName = "Text Editor";
    desktopName = "emacsclient";
    icon = "emacs";
    mimeType = "text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;";
    exec = "${config.home-manager.users.${userName}.programs.emacs.package}/bin/emacsclient -a \"\" %F";
  };
  emacsScratch = pkgs.stdenv.mkDerivation rec {
    pname = "scratch";
    version = "0077334cc299aa7885f804d88f52cdb1b35caf71";

    src = pkgs.fetchFromGitHub {
      owner = "ffevotte";
      repo = "scratch.el";
      rev = version;
      sha256 = "sha256-FUkKJ+1COGzgllzzv51yUIjMZI6slOFVExdwWl2ZEBA=";
    };

    phases = [ "installPhase" ];

    installPhase = ''
      mkdir -p $out/share/emacs/site-lisp
      cp $src/scratch.el $out/share/emacs/site-lisp/default.el
    '';
  };
  muteScript = pkgs.stdenv.mkDerivation {
    name = "mute";
    src = ./scripts/mute.zsh;

    buildInputs = with pkgs; [ makeWrapper ];

    phases = [ "installPhase" ];

    installPhase = ''
      mkdir -p $out/bin
      install -m 0755 $src $out/bin/mute
      wrapProgram $out/bin/mute \
        --prefix PATH : ${pkgs.zsh}/bin \
        --prefix PATH : ${pkgs.findutils}/bin \
        --prefix PATH : ${pkgs.util-linux}/bin \
        --prefix PATH : ${pkgs.coreutils}/bin \
        --prefix PATH : ${pkgs.pulseaudio}/bin
    '';
  };
  wrappedChrome = pkgs.runCommand "${pkgs.google-chrome.name}-wrapped" { buildInputs = with pkgs; [ makeWrapper ]; } ''
    mkdir -p "$out/bin"
    install -m 0755 ${pkgs.google-chrome}/bin/google-chrome-stable $out/bin/google-chrome
    wrapProgram $out/bin/google-chrome \
      --add-flags '--force-device-scale-factor=1.6'
  '';
  wrappedZulip = pkgs.runCommand "${pkgs.zulip.name}-wrapped" { buildInputs = with pkgs; [ makeWrapper ]; } ''
    mkdir -p "$out/bin"
    install -m 0755 ${pkgs.zulip}/bin/zulip $out/bin/zulip
    wrapProgram $out/bin/zulip \
      --add-flags '--force-device-scale-factor=1.6'
  '';
in {
  imports = with flake.nixosModules.userProfiles.${userName}; [
    mpv
  ];
  
  home-manager.users.${userName} = {
    programs = {
      ssh = {
        matchBlocks = import ./ssh-hosts.nix; # customUtils.nixImport { dir = ./ssh-hosts; };
        extraConfig = ''
          Match host uniworx3.ifi.lmu.de,uniworx4.ifi.lmu.de,uniworx5.ifi.lmu.de,uni2workgw.ifi.lmu.de,blackbeard.tcs.ifi.lmu.de,gitlab2.rz.ifi.lmu.de,oregon.tcs.ifi.lmu.de !exec "nc -z -w 1 %h %p &>/dev/null"
            ProxyJump remote.cip.ifi.lmu.de

          Match host *.mathinst.loc !exec "nc -z -w 1 %h %p &>/dev/null"
            IdentityFile ~/.ssh/gkleen@mathinst.loc
            ProxyJump mathw0g

          Match host *.cipmath.loc !exec "nc -z -w 1 %h %p &>/dev/null"
            IdentityFile ~/.ssh/gkleen@mathinst.loc
            ProxyJump mathw0h.mathinst.loc

          Host *
        '';
      };

      emacs = {
        enable = true;
        extraPackages = epkgs: with epkgs; [
          evil evil-dvorak undo-tree magit haskell-mode
          nix-mode yaml-mode json-mode shakespeare-mode
          smart-mode-line highlight-parentheses highlight-symbol
          notmuch ag sass-mode lua-mode fira-code-mode use-package
          use-package-ensure-system-package git-gutter emacsScratch
        ];
      };
      firefox = {
        enable = true;
        profiles.default = {
          settings = {
            "layout.css.devPixelsPerPx" = "1.75";
            "browser.tabs.drawInTitlebar" = false;
            "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
            "dom.security.https_only_mode" = true;
          };
        };
      };

      alacritty = {
        enable = true;
        settings = import ./alacritty.nix;
      };

      zathura = {
        enable = true;
        package = pkgs.zathura.override { useMupdf = false; };
      };

      mpv.config = {
        demuxer-max-bytes = 1073741824;
        demuxer-max-back-bytes = 268435456;
      };

      autorandr = {
        enable = true;
        hooks.postswitch = {
          # "restart-compton" = "${pkgs.systemd}/bin/systemctl --user try-restart picom";
          "restart-trays" = ''
              ${pkgs.coreutils}/bin/sleep 5
              ${pkgs.systemd}/bin/systemctl --user try-restart trayer xmobar
            '';
        };
        profiles = customUtils.nixImport { dir = ./autorandr-profiles; };
      };

      zsh.initExtra = "source ${./zshrc}";
      zsh.dirHashes = {
        u2w = "$HOME/projects/uni2work";
        docs = "$HOME/documents";
        dl = "$HOME/Downloads";
        flk = "$HOME/config/nixos-flakes";
        fsk-timi = "$HOME/projects/21s/fsk-timi";
        fsk-timi-exam = "$HOME/projects/21s/fsk-timi-exam";
      };

      obs-studio = {
        enable = true;
        plugins = with pkgs; [];
      };

      gh = {
        enable = true;
        editor = "${config.home-manager.users.${userName}.programs.emacs.package}/bin/emacsclient";
        gitProtocol = "ssh";
      };

      nix-index.enable = true;
    };

    services = {
      dunst = {
        settings = import ./dunst-settings.nix inputs;
        iconTheme = cfg.gtk.iconTheme;
        enable = true;
      };
      emacs.enable = true;
      gpg-agent = {
        enable = true;
        enableSshSupport = true;
        extraConfig = ''
          pinentry-program ${pkgs.pinentry-gtk2}/bin/pinentry
          grab
        '';
      };
      pasystray.enable = true;
      udiskie = {
        enable = true;
        automount = false;
      };
      unclutter = {
        enable = true;
        timeout = 5;
      };
      network-manager-applet.enable = true;
      blueman-applet.enable = true;

      sxhkd = {
        enable = true;
        keybindings = {
          "button8" = "${muteScript}/bin/mute unmute";
          "@button8" = "${muteScript}/bin/mute mute";
          "button9" = "${pkgs.pulseaudio}/bin/pacmd set-sink-mute @DEFAULT_SINK@ 1";
          "@button9" = "${pkgs.pulseaudio}/bin/pacmd set-sink-mute @DEFAULT_SINK@ 0";
        };
      };

      unison = {
        enable = true;
        pairs = {
          documents = {
            roots = ["${cfg.home.homeDirectory}/documents" "ssh://vidhar/documents"];
            stateDirectory = "${cfg.xdg.dataHome}/documents.unison";
          };
        };
      };
    };

    gtk = {
      enable = true;
      font.name = "DejaVu Sans 6";
      theme = {
        package = pkgs.equilux-theme;
        name = "Equilux-compact";
      };
      iconTheme = {
        package = pkgs.paper-icon-theme;
        name = "Paper";
      };
    };

    xsession = {
      enable = true;

      windowManager.command = "${pkgs.coreutils}/bin/env -u SHLVL -- ${xmonad}/bin/xmonad";

      initExtra = let
          lockScript = pkgs.writeScript "lock" ''
            #!${pkgs.stdenv.shell}
            ${pkgs.playerctl}/bin/playerctl -a pause
            exec ${pkgs.xsecurelock}/bin/xsecurelock
          '';
        in ''
             ${pkgs.coreutils}/bin/env XSECURELOCK_WANT_FIRST_KEYPRESS=1 XSECURELOCK_DIM_ALPHA=1 ${pkgs.xss-lock}/bin/xss-lock -l -n ${pkgs.xsecurelock}/libexec/xsecurelock/dimmer -- ${lockScript} &
             ${pkgs.xorg.xinput}/bin/xinput disable 'Synaptics TM3512-010'
             ${pkgs.xorg.xset}/bin/xset s 590 10
             ${pkgs.xorg.xmodmap}/bin/xmodmap -e 'keysym Caps_Lock = Multi_key'
           '';
    };

    xresources.properties = import ./xresources.nix;

    home = {
      packages = with pkgs; [
        fira-code powerline-fonts nerdfonts pavucontrol keepassxc
        youtube-dl sxiv xclip mumble pulseaudio-ctl libnotify synergy
        xorg.xbacklight screen-message pidgin-with-plugins
        google-play-music-desktop-player qt5ct playerctl evince
        thunderbird wrappedZulip zoom-us steam steam-run wireshark skype
        virt-manager rclone cached-nix-shell xournal discord xmonad
        worktime fira-code-symbols emacsclientDesktopItem libreoffice
        xournalpp wrappedChrome nixos-shell virt-viewer
      ];

      file = {
        ".emacs".source = ./emacs.el;
        ".backup-munin".source = ./backup-patterns;
        ".mozilla/firefox/default/chrome/userChrome.css".source = ./firefox-chrome.css;
        ".mozilla/firefox/default/chrome/userContent.css".source = ./firefox-content.css;
      };

      sessionVariables = {
        GDK_SCALE = 96.0 / 282.0;
        QT_AUTO_SCREEN_SCALE_FACTOR = 1;
        QT_QPA_PLATFORMTHEME = "qt5ct";
      };

      extraProfileCommands = ''
        export XDG_DATA_DIRS="${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/${pkgs.gsettings-desktop-schemas.name}:${pkgs.gtk3}/share/gsettings-schemas/${pkgs.gtk3.name}''${XDG_DATA_DIRS:+:''${XDG_DATA_DIRS}}"
      '';

      keyboard = {
        layout = "us";
        variant = "dvp";
        options = [ "ctl:nocaps" ];
      };
    };

    fonts.fontconfig.enable = true;

    systemd.user = import ./systemd.nix inputs;
  };
}