{ config, pkgs, lib, ... }:
with lib; {
  boot = {
    binfmt.emulatedSystems = [ "armv7l-linux" "aarch64-linux" ];
    # kernelPackages = pkgs.linuxPackages_latest;
    loader = {
      systemd-boot.enable = true;
      efi.canTouchEfiVariables = true;
    };
  };

  console = {
    font = "Lat2-Terminus16";
    keyMap = "it";
  };

  environment = {
    pathsToLink = [ "/share/zsh" ];
    systemPackages = with pkgs; [ kakoune tmux vim ];
  };

  hardware = {
    enableRedistributableFirmware = true;

    # nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_470;
    # nvidia.nvidiaPersistenced = true; # HEADLESS
    # nvidia.prime = {
    #   offload.enable = false;
    #   sync.enable = true;
    #   intelBusId = "PCI:0:2:0";
    #   nvidiaBusId = "PCI:1:0:0";
    # };

    opengl = {
      enable = true;
      extraPackages = with pkgs; [
        intel-media-driver
        libvdpau-va-gl
        vaapiIntel
        vaapiVdpau
      ];
    };

    bluetooth.enable = true;
  };

  i18n.defaultLocale = "it_IT.UTF-8";

  programs = {
    dconf.enable = true;
    gnupg.agent = {
      enable = true;
      enableSSHSupport = true;
    };
    zsh = {
      enable = true;
      syntaxHighlighting.enable = true;
    };
  };

  networking = {
    hostName = "loki";
    interfaces = {
      eno1.useDHCP = true;
      wlp7s0.useDHCP = true;
    };
    networkmanager.enable = true;
    useDHCP = false;
  };

  time.timeZone = "Europe/Rome";

  services = {
    avahi = {
      enable = true;
      openFirewall = true;
      nssmdns = true;
      publish = {
        enable = true;
        addresses = true;
        domain = true;
        userServices = true;
        workstation = true;
      };
      extraServiceFiles = {
        ssh = "${pkgs.avahi}/etc/avahi/services/ssh.service";
      };
    };
    bazarr = {
      enable = true;
      openFirewall = true;
      group = "users";
    };
    blueman.enable = true;
    dbus.packages = with pkgs; [ dconf ];
    fail2ban = {
      enable = true;
      bantime-increment.enable = true;
    };
    gnome.gnome-keyring.enable = true;
    gvfs = { enable = true; package = mkForce pkgs.gnome3.gvfs; };
    jackett = { enable = true; openFirewall = true; group = "users"; };
    jellyfin = { enable = true; package = pkgs.unstable.jellyfin; openFirewall = true; group = "users"; };
    logind.lidSwitch = "ignore";
    # node-red = { enable = true; openFirewall = true; withNpmAndGcc = true; };
    openssh = {
      enable = true;
      openFirewall = true;
      permitRootLogin = "no";
      passwordAuthentication = false;
    };
    # plex = { enable = true; openFirewall = true; group = "users"; };
    power-profiles-daemon.enable = true;
    radarr = {
      enable = true;
      openFirewall = true;
      group = "users";
    };
    samba-wsdd = {
      enable = true;
      discovery = true;
    };
    samba = {
      enable = true;
      enableNmbd = true;
      enableWinbindd = true;
      nsswins = true;
      extraConfig = ''
        workgroup = WORKGROUP
        load printers = no
        smb encrypt = required
      '';
      shares =
        let
          common = {
            "public" = "no";
            "writeable" = "yes";
            "create mask" = "0700";
            "directory mask" = "2700";
            "browseable" = "yes";
            "guest ok" = "no";
            "read only" = "no";
            "force group" = "users";
          };
        in
        {
          bertof = recursiveUpdate common {
            path = "/mnt/raid0/bertof";
            comment = "Bertof samba share";
            "force user" = "bertof";
            "valid users" = "bertof";
          };
          tiziano = recursiveUpdate common {
            path = "/mnt/raid0/tiziano";
            comment = "Tiziano samba share";
            "force user" = "tiziano";
            "valid users" = "tiziano";
          };
          condiviso = recursiveUpdate common {
            path = "/mnt/raid0/condiviso";
            comment = "Samba share condiviso";
            "valid users" = "bertof tiziano";
            "create mask" = "0770";
            "directory mask" = "2770";
            "force create mode" = "0660";
            "force directory mode" = "2770";
          };
          bertof_safe = recursiveUpdate common {
            path = "/mnt/raid1/bertof";
            comment = "Bertof samba share";
            "force user" = "bertof";
            "valid users" = "bertof";
          };
          tiziano_safe = recursiveUpdate common {
            path = "/mnt/raid1/tiziano";
            comment = "Tiziano samba share";
            "force user" = "tiziano";
            "valid users" = "tiziano";
          };
          condiviso_safe = recursiveUpdate common {
            path = "/mnt/raid1/condiviso";
            comment = "Samba share condiviso";
            "valid users" = "bertof tiziano";
            "create mask" = "0770";
            "directory mask" = "2770";
            "force create mode" = "0660";
            "force directory mode" = "2770";
          };
        };
    };
    smartd = {
      enable = true;
      notifications.x11.enable = true;
    };
    sonarr = {
      enable = true;
      openFirewall = true;
      group = "users";
    };
    thermald.enable = true;
    transmission = {
      enable = true;
      openFirewall = true;
      group = "users";
      settings = {
        download-dir = "/mnt/raid0/condiviso/Scaricati/Torrent";
        incomplete-dir = "/mnt/raid0/condiviso/Scaricati/Torrent/.incomplete";
      };
    };
    xserver = {
      # enable = true;
      # videoDrivers = [ "nvidia" ];
      # layout = "it";
      # xkbOptions = "eurosign:e;";
      # libinput.enable = true;
    };

    zoneminder = {
      enable = true;
      openFirewall = true;
      cameras = 3;
      hostname = "0.0.0.0";
      database = {
        username = "zoneminder";
        createLocally = true;
      };
    };

    mysql = {
      # enable = true;
      ensureUsers = [{
        name = "bertof";
        ensurePermissions = { "*.*" = "ALL PRIVILEGES"; };
      }];
    };
  };

  users.users = {
    bertof = {
      isNormalUser = true;
      extraGroups = [
        "audio"
        "input"
        "docker"
        "libvirtd"
        "network"
        "networkmanager"
        "usb"
        "video"
        "wheel"
      ];
      shell = pkgs.zsh;
    };
    tiziano = {
      isNormalUser = true;
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMExwtJFk6HjySrTZwJH67SOHC3hlL28NO4oe2GXsv6k"
      ];
    };
    jellyfin.extraGroups = [ "video" ];
  };

  services.snapper = {
    configs =
      let
        commonExtraConfig = ''
          ALLOW_USERS="bertof"
          TIMELINE_CREATE=yes
          TIMELINE_CLEANUP=yes
        '';
      in
      {
        bertof_raid0 = {
          subvolume = "/mnt/raid0/bertof";
          extraConfig = ''
            ALLOW_USERS="bertof"
            ${commonExtraConfig}
          '';
        };
        tiziano_raid0 = {
          subvolume = "/mnt/raid0/tiziano";
          extraConfig = ''
            ALLOW_USERS="tiziano"
            ${commonExtraConfig}
          '';
        };
        condiviso_raid0 = {
          subvolume = "/mnt/raid0/condiviso";
          extraConfig = ''
            ALLOW_USERS="bertof tiziano"
            ${commonExtraConfig}
          '';
        };
      };
  };

  systemd.packages = with pkgs; [ syncthing ];
  systemd.services =
    let
      common = {
        documentation = [ "man:syncthing(1)" ];
        startLimitIntervalSec = 60;
        startLimitBurst = 4;
        after = [ "network.target" ];
        environment = {
          STNORESTART = "yes";
          STNOUPGRADE = "yes";
        };
        wantedBy = [ "default.target" ];
        serviceConfig = {
          Restart = "on-failure";
          RestartSec = 1;
          SuccessExitStatus = "3 4";
          RestartForceExitStatus = "3 4";

          Group = config.ids.gids.users;
          MemoryDenyWriteExecute = true;
          NoNewPrivileges = true;
          PrivateDevices = true;
          PrivateMounts = true;
          PrivateTmp = true;
          PrivateUsers = true;
          ProtectControlGroups = true;
          ProtectHostname = true;
          ProtectKernelModules = true;
          ProtectKernelTunables = true;
          RestrictNamespaces = true;
          RestrictRealtime = true;
          RestrictSUIDSGID = true;
          CapabilityBoundingSet = [
            "~CAP_SYS_PTRACE"
            "~CAP_SYS_ADMIN"
            "~CAP_SETGID"
            "~CAP_SETUID"
            "~CAP_SETPCAP"
            "~CAP_SYS_TIME"
            "~CAP_KILL"
          ];
        };
      };
    in
    {
      syncthing-bertof = recursiveUpdate common {
        description = "Syncthing service bertof";
        serviceConfig = {
          User = "bertof";
          ExecStart =
            "${pkgs.syncthing}/bin/syncthing -no-browser -gui-address=0.0.0.0:8384 -home=/mnt/raid0/bertof/Syncthing/.config";
        };
      };
      syncthing-tiziano = recursiveUpdate common {
        description = "Syncthing service tiziano";
        serviceConfig = {
          User = "tiziano";
          ExecStart =
            "${pkgs.syncthing}/bin/syncthing -no-browser -gui-address=0.0.0.0:8385 -home=/mnt/raid0/tiziano/Syncthing/.config";
        };
      };
    };

  networking.firewall = {
    enable = true;
    allowPing = true;
    allowedTCPPorts = [
      445 # SAMBA
      139 # SAMBA
      5357 # SAMBA-WSDD
      8123 # HOME ASSISTANT
      8384 # SYNCTHING
      8385 # SYNCTHING
    ];
    allowedUDPPorts = [
      137 # SYNCTHING
      138 # SYNCTHING
      3702 # SAMBA-WSDD
    ];
    extraCommands =
      "iptables -t raw -A OUTPUT -p udp -m udp --dport 137 -j CT --helper netbios-ns";
  };

  virtualisation = {
    docker.enable = true;
    # kvmgt.enable = true;
    # libvirtd.enable = true;
    podman.enable = true;
    # virtualbox.host.enable = true;

    oci-containers.containers = {
      # hass = {
      #   image = "ghcr.io/home-assistant/home-assistant:stable";
      #   environment = { TZ = "Europe/Rome"; };
      #   extraOptions = [ "--privileged" "--network=host" "--pull=always" ];
      #   ports = [ "8123:8123" ];
      #   volumes = [ "/var/lib/hass:/config" "/mnt/raid0/condiviso:/media" ];
      # };
    };
  };

  services.home-assistant = {
    enable = true;
    # package = pkgs.unstable.home-assistant;
    # openFirewall = true;
    # config = {
    #   default_config = { };
    #   name = "Casa";
    #   latitude = 45.05197317019396;
    #   longitude = 11.653331816196443;
    #   elevation = 17;
    #   unit_system = "metric";
    #   time_zone = "Europe/Rome";
    # };
    config = null;
    configDir = "/var/lib/hass";
    configWritable = true;
    extraComponents = [
      "default_config"


      "accuweather"
      "alert"
      "analytics"
      "automation"
      "backup"
      "bayesian"
      "binary_sensor"
      "blueprint"
      # "bluetooth_le_tracker"
      # "bluetooth_tracker"
      "button"
      "camera"
      "cast"
      "citybikes"
      "config"
      "configurator"
      "coronavirus"
      "counter"
      "cover"
      "default_config"
      "derivative"
      "device_automation"
      "device_sun_light_trigger"
      "device_tracker"
      "dhcp"
      "dlib_face_detect"
      "dlib_face_identify"
      "dlna_dmr"
      "dlna_dms"
      "esphome"
      "flux"
      "group"
      "hassio"
      "input_boolean"
      "input_button"
      "input_datetime"
      "input_number"
      "input_select"
      "input_text"
      "jellyfin"
      "local_file"
      "media_player"
      "met"
      # "meteoalarm"
      "mobile_app"
      "network"
      "notify"
      "ping"
      "plex"
      "proximity"
      "radarr"
      "radio_browser"
      "random"
      # "schedule"
      "script"
      "sonarr"
      # "spotify"
      "tcp"
      "template"
      "threshold"
      "timer"
      "tod" # times of the day
      "trend"
      "upnp"
      "workday"
      "zeroconf"
      "zoneminder"
    ];
  };

  security.sudo.extraConfig = ''
    Defaults pwfeedback
  '';

  nixpkgs.config.allowUnfree = true;

  system.autoUpgrade = {
    enable = true;
    allowReboot = true;
    flags = [
      "-I"
      "nixos-config=/home/bertof/.config/nixpkgs/nixos/loki.nix"
      "--upgrade"
    ];
  };

  system.stateVersion = "21.11";
}
