{ config, lib, pkgs, ... }:

# usual environment, as a thin OS

let
  nixpkgs = builtins.fetchTarball (import ../nixpkgs.nix);
in {
  imports = [ ./users.nix ];

  console.font = "${pkgs.fira-mono}/share/fonts/opentype/FiraMono-Regular.otf";

  security.sudo.wheelNeedsPassword = true;
  security.pam.yubico.enable = true;
  security.pam.yubico.debug = false;
  security.pam.yubico.control = "sufficient";  # use yubikey in lieu of password
  security.pam.yubico.mode = "challenge-response";

  boot.initrd.availableKernelModules = [
    "ehci_pci" "ahci"
    "usb_storage" "sd_mod"
  ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [];

  fileSystems."/boot".device = "/dev/disk/by-label/boot";
  fileSystems."/boot".fsType = "vfat";

  fileSystems."/".device = "/dev/disk/by-label/nixos";
  fileSystems."/".fsType = "ext4";

  swapDevices = [
    { device = "/dev/disk/by-label/swap"; }
  ];

  networking.hostName = "helium";
  networking.networkmanager.enable = true;
  networking.firewall.allowedTCPPorts = [
    24800 # barrier
  ];

  time.timeZone = "America/New_York";

  location.latitude = 40.80;
  location.longitude = -81.52;

  fonts.fonts = with pkgs; [
    google-fonts mononoki source-code-pro fantasque-sans-mono hack-font
    fira fira-code fira-code-symbols
  ];

  environment.systemPackages = with pkgs; [
    yubioath-desktop
    yubico-pam
    yubikey-manager
    yubikey-personalization
  ];

  nixpkgs = {
    config = {
      allowUnfree = true;
      allowBroken = true;
    };
  };

  hardware.video.hidpi.enable = true;
  hardware.enableAllFirmware = true;
  hardware.bluetooth.enable = true;
  hardware.bluetooth.package = pkgs.bluezFull;
  # hardware.acpilight.enable = true;
  hardware.brillo.enable = true;
  hardware.opengl.enable = true;

  sound.enable = true;
  sound.mediaKeys.enable = true;
  hardware.pulseaudio.enable = true;
  hardware.pulseaudio.daemon.logLevel = "debug";
  # hardware.pulseaudio.extraConfig = "load-module module-loopback";

  programs = {
    bash.enableCompletion = true;
    command-not-found.enable = true;
    light.enable = true;
    gnupg.agent = {
      enable = true;
      enableSSHSupport = true;
    };
    mosh.enable = true;
    ssh.agentTimeout = "1h";
  };

  services = {
    pcscd.enable = true;

    logind.lidSwitch = "suspend";
    logind.lidSwitchDocked = "lock";
    logind.lidSwitchExternalPower = "lock";
    #logind.extraConfig = "IdleAction=lock";

    clight.enable = true;
    clight.temperature.day = 5000;
    clight.temperature.night = 1800;

    printing.enable = true;

    xserver.enable = true;
    xserver.autorun = true;
    xserver.layout = "us";
    xserver.libinput.enable = true;
    xserver.libinput.mouse.additionalOptions = ''
      Option "ScrollMethod" "Button"
      Option "ScrollButton" "3"
    '';
    xserver.libinput.mouse.buttonMapping = "1 2 8 4 5 6 7 3 9";
    xserver.xkbOptions = "caps:ctrl_modifier";
    xserver.dpi = 166;

    xserver.displayManager.sddm.enable = true;
    xserver.windowManager.xmonad.enable = true;
    xserver.desktopManager.xterm.enable = true;

    xserver.xautolock.enable = false;
    xserver.xautolock.locker = "${pkgs.xlockmore}/bin/xlock -mode matrix";
    xserver.xautolock.nowlocker = "${pkgs.xlockmore}/bin/xlock -mode matrix"; # xautolock -locknow
    xserver.xautolock.time = 5; # minutes
    #xserver.xautolock.killer = "${pkgs.systemd}/bin/systemctl suspend";
    #xserver.xautolock.killtime = 120; # minutes
    xserver.xautolock.enableNotifier = true;
    xserver.xautolock.notify = 30; # seconds
    xserver.xautolock.notifier = ''${pkgs.libnotify}/bin/notify-send "Locking in 30 seconds"'';

    vnstat.enable = true;

    # security stuff
    fail2ban.enable = true;
    clamav.daemon.enable = false;
    clamav.updater.enable = false;

    udev.extraRules = ''
      # allows xlock to read the yubikey for challenge-response when unlocking.
      # you need to do 'udevadm control --reload && udevadm trigger' after
      # changing this. 'ykinfo -v' without sudo should work.
      ACTION!="add|change", GOTO="yubico_end", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0010|0110|0111|0114|0116|0401|0403|0405|0407|0410", OWNER="ben", MODE="0600"
      LABEL="yubico_end"

      # when yubi is removed, activate yubilock
      #ACTION=="remove", ENV{ID_BUS}=="usb", ENV{ID_VENDOR_ID}=="1050", ENV{ID_MODEL_ID}=="0407", ENV{ID_SERIAL}="Yubico_Yubikey_4_OTP+U2F+CCID", RUN+="${pkgs.systemd}/bin/systemctl start xlock"

      #Flipper Zero serial port
      SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", ATTRS{manufacturer}=="Flipper Devices Inc.", TAG+="uaccess"
      #Flipper Zero DFU
      SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", ATTRS{manufacturer}=="STMicroelectronics", TAG+="uaccess"
    ''; # flipper is not in 21.11: + "${pkgs.qFlipper}/etc/udev/rules.d/42-flipperzero.rules";
  };
  systemd.services = {
    "xlock" = {
      enable = false;
      script = "xlock";
      path = [ pkgs.xlockmore  ];
      # nat sure about these targets
      wantedBy = [ "sleep.target" "suspend.target" "hibernate.target" ];
      after = [ "sleep.target" "suspend.target" "hibernate.target" ];
      environment = { DISPLAY = ":0"; };
      # i think i can get rid of user if I use this script:
      # https://0day.work/locking-the-screen-when-removing-a-yubikey/
      serviceConfig.User = "ben";
    };
  };

  # Use the systemd-boot EFI boot loader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  powerManagement.enable = true;
  powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";

  nix.nixPath = [
      "nixpkgs=${nixpkgs}"
      "nixos-config=/etc/nixos/configuration.nix"
      "/nix/var/nix/profiles/per-user/root/channels"
    ];

  nix.gc.automatic = false;
  nix.gc.dates = "03:15";

  nix.extraOptions = ''
    builders-use-substitutes = true
  '';

  nix.buildMachines = [
      {
        hostName = "dev.simatime.com";
        sshUser = "ben";
        sshKey = "/home/ben/.ssh/id_rsa";
        system = "x86_64-linux";
        supportedFeatures = [
          "x86_64-linux"
          "big-parallel"
        ];
      }
    ];
  nix.distributedBuilds = true;

  nix.settings.trusted-users = [ "root" "ben" ];
  nix.settings.substituters =  [ "https://cache.nixos.org/" ];
  nix.settings.max-jobs = lib.mkDefault 4;

  # This value determines the NixOS release with which your system is to be
  # compatible, in order to avoid breaking some software such as database
  # servers. You should change this only after NixOS release notes say you
  # should.
  system.stateVersion = "19.03"; # Did you read the comment?
  system.autoUpgrade.enable = true;

}