package com.atlassian.bitbucket.mail;

import com.atlassian.bitbucket.i18n.I18nKey;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.function.Function;

import static com.google.common.base.Preconditions.checkNotNull;

public class SoyMailMessageRequest {

    private final String cssModuleKey;
    private final Map<String, Object> context;
    private final Iterable<ApplicationUser> recipients;
    private final I18nKey subjectKey;
    private final String soyTemplateModuleKey;
    private final String soyTemplateName;
    private final Function<MailMessage.Builder, MailMessage.Builder> messageEffector;

    private SoyMailMessageRequest(Builder builder) {
        recipients = builder.recipients.build();
        subjectKey = builder.subjectKey;
        soyTemplateModuleKey = builder.soyTemplateModuleKey;
        soyTemplateName = builder.soyTemplateName;
        cssModuleKey = builder.cssModuleKey;
        context = builder.context;
        messageEffector = builder.messageEffector;
    }

    @Nonnull
    public Map<String, Object> getContext() {
        return context;
    }

    /**
     * @return the key of the css module to inline into the mail message
     */
    @Nonnull
    public String getCssModuleKey() {
        return cssModuleKey;
    }

    /**
     * @return the list of users to be sent the mail
     */
    @Nonnull
    public Iterable<ApplicationUser> getRecipients() {
        return recipients;
    }

    /**
     * @return the key of the module containing the soy template
     */
    @Nonnull
    public String getSoyTemplateModuleKey() {
        return soyTemplateModuleKey;
    }

    /**
     * @return the name of the soy template to render
     */
    @Nonnull
    public String getSoyTemplateName() {
        return soyTemplateName;
    }

    /**
     * @return the i18n key of the mail subject line
     */
    @Nullable
    public I18nKey getSubjectKey() {
        return subjectKey;
    }

    /**
     * Can be passed that will be given the opportunity to add to the MailMessage.Builder, returning a new Builder to
     * use for the MailMessage. The SoyMailer will set the text, to, subject etc, so these can be over-ridden or used to
     * set headers.
     */
    @Nonnull
    public Function<MailMessage.Builder, MailMessage.Builder> getMessageEffector() {
        return MoreObjects.firstNonNull(messageEffector, m -> m);
    }

    public static class Builder {

        private final ImmutableList.Builder<ApplicationUser> recipients = ImmutableList.builder();

        private String cssModuleKey;
        private Map<String, Object> context;
        private Function<MailMessage.Builder, MailMessage.Builder> messageEffector;
        private I18nKey subjectKey;
        private String soyTemplateModuleKey;
        private String soyTemplateName;

        @Nonnull
        public SoyMailMessageRequest build() {
            return new SoyMailMessageRequest(this);
        }

        @Nonnull
        public Builder cssModuleKey(@Nonnull String value) {
            cssModuleKey = checkNotNull(value, "cssModuleKey");

            return this;
        }

        @Nonnull
        public Builder context(@Nonnull Map<String, Object> value) {
            context = checkNotNull(value, "context");

            return this;
        }

        @Nonnull
        public Builder messageEffector(@Nullable Function<MailMessage.Builder, MailMessage.Builder> value) {
            messageEffector = value;

            return this;
        }

        @Nonnull
        public Builder recipients(@Nonnull Iterable<ApplicationUser> value) {
            recipients.addAll(value);

            return this;
        }

        @Nonnull
        public Builder soyTemplateModuleKey(@Nonnull String value) {
            soyTemplateModuleKey = checkNotNull(value, "soyTemplateModuleKey");

            return this;
        }

        @Nonnull
        public Builder soyTemplateName(@Nonnull String value) {
            soyTemplateName = checkNotNull(value, "soyTemplateName");

            return this;
        }

        public Builder subjectKey(@Nonnull I18nKey value) {
            subjectKey = checkNotNull(value, "subjectKey");

            return this;
        }
    }
}
