package com.capgemini.reports.emailing.templates;

import com.capgemini.framework.common.FileTemplate;
import com.capgemini.framework.common.MailHelper;
import com.capgemini.framework.common.ResourceHelper;
import com.capgemini.reports.database.javabean.DbUser;
import com.capgemini.reports.exceptions.FileLoadingException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * Template class for generating email content when a report has been scheduled, posted in the queue, has failed or is completed.<br>
 * This class provides a way to replace tags (found in the email template) by some provided content.
 */
@Slf4j
public abstract class AbstractEmailTemplate extends FileTemplate {

  @Getter
  private final String subject;

  /**
   * Constructor.
   *
   * @param subject the email's Subject
   */
  public AbstractEmailTemplate(final String subject) {
    super();
    this.subject = subject;
    try {
      // Select the corresponding template content
      String theTemplateContent = ResourceHelper.getResourceContent("/html/email/" + getEmailTemplate());
      // Assign the expected template
      setTemplateContent(theTemplateContent);
    }
    catch (FileLoadingException e) {
      log.warn("Could not load the email template file", e);
    }
  }

  protected abstract String getEmailTemplate();

  /**
   * Assign a tag value in the template.
   *
   * @param aTag      Tag identifier
   * @param aTagValue Tag value
   */
  protected void setTagValue(final EmailTagEnum aTag, final String aTagValue) {
    setTagValue(aTag.toString(), aTagValue);
  }

  /**
   * Sends this mail to the provided list of users.
   *
   * @param users a list of users, each of them having potentially several comma-separated email addresses
   */
  public void send(final List<DbUser> users) {
    List<String> validEmails = new ArrayList<>();
    List<DbUser> invalidUsers = new ArrayList<>();
    for (DbUser user : users) {
      String email = user.getEmail();
      if (email == null || email.isEmpty() || user.isGuest()) {
        invalidUsers.add(user);
      }
      else {
        validEmails.add(email);
      }
    }

    sendToAdresses(validEmails);
    if (users.isEmpty() || !invalidUsers.isEmpty()) { // no users, or at least one invalid user --> send to admins
      log.debug("Some User(s) do not have an email address in ActiveDirectory.");
    }
  }

  /**
   * Sends this mail to this user.
   *
   * @param user the user
   */
  public void send(final DbUser user) {
    String email = user.getEmail();
    if (email == null || email.isEmpty() || user.isGuest()) {
      log.debug("User {} does not have an email address in ActiveDirectory. Sending email to default address(es).", user.getLogin());
    }
    else {
      List<String> asList = new ArrayList<>();
      asList.add(email);
      sendToAdresses(asList);
    }
  }

  /**
   * Sends this mail to the users that required the report.
   *
   * @param destinators the email addresses for all receivers
   */
  public void sendToAdresses(final List<String> destinators) {
    // Generate content using parameters and template
    String content = this.generateCode();

    // Send the email
    MailHelper.sendAll(destinators, subject, content);
  }

  /**
   * This Enum contains specific tags constants. <br>
   * These tags exist whithin the eMail template files, and can be replaced by any String thanks to the {@link AbstractEmailTemplate} class.
   */
  protected enum EmailTagEnum {
    // Common tag
    REPORT_NAME,

    // Required when report state is: SCHEDULED
    QUEUE_NAME,
    ESTIMATED_COMPLETION_TIME,

    // Required when report state is: BAD PARAMETERS | FINISHED | FAILED
    POSTING_TIME,
    START_TIME,
    END_TIME,

    // Required when report state is FINISHED
    REPORT_LOCATION,

    // Required when report state is: BAD PARAMETERS | FAILED
    ERROR_MESSAGE
  }

}
