/*
 * 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.information;

import java.io.Serializable;
import java.util.*;
import javax.mail.MessagingException;

import org.aegee.runanddine.BasePage;
import org.aegee.runanddine.OverviewPage;
import org.aegee.runanddine.mail.Mail;
import org.aegee.runanddine.mail.MailService;
import org.aegee.runanddine.mail.MailServiceListener;
import org.aegee.runanddine.pathfinder.Course;
import org.aegee.runanddine.pathfinder.OptGroup;
import org.aegee.runanddine.status.RunAndDineStatus;
import org.aegee.runanddine.util.forms.DynamicForm;
import org.aegee.runanddine.util.forms.SelectionValueFormatter;

/**
 * Preview page for the InformationMail
 * @author s_wolff
 */
public class InformationMailPreview extends BasePage {

    /**
     * String formatter for OptGroups used for displaying
     */
    private static final SelectionValueFormatter<OptGroup> SELECTION_FORMATTER = new SelectionValueFormatter<OptGroup>() {

        public String format(OptGroup obj) {
            String course;
            switch (obj.getCourse()) {
                case Course.DESSERT:
                    course = "dessert";
                    break;
                case Course.MAIN:
                    course = "main";
                    break;
                case Course.HORS_DOEUVRE:
                    course = "starter";
                    break;
                default:
                    course = "";
            }
            return String.format("[%s] %s %s, %s %s", course, obj.getFirstName1(), obj.getLastName1(), obj.getFirstName2(), obj.getLastName2());
        }
    };
    
    /**
     * Comparator that compares OptGroups based on their course
     */
    private static final Comparator<OptGroup> COMPARATOR = new Comparator<OptGroup>() {

        public int compare(OptGroup t, OptGroup r) {
            int compCourse = new Integer(t.getCourse()).compareTo(r.getCourse());
            if (compCourse == 0) {
                return SELECTION_FORMATTER.format(t).compareToIgnoreCase(SELECTION_FORMATTER.format(r));
            } else {
                return compCourse;
            }
        }
    };

    public InformationMailPreview(InformationMail mail) {
        this(mail, null);
    }

    public InformationMailPreview(final InformationMail mail, OptGroup selected) {
        super(null);

        List<OptGroup> groupList = getObjectOr404(mail.getEvent().getId());
        Collections.sort(groupList, COMPARATOR);
        final SelectedOptGroup selection = new SelectedOptGroup(selected);

        DynamicForm form = new DynamicForm("form") {

            @Override
            protected void onSubmit() {
                super.onSubmit();
                this.setResponsePage(new InformationMailPreview(mail, selection.getSelection()));
            }
        };

        form.addHeadline("Mail Preview", "Select the group whose information mail you want to preview.", true);
        form.addSelection(selection, groupList, "selection", "Select Group", false, SELECTION_FORMATTER);

        if (selected != null) {
            InformationMailRenderer renderer = InformationMailRenderer.create(selected);
            String subject = renderer.render(mail.getSubject());
            String lines[] = renderer.render(mail.getContent()).split("\n");
            form.addPanel(new PreviewPanel(form.newChildId(), subject, lines));
        }

        form.addPanel(new ButtonPanel(form.newChildId()) {

            @Override
            protected void onBack() {
                this.setResponsePage(new InformationMailEditor(mail));
            }

            @Override
            protected void onSend() {
                // TODO: what about timeout?
                RunAndDineStatus.setStatusInformation(mail.getEvent().getId(), InformationMailEditor.class, "Mails written. Sending...");
                Collection<OptGroup> optGroups = OptGroup.OBJECTS.getAllByRunAndDineId(mail.getEvent().getId());
                Collection<Mail> mails = new ArrayList<Mail>(optGroups.size() * 2);
                for (OptGroup optGroup : optGroups) {
                    InformationMailRenderer renderer = InformationMailRenderer.create(optGroup);
                    String subject = renderer.render(mail.getSubject());
                    String content = renderer.render(mail.getContent());
                    mails.add(new Mail(subject, optGroup.getEmail1(), "", content));
                    mails.add(new Mail(subject, optGroup.getEmail2(), "", content));
                }
                MailService.getInstance().sendMail(mails, new MailServiceListener() {

                    public void mailsSend() {
                        RunAndDineStatus.setStatusInformation(mail.getEvent().getId(), InformationMailEditor.class, "Mails sent.");
                    }

                    public void failure(MessagingException ex) {
                        // will never be called
                    }
                });
                this.setResponsePage(OverviewPage.class);
            }
        });
        this.add(form);
    }

    private static List<OptGroup> getObjectOr404(int id) {
        return OptGroup.OBJECTS.getAllByRunAndDineId(id);
    }

    /**
     * Class for saving currently selected OptGroup in a session
     */
    private class SelectedOptGroup implements Serializable {

        OptGroup selection;

        public SelectedOptGroup(OptGroup selection) {
            this.selection = selection;
        }

        public OptGroup getSelection() {
            return selection;
        }

        public void setSelection(OptGroup selection) {
            this.selection = selection;
        }
    }
}
