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

with import <stockholm/lib>;
let

  cfg = config.krebs.Reaktor;
  homedir = "/var/lib/Reaktor";

  out = {
    options.krebs.Reaktor = api;
    config = mkIf (cfg != {}) imp;
  };

  api = mkOption {
    default = {};
    type = with types; attrsOf (submodule ({ options = {

      nickname = mkOption {
        default = config.krebs.build.host.name + "|r";
        type = types.str;
        description = ''
          The nick name of the irc bot.
          Defaults to {hostname}|r
        '';
      };

      overrideConfig = mkOption {
        default = null;
        type = types.nullOr types.str;
        description = ''
          configuration to be used instead of default ones.
          Reaktor default cfg can be retrieved via `reaktor get-config`
        '';
      };

      plugins = mkOption {
        default = [pkgs.ReaktorPlugins.nixos-version];
      };

      workdir = mkOption {
        default = "/var/lib/Reaktor";
        type = types.path;
        description = ''
          path to be used as workdir (home dir is still /var/lib/Reaktor)
        '';
      };

      extraConfig = mkOption {
        default = "";
        type = types.str;
        description = ''
          configuration appended to the default or overridden configuration
        '';
      };

      extraEnviron = mkOption {
        default = {};
        type = types.attrsOf types.str;
        description = ''
          Environment to be provided to the service, can be:
            REAKTOR_HOST
            REAKTOR_PORT
            REAKTOR_STATEDIR

            debug and nickname can be set separately via the Reaktor api
        '';
      };

      channels = mkOption {
        default = [ "#krebs" ];
        type = types.listOf types.str;
        description = ''
          Channels the Reaktor should connect to at startup.
        '';
      };

      debug = mkOption {
        default = false;
        description = ''
          Reaktor debug output
        '';
      };
    };}));
  };

  imp = {
    # TODO get user per configured bot
    # TODO get home from api
    # for reaktor get-config
    users.extraUsers = singleton rec {
      name = "Reaktor";
      uid = genid name;
      description = "Reaktor user";
      home = homedir;
      createHome = true;
    };

    #users.extraGroups = singleton {
    #  name = "Reaktor";
    #  gid = config.ids.gids.Reaktor;
    #};

    systemd.services = mapAttrs' (name: botcfg:
      let
        ReaktorConfig = pkgs.writeText "config.py" ''
          ${if (isString botcfg.overrideConfig ) then ''
          # Overriden Config
          ${botcfg.overrideConfig}
          '' else ""}
          ## Extra Config
          ${concatStringsSep "\n" (map (plug: plug.config) botcfg.plugins)}
          ${botcfg.extraConfig}
        '';
      in nameValuePair "Reaktor-${name}" {
        path = with pkgs; [
          git # for nag
          jq # for tell
          python # for caps
          utillinux # flock for tell
        ];
        description = "Reaktor IRC Bot";
        after = [ "network.target" ];
        wantedBy = [ "multi-user.target" ];
        environment = {
          GIT_SSL_CAINFO = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
          PYTHONPATH = "${pkgs.Reaktor}/lib/python3.6/site-packages";
          REAKTOR_NICKNAME = botcfg.nickname;
          REAKTOR_DEBUG = (if botcfg.debug  then "True" else "False");
          REAKTOR_CHANNELS = lib.concatStringsSep "," botcfg.channels;
          state_dir = botcfg.workdir;

        } // botcfg.extraEnviron;
        serviceConfig= {
          ExecStartPre = pkgs.writeScript "Reaktor-init" ''
            #! /bin/sh
            ${if (isString botcfg.overrideConfig) then
              ''cp ${ReaktorConfig} /tmp/reaktor-${name}-config.py''
            else
              ''(${pkgs.Reaktor}/bin/reaktor get-config;cat "${ReaktorConfig}" ) > /tmp/reaktor-${name}-config.py''
            }
            mkdir -p ${botcfg.workdir}
          '';
          ExecStart = "${pkgs.Reaktor}/bin/reaktor run /tmp/reaktor-${name}-config.py";
          PrivateTmp = "true";
          User = "Reaktor";
          Restart = "always";
          RestartSec= "30" ;
        };
      }
    ) cfg;

  };

in
out
