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

with lib;

let

  cfg = config.graylog.pipeline;

in {

  options.graylog.pipeline = mkOption {
    default = { };
    type = with types;
      attrsOf (submodule ({ name, ... }: {
        options = {
          name = mkOption {
            type = with types; str;
            default = name;
            description = ''
              name of the pipeline
            '';
          };
          streamId = mkOption {
            type = with types; nullOr str;
            default = null;
            example = "000000000000000001";
            description = ''
              stream id on which this pipeline should operate
              dont use terraform references here.
            '';
          };
          description = mkOption {
            type = with types; str;
            default = "";
            description = ''
              description of the pipeline
            '';
          };
          # todo : create proper module system here
          source = mkOption {
            type = with types; str;
            description = ''
              source of the pipeline (without the header and the end)
            '';
          };
        };
      }));
  };

  config = let
    allPipelines = cfg;
    allPipelineConnections = mapAttrsToList (name: values: {
      "${values.streamId}" = "\${graylog_pipeline.${name}.id}";
    }) (filterAttrs (name: values: values.streamId != null) allPipelines);
    collected = foldAttrs (n: a: [ n ] ++ a) [ ] allPipelineConnections;
  in mkIf (cfg != { }) {

    # create pipelines
    resource."graylog_pipeline" = mapAttrs (name: pipelineConfig: {
      source = ''
        pipeline "${pipelineConfig.name}"
        ${pipelineConfig.source}
        end
      '';
      description = pipelineConfig.description;
    }) allPipelines;

    resource."graylog_pipeline_connection" = let
      mapping = filter (name: builtins.match ".*\\$.*" name != null)
        (builtins.attrNames collected);

    in mkAssert (mapping == [ ]) ''
      graylog.pipeline.<name>.streamId =
        ${concatStringsSep "\n  " mapping}
      is not valid.

      use graylog.stream.<name>.pipelines instead
    '' (mapAttrs (name: pipelineConfig: {
      stream_id = name;
      pipeline_ids = pipelineConfig;
    }) collected);

  };

}