package com.airlock.iam.admin.application.configuration.event;

import com.airlock.iam.common.api.domain.service.email.EmailService;
import com.airlock.iam.common.application.configuration.event.AdminappSubscribedEventConfig;
import com.airlock.iam.common.application.configuration.event.EventEmailRecipientConfig.AdminappEventEmailRecipientConfig;
import com.airlock.iam.common.application.configuration.language.LanguageSettingsValidator;
import com.airlock.iam.core.application.configuration.contextdata.StringContextDataItemNameConfig;
import com.airlock.iam.core.misc.util.LanguageUtils;
import com.airlock.iam.plugin.api.annotation.config.ConfigurationValidator;
import com.airlock.iam.plugin.api.annotation.config.Plugin;
import com.airlock.iam.plugin.api.annotation.property.BooleanProperty;
import com.airlock.iam.plugin.api.annotation.property.PluginProperty;
import com.airlock.iam.plugin.api.annotation.property.StringProperty;
import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.Environment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.api.exception.PropertyConfigurationException;
import com.airlock.iam.plugin.api.valuereader.StringPropertyValueReader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Locale;

@Plugin(description = "An event subscriber that sends an email to notify a user.", displayName = "Email Event Subscriber (Adminapp)")
public final class AdminappEmailEventSubscriberConfig extends AdminappGeneralEventSubscriberConfig {
   @PluginProperty(description = "Email service for sending emails.", displayName = "Email Service", optional = false)
   private EmailService emailService;
   @PluginProperty(description = "Email address to which the notification email is sent.", optional = false)
   private AdminappEventEmailRecipientConfig recipientAddress;
   @StringProperty(
      description = "The resource key under which the localized template for the email subject can be found. The following syntax can be used to include data in the template. <ul><li><tt>${contextDataName}</tt> for the value of <tt>contextDataName</tt> in the context-data of the managed user.</li><li><tt>${event.createdAt,date,format}</tt> for the date/time at which the event was created, where \"format\" is a date pattern like \"yyyy-MM-dd HH:mm:ss\".</li></ul>Depending on the event and on the conditions in which the event originated, the following variables may also be available: <ul><li><tt>event.createdAt</tt></li><li><tt>event.data.addedRoles</tt> (list of strings)</li><li><tt>event.data.airlock2FAAccountId</tt></li><li><tt>event.data.airlock2FADeviceId</tt></li><li><tt>event.data.activeAuthenticationMethod</tt></li><li><tt>event.data.contextDataChanged.%s.newValue</tt> (where \"%s\" is replaced by the context-data field name).</li><li><tt>event.data.contextDataChanged.%s.oldValue</tt> (where \"%s\" is replaced by the context-data field name).</li><li><tt>event.data.crontoDeviceId</tt></li><li><tt>event.data.fidoCredentialId</tt></li><li><tt>event.data.lockReason</tt></li><li><tt>event.data.mtanNewPhoneNumber</tt></li><li><tt>event.data.mtanNumberId</tt></li><li><tt>event.data.mtanOldPhoneNumber</tt></li><li><tt>event.data.newEmailAddress</tt></li><li><tt>event.data.newRoles</tt> (list of strings)</li><li><tt>event.data.oldEmailAddress</tt></li><li><tt>event.data.oldRoles</tt> (list of strings)</li><li><tt>event.data.previousAuthenticationMethod</tt></li><li><tt>event.data.removedRoles</tt> (list of strings)</li><li><tt>event.data.userId</tt></li><li><tt>event.id</tt></li><li><tt>event.metadata.requestIp</tt></li><li><tt>event.metadata.userAgent</tt></li><li><tt>event.source.adminId</tt></li></ul>Variables that are not defined are replaced by an empty string. The Airlock IAM documentation provides further information about the availability of specific variables.",
      optional = true,
      defaultValue = "email.notification.subject",
      suggestedValues = {
            "email.notification.address-changed-event.subject",
            "email.notification.airlock2fa-device-deleted-event.subject",
            "email.notification.authentication-method-changed-event.subject",
            "email.notification.cronto-device-deleted-event.subject",
            "email.notification.cronto-letter-ordered-event.subject",
            "email.notification.device-token-deleted-event.subject",
            "email.notification.email-added-event.subject",
            "email.notification.email-changed-event.subject",
            "email.notification.email-deleted-event.subject",
            "email.notification.fido-credential-deleted-event.subject",
            "email.notification.mtan-token-deleted-event.subject",
            "email.notification.mtan-token-phone-number-changed-event.subject",
            "email.notification.mtan-token-registered-event.subject",
            "email.notification.password-changed-event.subject",
            "email.notification.password-letter-ordered-event.subject",
            "email.notification.user-created-event.subject",
            "email.notification.user-deleted-event.subject",
            "email.notification.user-locked-event.subject",
            "email.notification.user-roles-changed-event.subject",
            "email.notification.user-unlocked-event.subject"
      }
   )
   private String subjectResourceKey;
   @StringProperty(
      description = "The resource key under which the localized template for the email message body can be found. The following syntax can be used to include data in the template. <ul><li><tt>${contextDataName}</tt> for the value of <tt>contextDataName</tt> in the context-data of the managed user.</li><li><tt>${event.createdAt,date,format}</tt> for the date/time at which the event was created, where \"format\" is a date pattern like \"yyyy-MM-dd HH:mm:ss\".</li></ul>Depending on the event and on the conditions in which the event originated, the following variables may also be available: <ul><li><tt>event.createdAt</tt></li><li><tt>event.data.addedRoles</tt> (list of strings)</li><li><tt>event.data.airlock2FAAccountId</tt></li><li><tt>event.data.airlock2FADeviceId</tt></li><li><tt>event.data.activeAuthenticationMethod</tt></li><li><tt>event.data.contextDataChanged.%s.newValue</tt> (where \"%s\" is replaced by the context-data field name).</li><li><tt>event.data.contextDataChanged.%s.oldValue</tt> (where \"%s\" is replaced by the context-data field name).</li><li><tt>event.data.crontoDeviceId</tt></li><li><tt>event.data.fidoCredentialId</tt></li><li><tt>event.data.lockReason</tt></li><li><tt>event.data.mtanNewPhoneNumber</tt></li><li><tt>event.data.mtanNumberId</tt></li><li><tt>event.data.mtanOldPhoneNumber</tt></li><li><tt>event.data.newEmailAddress</tt></li><li><tt>event.data.newRoles</tt> (list of strings)</li><li><tt>event.data.oldEmailAddress</tt></li><li><tt>event.data.oldRoles</tt> (list of strings)</li><li><tt>event.data.previousAuthenticationMethod</tt></li><li><tt>event.data.removedRoles</tt> (list of strings)</li><li><tt>event.data.userId</tt></li><li><tt>event.id</tt></li><li><tt>event.metadata.requestIp</tt></li><li><tt>event.metadata.userAgent</tt></li><li><tt>event.source.adminId</tt></li></ul>Variables that are not defined are replaced by an empty string. The Airlock IAM documentation provides further information about the availability of specific variables.",
      optional = true,
      defaultValue = "email.notification.body",
      suggestedValues = {
            "email.notification.address-changed-event.body",
            "email.notification.airlock2fa-device-deleted-event.body",
            "email.notification.authentication-method-changed-event.body",
            "email.notification.cronto-device-deleted-event.body",
            "email.notification.cronto-letter-ordered-event.body",
            "email.notification.device-token-deleted-event.body",
            "email.notification.email-added-event.body",
            "email.notification.email-changed-event.body",
            "email.notification.email-deleted-event.body",
            "email.notification.fido-credential-deleted-event.body",
            "email.notification.mtan-token-deleted-event.body",
            "email.notification.mtan-token-phone-number-changed-event.body",
            "email.notification.mtan-token-registered-event.body",
            "email.notification.password-changed-event.body",
            "email.notification.password-letter-ordered-event.body",
            "email.notification.user-created-event.body",
            "email.notification.user-deleted-event.body",
            "email.notification.user-locked-event.body",
            "email.notification.user-roles-changed-event.body",
            "email.notification.user-unlocked-event.body"
      }
   )
   private String bodyResourceKey;
   @BooleanProperty(
      description = "If enabled, the verification email will be sent as an HTML mail. Otherwise it will be sent as plain text.",
      displayName = "Send As HTML",
      optional = true,
      defaultValue = "false"
   )
   private boolean sendAsHtml;
   @PluginProperty(
      description = "The context data field whose value is to be used as the recipient's message language. If the provided value is blank or invalid, the default language will be used.",
      optional = false
   )
   private StringContextDataItemNameConfig languageContextDataName;
   @StringProperty(
      description = "The default language code used when no (or no valid) information about the current language is present. A corresponding locale must be available.",
      optional = true,
      defaultValue = "de",
      suggestedValues = {"de", "fr", "en"}
   )
   private String defaultLanguage;
   private static final String DEFAULT_LANGUAGE_FIELD = "defaultLanguage";

   @ConfigurationValidator
   static void checkDefaultLanguage(PluginConfiguration pc, ConfigurationEnvironment env, ConfigurationContext context, Environment validationEnvironment) throws PropertyConfigurationException {
      String configuredDefaultLanguage = StringPropertyValueReader.effectiveStringConfigValue(pc, "defaultLanguage", env, context);
      LanguageSettingsValidator.ensureLocaleExists(pc, env, context, validationEnvironment, "defaultLanguage", configuredDefaultLanguage);
   }

   public Locale getDefaultLocale() {
      return LanguageUtils.getLocale(this.defaultLanguage);
   }

   public AdminappEmailEventSubscriberConfig(
      AdminappSubscribedEventConfig event,
      StringContextDataItemNameConfig languageContextDataName,
      String defaultLanguage,
      EmailService emailService,
      AdminappEventEmailRecipientConfig recipientAddress,
      String subjectResourceKey,
      String bodyResourceKey,
      boolean sendAsHtml
   ) {
      super(event);
      this.languageContextDataName = languageContextDataName;
      this.defaultLanguage = defaultLanguage;
      this.emailService = emailService;
      this.recipientAddress = recipientAddress;
      this.subjectResourceKey = subjectResourceKey;
      this.bodyResourceKey = bodyResourceKey;
      this.sendAsHtml = sendAsHtml;
   }

   public EmailService getEmailService() {
      return this.emailService;
   }

   public AdminappEventEmailRecipientConfig getRecipientAddress() {
      return this.recipientAddress;
   }

   public String getSubjectResourceKey() {
      return this.subjectResourceKey;
   }

   public String getBodyResourceKey() {
      return this.bodyResourceKey;
   }

   public boolean isSendAsHtml() {
      return this.sendAsHtml;
   }

   public StringContextDataItemNameConfig getLanguageContextDataName() {
      return this.languageContextDataName;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder builder() {
      return new AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder();
   }

   @SuppressFBWarnings(justification = "generated code")
   public AdminappEmailEventSubscriberConfig() {
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class AdminappEmailEventSubscriberConfigBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private AdminappSubscribedEventConfig event;
      @SuppressFBWarnings(justification = "generated code")
      private StringContextDataItemNameConfig languageContextDataName;
      @SuppressFBWarnings(justification = "generated code")
      private String defaultLanguage;
      @SuppressFBWarnings(justification = "generated code")
      private EmailService emailService;
      @SuppressFBWarnings(justification = "generated code")
      private AdminappEventEmailRecipientConfig recipientAddress;
      @SuppressFBWarnings(justification = "generated code")
      private String subjectResourceKey;
      @SuppressFBWarnings(justification = "generated code")
      private String bodyResourceKey;
      @SuppressFBWarnings(justification = "generated code")
      private boolean sendAsHtml;

      @SuppressFBWarnings(justification = "generated code")
      AdminappEmailEventSubscriberConfigBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder event(AdminappSubscribedEventConfig event) {
         this.event = event;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder languageContextDataName(
         StringContextDataItemNameConfig languageContextDataName
      ) {
         this.languageContextDataName = languageContextDataName;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder defaultLanguage(String defaultLanguage) {
         this.defaultLanguage = defaultLanguage;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder emailService(EmailService emailService) {
         this.emailService = emailService;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder recipientAddress(AdminappEventEmailRecipientConfig recipientAddress) {
         this.recipientAddress = recipientAddress;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder subjectResourceKey(String subjectResourceKey) {
         this.subjectResourceKey = subjectResourceKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder bodyResourceKey(String bodyResourceKey) {
         this.bodyResourceKey = bodyResourceKey;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder sendAsHtml(boolean sendAsHtml) {
         this.sendAsHtml = sendAsHtml;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public AdminappEmailEventSubscriberConfig build() {
         return new AdminappEmailEventSubscriberConfig(
            this.event,
            this.languageContextDataName,
            this.defaultLanguage,
            this.emailService,
            this.recipientAddress,
            this.subjectResourceKey,
            this.bodyResourceKey,
            this.sendAsHtml
         );
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "AdminappEmailEventSubscriberConfig.AdminappEmailEventSubscriberConfigBuilder(event="
            + this.event
            + ", languageContextDataName="
            + this.languageContextDataName
            + ", defaultLanguage="
            + this.defaultLanguage
            + ", emailService="
            + this.emailService
            + ", recipientAddress="
            + this.recipientAddress
            + ", subjectResourceKey="
            + this.subjectResourceKey
            + ", bodyResourceKey="
            + this.bodyResourceKey
            + ", sendAsHtml="
            + this.sendAsHtml
            + ")";
      }
   }
}
