package jp.sourceforge.shovel.device.impl;

import java.security.Security;
import java.util.Calendar;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.struts.util.MessageResources;
import org.seasar.framework.container.S2Container;

import com.sun.net.ssl.internal.ssl.Provider;

import jp.sourceforge.shovel.device.IDelayExecutorContext;
import jp.sourceforge.shovel.device.IMailWrapper;
import jp.sourceforge.shovel.entity.IDirectMessage;
import jp.sourceforge.shovel.entity.IFriendship;
import jp.sourceforge.shovel.entity.IStatus;
import jp.sourceforge.shovel.entity.IUser;
import jp.sourceforge.shovel.exception.ApplicationException;
import jp.sourceforge.shovel.logic.IDirectoryLogic;
import jp.sourceforge.shovel.logic.IShovelLogic;
import jp.sourceforge.shovel.util.ShovelUtil;

public class MailWrapperImpl implements IMailWrapper {
    Properties properties_;
    
    public String getDisplayName() {
        return null;
    }
    public void setDisplayName(String displayName) {
    }
    public String getAddress() {
        return null;
    }
    public String getExecutorId() {
        return "mail";
    }
    public boolean isConnected() {
        return true;
    }
    public void setProperty(String key, String value) {
        if (properties_ == null) {
            properties_ = new Properties();
        }
        properties_.setProperty("mail." + key, value);
    }
    
    public void connect() throws ApplicationException {
    }
    public void disconnect() {
    }
    void sendDirectMessage() {
        
    }
    public void execute(IDelayExecutorContext context) throws ApplicationException {
        if (context.isCommit()) {
            return;
        }
        
        MessageResources resources = MessageResources.getMessageResources("jp.sourceforge.shovel.application");
        String address = null, subject = null, text = null;
        
        switch (context.getDelayExecutionType()) {
        case SEND_DIRECT_MESSAGE:
            IDirectMessage directMessage = context.getDirectMessage();
            IUser recipient = getDirectoryLogic().getUser(directMessage.getRecipientId());
            if (!recipient.isRecipientDirectMessage()) {
                return;
            }
            address = recipient.getEmail();
            if (address == null || address.length() <= 0) {
                return;
            }
            IUser sender = getDirectoryLogic().getUser(directMessage.getSenderId());
            subject = resources.getMessage("mail.directMessage.subject", sender.getForeignKey());
            text = resources.getMessage("mail.directMessage.text", directMessage.getText(), sender.getForeignKey());
            break;
        case UPDATE_STATUS:
            IStatus status = context.getStatus();
            recipient = getDirectoryLogic().getUser(status.getReferenceSenderId());
            if (recipient == null) {
                return;
            }
            if (!recipient.isReply()) {
                return;
            }
            address = recipient.getEmail();
            if (address == null || address.length() <= 0) {
                return;
            }
            sender = getDirectoryLogic().getUser(status.getSenderId());
            IFriendship friend = getShovelLogic().getFriendship(recipient.getUserId(), sender.getUserId());
            if (friend == null) {
                //Re:を受ける人が送った人をフォローしていないと無効
                return;
            }
            subject = resources.getMessage("mail.reply.subject", sender.getForeignKey());
            text = resources.getMessage("mail.reply.text", status.getBody(), sender.getForeignKey());
            break;
        case FOLLOW_FRIEND:
            IFriendship friendship = context.getFriend();
            recipient = getDirectoryLogic().getUser(friendship.getPassiveId());
            if (!recipient.isNewFriends()) {
                return;
            }
            address = recipient.getEmail();
            if (address == null || address.length() <= 0) {
                return;
            }
            sender = getDirectoryLogic().getUser(friendship.getActiveId());
            subject = resources.getMessage("mail.followers.subject", sender.getForeignKey());
            text = resources.getMessage("mail.followers.text", recipient.getForeignKey(), sender.getDisplayName(), sender.getForeignKey(), context.getServerName());
            break;
        case RESEND_PASSWORD:
            IUser user = context.getUser();
            address = user.getEmail();
            if (address == null || address.length() <= 0) {
                return;
            }
            subject = resources.getMessage("mail.resendPassword.subject");
            String token = ShovelUtil.generateToken(address + ":" + user.getPassword());
            text = resources.getMessage("mail.resendPassword.text", context.getServerName(), address, token);
            break;
        default:
            return;
        }
        Security.addProvider(new Provider());
        Session session = Session.getDefaultInstance(properties_, new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(
                    properties_.getProperty("mail.username"),
                    properties_.getProperty("mail.password")
                );
            }
        });
        
        text += resources.getMessage("mail.signature");
        
        try {
            InternetAddress to[] = { new InternetAddress(address) };
            MimeMessage message=new MimeMessage(session);
            message.setRecipients(Message.RecipientType.TO, to);

            message.setSubject(subject,"iso-2022-jp");
            message.setText(text,"iso-2022-jp");
            message.setHeader("Content-Type","text/plain");
            message.setSentDate(Calendar.getInstance().getTime());

            Transport.send(message);
        } catch (MessagingException e) {
            throw new ApplicationException("");
        }
    }
    
    /////
    
    S2Container container_;
    
    public void setContainer(S2Container container) {
        container_ = container;
    }
    S2Container getContainer() {
        return container_;
    }
    IDirectoryLogic getDirectoryLogic() {
        return (IDirectoryLogic)getContainer().getComponent(IDirectoryLogic.class);
    }
    IShovelLogic getShovelLogic() {
        return (IShovelLogic)getContainer().getComponent(IShovelLogic.class);
    }
}
