{ pkgs, config, scrapers, ... }:

let
  freifunkNodes = {
    "1139" = "10.200.4.120";
    "1884" = "10.200.7.100";
    "1891" = "10.200.7.107";
    "1099" = "10.200.4.80";
    "1864" = "10.200.7.80";
  };
  luftqualitaetStations = [ "1672" "1649" "1680" "1639" ];
in {
  c3d2.deployment.server = "server10";

  microvm.mem = 1024;

  networking.hostName = "scrape";

  users.groups.scrape = {};
  users.users.scrape = {
    isNormalUser = true;
    group = "scrape";
    # don't make /home/scrape inaccessible by nginx
    createHome = false;
  };

  services.nginx = {
    enable = true;
    virtualHosts."scrape.hq.c3d2.de" = {
      default = true;
      forceSSL = true;
      enableACME = true;
      root = config.users.users.scrape.home;
      extraConfig = ''
        autoindex on;
      '';
    };
  };

  systemd.services = let
    serviceConfig = {
      User = config.users.users.scrape.name;
      Group = config.users.users.scrape.group;
    };
    scraperPkgs = import scrapers { inherit pkgs; };
    makeService = { script, host ? "", user ? "", password ? "" }: {
      script = "${scraperPkgs."${script}"}/bin/${script} ${host} ${user} ${password}";
      inherit serviceConfig;
    };
    makeNodeScraper = nodeId: {
      name = "scrape-node${nodeId}";
      value = makeService {
        script = "freifunk_node";
        host = freifunkNodes."${nodeId}";
      };
    };
    makeLuftScraper = station: {
      name = "scrape-luftqualitaet${station}";
      value = makeService {
        script = "luftqualitaet";
        host = station;
      };
    };
  in {
    nginx.serviceConfig.ProtectHome = "read-only";

    scrape-xeri = makeService {
      script = "xerox";
      host = "xeri.hq.c3d2.de";
      inherit (pkgs.scrape-xeri-login) user password;
    };
    scrape-roxi = makeService {
      script = "xerox";
      host = "roxi.hq.c3d2.de";
    };
    scrape-matemat = makeService {
      script = "matemat";
      host = "matemat.hq.c3d2.de";
      inherit (pkgs.scrape-matemat-login) user password;
    };
    scrape-impfee = makeService {
      script = "impfee";
    };
    scrape-riesa-efau-kalender = {
      script = ''
        ${scraperPkgs.riesa-efau-kalender}/bin/riesa-efau-kalender > /tmp/riesa-efau-kalender.ics
        mv /tmp/riesa-efau-kalender.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-kreuzchor-termine = {
      script = ''
        ${scraperPkgs.kreuzchor-termine}/bin/kreuzchor-termine > /tmp/kreuzchor-termine.ics
        mv /tmp/kreuzchor-termine.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-dhmd-veranstaltungen = {
      script = ''
        ${scraperPkgs.dhmd-veranstaltungen}/bin/dhmd-veranstaltungen > /tmp/dhmd-veranstaltungen.ics
        mv /tmp/dhmd-veranstaltungen.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-mkz-programm = {
      script = ''
        ${scraperPkgs.mkz-programm}/bin/mkz-programm > /tmp/mkz-programm.ics
        mv /tmp/mkz-programm.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-drk-impfaktionen = {
      script = ''
        ${scraperPkgs.drk-impfaktionen}/bin/drk-impfaktionen > /tmp/drk-impfaktionen.ics
        mv /tmp/drk-impfaktionen.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-zuendstoffe = {
      script = ''
        ${scraperPkgs.zuendstoffe}/bin/zuendstoffe > /tmp/zuendstoffe.xml
        mv /tmp/zuendstoffe.xml ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-dresden-versammlungen = {
      script = ''
        ${scraperPkgs.dresden-versammlungen}/bin/dresden-versammlungen > /tmp/dresden-versammlungen.ics
        mv /tmp/dresden-versammlungen.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-azconni = {
      script = ''
        ${scraperPkgs.azconni}/bin/azconni > /tmp/azconni.ics
        mv /tmp/azconni.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-kunsthaus = {
      script = ''
        ${scraperPkgs.kunsthaus}/bin/kunsthaus > /tmp/kunsthaus.ics
        mv /tmp/kunsthaus.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-hfmdd = {
      script = ''
        ${scraperPkgs.hfmdd}/bin/hfmdd > /tmp/hfmdd.ics
        mv /tmp/hfmdd.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-hfbk-dresden = {
      script = ''
        ${scraperPkgs.hfbk-dresden}/bin/hfbk-dresden > /tmp/hfbk-dresden.ics
        mv /tmp/hfbk-dresden.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-staatsoperette = {
      script = ''
        ${scraperPkgs.staatsoperette}/bin/staatsoperette > /tmp/staatsoperette.ics
        mv /tmp/staatsoperette.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-tjg-dresden = {
      script = ''
        ${scraperPkgs.tjg-dresden}/bin/tjg-dresden > /tmp/tjg-dresden.ics
        mv /tmp/tjg-dresden.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-dresden-kulturstadt = {
      script = ''
        ${scraperPkgs.dresden-kulturstadt}/bin/dresden-kulturstadt > /tmp/dresden-kulturstadt.ics
        mv /tmp/dresden-kulturstadt.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-nabu = {
      script = ''
        ${scraperPkgs.nabu}/bin/nabu > /tmp/nabu.ics
        mv /tmp/nabu.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-museen-dresden = {
      script = ''
        ${scraperPkgs.museen-dresden}/bin/museen-dresden > /tmp/museen-dresden.ics
        mv /tmp/museen-dresden.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-criticalmass = {
      script = ''
        ${scraperPkgs.criticalmass}/bin/criticalmass > /tmp/criticalmass.ics
        mv /tmp/criticalmass.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
    scrape-kosmotique = {
      script = ''
        ${scraperPkgs.kosmotique}/bin/kosmotique > /tmp/kosmotique.ics
        mv /tmp/kosmotique.ics ${config.users.users.scrape.home}/
      '';
      inherit serviceConfig;
    };
  } // builtins.listToAttrs
    (map makeNodeScraper (builtins.attrNames freifunkNodes) ++
     map makeLuftScraper luftqualitaetStations
    );

  systemd.timers = let
    makeTimer = service: interval: {
      partOf = [ "${service}.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = interval;
    };
    makeNodeScraperTimer = nodeId:
      let name = "scrape-node${nodeId}";
      in {
        inherit name;
        value = makeTimer name "minutely";
      };
    makeLuftScraperTimer = station:
      let name = "scrape-luftqualitaet${station}";
      in {
        inherit name;
        value = makeTimer name "hourly";
      };
  in {
    scrape-xeri = makeTimer "scrape-xeri.service" "minutely";
    scrape-roxi = makeTimer "scrape-roxi.service" "minutely";
    scrape-fhem = makeTimer "scrape-fhem.service" "minutely";
    scrape-matemat = makeTimer "scrape-matemat.service" "minutely";
    scrape-impfee = makeTimer "scrape-impfee.service" "minutely";
    scrape-riesa-efau-kalender = {
      partOf = [ "scrape-riesa-efau-kalender.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-kreuzchor-termine = {
      partOf = [ "scrape-kreuzchor-termine.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "daily";
    };
    scrape-dhmd-veranstaltungen = {
      partOf = [ "scrape-dhmd-veranstaltungen.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-mkz-programm = {
      partOf = [ "scrape-mkz-programm.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-drk-impfaktionen = {
      partOf = [ "scrape-drk-impfaktionen.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-zuendstoffe = {
      partOf = [ "scrape-zuendstoffe.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-dresden-versammlungen = {
      partOf = [ "scrape-dresden-versammlungen.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-azconni = {
      partOf = [ "scrape-azconni.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-kunsthaus = {
      partOf = [ "scrape-kunsthaus.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-hfmdd = {
      partOf = [ "scrape-hfmdd.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-hfbk-dresden = {
      partOf = [ "scrape-hfbk-dresden.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-staatsoperette = {
      partOf = [ "scrape-staatsoperette.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-tjg-dresden = {
      partOf = [ "scrape-tjg-dresden.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-dresden-kulturstadt = {
      partOf = [ "scrape-dresden-kulturstadt.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-nabu = {
      partOf = [ "scrape-nabu.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-museen-dresden = {
      partOf = [ "scrape-museen-dresden.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-criticalmass = {
      partOf = [ "scrape-criticalmass.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
    scrape-kosmotique = {
      partOf = [ "scrape-kosmotique.service" ];
      wantedBy = [ "timers.target" ];
      timerConfig.OnCalendar = "hourly";
    };
  } // builtins.listToAttrs
    (map makeNodeScraperTimer (builtins.attrNames freifunkNodes) ++
     (map makeLuftScraperTimer luftqualitaetStations)
    );

  system.stateVersion = "20.03";
}
