{ lib, pkgs, config, ... }:
let
  cfg = config.cos.bikeability;
in
{
  imports = [];

  options.cos.bikeability = {
    enable = lib.mkEnableOption "Bikeability server";
    dataDir = lib.mkOption {
      type = lib.types.path;
    };
    tileserverHost = lib.mkOption {
      type = lib.types.str;
      default = "0.0.0.0";
    };
    tileserverPort = lib.mkOption {
      type = lib.types.port;
      default = 8000;
    };
    clientHost = lib.mkOption {
      type = lib.types.str;
      default = "0.0.0.0";
    };
    clientPort = lib.mkOption {
      type = lib.types.port;
      default = 8000;
    };
    openFirewall = lib.mkOption {
      type = lib.types.bool;
      default = false;
    };
    firewallInterface = lib.mkOption {
      type = lib.types.str;
      default = "";
    };
    fetchAndRenderTimerConfig = lib.mkOption {
      type = lib.types.attrs;
      default = {
        OnCalendar = "daily";
        Persistent = true;
      };
    };
  };

  config = lib.mkIf cfg.enable {

    systemd.services.bikeability-tileserver = {
      description = "bikeability-tileserver.claytonhickey.me";
      wantedBy = [ "default.target" ];
      script = ''#!/bin/sh
        cd ${cfg.dataDir} &&
        ${pkgs.mbtileserver}/bin/mbtileserver --host ${cfg.tileserverHost} --port ${builtins.toString cfg.tileserverPort} --enable-fs-watch
      '';
      serviceConfig = {
        Restart = "on-failure";
      };
    };

    virtualisation.oci-containers.containers.tileserver-gl = {
      image = "maptiler/tileserver-gl:latest";
      volumes = [
        "${cfg.dataDir}/tileserver-gl-data:/data"
      ];
      ports = [
        "${cfg.clientHost}:9000:8080"
      ];
    };

    systemd.services.bikeability-fetch-and-render = {
      script = ''
        set -eu
        cd ${cfg.dataDir}/bikeability-tilemaker
        ls
        PATH="${pkgs.wget}/bin:${pkgs.osmium-tool}/bin:$PATH" ./fetch-data.sh
        ${pkgs.tilemaker}/bin/tilemaker --config ${cfg.dataDir}/bikeability-tilemaker/tilemaker-config.json --process ${cfg.dataDir}/bikeability-tilemaker/tilemaker-process.lua --output ${cfg.dataDir}/bikeability-new.mbtiles --input ${cfg.dataDir}/bikeability-tilemaker/data.osm.pbf
        mv ${cfg.dataDir}/bikeability-new.mbtiles ${cfg.dataDir}/tilesets/bikeability.mbtiles
        cp ${cfg.dataDir}/tilesets/bikeability.mbtiles ${cfg.dataDir}/tileserver-gl-data/bikeability.mbtiles
      '';
      serviceConfig = {
        Type = "oneshot";
        User = "clhickey";
      };
    };

    systemd.timers.bikeability-fetch-and-render = {
      wantedBy = [ "timers.target" ];
      timerConfig = cfg.fetchAndRenderTimerConfig // {
        Unit = "bikeability-fetch-and-render.service";
      };
    };
    
    services.nginx = {
      enable = true;
      virtualHosts."bikeability-client" = {
        listen = [ { addr = cfg.clientHost; port = cfg.clientPort; } ];
        locations."/" = {
          root = "${cfg.dataDir}/bikeability-client/";
        };
      };
    };

    networking.firewall.allowedTCPPorts = lib.mkIf (cfg.openFirewall && cfg.firewallInterface == "") [
      cfg.tileserverPort
      cfg.clientPort
    ];

    networking.firewall.interfaces.${cfg.firewallInterface}.allowedTCPPorts = lib.mkIf (cfg.openFirewall && cfg.firewallInterface != "") [
      cfg.tileserverPort
      cfg.clientPort
    ];

  };
}
