package org.springframework.prospring.ticket.web.confirmation;

import org.springframework.prospring.ticket.domain.*;
import org.springframework.prospring.ticket.service.*;
import org.springframework.mail.*;

/**
 * Wysyła prostą wiadomość poczty elektronicznej z potwierdzeniem zamówienia.
 */
public class SimpleMailPurchaseConfirmationSender implements PurchaseConfirmationSender {

    // usługa używana do wysyłania wiadomości poczty elektronicznej.
    private MailSender mailSender;

    // adres poczty elektronicznej nadawcy wiadomości z potwierdzeniem.
    private String senderEmail;

    public void sendPurchaseConfirmation(Purchase purchase, PurchaseRequest purchaseRequest)
        throws PurchaseConfirmationSendingException {

        try {
            mailSender.send(createPurchaseConfirmationMessage(purchase, purchaseRequest));
        } catch (MailException me) {
            throw new PurchaseConfirmationSendingException("Nie można było wysłać wiadomości z potwierdzeniem zamówienia nr. " +
                purchase.getId(), me);
        }
    }

    /**
     * Ustawia adres nadawcy wysyłającego wiadomości z potwierdzeniem.
     * @param mailSender Adres nadawcy wysyłającego wiadomości z potwierdzeniem.
     */
    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    /**
     * Sets the email that will apear in the "from" field of the email messages.
     * Ustawia adres poczty elektronicznej, który będize widoczny w polu "from" (od) potwierdzenia.
     * @param senderEmail Adres poczty elektronicznej, który będize widoczny w polu "from" (od) potwierdzenia.
     */
    public void setSenderEmail(String senderEmail) {
        this.senderEmail = senderEmail;
    }

    /**
     * Tworzy wiadomość z potwierdzeniem danego zamówienia. Ta metoda może zostać przesłonięta
     * w celu generacji bardziej złożonych wiadomości (na przykład, przy wykorzystaniu szablonów
     * Velocity).
     *
     * @param purchase Zamówienie które potwierdzamy.
     * @param request Żądanie zamówienia.
     * @return Wiadomość stanowiąca potwierdzenie danego zamówienia.
     */
    protected SimpleMailMessage createPurchaseConfirmationMessage(Purchase purchase, PurchaseRequest request) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(purchase.getEmail());
        message.setFrom(senderEmail);
        message.setSubject("Potwierdzenie zamówienia " + purchase.getPaymentAuthorizationCode());
        message.setText(createMessageText(purchase, request));
        return message;
    }

    protected String createMessageText(Purchase purchase, PurchaseRequest request) {
        Performance performance = request.getPerformance();

        StringBuffer text = new StringBuffer();
        text.append("Złożone przez Ciebie zamówienie miejsc na spektakl ").append(performance.getShow().getName());
        text.append(" dnia ").append(performance.getDateAndTime()).append(" zostało przyjęte.\n\n");
        text.append("Twoja karta kredytowa o numerze ").append(purchase.getEncryptedCardNumber()).append(" zostanie obciążona kwotą ");
        text.append(request.getReservation().getBooking().getPrice()).append("PLN.\n\n");
        text.append("Zostały Ci przydzielone miejsca ");
        Seat[] seats = request.getReservation().getSeats();
        for (int i=0; i<seats.length; i++) {
            if (i > 0) {
                text.append("; ");
            }
            text.append(seats[i].getName());
        }
        text.append(".\n\n");
        if (purchase.isUserCollected()) {
            text.append("Twoje bilety czekają na odbiór w kasie teatru.");
        } else {
            text.append("Twoje bilety zostaną przesłane pocztą na następujący adres:\n\n");
            Address deliveryAddress = getDeliveryAddress(purchase);
            text.append(purchase.getCustomerName()).append("\n");
            text.append(deliveryAddress.getStreet()).append("\n");
            text.append(deliveryAddress.getCity()).append("\n");
            text.append(deliveryAddress.getCountry()).append("\n");
            text.append(deliveryAddress.getPostcode());
        }
        text.append("\n\n");
        text.append("Numer referencyjny zamówienia: ").append(purchase.getPaymentAuthorizationCode()).append(".");
        text.append("Prosimy o zachowanie tego numeru (na przykład wydrukuj tę wiadomość). W przypadku wątpliwości ");
        text.append("lub anulowania rezerwacji będziesz go potrzebował.\n\n");
        return text.toString();
    }

    private Address getDeliveryAddress(Purchase purchase) {
        if (purchase.getDeliveryAddress() == null) {
            return purchase.getBillingAddress();
        }
        Address deliveryAddress = purchase.getDeliveryAddress();
        if (deliveryAddress.getCountry() == null || deliveryAddress.getCountry().length() == 0) {
            return purchase.getBillingAddress();
        }
        return deliveryAddress;
    }
}
