{
  buildNpmPackage,
  buildPackages,
  fetchFromGitHub,
  fetchurl,
  fetchpatch,
  lib,
  overrideCC,
  stdenv,

  # build time
  autoconf,
  cargo,
  dump_syms,
  git,
  gnum4,
  nodejs,
  patchelf,
  pkg-config,
  pkgsBuildBuild,
  pkgsCross,
  python3,
  runCommand,
  rsync,
  rustc,
  rust-cbindgen,
  rustPlatform,
  unzip,
  vips,
  wrapGAppsHook3,
  writeShellScript,

  # runtime
  alsa-lib,
  atk,
  cairo,
  cups,
  dbus,
  dbus-glib,
  ffmpeg,
  fontconfig,
  freetype,
  gdk-pixbuf,
  gtk3,
  glib,
  icu73,
  jemalloc,
  libGL,
  libGLU,
  libdrm,
  libevent,
  libffi,
  libglvnd,
  libjack2,
  libjpeg,
  libkrb5,
  libnotify,
  libpng,
  libpulseaudio,
  libstartup_notification,
  libva,
  libvpx,
  libwebp,
  libxkbcommon,
  libxml2,
  makeWrapper,
  mesa,
  nasm,
  nspr,
  nss_latest,
  pango,
  pciutils,
  pipewire,
  sndio,
  udev,
  xcb-util-cursor,
  xorg,
  zlib,

  # Generic changes the compatibility mode of the final binaries.
  #
  # Enabling generic will make the browser compatible with more devices at the
  # cost of disabling hardware-specific optimizations. It is highly recommended
  # to leave `generic` disabled.
  generic ? false,
  debugBuild ? false,

  # On 32bit platforms, we disable adding "-g" for easier linking.
  enableDebugSymbols ? !stdenv.hostPlatform.is32bit,
  alsaSupport ? stdenv.hostPlatform.isLinux,
  ffmpegSupport ? true,
  gssSupport ? true,
  jackSupport ? stdenv.hostPlatform.isLinux,
  jemallocSupport ? !stdenv.hostPlatform.isMusl,
  pipewireSupport ? waylandSupport && webrtcSupport,
  pulseaudioSupport ? stdenv.hostPlatform.isLinux,
  sndioSupport ? stdenv.hostPlatform.isLinux,
  waylandSupport ? true,

  privacySupport ? false,

  # WARNING: NEVER set any of the options below to `true` by default.
  # Set to `!privacySupport` or `false`.
  crashreporterSupport ?
    !privacySupport && !stdenv.hostPlatform.isRiscV && !stdenv.hostPlatform.isMusl,
  geolocationSupport ? !privacySupport,
  webrtcSupport ? !privacySupport,
}:
let
  surfer = buildNpmPackage {
    pname = "surfer";
    version = "1.5.0";

    src = fetchFromGitHub {
      owner = "zen-browser";
      repo = "surfer";
      rev = "50af7094ede6e9f0910f010c531f8447876a6464";
      hash = "sha256-wmAWg6hoICNHfoXJifYFHmyFQS6H22u3GSuRW4alexw=";
    };

    patches = [
      (fetchpatch {
        url = "https://raw.githubusercontent.com/NixOS/nixpkgs/4a6be22d0d52df01d0be2346cc6504962251fea7/pkgs/by-name/ze/zen-browser-unwrapped/surfer-dont-check-update.patch";
        hash = "sha256-CC8+hw6p8Mf9XGaLcerAmbfrIWffuMsy7tx81IBYEps=";
      })
    ];

    npmDepsHash = "sha256-p0RVqn0Yfe0jxBcBa/hYj5g9XSVMFhnnZT+au+bMs18=";
    makeCacheWritable = true;

    SHARP_IGNORE_GLOBAL_LIBVIPS = false;
    nativeBuildInputs = [ pkg-config ];
    buildInputs = [ vips ];
  };

  llvmPackages0 = rustc.llvmPackages;
  llvmPackagesBuildBuild0 = pkgsBuildBuild.rustc.llvmPackages;

  llvmPackages = llvmPackages0.override {
    bootBintoolsNoLibc = null;
    bootBintools = null;
  };
  llvmPackagesBuildBuild = llvmPackagesBuildBuild0.override {
    bootBintoolsNoLibc = null;
    bootBintools = null;
  };

  buildStdenv = overrideCC llvmPackages.stdenv (
    llvmPackages.stdenv.cc.override { bintools = buildPackages.rustc.llvmPackages.bintools; }
  );

  inherit (pkgsCross) wasi32;

  wasiSysRoot = runCommand "wasi-sysroot" { } ''
    mkdir -p "$out"/lib/wasm32-wasi
    for lib in ${wasi32.llvmPackages.libcxx}/lib/*; do
      ln -s "$lib" "$out"/lib/wasm32-wasi
    done
  '';

  firefox-l10n = fetchFromGitHub {
    owner = "mozilla-l10n";
    repo = "firefox-l10n";
    rev = "9d639cd79d6b73081fadb3474dd7d73b89732e7b";
    hash = "sha256-+2JCaPp+c2BRM60xFCeY0pixIyo2a3rpTPaSt1kTfDw=";
  };
in
buildStdenv.mkDerivation (finalAttrs: {
  pname = "zen-browser-unwrapped";
  version = "1.0.1-a.19";

  src = fetchFromGitHub {
    owner = "zen-browser";
    repo = "desktop";
    rev = finalAttrs.version;
    hash = "sha256-+eehLsnQoWapkSKo3zWFxaz6N68BryK1XsmSk48zbbk=";
    fetchSubmodules = true;
  };

  # DO NOT UPDATE THE FIREFOX VERSION MANUALLY!
  #
  # Both `firefoxVersion` and `firefoxSrc` are managed by the `update.sh` script.
  # The Firefox version is specified by `zen-browser` in the `surfer.json` file.
  #
  # We need to manually set the version here to avoid IFD.
  firefoxVersion = "132.0.1";
  firefoxSrc = fetchurl {
    url = "mirror://mozilla/firefox/releases/${finalAttrs.firefoxVersion}/source/firefox-${finalAttrs.firefoxVersion}.source.tar.xz";
    hash = "sha256-XAMbVywdpyZnfi/5e2rVp+OyM4em/DljORy1YvgKXkg=";
  };

  SURFER_COMPAT = generic;

  nativeBuildInputs =
    [
      autoconf
      cargo
      git
      gnum4
      llvmPackagesBuildBuild.bintools
      makeWrapper
      nasm
      nodejs
      pkg-config
      python3
      rsync
      rust-cbindgen
      rustPlatform.bindgenHook
      rustc
      surfer
      unzip
      wrapGAppsHook3
      xorg.xvfb
    ]
    ++ lib.optionals crashreporterSupport [
      dump_syms
      patchelf
    ];

  buildInputs =
    [
      atk
      cairo
      cups
      dbus
      dbus-glib
      ffmpeg
      fontconfig
      freetype
      gdk-pixbuf
      gtk3
      glib
      icu73
      libGL
      libGLU
      libevent
      libffi
      libglvnd
      libjpeg
      libnotify
      libpng
      libstartup_notification
      libva
      libvpx
      libwebp
      libxml2
      mesa
      nspr
      nss_latest
      pango
      pciutils
      pipewire
      udev
      xcb-util-cursor
      xorg.libX11
      xorg.libXcursor
      xorg.libXdamage
      xorg.libXext
      xorg.libXft
      xorg.libXi
      xorg.libXrender
      xorg.libXt
      xorg.libXtst
      xorg.pixman
      xorg.xorgproto
      xorg.libxcb
      xorg.libXrandr
      xorg.libXcomposite
      xorg.libXfixes
      xorg.libXScrnSaver
      zlib
    ]
    ++ lib.optional alsaSupport alsa-lib
    ++ lib.optional jackSupport libjack2
    ++ lib.optional pulseaudioSupport libpulseaudio
    ++ lib.optional sndioSupport sndio
    ++ lib.optional gssSupport libkrb5
    ++ lib.optional jemallocSupport jemalloc
    ++ lib.optionals waylandSupport [
      libdrm
      libxkbcommon
    ];

  configureFlags = [
    "--disable-bootstrap"
    "--disable-updater"
    "--enable-default-toolkit=cairo-gtk3${lib.optionalString waylandSupport "-wayland"}"
    "--enable-system-pixman"
    "--with-distribution-id=org.nixos"
    "--with-libclang-path=${llvmPackagesBuildBuild.libclang.lib}/lib"
    "--with-system-ffi"
    "--with-system-icu"
    "--with-system-jpeg"
    "--with-system-libevent"
    "--with-system-libvpx"
    "--with-system-nspr"
    "--with-system-nss"
    "--with-system-png" # needs APNG support
    "--with-system-webp"
    "--with-system-zlib"
    "--with-wasi-sysroot=${wasiSysRoot}"
    "--host=${buildStdenv.buildPlatform.config}"
    "--target=${buildStdenv.hostPlatform.config}"
    (lib.enableFeature alsaSupport "alsa")
    (lib.enableFeature ffmpegSupport "ffmpeg")
    (lib.enableFeature geolocationSupport "necko-wifi")
    (lib.enableFeature gssSupport "negotiateauth")
    (lib.enableFeature jackSupport "jack")
    (lib.enableFeature jemallocSupport "jemalloc")
    (lib.enableFeature pulseaudioSupport "pulseaudio")
    (lib.enableFeature sndioSupport "sndio")
    (lib.enableFeature webrtcSupport "webrtc")
    # --enable-release adds -ffunction-sections & LTO that require a big amount
    # of RAM, and the 32-bit memory space cannot handle that linking
    (lib.enableFeature (!debugBuild && !stdenv.hostPlatform.is32bit) "release")
    (lib.enableFeature enableDebugSymbols "debug-symbols")
  ] ++ lib.optional stdenv.hostPlatform.isAarch "--disable-wasm-avx";

  configureScript = writeShellScript "configureMozconfig" (
    (lib.optionalString stdenv.hostPlatform.isAarch ''
      echo "ac_add_options --with-libclang-path=/usr/lib64" >> ./configs/linux/mozconfig

      # linux mozconfig
      sed -i 's/x86-\(64\|64-v3\)/native/g' ./configs/linux/mozconfig
      sed -i 's/x86_64-pc-linux/aarch64-linux-gnu/g' ./configs/linux/mozconfig

      # eme/widevine must be disabled on arm64 (thx google)
      sed -i '/--enable-eme/s/^/# /' ./configs/common/mozconfig
      sed -i 's/-msse3//g' ./configs/linux/mozconfig
      sed -i 's/-mssse3//g' ./configs/linux/mozconfig
      sed -i 's/-msse4.1//g' ./configs/linux/mozconfig
      sed -i 's/-msse4.2//g' ./configs/linux/mozconfig
      sed -i 's/-mavx2//g' ./configs/linux/mozconfig
      sed -i 's/-mavx//g' ./configs/linux/mozconfig
      sed -i 's/-mfma//g' ./configs/linux/mozconfig
      sed -i 's/-maes//g' ./configs/linux/mozconfig
      sed -i 's/-mpopcnt//g' ./configs/linux/mozconfig
      sed -i 's/-mpclmul//g' ./configs/linux/mozconfig
      sed -i 's/+avx2//g' ./configs/linux/mozconfig
      sed -i 's/+sse4.1//g' ./configs/linux/mozconfig

    '')
    + ''
      for flag in $@; do
        echo "ac_add_options $flag" >> mozconfig
      done
    ''
  );

  # To the person reading this wondering what is going on here, this is what
  # happens when a build process relies on Git. Normally you would use `fetchgit`
  # with `leaveDotGit = true`, however that leads to reproducibility issues, so
  # instead we create our own Git repo with a single commit.
  #
  # `surfer` (the build tool made for zen-browser) uses git to read the latest
  # HEAD commit, `git apply`, and likely a few other operations.
  preConfigure = ''
    export HOME="$TMPDIR"
    git config --global user.email "nixbld@localhost"
    git config --global user.name "nixbld"
    git init
    git add --all
    git commit -m 'nixpkgs'

    export LLVM_PROFDATA=llvm-profdata
    export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system
    export WASM_CC=${wasi32.stdenv.cc}/bin/${wasi32.stdenv.cc.targetPrefix}cc
    export WASM_CXX=${wasi32.stdenv.cc}/bin/${wasi32.stdenv.cc.targetPrefix}c++

    export ZEN_RELEASE=1
    surfer ci --brand alpha --display-version ${finalAttrs.version}

    install -D ${finalAttrs.firefoxSrc} .surfer/engine/firefox-${finalAttrs.firefoxVersion}.source.tar.xz
    surfer download
    surfer import
    patchShebangs engine/mach engine/build engine/tools
  '';

  preBuild = ''
    cp -r ${firefox-l10n} l10n/firefox-l10n

    for lang in $(cat ./l10n/supported-languages); do
      rsync -av --progress l10n/firefox-l10n/"$lang"/ l10n/"$lang" --exclude .git
    done

    sh scripts/copy-language-pack.sh en-US

    for lang in $(cat ./l10n/supported-languages); do
      sh scripts/copy-language-pack.sh "$lang"
    done

    Xvfb :2 -screen 0 1024x768x24 &
    export DISPLAY=:2
  '';

  buildPhase = ''
    runHook preBuild

    surfer build

    runHook postBuild
  '';

  preInstall = ''
    cd engine/obj-*
  '';

  meta = {
    mainProgram = "zen";
    description = "Firefox based browser with a focus on privacy and customization";
    homepage = "https://www.zen-browser.app/";
    license = lib.licenses.mpl20;
    maintainers = with lib.maintainers; [
      matthewpi
      titaniumtown
    ];
    platforms = [
      "aarch64-linux"
      "x86_64-linux"
    ];
  };

  enableParallelBuilding = true;
  requiredSystemFeatures = [ "big-parallel" ];

  passthru = {
    updateScript = ./update.sh;

    # These values are used by `wrapFirefox`.
    # ref; `pkgs/applications/networking/browsers/firefox/wrapper.nix'
    binaryName = finalAttrs.meta.mainProgram;
    inherit alsaSupport;
    inherit jackSupport;
    inherit pipewireSupport;
    inherit sndioSupport;
    inherit nspr;
    inherit ffmpegSupport;
    inherit gssSupport;
    inherit gtk3;
    inherit wasiSysRoot;
  };
})