package com.airlock.iam.servicecontainer.app.application.service.radius;

import com.airlock.iam.servicecontainer.app.application.service.radius.wrapper.context.IamRadiusServerContext;
import com.airlock.iam.servicecontainer.app.application.service.radius.wrapper.lib.IamRadiusServerAttribute;
import com.airlock.iam.servicecontainer.app.application.service.radius.wrapper.lib.IamRadiusServerAttributeCreationInfo;
import com.airlock.iam.servicecontainer.app.application.service.radius.wrapper.lib.NameValueResolved;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Nullable;
import java.util.Optional;
import java.util.function.Function;

public enum RadiusAttribute {
   ACCT_AUTHENTIC_NV("Acct-Authentic", 45, RadiusAttributeValueSetter.NAMED_VALUE),
   ACCT_DELAY_TIME_INT("Acct-Delay-Time", 41, RadiusAttributeValueSetter.INTEGER),
   ACCT_INPUT_GIGAWORDS_INT("Acct-Input-Gigawords", 52, RadiusAttributeValueSetter.INTEGER),
   ACCT_INPUT_OCTETS_INT("Acct-Input-Octets", 42, RadiusAttributeValueSetter.INTEGER),
   ACCT_INPUT_PACKETS_INT("Acct-Input-Packets", 47, RadiusAttributeValueSetter.INTEGER),
   ACCT_INTERIM_INTERVAL_INT("Acct-Interim-Interval", 85, RadiusAttributeValueSetter.INTEGER),
   ACCT_LINK_COUNT_INT("Acct-Link-Count", 51, RadiusAttributeValueSetter.INTEGER),
   ACCT_MULTI_SESSION_ID_STRING("Acct-Multi-Session-Id", 50, RadiusAttributeValueSetter.STRING_UTF8),
   ACCT_OUTPUT_GIGAWORDS_INT("Acct-Output-Gigawords", 53, RadiusAttributeValueSetter.INTEGER),
   ACCT_OUTPUT_OCTETS_INT("Acct-Output-Octets", 43, RadiusAttributeValueSetter.INTEGER),
   ACCT_OUTPUT_PACKETS_INT("Acct-Output-Packets", 48, RadiusAttributeValueSetter.INTEGER),
   ACCT_SESSION_ID_STRING("Acct-Session-Id", 44, RadiusAttributeValueSetter.STRING_UTF8),
   ACCT_SESSION_TIME_INT("Acct-Session-Time", 46, RadiusAttributeValueSetter.INTEGER),
   ACCT_STATUS_TYPE_NV("Acct-Status-Type", 40, RadiusAttributeValueSetter.NAMED_VALUE),
   ACCT_TERMINATE_CAUSE_NV("Acct-Terminate-Cause", 49, RadiusAttributeValueSetter.NAMED_VALUE),
   ACCT_TUNNEL_CONNECTION_STRING("Acct-Tunnel-Connection", 68, RadiusAttributeValueSetter.STRING_UTF8),
   ACCT_TUNNEL_PACKETS_LOST_INT("Acct-Tunnel-Packets-Lost", 86, RadiusAttributeValueSetter.INTEGER),
   ALLOWED_CALLED_STATION_ID_STRING("Allowed-Called-Station-Id", 174, RadiusAttributeValueSetter.STRING_UTF8),
   ARAP_CHALLENGE_RESPONSE_BYTES("ARAP-Challenge-Response", 84, RadiusAttributeValueSetter.OCTETS),
   ARAP_FEATURES_BYTES("ARAP-Features", 71, RadiusAttributeValueSetter.OCTETS),
   ARAP_PASSWORD_BYTES("ARAP-Password", 70, RadiusAttributeValueSetter.OCTETS),
   ARAP_SECURITY_INT("ARAP-Security", 73, RadiusAttributeValueSetter.INTEGER),
   ARAP_SECURITY_DATA_STRING("ARAP-Security-Data", 74, RadiusAttributeValueSetter.STRING_UTF8),
   ARAP_ZONE_ACCESS_NV("ARAP-Zone-Access", 72, RadiusAttributeValueSetter.NAMED_VALUE),
   BASIC_LOCATION_POLICY_RULES_BYTES("Basic-Location-Policy-Rules", 129, RadiusAttributeValueSetter.OCTETS),
   CALLBACK_ID_STRING("Callback-Id", 20, RadiusAttributeValueSetter.STRING_UTF8),
   CALLBACK_NUMBER_STRING("Callback-Number", 19, RadiusAttributeValueSetter.STRING_UTF8),
   CALLED_STATION_ID_STRING("Called-Station-Id", 30, RadiusAttributeValueSetter.STRING_UTF8),
   CALLER_ID_STRING("Caller-ID", 31, RadiusAttributeValueSetter.STRING_UTF8),
   CALLING_STATION_ID_STRING("Calling-Station-Id", 31, RadiusAttributeValueSetter.STRING_UTF8),
   CHALLENGE_STATE_STRING("Challenge-State", 24, RadiusAttributeValueSetter.STRING_UTF8),
   CHAP_CHALLENGE_BYTES("CHAP-Challenge", 60, RadiusAttributeValueSetter.OCTETS),
   CHAP_PASSWORD_BYTES("CHAP-Password", 3, RadiusAttributeValueSetter.OCTETS),
   CHARGEABLE_USER_IDENTITY_STRING("Chargeable-User-Identity", 89, RadiusAttributeValueSetter.STRING_UTF8),
   CHAR_NOECHO_INT("Char-Noecho", 250, RadiusAttributeValueSetter.INTEGER),
   CLASS_BYTES("Class", 25, RadiusAttributeValueSetter.OCTETS),
   CLIENT_ID_IPV4("Client-Id", 4, RadiusAttributeValueSetter.IPV4_ADDRESS),
   CLIENT_PORT_DNIS_STRING("Client-Port-DNIS", 30, RadiusAttributeValueSetter.STRING_UTF8),
   CLIENT_PORT_ID_INT("Client-Port-Id", 5, RadiusAttributeValueSetter.INTEGER),
   CONFIGURATION_TOKEN_STRING("Configuration-Token", 78, RadiusAttributeValueSetter.STRING_UTF8),
   CONNECT_INFO_STRING("Connect-Info", 77, RadiusAttributeValueSetter.STRING_UTF8),
   DELEGATED_IPV6_PREFIX_BYTES("Delegated-IPv6-Prefix", 123, RadiusAttributeValueSetter.OCTETS),
   DELEGATED_IPV6_PREFIX_POOL_STRING("Delegated-IPv6-Prefix-Pool", 171, RadiusAttributeValueSetter.STRING_UTF8),
   DIALBACK_NAME_STRING("Dialback-Name", 20, RadiusAttributeValueSetter.STRING_UTF8),
   DIALBACK_NO_STRING("Dialback-No", 19, RadiusAttributeValueSetter.STRING_UTF8),
   DIGEST_ATTRIBUTES_BYTES("Digest-Attributes", 207, RadiusAttributeValueSetter.OCTETS),
   DIGEST_RESPONSE_STRING("Digest-Response", 206, RadiusAttributeValueSetter.STRING_UTF8),
   DNS_SERVER_IPV6_ADDRESS_IPV6("DNS-Server-IPv6-Address", 169, RadiusAttributeValueSetter.IPV6_ADDRESS),
   DS_LITE_TUNNEL_NAME_STRING("DS-Lite-Tunnel-Name", 144, RadiusAttributeValueSetter.STRING_UTF8),
   EAP_KEY_NAME_STRING("EAP-Key-Name", 102, RadiusAttributeValueSetter.STRING_UTF8),
   EAP_LOWER_LAYER_NV("EAP-Lower-Layer", 163, RadiusAttributeValueSetter.NAMED_VALUE),
   EAP_MESSAGE_BYTES("EAP-Message", 79, RadiusAttributeValueSetter.OCTETS),
   EAP_OL_ANNOUNCEMENT_BYTES("EAPoL-Announcement", 180, RadiusAttributeValueSetter.OCTETS),
   EAP_PEER_ID_BYTES("EAP-Peer-Id", 175, RadiusAttributeValueSetter.OCTETS),
   EAP_SERVER_ID_BYTES("EAP-Server-Id", 176, RadiusAttributeValueSetter.OCTETS),
   EGRESS_VLAN_I_D_INT("Egress-VLANID", 56, RadiusAttributeValueSetter.INTEGER),
   EGRESS_VLAN_NAME_STRING("Egress-VLAN-Name", 58, RadiusAttributeValueSetter.STRING_UTF8),
   ERROR_CAUSE_NV("Error-Cause", 101, RadiusAttributeValueSetter.NAMED_VALUE),
   EVENT_TIMESTAMP_DATE("Event-Timestamp", 55, RadiusAttributeValueSetter.DATE),
   EXTENDED_ATTRIBUTE1_BYTES("Extended-Attribute-1", 241, RadiusAttributeValueSetter.OCTETS),
   EXTENDED_ATTRIBUTE2_BYTES("Extended-Attribute-2", 242, RadiusAttributeValueSetter.OCTETS),
   EXTENDED_ATTRIBUTE3_BYTES("Extended-Attribute-3", 243, RadiusAttributeValueSetter.OCTETS),
   EXTENDED_ATTRIBUTE4_BYTES("Extended-Attribute-4", 244, RadiusAttributeValueSetter.OCTETS),
   EXTENDED_ATTRIBUTE5_BYTES("Extended-Attribute-5", 245, RadiusAttributeValueSetter.OCTETS),
   EXTENDED_ATTRIBUTE6_BYTES("Extended-Attribute-6", 246, RadiusAttributeValueSetter.OCTETS),
   EXTENDED_LOCATION_POLICY_RULES_BYTES("Extended-Location-Policy-Rules", 130, RadiusAttributeValueSetter.OCTETS),
   FILTER_ID_STRING("Filter-Id", 11, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_ADDRESS_IPV4("Framed-Address", 8, RadiusAttributeValueSetter.IPV4_ADDRESS),
   FRAMED_APPLE_TALK_LINK_INT("Framed-AppleTalk-Link", 37, RadiusAttributeValueSetter.INTEGER),
   FRAMED_APPLE_TALK_NETWORK_INT("Framed-AppleTalk-Network", 38, RadiusAttributeValueSetter.INTEGER),
   FRAMED_APPLE_TALK_ZONE_STRING("Framed-AppleTalk-Zone", 39, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_CALLBACK_ID_STRING("Framed-Callback-Id", 20, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_COMPRESSION_NV("Framed-Compression", 13, RadiusAttributeValueSetter.NAMED_VALUE),
   FRAMED_FILTER_ID_STRING("Framed-Filter-Id", 11, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_INTERFACE_ID_BYTES("Framed-Interface-Id", 96, RadiusAttributeValueSetter.OCTETS),
   FRAMED_IP_ADDRESS_IPV4("Framed-IP-Address", 8, RadiusAttributeValueSetter.IPV4_ADDRESS),
   FRAMED_IP_NETMASK_IPV4("Framed-IP-Netmask", 9, RadiusAttributeValueSetter.IPV4_ADDRESS),
   FRAMED_IPV6_ADDRESS_IPV6("Framed-IPv6-Address", 168, RadiusAttributeValueSetter.IPV6_ADDRESS),
   FRAMED_IPV6_POOL_STRING("Framed-IPv6-Pool", 100, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_IPV6_PREFIX_BYTES("Framed-IPv6-Prefix", 97, RadiusAttributeValueSetter.OCTETS),
   FRAMED_IPV6_ROUTE_STRING("Framed-IPv6-Route", 99, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_IPX_NETWORK_IPV4("Framed-IPX-Network", 23, RadiusAttributeValueSetter.IPV4_ADDRESS),
   FRAMED_MANAGEMENT_NV("Framed-Management", 133, RadiusAttributeValueSetter.NAMED_VALUE),
   FRAMED_MTU_INT("Framed-MTU", 12, RadiusAttributeValueSetter.INTEGER),
   FRAMED_NETMASK_IPV4("Framed-Netmask", 9, RadiusAttributeValueSetter.IPV4_ADDRESS),
   FRAMED_POOL_STRING("Framed-Pool", 88, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_PROTOCOL_NV("Framed-Protocol", 7, RadiusAttributeValueSetter.NAMED_VALUE),
   FRAMED_ROUTE_STRING("Framed-Route", 22, RadiusAttributeValueSetter.STRING_UTF8),
   FRAMED_ROUTING_NV("Framed-Routing", 10, RadiusAttributeValueSetter.NAMED_VALUE),
   GSS_ACCEPTOR_HOST_NAME_STRING("GSS-Acceptor-Host-Name", 165, RadiusAttributeValueSetter.STRING_UTF8),
   GSS_ACCEPTOR_REALM_NAME_STRING("GSS-Acceptor-Realm-Name", 167, RadiusAttributeValueSetter.STRING_UTF8),
   GSS_ACCEPTOR_SERVICE_NAME_STRING("GSS-Acceptor-Service-Name", 164, RadiusAttributeValueSetter.STRING_UTF8),
   GSS_ACCEPTOR_SERVICE_SPECIFICS_STRING("GSS-Acceptor-Service-Specifics", 166, RadiusAttributeValueSetter.STRING_UTF8),
   IDLE_TIMEOUT_INT("Idle-Timeout", 28, RadiusAttributeValueSetter.INTEGER),
   INGRESS_FILTERS_NV("Ingress-Filters", 57, RadiusAttributeValueSetter.NAMED_VALUE),
   IPV66RD_CONFIGURATION_BYTES("IPv6-6rd-Configuration", 173, RadiusAttributeValueSetter.OCTETS),
   LOCATION_CAPABLE_NV("Location-Capable", 131, RadiusAttributeValueSetter.NAMED_VALUE),
   LOCATION_DATA_BYTES("Location-Data", 128, RadiusAttributeValueSetter.OCTETS),
   LOCATION_INFORMATION_BYTES("Location-Information", 127, RadiusAttributeValueSetter.OCTETS),
   LOGIN_CALLBACK_NUMBER_STRING("Login-Callback-Number", 19, RadiusAttributeValueSetter.STRING_UTF8),
   LOGIN_HOST_IPV4("Login-Host", 14, RadiusAttributeValueSetter.IPV4_ADDRESS),
   LOGIN_IP_HOST_IPV4("Login-IP-Host", 14, RadiusAttributeValueSetter.IPV4_ADDRESS),
   LOGIN_IPV6_HOST_IPV6("Login-IPv6-Host", 98, RadiusAttributeValueSetter.IPV6_ADDRESS),
   LOGIN_LAT_GROUP_BYTES("Login-LAT-Group", 36, RadiusAttributeValueSetter.OCTETS),
   LOGIN_LAT_NODE_STRING("Login-LAT-Node", 35, RadiusAttributeValueSetter.STRING_UTF8),
   LOGIN_LAT_PORT_STRING("Login-LAT-Port", 63, RadiusAttributeValueSetter.STRING_UTF8),
   LOGIN_LAT_SERVICE_STRING("Login-LAT-Service", 34, RadiusAttributeValueSetter.STRING_UTF8),
   LOGIN_PORT_INT("Login-Port", 16, RadiusAttributeValueSetter.INTEGER),
   LOGIN_SERVICE_NV("Login-Service", 15, RadiusAttributeValueSetter.NAMED_VALUE),
   LOGIN_TCP_PORT_NV("Login-TCP-Port", 16, RadiusAttributeValueSetter.NAMED_VALUE),
   MANAGEMENT_POLICY_ID_STRING("Management-Policy-Id", 135, RadiusAttributeValueSetter.STRING_UTF8),
   MANAGEMENT_PRIVILEGE_LEVEL_INT("Management-Privilege-Level", 136, RadiusAttributeValueSetter.INTEGER),
   MANAGEMENT_TRANSPORT_PROTECTION_NV("Management-Transport-Protection", 134, RadiusAttributeValueSetter.NAMED_VALUE),
   MESSAGE_AUTHENTICATOR_BYTES("Message-Authenticator", 80, RadiusAttributeValueSetter.OCTETS),
   MIP6_FEATURE_VECTOR_BYTES("MIP6-Feature-Vector", 124, RadiusAttributeValueSetter.OCTETS),
   MIP6_HOME_LINK_PREFIX_BYTES("MIP6-Home-Link-Prefix", 125, RadiusAttributeValueSetter.OCTETS),
   MOBILE_NODE_IDENTIFIER_BYTES("Mobile-Node-Identifier", 145, RadiusAttributeValueSetter.OCTETS),
   MOBILITY_DOMAIN_ID_INT("Mobility-Domain-Id", 177, RadiusAttributeValueSetter.INTEGER),
   MULTI_LINK_FLAG_NV("Multi-Link-Flag", 126, RadiusAttributeValueSetter.NAMED_VALUE),
   NAS_FILTER_RULE_STRING("NAS-Filter-Rule", 92, RadiusAttributeValueSetter.STRING_UTF8),
   NAS_IDENTIFIER_STRING("NAS-Identifier", 32, RadiusAttributeValueSetter.STRING_UTF8),
   NAS_IP_ADDRESS_IPV4("NAS-IP-Address", 4, RadiusAttributeValueSetter.IPV4_ADDRESS),
   NAS_IPV6_ADDRESS_IPV6("NAS-IPv6-Address", 95, RadiusAttributeValueSetter.IPV6_ADDRESS),
   NAS_PORT_INT("NAS-Port", 5, RadiusAttributeValueSetter.INTEGER),
   NAS_PORT_ID_STRING("NAS-Port-Id", 87, RadiusAttributeValueSetter.STRING_UTF8),
   NAS_PORT_TYPE_NV("NAS-Port-Type", 61, RadiusAttributeValueSetter.NAMED_VALUE),
   NETWORK_ID_NAME_BYTES("Network-Id-Name", 179, RadiusAttributeValueSetter.OCTETS),
   OLD_PASSWORD_STRING("Old-Password", 17, RadiusAttributeValueSetter.STRING_UTF8),
   OPERATOR_NAME_STRING("Operator-Name", 126, RadiusAttributeValueSetter.STRING_UTF8),
   ORIGINATING_LINE_INFO_BYTES("Originating-Line-Info", 94, RadiusAttributeValueSetter.OCTETS),
   PASSWORD_RETRY_INT("Password-Retry", 75, RadiusAttributeValueSetter.INTEGER),
   PKM_AUTH_KEY_BYTES("PKM-Auth-Key", 143, RadiusAttributeValueSetter.OCTETS),
   PKM_CA_CERT_BYTES("PKM-CA-Cert", 138, RadiusAttributeValueSetter.OCTETS),
   PKM_CONFIG_SETTINGS_BYTES("PKM-Config-Settings", 139, RadiusAttributeValueSetter.OCTETS),
   PKM_CRYPTOSUITE_LIST_BYTES("PKM-Cryptosuite-List", 140, RadiusAttributeValueSetter.OCTETS),
   PKM_SA_DESCRIPTOR_BYTES("PKM-SA-Descriptor", 142, RadiusAttributeValueSetter.OCTETS),
   PKM_SA_ID_INT("PKM-SAID", 141, 2, RadiusAttributeValueSetter.INTEGER),
   PKM_SS_CERT_BYTES("PKM-SS-Cert", 137, RadiusAttributeValueSetter.OCTETS),
   PMIP6_HOME_DHCP4_SERVER_ADDRESS_IPV4("PMIP6-Home-DHCP4-Server-Address", 157, RadiusAttributeValueSetter.IPV4_ADDRESS),
   PMIP6_HOME_DHCP6_SERVER_ADDRESS_IPV6("PMIP6-Home-DHCP6-Server-Address", 159, RadiusAttributeValueSetter.IPV6_ADDRESS),
   PMIP6_HOME_HN_PREFIX_BYTES("PMIP6-Home-HN-Prefix", 151, RadiusAttributeValueSetter.OCTETS),
   PMIP6_HOME_INTERFACE_ID_BYTES("PMIP6-Home-Interface-ID", 153, RadiusAttributeValueSetter.OCTETS),
   PMIP6_HOME_IPV4_GATEWAY_IPV4("PMIP6-Home-IPv4-Gateway", 161, RadiusAttributeValueSetter.IPV4_ADDRESS),
   PMIP6_HOME_IPV4_HO_A_BYTES("PMIP6-Home-IPv4-HoA", 155, RadiusAttributeValueSetter.OCTETS),
   PMIP6_HOME_LMA_IPV4_ADDRESS_IPV4("PMIP6-Home-LMA-IPv4-Address", 149, RadiusAttributeValueSetter.IPV4_ADDRESS),
   PMIP6_HOME_LMA_IPV6_ADDRESS_IPV6("PMIP6-Home-LMA-IPv6-Address", 147, RadiusAttributeValueSetter.IPV6_ADDRESS),
   PMIP6_VISITED_DHCP4_SERVER_ADDRESS_IPV4("PMIP6-Visited-DHCP4-Server-Address", 158, RadiusAttributeValueSetter.IPV4_ADDRESS),
   PMIP6_VISITED_DHCP6_SERVER_ADDRESS_IPV6("PMIP6-Visited-DHCP6-Server-Address", 160, RadiusAttributeValueSetter.IPV6_ADDRESS),
   PMIP6_VISITED_HN_PREFIX_BYTES("PMIP6-Visited-HN-Prefix", 152, RadiusAttributeValueSetter.OCTETS),
   PMIP6_VISITED_INTERFACE_ID_BYTES("PMIP6-Visited-Interface-ID", 154, RadiusAttributeValueSetter.OCTETS),
   PMIP6_VISITED_IPV4_GATEWAY_IPV4("PMIP6-Visited-IPv4-Gateway", 162, RadiusAttributeValueSetter.IPV4_ADDRESS),
   PMIP6_VISITED_IPV4_HO_A_BYTES("PMIP6-Visited-IPv4-HoA", 156, RadiusAttributeValueSetter.OCTETS),
   PMIP6_VISITED_LMA_IPV4_ADDRESS_IPV4("PMIP6-Visited-LMA-IPv4-Address", 150, RadiusAttributeValueSetter.IPV4_ADDRESS),
   PMIP6_VISITED_LMA_IPV6_ADDRESS_IPV6("PMIP6-Visited-LMA-IPv6-Address", 148, RadiusAttributeValueSetter.IPV6_ADDRESS),
   PORT_LIMIT_INT("Port-Limit", 62, RadiusAttributeValueSetter.INTEGER),
   PORT_MESSAGE_STRING("Port-Message", 18, RadiusAttributeValueSetter.STRING_UTF8),
   PREAUTH_TIMEOUT_INT("Preauth-Timeout", 178, RadiusAttributeValueSetter.INTEGER),
   PROMPT_NV("Prompt", 76, RadiusAttributeValueSetter.NAMED_VALUE),
   PROXY_STATE_BYTES("Proxy-State", 33, RadiusAttributeValueSetter.OCTETS),
   REPLY_MESSAGE_STRING("Reply-Message", 18, RadiusAttributeValueSetter.STRING_UTF8),
   REQUESTED_LOCATION_INFO_NV("Requested-Location-Info", 132, RadiusAttributeValueSetter.NAMED_VALUE),
   ROUTE_IPV6_INFORMATION_BYTES("Route-IPv6-Information", 170, RadiusAttributeValueSetter.OCTETS),
   SERVICE_SELECTION_STRING("Service-Selection", 146, RadiusAttributeValueSetter.STRING_UTF8),
   SERVICE_TYPE_NV("Service-Type", 6, RadiusAttributeValueSetter.NAMED_VALUE),
   SESSION_TIMEOUT_INT("Session-Timeout", 27, RadiusAttributeValueSetter.INTEGER),
   STATE_BYTES("State", 24, RadiusAttributeValueSetter.OCTETS),
   STATEFUL_IPV6_ADDRESS_POOL_STRING("Stateful-IPv6-Address-Pool", 172, RadiusAttributeValueSetter.STRING_UTF8),
   TERMINATION_ACTION_NV("Termination-Action", 29, RadiusAttributeValueSetter.NAMED_VALUE),
   TUNNEL_ASSIGNMENT_ID_STRING("Tunnel-Assignment-Id", 82, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_CLIENT_AUTH_ID_STRING("Tunnel-Client-Auth-Id", 90, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_CLIENT_ENDPOINT_STRING("Tunnel-Client-Endpoint", 66, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_MEDIUM_TYPE_NV("Tunnel-Medium-Type", 65, RadiusAttributeValueSetter.NAMED_VALUE),
   TUNNEL_PASSWORD_STRING("Tunnel-Password", 69, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_PREFERENCE_INT("Tunnel-Preference", 83, RadiusAttributeValueSetter.INTEGER),
   TUNNEL_PRIVATE_GROUP_ID_STRING("Tunnel-Private-Group-Id", 81, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_SERVER_AUTH_ID_STRING("Tunnel-Server-Auth-Id", 91, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_SERVER_ENDPOINT_STRING("Tunnel-Server-Endpoint", 67, RadiusAttributeValueSetter.STRING_UTF8),
   TUNNEL_TYPE_NV("Tunnel-Type", 64, RadiusAttributeValueSetter.NAMED_VALUE),
   USER_NAME_STRING("User-Name", 1, RadiusAttributeValueSetter.STRING_UTF8),
   USER_PRIORITY_TABLE_BYTES("User-Priority-Table", 59, RadiusAttributeValueSetter.OCTETS),
   USER_SERVICE_TYPE_INT("User-Service-Type", 6, RadiusAttributeValueSetter.INTEGER),
   WLAN_AKM_SUITE_INT("WLAN-AKM-Suite", 188, RadiusAttributeValueSetter.INTEGER),
   WLAN_GROUP_CIPHER_INT("WLAN-Group-Cipher", 187, RadiusAttributeValueSetter.INTEGER),
   WLAN_GROUP_MGMT_CIPHER_INT("WLAN-Group-Mgmt-Cipher", 189, RadiusAttributeValueSetter.INTEGER),
   WLAN_HESS_ID_STRING("WLAN-HESSID", 181, RadiusAttributeValueSetter.STRING_UTF8),
   WLAN_PAIRWISE_CIPHER_INT("WLAN-Pairwise-Cipher", 186, RadiusAttributeValueSetter.INTEGER),
   WLAN_REASON_CODE_INT("WLAN-Reason-Code", 185, RadiusAttributeValueSetter.INTEGER),
   WLAN_RF_BAND_INT("WLAN-RF-Band", 190, RadiusAttributeValueSetter.INTEGER),
   WLAN_VENUE_INFO_INT("WLAN-Venue-Info", 182, RadiusAttributeValueSetter.INTEGER),
   WLAN_VENUE_LANGUAGE_BYTES("WLAN-Venue-Language", 183, RadiusAttributeValueSetter.OCTETS),
   WLAN_VENUE_NAME_STRING("WLAN-Venue-Name", 184, RadiusAttributeValueSetter.STRING_UTF8);

   private final IamRadiusServerAttributeCreationInfo info;
   private final RadiusAttributeValueSetter conversionType;
   private final Optional<Integer> specificLength;

   RadiusAttribute(String name, int type, RadiusAttributeValueSetter conversionType) {
      this.info = IamRadiusServerAttributeCreationInfo.info(name, type);
      this.conversionType = conversionType;
      this.specificLength = Optional.empty();
   }

   RadiusAttribute(String name, int type, int specificLength, RadiusAttributeValueSetter conversionType) {
      this.info = IamRadiusServerAttributeCreationInfo.info(name, type);
      this.conversionType = conversionType;
      this.specificLength = Optional.of(specificLength);
   }

   public Optional<IamRadiusServerAttribute> createAttribute(@Nullable Object input) {
      return this.createAttribute(input, IamRadiusServerContext::createRadiusAttribute, IamRadiusServerContext.toNamedValue(this.info));
   }

   @VisibleForTesting
   public Optional<IamRadiusServerAttribute> createAttribute(
      @Nullable Object input,
      Function<IamRadiusServerAttributeCreationInfo, IamRadiusServerAttribute> attributeCreation,
      Function<String, NameValueResolved> toNamedValue
   ) {
      if (input == null) {
         return Optional.empty();
      }

      IamRadiusServerAttribute a;
      try {
         a = attributeCreation.apply(this.info);
      } catch (RuntimeException e) {
         throw new IllegalStateException(e);
      }

      if (this.conversionType.trySetAttributeValue(a, input, toNamedValue)) {
         this.specificLength.ifPresent(a::adjustLength);
         return Optional.of(a);
      } else {
         return Optional.empty();
      }
   }

   @VisibleForTesting
   public IamRadiusServerAttributeCreationInfo info() {
      return this.info;
   }

   @VisibleForTesting
   public RadiusAttributeValueSetter conversionType() {
      return this.conversionType;
   }

   public String asReadableString(byte[] bytes, Function<Long, String> nameResolver) {
      return this.conversionType.asReadableString(bytes, nameResolver);
   }
}
