{ pkgs, lib, config, userName, ... }:
let
  inherit (lib) listToAttrs nameValuePair;

  xmobar = import ./xmobar pkgs.haskellPackages;
  cfg = config.home-manager.users.${userName};

  autossh-socks-script = pkgs.writeScript "autossh" ''
    #!${pkgs.zsh}/bin/zsh -xe

    host="''${1%:*}"
    port="''${1#*:}"

    typeset -a cmd
    cmd=()

    if [[ -n "''${SSHPASS_SECRET}" ]]; then
      cmd+=(${pkgs.sshpassSecret}/bin/sshpass-secret)
      cmd+=("''${(@s/:/)SSHPASS_SECRET}")
      cmd+=(--)
    fi

    cmd+=(${pkgs.openssh}/bin/ssh -vN -D localhost:''${port} "''${host}")

    ( exec -a "''${cmd[1]}" -- ''${cmd} ) &
    pid=$!

    newpid=""
    i=200
    while ! newpid=$(${pkgs.lsof}/bin/lsof -Pi @localhost:"''${port}" -sTCP:LISTEN -t); do
      if ! kill -0 "''${pid}"; then
        wait "''${pid}"
        exit $?
      fi
      [[ "''${i}" -gt 0 ]] || exit 1
      i=$((''${i} - 1))
      ${pkgs.coreutils}/bin/sleep 0.1
    done

    ${config.systemd.package}/bin/systemd-notify --ready

    wait "''${pid}" "''${newpid}"
  '';
in {
  tmpfiles.rules = [
    "e /home/gkleen/screenshots - - - 365d -"
    "d /home/gkleen/.cache/qalc-fuzzel - - - 1d -"
  ];

  services = {
    sync-keepass = {
      Service = {
        Type = "oneshot";
        WorkingDirectory = "~";
        ExecStart = toString (pkgs.writers.writePython3 "sync-keepass" {
          libraries = with pkgs.python3Packages; [ python-dateutil ];
        } ''
          import json
          import subprocess
          from os.path import (expanduser, getmtime, dirname)
          from datetime import datetime
          from dateutil.tz import tzlocal
          from dateutil.parser import isoparse
          from sys import stderr


          remote_fs = 'surtr'
          remote_file = 'store.kdbx'
          target_file = expanduser('~/store.kdbx')
          meta_file = expanduser('~/.store.kdbx.json')

          upload_time = None
          our_last_upload_time = None
          mod_time = None


          def get_upload_time():
              upload_time = None
              with subprocess.Popen(['rclone', 'lsjson', f'{remote_fs}:{dirname(remote_file)}'], stdout=subprocess.PIPE) as proc:  # noqa: E501
                  for file in json.load(proc.stdout):
                      if file['Path'] != remote_file:
                          continue
                      else:
                          upload_time = isoparse(file['ModTime'])
                          break
              return upload_time


          def do_upload():
              print('Uploading', file=stderr)
              subprocess.run(['rclone', 'copy', '-I', target_file, f'{remote_fs}:{dirname(remote_file)}'], check=True)  # noqa: E501
              upload_time = get_upload_time()
              with open(meta_file, 'w') as file:
                  json.dump({'our_last_upload_time': upload_time.isoformat()}, file)


          def do_download():
              print('Downloading', file=stderr)
              subprocess.run(['rclone', 'copy', '-I', f'{remote_fs}:{remote_file}', dirname(target_file)], check=True)  # noqa: E501


          upload_time = get_upload_time()

          try:
              with open(meta_file, 'r') as file:
                  file_content = json.load(file)
                  our_last_upload_time = isoparse(file_content['our_last_upload_time'])  # noqa: E501
          except FileNotFoundError:
              pass

          try:
              mod_time = datetime.fromtimestamp(getmtime(target_file)).replace(tzinfo=tzlocal())  # noqa: E501
          except FileNotFoundError:
              pass

          if upload_time is None or (mod_time is not None and mod_time > upload_time):  # noqa: E501
              do_upload()
          elif upload_time is not None and (mod_time is None or upload_time > mod_time) and (our_last_upload_time is None or upload_time > our_last_upload_time):  # noqa: E501
              do_download()
        '');
        Environment = [ "RCLONE_PASSWORD_COMMAND=\"${pkgs.coreutils}/bin/cat ${config.sops.secrets.gkleen-rclone.path}\"" "PATH=${pkgs.rclone}/bin" ];
      };
    };
    emacs = {
      Unit = {
        After = [ "graphical-session.target" ];
        BindsTo = [ "graphical-session.target" ];
      };
    };
    keepassxc = {
      Service = {
        Type = "dbus";
        BusName = "org.keepassxc.KeePassXC.MainWindow";
        WorkingDirectory = "~";
        ExecStart = "${pkgs.keepassxc}/bin/keepassxc";
        Environment = [ "QT_QPA_PLATFORM=wayland" ];
      };
      Unit = {
        After = [ "graphical-session.target" ];
        BindsTo = [ "graphical-session.target" ];
      };
    };
    mpris-proxy = {
      Unit.Description = "Mpris proxy";
      Unit.After = [ "network.target" "sound.target" ];
      Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy";
      Install.WantedBy = [ "default.target" ];
    };
    "autossh-socks@proxy.mathw0h:8119" = {
      Service = {
        Type = "notify";
        NotifyAccess = "all";
        WorkingDirectory = "~";
        Restart = "always";
        RestartSec = "23s";
        ExecStart = "${autossh-socks-script} \"%I\"";
        Environment = [ "SSHPASS_SECRET=gkleen@mathw0g.math.lmu.de" ];
      };
      Unit = {
        StopWhenUnneeded = true;
        StartLimitInterval = "180s";
        StartLimitBurst = 7;
      };
    };
    "autossh-socks@proxy.vidhar:8121" = {
      Service = {
        Type = "notify";
        NotifyAccess = "all";
        WorkingDirectory = "~";
        Restart = "always";
        RestartSec = "2s";
        ExecStart = "${autossh-socks-script} \"%I\"";
      };
      Unit = {
        StopWhenUnneeded = true;
      };
    };
    swayidle = {
      Service = {
        RuntimeDirectory = "swayidle";
      };
    };
    psi-notify = {
      Install = {
        WantedBy = ["graphical-session.target"];
      };
      Unit = {
        After = [ "graphical-session.target" ];
        PartOf = [ "graphical-session.target" ];
      };
      Service = {
        ExecStart = lib.getExe pkgs.psi-notify;
        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
        Type = "notify";
        Restart = "always";
        WatchdogSec = "2s";
      };
    };
    gtklock = {
      Unit = {
        Requisite = ["graphical-session.target"];
        After = [ "graphical-session.target" ];
        PartOf = ["graphical-session.target"];
      };
      Service = {
        Type = "notify";
        RuntimeDirectory = "gtklock";
        CacheDirectory = "gtklock";
        ExecStartPre = [
          "${lib.getExe' pkgs.libsForQt5.qt5.qttools.bin "qdbus"} org.keepassxc.KeePassXC.MainWindow /keepassxc org.keepassxc.KeePassXC.MainWindow.lockAllDatabases"
          "${lib.getExe' config.systemd.package "systemctl"} --user stop gpg-agent.service"
          "${lib.getExe pkgs.playerctl} -a pause"
          (lib.getExe (pkgs.writeShellApplication {
            name = "generate-css";
            runtimeInputs = with pkgs; [cfg.programs.wpaperd.package jq coreutils imagemagick findutils];
            text = ''
              declare -A monitors
              monitors=()
              while IFS= read -r entry; do
                  path=$(jq -r ".path" <<<"$entry")
                  [[ -z "$path" || ! -f "$path" ]] && continue
                  blurred_path="$CACHE_DIRECTORY"/"$(b2sum -l 128 <<<"$path" | cut -d' ' -f1)"."''${path##*.}"
                  monitor=$(jq -r ".display" <<<"$entry")
                  if [[ ! -f "$blurred_path" ]]; then
                      mkdir -p "$(dirname "$blurred_path")"
                      magick "$path" -filter Gaussian -resize 6.25% -define filter:sigma=2.5 -resize 1600% "$blurred_path" &
                  fi
                  monitors+=([$monitor]="$blurred_path")
              done < <(wpaperctl all-wallpapers -j | jq -c ".[]")
              # wait

              cp --no-preserve=mode ${pkgs.writeText "gtklock.css" ''
                #window-box {
                  padding: 64px;
                  /* border: 1px solid black; */
                  border-radius: 4px;
                  box-shadow: rgba(0, 0, 0, 0.8) 0px 4px 12px;
                  /* background-color: white; */
                  background-color: rgba(0, 0, 0, 0.5);
                }
              ''} "$RUNTIME_DIRECTORY"/style.css
              for monitor in "''${!monitors[@]}"; do
              cat >>"$RUNTIME_DIRECTORY"/style.css <<EOF
              window#''${monitor} {
                background-image: url("''${monitors[$monitor]}");
                background-repeat: no-repeat;
                background-size: 100% 100%;
                background-origin: content-box;
              }
              EOF
              done
            '';
          }))
        ];
        NotifyAccess = "all";
        ExecStart = ''${lib.getExe pkgs.gtklock} -s "''${RUNTIME_DIRECTORY}/style.css" -L ${pkgs.writeShellScript "after-lock" ''
          ${lib.getExe cfg.programs.niri.package} msg action power-off-monitors
          ${lib.getExe' config.systemd.package "systemd-notify"} --ready
        ''}'';
      };
    };
    "yt-dlp@" = {
      Service = {
        Type = "notify";
        CacheDirectory = "yt-dlp/%N";
        StandardInput = "socket";
        StandardOutput = "journal";
        WatchdogSec = "30min";
        Environment = [
          "PATH=${lib.makeBinPath (with pkgs; [atomicparsley ffmpeg-headless rtmpdump])}"
          "DSCP=8"
        ];
        ExecStart = ''${lib.getExe pkgs.dscp} ${pkgs.writers.writePython3 "yt-dlp" {
          libraries = with pkgs.python3Packages; [ yt-dlp sdnotify ];
        } ''
          import json
          from yt_dlp import YoutubeDL, parse_options
          from sys import stdin
          from sdnotify import SystemdNotifier
          from os import environ
          from pathlib import Path


          n = SystemdNotifier()
          args = json.load(stdin)
          ydl_opts = {
              **parse_options().ydl_opts,
              'progress_hooks': [lambda _d: n.notify('WATCHDOG=1')],
              'postprocessor_hooks': [lambda _d: n.notify('WATCHDOG=1')],
              'progress_with_newline': True,
              'progress_delta': 5,
              'paths': {
                  'home': str(Path.home() / 'media'),
                  'temp': str(Path(environ['CACHE_DIRECTORY'])),
              },
              'noplaylist': True,
              **(args['params'] if 'params' in args else {}),
          }
          with YoutubeDL(ydl_opts) as ytdl:
              n.notify('READY=1')
              ytdl.download(args['urls'])
        ''}'';
        ExecStopPost = "${pkgs.coreutils}/bin/rm -rfv \"$CACHE_DIRECTORY\"";
      };
    };
    wpaperd = {
      Install = {
        WantedBy = ["graphical-session.target"];
      };
      Unit = {
        After = [ "graphical-session.target" ];
        PartOf = [ "graphical-session.target" ];
      };
      Service = {
        ExecStart = lib.getExe cfg.programs.wpaperd.package;
        Type = "simple";
        Restart = "always";
        RestartSec = "2s";
      };
    };
    xembed-sni-proxy = {
      Unit = {
        BindsTo = ["xwayland-satellite.service"];
        After = ["xwayland-satellite.service"];
      };
    };
    poweralertd = {
      Unit = {
        After = ["graphical-session.target"];
      };
    };
  } // listToAttrs (map ({host, port}: nameValuePair "proxy-to-autossh-socks@${toString port}" {
      Unit = {
        Requires = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"];
        After = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"];
      };
      Service = {
        ExecStart = "${config.systemd.package}/lib/systemd/systemd-socket-proxyd --exit-idle-time=10s localhost:${toString (port + 1)}";
      };
  }) [{ host = "proxy.mathw0h"; port = 8118; } { host = "proxy.vidhar"; port = 8120; }]);
  sockets = listToAttrs (map (port: nameValuePair "proxy-to-autossh-socks@${toString port}" {
    Socket = {
      ListenStream = "%I";
    };
    Install = {
      WantedBy = ["default.target"];
    };
  }) [8118 8120]) // {
    "yt-dlp" = {
      Socket = {
        SocketMode = "0600";
        Accept = true;
        ListenStream = "%t/yt-dlp.sock";
        TriggerLimitIntervalSec = 0;
      };
      Install = {
        WantedBy = ["sockets.target"];
      };
    };
  };
  timers = {
    sync-keepass = {
      Timer = {
        OnActiveSec = "1m";
        OnUnitActiveSec = "1m";
      };

      Install = {
        WantedBy = ["default.target"];
      };
    };
  };
  targets = {
    graphical-session = {
      Unit = {
        BindsTo = ["default.target"];
        After = ["basic.target"];
      };
    };
    tray = {
      Unit = {
        PartOf = [ "graphical-session.target" ];
        Requires = [ "waybar.service" ];
        After = [ "graphical-session.target" "waybar.service" ];
        Wants = ["blueman-applet.service" "udiskie.service" "network-manager-applet.service"];
      };
    };
  };
}