# Display contact information during boot. https://discourse.nixos.org/t/display-contact-info-in-nixos-boot-stage-1/38118/4

{ config, pkgs, lib, ... }:
let
  # TODO: Once `lib.string.trim` is available in stable nix, remove the below.
  # Copied from https://github.com/NixOS/nixpkgs/blob/5633bcff0c6162b9e4b5f1264264611e950c8ec7/lib/strings.nix#L362-L434
  trim = trimWith {
    start = true;
    end = true;
  };
  trimWith =
    {
      start ? false,
      end ? false,
    }:
    let
      # Define our own whitespace character class instead of using
      # `[:space:]`, which is not well-defined.
      chars = " \t\r\n";

      # To match up until trailing whitespace, we need to capture a
      # group that ends with a non-whitespace character.
      regex =
        if start && end then
          "[${chars}]*(.*[^${chars}])[${chars}]*"
        else if start then
          "[${chars}]*(.*)"
        else if end then
          "(.*[^${chars}])[${chars}]*"
        else
          "(.*)";
    in
    s:
    let
      # If the string was empty or entirely whitespace,
      # then the regex may not match and `res` will be `null`.
      res = lib.match regex s;
    in
    lib.optionalString (res != null) (lib.head res);

  contact_name = "Daniel Langbein";
  # The file `phone-number` contains only one line with our phone number, e.g. +49 0173 ...
  # Be aware that the phone number will be written to the nix store in plaintext!
  # TODO: strip the read string (no tailing newlines)
  contact_phone = trim (builtins.readFile ../secrets/phone-number);
  contact_mail = "daniel@systemli.org";

  # https://wiki.nixos.org/wiki/Shell_Scripts
  contact-info-str = pkgs.stdenv.mkDerivation rec {
    name = "Contact information string";
    # disable unpackPhase etc
    phases = "buildPhase";
    builder = pkgs.writeShellScript "builder.sh" ''
      set -eu -o pipefail
      echo -e "If found, please contact:\n${contact_name}\n${contact_phone}\n${contact_mail}" \
      | cowsay --bold --aurora -f dragon > $out
    '';
    nativeBuildInputs = with pkgs; [ coreutils neo-cowsay ];
    PATH = lib.makeBinPath nativeBuildInputs;
  };

  contact-info-img = pkgs.stdenv.mkDerivation rec{
    name = "Contact information image";
    nativeBuildInputs = with pkgs; [ imagemagick liberation_ttf ];
    phases = "installPhase";
    # magick add label: https://imagemagick.org/Usage/text/#label
    # magick font list: magick -list font | grep Font
    installPhase = ''
      set -eu -o pipefail
      mkdir -p $out
      #export XDG_CACHE_HOME="$out/.cache"
      magick -background black -fill 'hsb(120, 255,   63.75)' -font ${pkgs.liberation_ttf}/share/fonts/truetype/LiberationSans-Regular.ttf -pointsize 92 'label:If found, please contact:\n${contact_name}\n${contact_phone}\n${contact_mail}' $out/img.png
    '';
  };
in
{
  # We found no non-graphical solution to print the contact info with systemd initrd.
  # Workaround: Run a dummy service that has the contact info as service name ...
  #
  # Alternative: Use Plymouth for a graphical boot splash screen.
  # TODO: Only on graphical installations!
  #
  # To see the splash screen. https://wiki.archlinux.org/title/Plymouth#Installation
  #boot.kernelParams = [ "splash" ];
  #
  boot.plymouth = lib.mkIf (config.boot.initrd.systemd.enable) {
    enable = true;
    #theme = "breeze";
    logo = "${contact-info-img}/img.png";
  };

  # Print contact info as text during boot.
  boot.initrd.preDeviceCommands = lib.mkIf (! config.boot.initrd.systemd.enable) ''
    cat <<'EOF'
    ${builtins.readFile contact-info-str}
    EOF
  '';

# TODO: cleanup

#
# TODO: systemd service output is not displayed during boot. onyl [info] service xxx started
#

#  # https://github.com/oxalica/nixpkgs/blob/3562c1d5c6ff868924fe95ba7b51344f3c141311/nixos/modules/config/console.nix#L158
#  boot.initrd.systemd.storePaths = [
#    "${config.boot.initrd.systemd.package.kbd}/bin/some-foo-package"
#  ];
#
#  boot.initrd.systemd.services."If-found-please-send-email-to___${mail}___" = lib.mkIf (config.boot.initrd.systemd.enable) {
#    description = "Display part of the contact information inside service name";
#    wantedBy = [ "initrd.target" ];
#    after = [ "systemd-vconsole-setup.service" ];
#    before = [ "cryptsetup-pre.target" "local-fs-pre.target" ];
#    unitConfig.DefaultDependencies = "no";
#    serviceConfig.Type = "oneshot";
#    script = ''
#      wall TESTING-SOMETHING-OUT
#    '';
#  };
#
#  # Soruces:
#  # - https://discourse.nixos.org/t/zfs-rollback-not-working-using-boot-initrd-systemd/37195/3
#  # - https://github.com/cole-h/nixos-config/blob/26f77d5d24e5859a1bb690cff63371d1ebf7d707/hosts/nixos/scadrial/modules/boot/remote-unlock.nix#L57-L69
#  boot.initrd.systemd.services."contact-info" = lib.mkIf (config.boot.initrd.systemd.enable) {
#    description = "Display contact information";
#    wantedBy = [
#      "initrd.target"
#    ];
#    after = [
#      "systemd-vconsole-setup.service"
#    ];
#    before = [
#      # Flowchart displaying the ordering of targets: https://www.freedesktop.org/software/systemd/man/latest/bootup.html
#      #   cryptsetup-pre.target and local-fs-pre.target don't depend on each other but are instead orthogonal
#
#      # This passive target unit may be pulled in by services that want to run before any encrypted block device is set up.
#      # https://www.freedesktop.org/software/systemd/man/systemd.special#cryptsetup-pre.target
#      "cryptsetup-pre.target"
#
#      # This target unit is automatically ordered before all local mount points marked with auto.
#      # https://www.freedesktop.org/software/systemd/man/systemd.special#local-fs-pre.target
#      "local-fs-pre.target"
#
#      # If the root device can be mounted at /sysroot, the sysroot.mount unit becomes active and initrd-root-fs.target is reached.
#      # https://man7.org/linux/man-pages/man7/bootup.7.html
#      #"sysroot.mount"
#    ];
##    path = with pkgs; [
##      neo-cowsay
##    ];
#    unitConfig.DefaultDependencies = "no";
#    serviceConfig.Type = "oneshot";
#    script = ''
#      cat <<'EOF'
#      ${builtins.readFile contact-info-str}
#      EOF
#    '';
#  };
}