{ config, lib, ... }:

with lib;
let
  cfg = config.my.nixpkgs;

  overlayType = mkOptionType {
    name = "nixpkgs-overlay";
    description = "nixpkgs overlay";
    check = lib.isFunction;
    merge = lib.mergeOneOption;
  };
in
{
  options.my.nixpkgs = {
    overlays = mkOption {
      default = [ ];
      type = types.listOf overlayType;
      example = literalExpression
        ''
          [
            (self: super: {
              openssh = super.openssh.override {
                hpnSupport = true;
                kerberos = self.libkrb5;
              };
            })
          ]
        '';
    };
    channels = mkOption {
      default = { };
      example = literalExpression ''
        {
          stable = inputs.nixpkgs-stable;
        }
      '';
      type = with types; attrsOf package;
    };
    overlaysForAllChannels = mkEnableOption "apply overlays for all channels";
  };

  config.nixpkgs = {
    overlays =
      let
        channelOverlays = _: prev:
          mapAttrs
            (_: value:
              import value {
                inherit (prev) system;
                config.allowUnfree = true;
                overlays = optional cfg.overlaysForAllChannels cfg.overlays;
              }
            )
            cfg.channels;
      in
      cfg.overlays ++ [ channelOverlays ];

    config.allowUnfree = true;
  };
}