// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.mail;

import jodd.io.FastByteArrayOutputStream;
import jodd.io.StreamUtil;
import jodd.mail.att.ByteArrayAttachment;
import jodd.util.StringPool;

import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimePart;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

/**
 * Received email.
 */
public class ReceivedEmail extends CommonEmail {

	public ReceivedEmail() {
	}

	public ReceivedEmail(Message message) {
		try {
			parseMessage(message);
		} catch (Exception ex) {
			throw new MailException("Message parsing failed", ex);
		}
	}

	/**
	 * Parse java <code>Message</code> and extracts all data for the received message.
	 */
	@SuppressWarnings("unchecked")
	protected void parseMessage(Message msg) throws MessagingException, IOException {
		// flags
		setFlags(msg.getFlags());

		// msg no
		setMessageNumber(msg.getMessageNumber());

		// single from
		Address[] addresses = msg.getFrom();

		if (addresses != null && addresses.length > 0) {
			setFrom(new MailAddress(addresses[0]));
		}

		// common field
		setTo(MailAddress.createFrom(msg.getRecipients(Message.RecipientType.TO)));
		setCc(MailAddress.createFrom(msg.getRecipients(Message.RecipientType.CC)));
		setBcc(MailAddress.createFrom(msg.getRecipients(Message.RecipientType.BCC)));

		setSubject(msg.getSubject());

		Date recvDate = msg.getReceivedDate();
		if (recvDate == null) {
			recvDate = new Date();
		}
		setReceiveDate(recvDate);
		setSentDate(msg.getSentDate());

		// copy headers
		Enumeration<Header> headers = msg.getAllHeaders();
		while (headers.hasMoreElements()) {
			Header header = headers.nextElement();
			setHeader(header.getName(), header.getValue());
		}

		// content
		processPart(this, msg);
	}

	/**
	 * Process single part of received message. All parts are simple added to the message, i.e. hierarchy is not saved.
	 */
	protected void processPart(ReceivedEmail email, Part part) throws IOException, MessagingException {
		Object content = part.getContent();

		if (content instanceof String) {
			String stringContent = (String) content;

			String disposition = part.getDisposition();
			if (disposition != null && disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
				String contentType = part.getContentType();

				String mimeType = EmailUtil.extractMimeType(contentType);
				String encoding = EmailUtil.extractEncoding(contentType);
				String fileName = part.getFileName();
				String contentId = (part instanceof MimePart) ? ((MimePart)part).getContentID() : null;

				if (encoding == null) {
					encoding = StringPool.US_ASCII;
				}

				email.addAttachment(fileName, mimeType, contentId, stringContent.getBytes(encoding));
			} else {
				String contentType = part.getContentType();
				String encoding = EmailUtil.extractEncoding(contentType);
				String mimeType = EmailUtil.extractMimeType(contentType);

				if (encoding == null) {
					encoding = StringPool.US_ASCII;
				}

				email.addMessage(stringContent, mimeType, encoding);
			}
		} else if (content instanceof Multipart) {
			Multipart mp = (Multipart) content;
			int count = mp.getCount();
			for (int i = 0; i < count; i++) {
				Part innerPart = mp.getBodyPart(i);
				processPart(email, innerPart);
			}
		} else if (content instanceof InputStream) {
			String fileName = part.getFileName();
			String contentId = (part instanceof MimePart) ? ((MimePart)part).getContentID() : null;
			String mimeType = EmailUtil.extractMimeType(part.getContentType());

			InputStream is = (InputStream) content;
			FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
			StreamUtil.copy(is, fbaos);

			email.addAttachment(fileName, mimeType, contentId, fbaos.toByteArray());
		} else if (content instanceof MimeMessage) {
			MimeMessage mimeMessage = (MimeMessage) content;

			addAttachmentMessage(new ReceivedEmail(mimeMessage));
		}
	}

	// ---------------------------------------------------------------- flags

	protected Flags flags;

	public Flags getFlags() {
		return flags;
	}

	public void setFlags(Flags flags) {
		this.flags = flags;
	}

	/**
	 * Returns <code>true</code> if message is answered.
	 */
	public boolean isAnswered() {
		return flags.contains(Flags.Flag.ANSWERED);
	}

	/**
	 * Returns <code>true</code> if message is deleted.
	 */
	public boolean isDeleted() {
		return flags.contains(Flags.Flag.DELETED);
	}

	/**
	 * Returns <code>true</code> if message is draft.
	 */
	public boolean isDraf() {
		return flags.contains(Flags.Flag.DRAFT);
	}

	/**
	 * Returns <code>true</code> is message is flagged.
	 */
	public boolean isFlagged() {
		return flags.contains(Flags.Flag.FLAGGED);
	}

	/**
	 * Returns <code>true</code> if message is recent.
	 */
	public boolean isRecent() {
		return flags.contains(Flags.Flag.RECENT);
	}

	/**
	 * Returns <code>true</code> if message is seen.
	 */
	public boolean isSeen() {
		return flags.contains(Flags.Flag.SEEN);
	}

	// ---------------------------------------------------------------- additional properties

	protected int messageNumber;
	protected Date recvDate;

	/**
	 * Returns message number.
	 */
	public int getMessageNumber() {
		return messageNumber;
	}

	/**
	 * Sets message number.
	 */
	public void setMessageNumber(int messageNumber) {
		this.messageNumber = messageNumber;
	}

	/**
	 * Sets e-mails receive date.
	 */
	public void setReceiveDate(Date date) {
		recvDate = date;
	}

	/**
	 * Returns emails received date.
	 */
	public Date getReceiveDate() {
		return recvDate;
	}

	// ---------------------------------------------------------------- attachments

	protected List<EmailAttachment> attachments;

	/**
	 * Adds received attachment.
	 */
	public void addAttachment(String filename, String mimeType, String contentId, byte[] content) {
		if (attachments == null) {
			attachments = new ArrayList<EmailAttachment>();
		}
		EmailAttachment emailAttachment = new ByteArrayAttachment(content, mimeType, filename, contentId);
		emailAttachment.setSize(content.length);
		attachments.add(emailAttachment);
	}

	/**
	 * Returns the list of all attachments.
	 * If no attachment is available, returns <code>null</code>.
	 */
	public List<EmailAttachment> getAttachments() {
		return attachments;
	}


	// ---------------------------------------------------------------- inner messages

	protected List<ReceivedEmail> attachedMessages;

	/**
	 * Adds attached messages.
	 */
	public void addAttachmentMessage(ReceivedEmail receivedEmail) {
		if (attachedMessages == null) {
			attachedMessages = new ArrayList<ReceivedEmail>();
		}
		attachedMessages.add(receivedEmail);
	}

	/**
	 * Returns the list of attached messages.
	 * If not attached message is available, returns <code>null</code>.
	 */
	public List<ReceivedEmail> getAttachedMessages() {
		return attachedMessages;
	}

}
@@ -771,41 +771,8 @@
 %0D%0A%0D%0A
-%09public ReceivedEmail() %7B%0D%0A%09%7D%0D%0A%0D%0A
 %09pub

Remove unused ctor.