# D-Bus configuration and system bus daemon.
{ config, lib, pkgs, ... }:
with lib;
let
  cfg = config.services.dbus;
  homeDir = "/run/dbus";
  configDir = pkgs.makeDBusConf {
    suidHelper = "${config.security.wrapperDir}/dbus-daemon-launch-helper";
    serviceDirectories = cfg.packages;
  };
in
{
  ###### interface
  options = {
    services.dbus = {
      enable = mkOption {
        type = types.bool;
        default = false;
        internal = true;
        description = ''
          Whether to start the D-Bus message bus daemon, which is
          required by many other system services and applications.
        '';
      };
      packages = mkOption {
        type = types.listOf types.path;
        default = [ ];
        description = ''
          Packages whose D-Bus configuration files should be included in
          the configuration of the D-Bus system-wide or session-wide
          message bus.  Specifically, files in the following directories
          will be included into their respective DBus configuration paths:
          pkg/etc/dbus-1/system.d
          pkg/share/dbus-1/system.d
          pkg/share/dbus-1/system-services
          pkg/etc/dbus-1/session.d
          pkg/share/dbus-1/session.d
          pkg/share/dbus-1/services
        '';
      };
      socketActivated = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Make the user instance socket activated.
        '';
      };
    };
  };
  ###### implementation
  config = mkIf cfg.enable {
    environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus ];
    environment.etc."dbus-1".source = configDir;
    users.users.messagebus = {
      uid = config.ids.uids.messagebus;
      description = "D-Bus system message bus daemon user";
      home = homeDir;
      group = "messagebus";
    };
    users.groups.messagebus.gid = config.ids.gids.messagebus;
    systemd.packages = [ pkgs.dbus.daemon ];
    security.wrappers.dbus-daemon-launch-helper = {
      source = "${pkgs.dbus.daemon}/libexec/dbus-daemon-launch-helper";
      owner = "root";
      group = "messagebus";
      setuid = true;
      setgid = false;
      permissions = "u+rx,g+rx,o-rx";
    };
    services.dbus.packages = [
      pkgs.dbus.out
      config.system.path
    ];
    systemd.services.dbus = {
      # Don't restart dbus-daemon. Bad things tend to happen if we do.
      reloadIfChanged = true;
      restartTriggers = [ configDir ];
      environment = { LD_LIBRARY_PATH = config.system.nssModules.path; };
    };
    systemd.user = {
      services.dbus = {
        # Don't restart dbus-daemon. Bad things tend to happen if we do.
        reloadIfChanged = true;
        restartTriggers = [ configDir ];
      };
      sockets.dbus.wantedBy = mkIf cfg.socketActivated [ "sockets.target" ];
    };
    environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ];
  };
}