<%#
 Copyright 2013-2023 the original author or authors from the JHipster project.

 This file is part of the JHipster project, see https://www.jhipster.tech/
 for more information.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-%>
package <%= packageName %>.service;

import <%= entityAbsoluteClass %>;

import tech.jhipster.config.JHipsterProperties;

import java.nio.charset.StandardCharsets;
import java.util.Locale;
import <%= javaVersion === '17' ? 'jakarta' : 'javax'%>.mail.MessagingException;
import <%= javaVersion === '17' ? 'jakarta' : 'javax'%>.mail.internet.MimeMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
<%_ if (javaVersion === '17') { _%>
import org.thymeleaf.spring6.SpringTemplateEngine;
<%_ } else { _%>
import org.thymeleaf.spring5.SpringTemplateEngine;
<%_ } _%>
<%_ if (reactive) { _%>
import reactor.core.publisher.Mono;
<%_ } else { _%>
import org.springframework.scheduling.annotation.Async;
<%_ } _%>
<%_
    const localSendEmailFromTemplateApi = reactive ? 'sendEmailFromTemplate' : 'sendEmailFromTemplateSync';
_%>


/**
 * Service for sending emails asynchronously.
<%_ if (!reactive) { _%>
 * <p>
 * We use the {@link Async} annotation to send emails asynchronously.
<%_ } _%>
 */
@Service
public class MailService {

    private final Logger log = LoggerFactory.getLogger(MailService.class);

    private static final String USER = "user";

    private static final String BASE_URL = "baseUrl";

    private final JHipsterProperties jHipsterProperties;

    private final JavaMailSender javaMailSender;

    private final MessageSource messageSource;

    private final SpringTemplateEngine templateEngine;

    public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender,
            MessageSource messageSource, SpringTemplateEngine templateEngine) {

        this.jHipsterProperties = jHipsterProperties;
        this.javaMailSender = javaMailSender;
        this.messageSource = messageSource;
        this.templateEngine = templateEngine;
    }

<%_ if (!reactive) { _%>
    @Async
<%_ } _%>
    public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
<%_ if (reactive) { _%>
        Mono.defer(() -> {
            this.sendEmailSync(to, subject, content, isMultipart, isHtml);
            return Mono.empty();
        }).subscribe();
<%_ } else { _%>
        this.sendEmailSync(to, subject, content, isMultipart, isHtml);
<%_ } _%>
    }

    private void sendEmailSync(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
        log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
            isMultipart, isHtml, to, subject, content);

        // Prepare message using a Spring helper
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name());
            message.setTo(to);
            message.setFrom(jHipsterProperties.getMail().getFrom());
            message.setSubject(subject);
            message.setText(content, isHtml);
            javaMailSender.send(mimeMessage);
            log.debug("Sent email to User '{}'", to);
        }  catch (MailException | MessagingException e) {
            log.warn("Email could not be sent to user '{}'", to, e);
        }
    }

<%_ if (!reactive) { _%>
    @Async
<%_ } _%>
    public void sendEmailFromTemplate(<%= persistClass %> user, String templateName, String titleKey) {
<%_ if (reactive) { _%>
        Mono.defer(() -> {
            this.sendEmailFromTemplateSync(user, templateName, titleKey);
            return Mono.empty();
        }).subscribe();
<%_ } else { _%>
        this.sendEmailFromTemplateSync(user, templateName, titleKey);
<%_ } _%>
    }

    private void sendEmailFromTemplateSync(<%= user.persistClass %> user, String templateName, String titleKey) {
        if (user.getEmail() == null) {
            log.debug("Email doesn't exist for user '{}'", user.getLogin());
            return;
        }
        Locale locale = Locale.forLanguageTag(user.getLangKey());
        Context context = new Context(locale);
        context.setVariable(USER, user);
        context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
        String content = templateEngine.process(templateName, context);
        String subject = messageSource.getMessage(titleKey, null, locale);
        this.sendEmailSync(user.getEmail(), subject, content, false, true);
    }
<%_ if (!authenticationTypeOauth2) { _%>

<%_ if (!reactive) { _%>
    @Async
<%_ } _%>
    public void sendActivationEmail(<%= persistClass %> user) {
        log.debug("Sending activation email to '{}'", user.getEmail());
        this.<%- localSendEmailFromTemplateApi %>(user, "mail/activationEmail", "email.activation.title");
    }

<%_ if (!reactive) { _%>
    @Async
<%_ } _%>
    public void sendCreationEmail(<%= persistClass %> user) {
        log.debug("Sending creation email to '{}'", user.getEmail());
        this.<%- localSendEmailFromTemplateApi %>(user, "mail/creationEmail", "email.activation.title");
    }

<%_ if (!reactive) { _%>
    @Async
<%_ } _%>
    public void sendPasswordResetMail(<%= persistClass %> user) {
        log.debug("Sending password reset email to '{}'", user.getEmail());
        this.<%- localSendEmailFromTemplateApi %>(user, "mail/passwordResetEmail", "email.reset.title");
    }
<%_ } _%>
}
