/*
 * Copyright 2012 s_wolff.
 *
 * 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
 *
 *      http://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 org.aegee.runanddine.feedback;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedList;
import javax.mail.MessagingException;

import org.aegee.runanddine.RunAndDineApplication;
import org.aegee.runanddine.mail.Mail;
import org.aegee.runanddine.mail.MailService;
import org.aegee.runanddine.mail.MailServiceListener;
import org.aegee.runanddine.registration.GroupRegistration;
import org.aegee.runanddine.registration.SingleRegistration;
import org.aegee.runanddine.runanddine.RunAndDine;
import org.aegee.runanddine.status.RunAndDineStatus;
import org.aegee.runanddine.util.data.ModelNotExistingException;
import org.apache.wicket.request.http.flow.AbortWithHttpErrorCodeException;

/**
 * Class for perserving a mail between page reloads. Furthermore it serves to
 * save the information of the
 * <code>AdvertisementMailEditor</code>, e.g. the recipiants.
 *
 * @author s_wolff
 */
class TemporaryMail implements Serializable {

    /**
     * MailRenderer
     */
    private GracefulMailOfThanksMailRenderer dummyRenderer;
    
    /**
     * Mail subject
     */
    private String subject;
    
    /**
     * Mail content
     */
    private String content;
    
    /**
     * ID of related RunAndDine
     */
    private int runAndDineId;

    /**
     * Default constructor
     */
    TemporaryMail() {
        GracefulMailOfThanksMailTemplate temp = GracefulMailOfThanksMailTemplate.getTemplate();
        this.subject = temp.getSubject();
        this.content = temp.getContent();
    }

    /**
     * Constructor setting ID of related RunAndDine
     * @param runAndDineId ID of related RunAndDine
     */
    TemporaryMail(int runAndDineId) {
        this();
        this.runAndDineId = runAndDineId;
        this.initDummyRenderer();
    }

    /**
     * Initialize dummy renderer for mail
     */
    final void initDummyRenderer() {
        try {
            final String name = "Max Mustermann";
            final String feedbackLink = createFeedbackLink("dummyToken");
            this.dummyRenderer = GracefulMailOfThanksMailRenderer.create(this.runAndDineId, feedbackLink, name);
        } catch (ModelNotExistingException e) {
            throw new AbortWithHttpErrorCodeException(500, "Specified Run&Dine not found.");
        }
    }

    /**
     * Create MailRenderer
     * @param feedbackLink Feedback link for participant
     * @param name Name of participant
     * @return GracefulMailOfThanksMailRenderer
     * @throws ModelNotExistingException
     */
    GracefulMailOfThanksMailRenderer createRenderer(String feedbackLink, String name) throws ModelNotExistingException {
        return GracefulMailOfThanksMailRenderer.create(this.runAndDineId, feedbackLink, name);
    }

    /**
     * Create MailRenderer for RunAndDine
     * @param runAndDine ID of related RunAndDine
     * @param feedbackLink Feedback link for participant
     * @param name Name of participant
     * @return GracefulMailOfThanksMailRenderer
     */
    static GracefulMailOfThanksMailRenderer createRenderer(RunAndDine runAndDine, String feedbackLink, String name) {
        return GracefulMailOfThanksMailRenderer.create(runAndDine, feedbackLink, name);
    }

    /**
     * Get ID of related RunAndDine
     * @return ID of related RunAndDine
     */
    int getRunAndDineId() {
        return runAndDineId;
    }

    /**
     * Get mail content
     * @return Mail content
     */
    String getContent() {
        return this.content;
    }

    /**
     * Get rendered mail content
     * @return Rendered mail content
     */
    String getRenderedContent() {
        return this.dummyRenderer.render(content);
    }

    /**
     * Get mail subject
     * @return Mail subject
     */
    String getSubject() {
        return this.subject;
    }

    /**
     * Get rendered mail subject
     * @return Rendered mail subject
     */
    String getRenderedSubject() {
        return this.dummyRenderer.render(subject);
    }

    /**
     * Set mail content
     * @param content Mail content
     */
    void setContent(String content) {
        this.content = content;
    }

    /**
     * Set mail subject
     * @param subject Mail subject
     */
    void setSubject(String subject) {
        this.subject = subject;
    }

    /**
     * Get dummy renderer for mail
     * @return MailRenderer
     */
    GracefulMailOfThanksMailRenderer getDummyRenderer() {
        return dummyRenderer;
    }

    /**
     * Send mail
     */
    void send() {
        RunAndDineStatus.setStatusInformation(this.runAndDineId, GracefulMailOfThanksMailEditor.class, "Mail written. Sending...");
        Collection<Mail> mails = new LinkedList<Mail>();
        RunAndDine runAndDine;
        try {
            runAndDine = RunAndDine.OBJECTS.getById(this.runAndDineId);
        } catch (ModelNotExistingException e) {
            throw new AbortWithHttpErrorCodeException(500, "The specified Run&Dine was not found.");
        }
        for (SingleRegistration sr : SingleRegistration.OBJECTS.getAllValidatedByRunAndDineId(this.runAndDineId)) {
            String feedbackLink = this.createFeedbackLink(sr.getValidationToken());
            String name = formatName(sr.getFirstName(), sr.getLastName());
            GracefulMailOfThanksMailRenderer renderer = createRenderer(runAndDine, feedbackLink, name);
            mails.add(createMail(renderer, sr.getEmail()));
        }
        for (GroupRegistration gr : GroupRegistration.OBJECTS.getAllValidatedByRunAndDineId(this.runAndDineId)) {
            String feedbackLink1 = this.createFeedbackLink(gr.getValidationToken1());
            String feedbackLink2 = this.createFeedbackLink(gr.getValidationToken2());
            String name1 = formatName(gr.getFirstName1(), gr.getLastName1());
            String name2 = formatName(gr.getFirstName2(), gr.getLastName2());
            GracefulMailOfThanksMailRenderer renderer1 = createRenderer(runAndDine, feedbackLink1, name1);
            GracefulMailOfThanksMailRenderer renderer2 = createRenderer(runAndDine, feedbackLink2, name2);
            mails.add(createMail(renderer1, gr.getEmail1()));
            mails.add(createMail(renderer2, gr.getEmail2()));
        }
        MailService.getInstance().sendMail(mails, new MailServiceListener() {

            public void mailsSend() {
                RunAndDineStatus.setStatusInformation(TemporaryMail.this.runAndDineId, GracefulMailOfThanksMailEditor.class, "Mail sent.");
            }

            public void failure(MessagingException ex) {
                // will never be called
            }
        });
    }

    /**
     * Create feedback link for participant
     * @param token Token of participant
     * @return Feedback link for participant
     */
    private String createFeedbackLink(String token) {
        return String.format("%s/feedback/?id=%s&token=%s", RunAndDineApplication.DOMAIN, this.runAndDineId, token);
    }

    /**
     * Format name of participant
     * @param firstName Firstname of participant
     * @param lastName Lastname of participant
     * @return Formatted name of participant
     */
    private static String formatName(String firstName, String lastName) {
        return String.format("%s %s", firstName, lastName);
    }

    /**
     * Create mail
     * @param renderer MailRenderer to be used
     * @param toAddress Recipient to be used
     * @return Mail
     */
    private Mail createMail(GracefulMailOfThanksMailRenderer renderer, String toAddress) {
        String renderedSubject = renderer.render(this.subject);
        String renderedContent = renderer.render(this.content);
        return new Mail(renderedSubject, toAddress, "", renderedContent);
    }
}
