/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.geronimo.javamail.transport.nntp;

import java.io.PrintStream;
import java.util.ArrayList;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.event.TransportEvent;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.NewsAddress;

import org.apache.geronimo.javamail.util.ProtocolProperties; 

/**
 * Simple implementation of NNTP transport. Just does plain RFC977-ish delivery.
 * <p/> There is no way to indicate failure for a given recipient (it's possible
 * to have a recipient address rejected). The sun impl throws exceptions even if
 * others successful), but maybe we do a different way... <p/>
 * 
 * @version $Rev$ $Date$
 */
public class NNTPTransport extends Transport {
    /**
     * property keys for protocol properties.
     */
    protected static final String NNTP_FROM = "from";

    protected static final int DEFAULT_NNTP_PORT = 119;
    protected static final int DEFAULT_NNTP_SSL_PORT = 563;

    // our accessor for protocol properties and the holder of 
    // protocol-specific information 
    protected ProtocolProperties props; 
    // our active connection object (shared code with the NNTPStore).
    protected NNTPConnection connection;

    /**
     * Normal constructor for an NNTPTransport() object. This constructor is
     * used to build a transport instance for the "smtp" protocol.
     * 
     * @param session
     *            The attached session.
     * @param name
     *            An optional URLName object containing target information.
     */
    public NNTPTransport(Session session, URLName name) {
        this(session, name, "nntp-post", DEFAULT_NNTP_PORT, false);
    }

    /**
     * Common constructor used by the POP3Store and POP3SSLStore classes
     * to do common initialization of defaults.
     *
     * @param session
     *            The host session instance.
     * @param name
     *            The URLName of the target.
     * @param protocol
     *            The protocol type ("pop3"). This helps us in
     *            retrieving protocol-specific session properties.
     * @param defaultPort
     *            The default port used by this protocol. For pop3, this will
     *            be 110. The default for pop3 with ssl is 995.
     * @param sslConnection
     *            Indicates whether an SSL connection should be used to initial
     *            contact the server. This is different from the STARTTLS
     *            support, which switches the connection to SSL after the
     *            initial startup.
     */
    protected NNTPTransport(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection) {
        super(session, name);
        
        // create the protocol property holder.  This gives an abstraction over the different 
        // flavors of the protocol. 
        props = new ProtocolProperties(session, protocol, sslConnection, defaultPort); 
        // the connection manages connection for the transport 
        connection = new NNTPConnection(props); 
    }

    /**
     * Do the protocol connection for an NNTP transport. This handles server
     * authentication, if possible. Returns false if unable to connect to the
     * server.
     * 
     * @param host
     *            The target host name.
     * @param port
     *            The server port number.
     * @param user
     *            The authentication user (if any).
     * @param password
     *            The server password. Might not be sent directly if more
     *            sophisticated authentication is used.
     * 
     * @return true if we were able to connect to the server properly, false for
     *         any failures.
     * @exception MessagingException
     */
    protected boolean protocolConnect(String host, int port, String username, String password)
            throws MessagingException {
        // the connection pool handles all of the details here. 
        return connection.protocolConnect(host, port, username, password);
    }
    

    /**
     * Send a message to multiple addressees.
     * 
     * @param message
     *            The message we're sending.
     * @param addresses
     *            An array of addresses to send to.
     * 
     * @exception MessagingException
     */
    public void sendMessage(Message message, Address[] addresses) throws MessagingException {
        if (!isConnected()) {
            throw new IllegalStateException("Not connected");
        }

        if (!connection.isPostingAllowed()) {
            throw new MessagingException("Posting disabled for host server");
        }
        // don't bother me w/ null messages or no addreses
        if (message == null) {
            throw new MessagingException("Null message");
        }

        // NNTP only handles instances of MimeMessage, not the more general
        // message case.
        if (!(message instanceof MimeMessage)) {
            throw new MessagingException("NNTP can only send MimeMessages");
        }

        // need to sort the from value out from a variety of sources.
        InternetAddress from = null;

        Address[] fromAddresses = message.getFrom();

        // If the message has a From address set, we just use that. Otherwise,
        // we set a From using
        // the property version, if available.
        if (fromAddresses == null || fromAddresses.length == 0) {
            // the from value can be set explicitly as a property
            String defaultFrom = props.getProperty(NNTP_FROM);
            if (defaultFrom == null) {
                message.setFrom(new InternetAddress(defaultFrom));
            }
        }

        // we must have a message list.
        if (addresses == null || addresses.length == 0) {
            throw new MessagingException("Null or empty address array");
        }

        boolean haveGroup = false;

        // enforce the requirement that all of the targets are NewsAddress
        // instances.
        for (int i = 0; i < addresses.length; i++) {
            if (!(addresses[i] instanceof NewsAddress)) {
                throw new MessagingException("Illegal NewsAddress " + addresses[i]);
            }
        }

        // event notifcation requires we send lists of successes and failures
        // broken down by category.
        // The categories are:
        //
        // 1) addresses successfully processed.
        // 2) addresses deemed valid, but had a processing failure that
        // prevented sending.
        // 3) addressed deemed invalid (basically all other processing
        // failures).
        ArrayList sentAddresses = new ArrayList();
        ArrayList unsentAddresses = new ArrayList();
        ArrayList invalidAddresses = new ArrayList();

        boolean sendFailure = false;

        // now try to post this message to the different news groups.
        for (int i = 0; i < addresses.length; i++) {
            try {
                // select the target news group
                NNTPReply reply = connection.selectGroup(((NewsAddress) addresses[i]).getNewsgroup());

                if (reply.getCode() != NNTPReply.GROUP_SELECTED) {
                    invalidAddresses.add(addresses[i]);
                    sendFailure = true;
                } else {
                    // send data
                    connection.sendPost(message);
                    sentAddresses.add(addresses[i]);
                }
            } catch (MessagingException e) {
                unsentAddresses.add(addresses[i]);
                sendFailure = true;
            }
        }

        // create our lists for notification and exception reporting from this
        // point on.
        Address[] sent = (Address[]) sentAddresses.toArray(new Address[0]);
        Address[] unsent = (Address[]) unsentAddresses.toArray(new Address[0]);
        Address[] invalid = (Address[]) invalidAddresses.toArray(new Address[0]);

        if (sendFailure) {
            // did we deliver anything at all?
            if (sent.length == 0) {
                // notify of the error.
                notifyTransportListeners(TransportEvent.MESSAGE_NOT_DELIVERED, sent, unsent, invalid, message);
            } else {
                // notify that we delivered at least part of this
                notifyTransportListeners(TransportEvent.MESSAGE_PARTIALLY_DELIVERED, sent, unsent, invalid, message);
            }

            throw new MessagingException("Error posting NNTP message");
        }

        // notify our listeners of successful delivery.
        notifyTransportListeners(TransportEvent.MESSAGE_DELIVERED, sent, unsent, invalid, message);
    }

    /**
     * Close the connection. On completion, we'll be disconnected from the
     * server and unable to send more data.
     * 
     * @exception MessagingException
     */
    public void close() throws MessagingException {
        // This is done to ensure proper event notification.
        super.close();
        // NB:  We reuse the connection if asked to reconnect 
        connection.close();
    }
}
