{ config, pkgs, ... }:
#
# xmpp chat service
#
let
  salespage = pkgs.runCommand "salespage" {} ''
    mkdir -p $out
    ${pkgs.pandoc}/bin/pandoc \
      --standalone \
      -f commonmark_x \
      --include-in-header ${./Que/Style.css} \
      --include-in-header ${./Nixpert/ChatWidget.html} \
      -t html \
      ${./Nixpert.md} \
      > $out/index.html
  '';
  ports = import ../Cloud/Ports.nix;
  ssl = {
    cert = "/var/lib/acme/simatime.com/fullchain.pem";
    key = "/var/lib/acme/simatime.com/key.pem";
  };
in {
  networking.firewall.allowedTCPPorts = [
    # https://prosody.im/doc/ports
    5000  # file transfer
    5222  # client connections
    5269  # server-to-server
    5280  # http
    5281  # https
    5347  # external components
    5582  # telnet console
  ];

  services.prosody = {
    enable = true;
    package = pkgs.prosody.override {
      withCommunityModules = [
        "conversejs"
      ];
    };
    # when i learn how to use security.acme better, and use separate certs, then i
    # can fix this group
    group = "nginx";
    admins = [ "bsima@simatime.com" ];
    allowRegistration = true;
    inherit ssl;
    uploadHttp = {
      domain = "upload.simatime.com";
      uploadExpireAfter = toString (60*60*24*30); # 30 days, as seconds
    };
    modules = {
      announce = true;
      bosh = true;
      groups = true;
      motd = true;
      register = true;
      server_contact_info = true;
      vcard = true;
      watchregistrations = true;
      websocket = true;
      welcome = true;
    };
    extraConfig = ''
      conversejs_options = {
        allow_registration = true;
        --- authentication = "internal_plain";
        bosh_service_url = "https://simatime.com/http-bind";
        debug = true;
        loglevel = "debug";
        -- default_domain = "simatime.com";
        -- domain_placeholder = "simatime.com";
        -- jid = "simatime.com";
        -- keepalive = true;
        -- registration_domain = "simatime.com";
        websocket_url = "wss://simatime.com/xmpp-websocket";
      }

      cross_domain_websocket = { "https://simatime.com", "https://anon.simatime.com" }
      cross_domain_bosh = false; -- handle this with nginx
      consider_bosh_secure = true;

      -- this is a virtualhost that allows anonymous authentication. use this
      -- for the sales lobby. the nix module doesn't support 'authentication'
      -- so i have to do this here.
      VirtualHost "anon.simatime.com"
        authentication = "anonymous"
        ssl = {
          cafile = "/etc/ssl/certs/ca-bundle.crt";
          key = "/var/lib/acme/simatime.com/key.pem";
          certificate = "/var/lib/acme/simatime.com/fullchain.pem";
        };
    '';
    muc = [
      {
        domain = "conference.simatime.com";
        maxHistoryMessages = 10000;
        name = "Chat Rooms";
        restrictRoomCreation = "admin";
        roomDefaultHistoryLength = 20;
        roomDefaultMembersOnly = true;
        roomDefaultModerated = true;
        roomDefaultPublic = false;
      }
    ];
    virtualHosts = {
      "simatime.com" = {
        domain = "simatime.com";
        enabled = true;
        inherit ssl;
      };
    };
  };

  services.nginx.virtualHosts."simatime.com".locations."/http-bind" = {
    proxyPass = "https://simatime.com:5281/http-bind";
    extraConfig = ''
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_buffering off;
      add_header Access-Control-Allow-Origin "*";
    '';
  };

  services.nginx.virtualHosts."simatime.com".locations."/".return = "301 https://nixpert.chat";

  services.nginx.virtualHosts."nixpert.chat" = {
    forceSSL = true;
    enableACME = true;
    locations."/" = {
      root = "${salespage}";
      extraConfig = ''
        add_header Access-Control-Allow-Origin "*";
      '';
    };
  };

  services.nginx.virtualHosts."simatime.com".locations."/xmpp-websocket" = {
    proxyPass = "https://simatime.com:5281/xmpp-websocket";
    extraConfig = ''
      proxy_http_version 1.1;
      proxy_buffering off;
      proxy_set_header Host $host;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_read_timeout 86400;
      add_header Access-Control-Allow-Origin "*";
    '';
  };

  services.nginx.virtualHosts."simatime.com".locations."/chat" = {
    proxyPass = "https://simatime.com:5281/conversejs";
    extraConfig = ''
      add_header Access-Control-Allow-Origin "*";
    '';
  };

  services.nginx.virtualHosts."anon.simatime.com" = {
    useACMEHost = "simatime.com";
    forceSSL = true;
    locations = {
      "/http-bind" = {
        proxyPass = "https://anon.simatime.com:5281/http-bind";
        extraConfig = ''
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_buffering off;
          if ($request_method ~* "(GET|POST)") {
            add_header Access-Control-Allow-Origin "*";
          }
          if ($request_method = OPTIONS) {
            add_header Access-Control-Allow-Origin  "*";
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD";
            add_header Access-Control-Allow-Headers "Authorization, Origin, X-Requested-With, Content-Type, Accept";
            return 200;
          }
        '';
      };
    };
  };

  users.users.nginx.extraGroups = [ "prosody" ];

  security.acme.certs.${config.networking.domain}.extraDomainNames = [
    "upload.simatime.com" "conference.simatime.com" "simatime.com" "anon.simatime.com"
  ];

  #security.acme.certs.prosody = {
  #  domain = "${domain}";
  #  group = "prosody";
  #  dnsProvider = "rfc2136";
  #  #credentialsFile = config.secrets.files.dns_creds.path;
  #  postRun = "systemctl restart prosody";
  #  extraDomainNames = [
  #    domain
  #    "upload.${domain}"
  #  ];
  #};
}