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

import java.util.Vector;

import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.MethodNotSupportedException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
import javax.mail.event.ConnectionEvent;

import org.apache.geronimo.javamail.store.pop3.message.POP3Message;
import org.apache.geronimo.javamail.store.pop3.message.POP3MessageFactory;
import org.apache.geronimo.javamail.store.pop3.response.POP3ResponseFactory;
import org.apache.geronimo.javamail.store.pop3.response.POP3StatusResponse;

/**
 * The POP3 implementation of the javax.mail.Folder Note that only INBOX is
 * supported in POP3
 * <p>
 * <url>http://www.faqs.org/rfcs/rfc1939.html</url>
 * </p>
 * 
 * @see javax.mail.Folder
 * 
 * @version $Rev$ $Date$
 */
public class POP3Folder extends Folder {

    private boolean isFolderOpen = false;

    private int mode;

    private POP3Connection pop3Con;

    private int msgCount;

    private Session session;

    /**
     * Vector is synchronized so choose over the other Collection impls This is
     * initialized on open A chache will save the expensive operation of
     * retrieving the message again from the server.
     */
    private Vector msgCache;

    protected POP3Folder(Store store, URLName url) {
        super(store);
    }

    protected POP3Folder(Store store, Session session, POP3Connection pop3Con) {
        super(store);
        this.pop3Con = pop3Con;
        this.session = session;
    }

    public String getName() {
        return "INBOX";
    }

    public String getFullName() {
        return "INBOX";
    }

    /**
     * Never return "this" as the parent folder. Somebody not familliar with
     * POP3 may do something like while(getParent() != null) or something
     * simmilar which will result in an infinte loop
     */
    public Folder getParent() throws MessagingException {
        throw new MethodNotSupportedException("INBOX is the root folder");
    }

    public boolean exists() throws MessagingException {
        // INBOX always exists at the backend
        return true;
    }

    public Folder[] list(String pattern) throws MessagingException {
        throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
    }

    /**
     * No sub folders, hence there is no notion of a seperator
     */
    public char getSeparator() throws MessagingException {
        throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
    }

    public int getType() throws MessagingException {
        return HOLDS_MESSAGES;
    }

    public boolean create(int type) throws MessagingException {
        throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
    }

    public boolean hasNewMessages() throws MessagingException {
        throw new MethodNotSupportedException("POP3 doesn't support this operation");
    }

    public Folder getFolder(String name) throws MessagingException {
        throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
    }

    public boolean delete(boolean recurse) throws MessagingException {
        throw new MethodNotSupportedException("Only INBOX is supported in POP3 and INBOX cannot be deleted");
    }

    public boolean renameTo(Folder f) throws MessagingException {
        throw new MethodNotSupportedException("Only INBOX is supported in POP3 and INBOX cannot be renamed");
    }

    /**
     * @see javax.mail.Folder#open(int)
     */
    public void open(int mode) throws MessagingException {
        // Can only be performed on a closed folder
        checkClosed();

        try {

            POP3StatusResponse res = (POP3StatusResponse) POP3ResponseFactory.getStatusResponse(pop3Con
                    .sendCommand(POP3CommandFactory.getCOMMAND_STAT()));

            // I am not checking for the res == null condition as the
            // try catch block will handle it.

            this.mode = mode;
            this.isFolderOpen = true;
            this.msgCount = res.getNumMessages();
            // JavaMail API has no method in Folder to expose the total
            // size (no of bytes) of the mail drop;

            // NB:  We use the actual message number to access the messages from 
            // the cache, which is origin 1.  Vectors are origin 0, so we add one additional 
            // element and burn the 
            msgCache = new Vector(msgCount + 1);
            msgCache.setSize(msgCount + 1);

        } catch (Exception e) {
            throw new MessagingException("Unable to execute STAT command", e);
        }

        notifyConnectionListeners(ConnectionEvent.OPENED);
    }

    public void close(boolean expunge) throws MessagingException {
        // Can only be performed on an open folder
        checkOpen();

        try {
            if (mode == READ_WRITE) {
                // find all messages marked deleted and issue DELE commands
                POP3Message m;
                // NB: the first element in the cache is not used.
                for (int i = 1; i < msgCache.size(); i++) {
                    if ((m = (POP3Message) msgCache.elementAt(i)) != null) {
                        if (m.isSet(Flags.Flag.DELETED)) {
                            try {
                                pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_DELE(i + 1));
                            } catch (Exception e) {
                                throw new MessagingException("Exception deleting message no [" + (i + 1)
                                        + "] during close", e);
                            }
                        }
                    }
                }
            }

            try {
                pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_QUIT());
            } catch (Exception e) {
                // doesn't really care about the response
            }
            // dosn't need a catch block here, but added incase something goes
            // wrong
            // so that the finnaly is garunteed to execute in such a case.
        } finally {
            try {
                pop3Con.close();
            } catch (Exception e) {
                // doesn't really care about the response
                // all we can do is to set the reference explicitly to null
                pop3Con = null;
            }

            /*
             * The message numbers depend on the mail drop if the connection is
             * closed, then purge the cache
             */
            msgCache = null;
            isFolderOpen = false;
            notifyConnectionListeners(ConnectionEvent.CLOSED);
        }
    }

    public boolean isOpen() {
        return isFolderOpen;
    }

    public Flags getPermanentFlags() {
        // unfortunately doesn't have a throws clause for this method
        // throw new MethodNotSupportedException("POP3 doesn't support permanent
        // flags");

        // Better than returning null, save the extra condition from a user to
        // check for null
        // and avoids a NullPointerException for the careless.
        return new Flags();
    }

    public int getMessageCount() throws MessagingException {
        return msgCount;
    }

    /**
     * Checks wether the message is in cache, if not will create a new message
     * object and return it.
     * 
     * @see javax.mail.Folder#getMessage(int)
     */
    public Message getMessage(int msgNum) throws MessagingException {
        // Can only be performed on an Open folder
        checkOpen();
        if (msgNum < 1 || msgNum > getMessageCount()) {
            throw new MessagingException("Invalid Message number");
        }

        Message msg = null;
        try {
            msg = (Message) msgCache.elementAt(msgNum);
        } catch (RuntimeException e) {
            session.getDebugOut().println("Message not in cache");
        }
        if (msg == null) {
            msg = POP3MessageFactory.createMessage(this, session, pop3Con, msgNum);
            msgCache.setElementAt(msg, msgNum);
        }

        return msg;
    }

    public void appendMessages(Message[] msgs) throws MessagingException {
        throw new MethodNotSupportedException("Message appending is not supported in POP3");

    }

    public Message[] expunge() throws MessagingException {
        throw new MethodNotSupportedException("Expunge is not supported in POP3");
    }

    public int getMode() throws IllegalStateException {
        // Can only be performed on an Open folder
        checkOpen();
        return mode;
    }

    /**
     * @see javax.mail.Folder#fetch(javax.mail.Message[],
     *      javax.mail.FetchProfile)
     * 
     * The JavaMail API recommends that this method be overrident to provide a
     * meaningfull implementation.
     */
    public void fetch(Message[] msgs, FetchProfile fp) throws MessagingException {
        // Can only be performed on an Open folder
        checkOpen();
        for (int i = 0; i < msgs.length; i++) {
            Message msg = msgs[i];
            if (msg == null) {
                msg = POP3MessageFactory.createMessage(this, session, pop3Con, i);
            }
            if (fp.contains(FetchProfile.Item.ENVELOPE)) {
                msg = POP3MessageFactory.createMessageWithEvelope((POP3Message) msg);
            }

            if (fp.contains(FetchProfile.Item.CONTENT_INFO)) {
                msg = POP3MessageFactory.createMessageWithContentInfo((POP3Message) msg);
            }

            if (fp.contains(FetchProfile.Item.FLAGS)) {
                msg = POP3MessageFactory.createMessageWithFlags((POP3Message) msg);
            }

            msgs[i] = msg;
        }
    }

    /**
     * Below is a list of covinience methods that avoid repeated checking for a
     * value and throwing an exception
     */

    /** Ensure the folder is open */
    private void checkOpen() throws IllegalStateException {
        if (!isFolderOpen) {
            throw new IllegalStateException("Folder is not Open");
        }
    }

    /** Ensure the folder is not open */
    private void checkClosed() throws IllegalStateException {
        if (isFolderOpen) {
            throw new IllegalStateException("Folder is Open");
        }
    }

    /**
     * @see javax.mail.Folder#notifyMessageChangedListeners(int,
     *      javax.mail.Message)
     * 
     * this method is protected and cannot be used outside of Folder, therefore
     * had to explicitly expose it via a method in POP3Folder, so that
     * POP3Message has access to it
     * 
     * Bad design on the part of the Java Mail API.
     */
    public void notifyMessageChangedListeners(int type, Message m) {
        super.notifyMessageChangedListeners(type, m);
    }

}
