{ config, pkgs, ... }:
{
  # Enable networking
  networking.networkmanager.enable = true;
  # virtual file system
  services.gvfs.enable = true;

  #disable power save for better latency
  networking.networkmanager.wifi.powersave = false;

  #stop systemd from taking too long to time out
  systemd.settings.Manager = {
    DefaultTimeoutStopSec="10s";
  };

  systemd.user.extraConfig = "DefaultTimeoutStopSec=10s";
  networking.firewall.enable = false;
  networking.extraHosts =
  ''
    255.255.255.255 wpad
    255.255.255.255 wpad.lan
  '';

  # Enable CUPS to print documents.
  #services.printing.enable = true;

  # Enable automatic login for the user.
  services.displayManager.autoLogin.enable = true;
  services.displayManager.autoLogin.user = "iopq";

  services.xserver.enable = true;

  #kde
  services.desktopManager.plasma6.enable = true;
  security.pam.services.sddm.enableKwallet = true;
  #sddm
  services.displayManager.sddm.enable = true;
  services.displayManager.sddm.wayland.enable = true;

  services.flatpak.enable = true;

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  hardware.bluetooth.enable = true;

  services.pipewire = {
    enable = true;
    alsa.enable = true;
    pulse.enable = true;
  };
/*  services.pulseaudio.enable = true;
  services.pulseaudio.support32Bit = true;

  services.pulseaudio.daemon.config = {
    avoid-resampling = "yes";
    resample-method = "soxr-vhq";
  };
*/

  #services.pipewire.package = (pkgs.pipewire.override { alsa-lib = pkgs.alsa-lib.overrideAttrs { separateDebugInfo = true; }; }).overrideAttrs { separateDebugInfo = true; };

  # graphics
  hardware.graphics = {
    enable = true;
    enable32Bit = true;
  };

  #fonts
  fonts.packages = with pkgs; [
    noto-fonts-cjk-sans
    babelstone-han
  ];

  programs.steam = {
    enable = true;
  };

  nixpkgs.config.packageOverrides = pkgs: {
    steam = pkgs.steam.override {
      extraPkgs = pkgs: with pkgs; [
        libgdiplus
      ];
    };
  };

  #fingerprint reader
  services.fprintd = {
    enable = true;
  };

    i18n.inputMethod = {
    enable = true;
    type = "fcitx5";
    fcitx5.waylandFrontend = true;
    fcitx5.addons = with pkgs; [
       rime-data
       fcitx5-gtk
       fcitx5-rime
       fcitx5-hangul
     ];
  };

#  services.daed.enable = true;

  nixpkgs.config.firefox.speechSynthesisSupport = true;
  services.speechd.enable = true; #firefox error

  #programs.ssh.startAgent = true; #can't start it and GnuPG at the same time
  #GnuPG
  programs.gnupg.agent = {
    enable = true;
    enableSSHSupport = true;
  };
  #services.pcscd.enable = true; #smartcard reader

  services.tlp.enable = true;
  services.power-profiles-daemon.enable = false; # avoid conflicts

  services.xray.settingsFile = "/etc/nixos/scripts/config.json";
  services.xray.enable = true;

  systemd.services.xray.serviceConfig = {
    User="xray_tproxy";
  };

  users.users.xray_tproxy.linger = true;
#  users.users.xray_tproxy.isSystemUser= true;
  users.users.xray_tproxy.isNormalUser= true;

  users.users.xray_tproxy.group = "xray_tproxy";

  users.groups.xray_tproxy = {
    gid = 1988;
  };

#  systemd.tmpfiles.rules = [
#    "d /run/tproxy 0755 xray_tproxy xray_tproxy -"
#  ];

  systemd.services.NetworkManager-wait-online.enable = true;

  systemd.services.tproxy = {
    description = "Transparent Proxy Rule Manager";
    wantedBy = [ "multi-user.target" ];
    wants = [ "network-online.target" ];
    after = [ "network-online.target" ];
    path = [ pkgs.iproute2 pkgs.iptables];

    serviceConfig = {
      ExecStartPre = [ "/run/current-system/sw/bin/sleep 7" ];
      ExecStart = "/etc/nixos/scripts/tproxy-controller /etc/nixos/scripts/servers.yaml";
      Restart = "always";
      User = "xray_tproxy";
      RuntimeDirectory = "tproxy";
      AmbientCapabilities = [ "CAP_NET_ADMIN" ];
      CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
      WorkingDirectory = "/run/tproxy";
      RestartSec=5;
    };
  };

  systemd.services.restart-trigger = {
    description = "Trigger restart of udp2raw and xray on .env change";
    serviceConfig = {
      Type = "oneshot";
      # The actual command to restart the service
      ExecStart = "${pkgs.systemd}/bin/systemctl restart udp2raw & ${pkgs.systemd}/bin/systemctl restart xray";
    };
  };

  systemd.paths.tproxy_restart = {
    description = "Watch tproxy IP env file";
    wantedBy = [ "multi-user.target" ];

    pathConfig = {
      PathChanged = "/run/tproxy/.env";
      Unit = "restart-trigger.service";
    };
  };

  systemd.paths.tproxy_start = {
    description = "Watch tproxy .env creation";
    wantedBy = [ "multi-user.target" ];

    pathConfig = {
      PathExists = "/run/tproxy/.env";
      Unit = ["udpspeeder.service"];
    };
  };


  systemd.services.udp2raw = {
    description = "udp2raw tunnel";
    wantedBy = [ "udpspeeder.service" ];

    serviceConfig = {
      User = "xray_tproxy";
      EnvironmentFile = "/run/tproxy/.env";

      ExecStart = ''/etc/udp2raw_binaries/udp2raw_amd64_hw_aes \
                    -c \
                    -l 127.0.0.1:6443 \
                    -r ''${SERVER_IP}:''${PORT} \
                    -k $UDP2RAW_PWD \
                    --raw-mode $RAW_MODE \
                    --auth-mode hmac_sha1 \
                    --fix-gro'';

      Restart = "always";
      RestartSec = "3s";
    };
  };

  systemd.services.udpspeeder = {
    description = "Run udpspeeder as a tproxy user";

    path = [ pkgs.udpspeeder ];
    serviceConfig = {
      EnvironmentFile = "/run/tproxy/.env";
      #ExecStart = ''${pkgs.udpspeeder}/bin/speederv2 -c -l 0.0.0.0:7443 -r 127.0.0.1:6443 -k $UDPSPEEDER_PWD -f2:1,150:50 --timeout 10 -i 10 --mode 0 --log-level 5'';
      #udpspeeder broken
      ExecStart = ''/etc/speederv2_binaries/speederv2_amd64 -c -l 0.0.0.0:7443 -r 127.0.0.1:6443 -k $UDPSPEEDER_PWD -f3:1,50:10 --timeout 10 -i 10 --mode 0 --log-level 5'';

      User="xray_tproxy";
    };
  };

  /*
    services.samba = {
    enable = true;
    settings = {
      myshare = {
        path = "/home/iopq/Public/";
        writable = true;
        "browseable" = "yes";
        "create mask" = "0644";
        "directory mask" = "0755";
        "force user" = "iopq";
        guestOk = true;
      };
    };

  };*/
}