# SPDX-FileCopyrightText: 2024 Lubin Bailly <lubin.bailly@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2

{ config, lib, ... }:

let
  inherit (lib)
    concatStrings
    concatStringsSep
    filter
    hasPrefix
    length
    mkOption
    splitString
    ;

  inherit (lib.types)
    enum
    listOf
    port
    str
    ;
in

{
  options = {
    system = {
      host-name = mkOption {
        type = str;
        description = "The hostname of the switch.";
      };
      root-authentication = {
        hashedPasswd = mkOption {
          type = str;
          description = "Hashed password for root.";
        };
        ssh-keys = mkOption {
          type = listOf str;
          description = "ssh keys for root user.";
          default = [ ];
        };
      };
      services = {
        ssh.root-login = mkOption {
          type = enum [
            "allow"
            "deny"
            "deny-password"
          ];
          description = "Login policy to use for root.";
        };
        netconf.port = mkOption {
          type = port;
          description = "Port to use for netconf.";
          default = 830;
        };
      };
    };
    netconf.xmls.system = mkOption {
      type = str;
      visible = false;
      readOnly = true;
    };
  };
  config.netconf.xmls.system =
    let
      ssh-keys1 = map (splitString " ") config.system.root-authentication.ssh-keys;
      ssh-keys2 = map (key: if length key < 3 then key ++ [ "foo@bar" ] else key) ssh-keys1;
      ssh-keys = map (concatStringsSep " ") ssh-keys2;
      edsca = map (key: "<ssh-edsca><name>${key}</name></ssh-edsca>") (
        filter (hasPrefix "ssh-edsca ") ssh-keys
      );
      rsa = map (key: "<ssh-rsa><name>${key}</name></ssh-rsa>") (filter (hasPrefix "ssh-rsa ") ssh-keys);
      ed25519 = map (key: "<ssh-ed25519><name>${key}</name></ssh-ed25519>") (
        filter (hasPrefix "ssh-ed25519 ") ssh-keys
      );
    in
    ''
      <system>
        <host-name operation="replace">${config.system.host-name}</host-name>
        <root-authentication operation="replace">
          <encrypted-password>${config.system.root-authentication.hashedPasswd}</encrypted-password>
          ${concatStrings (edsca ++ rsa ++ ed25519)}
        </root-authentication>
        <services operation="replace">
          <ssh><root-login>${config.system.services.ssh.root-login}</root-login></ssh>
          <netconf>
            <ssh><port>${toString config.system.services.netconf.port}</port></ssh>
            <rfc-compliant/><yang-compliant/>
          </netconf>
        </services>
      </system>
    '';
}