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

with lib;
with types;
let
  cfg = config.samba-share;
in
{

  options.samba-share = {
    openPorts = mkEnableOption "open samba ports everywher";
    enable = mkEnableOption "enable samba-share";
    enableWSDD = mkEnableOption "enable services.samba-wsdd.enable";
    guestUser = mkOption {
      default = "media";
      type = str;
      description = ''
        user name a guest users uses.
      '';
    };
    folders = mkOption {
      default = { };
      type = with types; attrsOf str;
      description = ''
        folders to share as readonly
      '';
      example = {
        public = "/srv/downloads/movies";
      };
    };
    private = mkOption {
      default = { };
      type =
        with types;
        attrsOf (submodule {
          options = {
            users = mkOption {
              type = with types; str;
              description = ''
                System users allowed to access the folder.
                To set password:
                # nix-shell -p samba
                # smbpasswd -a <user>
              '';
            };
            folder = mkOption { type = with types; str; };
          };
        });
    };
  };

  config = mkMerge [

    (mkIf cfg.enable {

      services.samba = {
        enable = true;
        # services.samba.securityType = "share";
        settings = {
          "guest account" = cfg.guestUser;
          "map to guest" = "bad user";

          # disable printing
          "load printers" = "no";
          "printing" = "bsd";
          "printcap name" = "/dev/null";
          "disable spoolss" = "yes";
        };
        #extraConfig = ''
        #  guest account = ${cfg.guestUser}
        #  map to guest = bad user
        #  # disable printing
        #  load printers = no
        #  printing = bsd
        #  printcap name = /dev/null
        #  disable spoolss = yes
        #'';

        shares =
          mapAttrs' (name: path: {
            name = name;
            value = {
              browsable = "yes";
              comment = "read only share ${name}";
              path = path;
              "read only" = "yes";
              "guest ok" = "yes";
            };
          }) cfg.folders
          // (mapAttrs' (
            name:
            { users, folder, ... }:
            {
              name = name;
              value = {
                browsable = "yes";
                comment = "read write share ${name}";
                path = folder;
                "valid users" = users;
                "read only" = "no";
                "guest ok" = "no";
              };
            }
          ) cfg.private);
      };

      #users.users.smbguest = {
      #  name = "smbguest";
      #  uid = config.ids.uids.smbguest;
      #  description = "smb guest user";
      #  home = "/home/smbguest";
      #  createHome = true;
      #  group = "smbguest";
      #};
      #users.groups.smbguest = { };

    })

    # todo : maybe better to have a parameter for this
    (mkIf config.services.syncthing.enable {
      users.groups."syncthing".members = [ "smbguest" ];
    })

    (mkIf cfg.openPorts {
      networking.firewall.allowedTCPPorts = [
        445
        139
        5357
      ];
      networking.firewall.allowedUDPPorts = [
        137
        138
        3702
      ];
    })

    (mkIf cfg.enableWSDD {
      services.samba-wsdd.enable = true;
      services.samba-wsdd.discovery = true;
    })
  ];
}