/*
 * 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.commons.net.imap;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.SocketClient;
import org.apache.commons.net.io.CRLFLineReader;


/**
 * The IMAP class provides the basic the functionality necessary to implement your
 * own IMAP client.
 */
public class IMAP extends SocketClient
{
    /** The default IMAP port (RFC 3501). */
    public static final int DEFAULT_PORT = 143;

    public enum IMAPState
    {
        /** A constant representing the state where the client is not yet connected to a server. */
        DISCONNECTED_STATE,
        /**  A constant representing the "not authenticated" state. */
        NOT_AUTH_STATE,
        /**  A constant representing the "authenticated" state. */
        AUTH_STATE,
        /**  A constant representing the "logout" state. */
        LOGOUT_STATE;
    }

    // RFC 3501, section 5.1.3. It should be "modified UTF-7".
    /**
     * The default control socket ecoding.
     */
    protected static final String __DEFAULT_ENCODING = "ISO-8859-1";

    private IMAPState __state;
    protected BufferedWriter __writer;

    protected BufferedReader _reader;
    private int _replyCode;
    private final List<String> _replyLines;

    /**
     * Implement this interface and register it via {@link #setChunkListener(IMAPChunkListener)}
     * in order to get access to multi-line partial command responses.
     * Useful when processing large FETCH responses.
     */
    public interface IMAPChunkListener {
        /**
         * Called when a multi-line partial response has been received.
         * @param imap the instance, get the response
         * by calling {@link #getReplyString()} or {@link #getReplyStrings()}
         * @return {@code true} if the reply buffer is to be cleared on return
         */
        boolean chunkReceived(IMAP imap);
    }

    /**
     * <p>
     * Implementation of IMAPChunkListener that returns {@code true}
     * but otherwise does nothing.
     * </p>
     * <p>
     * This is intended for use with a suitable ProtocolCommandListener.
     * If the IMAP response contains multiple-line data, the protocol listener
     * will be called for each multi-line chunk.
     * The accumulated reply data will be cleared after calling the listener.
     * If the response is very long, this can significantly reduce memory requirements.
     * The listener will also start receiving response data earlier, as it does not have
     * to wait for the entire response to be read.
     * </p>
     * <p>
     * The ProtocolCommandListener must be prepared to accept partial responses.
     * This should not be a problem for listeners that just log the input.
     * </p>
     * @see #setChunkListener(IMAPChunkListener)
     * @since 3.4
     */
    public static final IMAPChunkListener TRUE_CHUNK_LISTENER = new IMAPChunkListener(){
        @Override
        public boolean chunkReceived(IMAP imap) {
            return true;
        }

    };
    private volatile IMAPChunkListener __chunkListener;

    private final char[] _initialID = { 'A', 'A', 'A', 'A' };

    /**
     * The default IMAPClient constructor.  Initializes the state
     * to <code>DISCONNECTED_STATE</code>.
     */
    public IMAP()
    {
        setDefaultPort(DEFAULT_PORT);
        __state = IMAPState.DISCONNECTED_STATE;
        _reader = null;
        __writer = null;
        _replyLines = new ArrayList<String>();
        createCommandSupport();
    }

    /**
     * Get the reply for a command that expects a tagged response.
     *
     * @throws IOException
     */
    private void __getReply() throws IOException
    {
        __getReply(true); // tagged response
    }

    /**
     * Get the reply for a command, reading the response until the
     * reply is found.
     *
     * @param wantTag {@code true} if the command expects a tagged response.
     * @throws IOException
     */
    private void __getReply(boolean wantTag) throws IOException
    {
        _replyLines.clear();
        String line = _reader.readLine();

        if (line == null) {
            throw new EOFException("Connection closed without indication.");
        }

        _replyLines.add(line);

        if (wantTag) {
            while(IMAPReply.isUntagged(line)) {
                int literalCount = IMAPReply.literalCount(line);
                final boolean isMultiLine = literalCount >= 0;
                while (literalCount >= 0) {
                    line=_reader.readLine();
                    if (line == null) {
                        throw new EOFException("Connection closed without indication.");
                    }
                    _replyLines.add(line);
                    literalCount -= (line.length() + 2); // Allow for CRLF
                }
                if (isMultiLine) {
                    IMAPChunkListener il = __chunkListener;
                    if (il != null) {
                        boolean clear = il.chunkReceived(this);
                        if (clear) {
                            fireReplyReceived(IMAPReply.PARTIAL, getReplyString());
                            _replyLines.clear();
                        }
                    }
                }
                line = _reader.readLine(); // get next chunk or final tag
                if (line == null) {
                    throw new EOFException("Connection closed without indication.");
                }
                _replyLines.add(line);
            }
            // check the response code on the last line
            _replyCode = IMAPReply.getReplyCode(line);
        } else {
            _replyCode = IMAPReply.getUntaggedReplyCode(line);
        }

        fireReplyReceived(_replyCode, getReplyString());
    }

    /**
     * Overrides {@link SocketClient#fireReplyReceived(int, String)} so as to
     * avoid creating the reply string if there are no listeners to invoke.
     *
     * @param replyCode passed to the listeners
     * @param ignored the string is only created if there are listeners defined.
     * @see #getReplyString()
     * @since 3.4
     */
    @Override
    protected void fireReplyReceived(int replyCode, String ignored) {
        if (getCommandSupport().getListenerCount() > 0) {
            getCommandSupport().fireReplyReceived(replyCode, getReplyString());
        }
    }

    /**
     * Performs connection initialization and sets state to
     * {@link IMAPState#NOT_AUTH_STATE}.
     */
    @Override
    protected void _connectAction_() throws IOException
    {
        super._connectAction_();
        _reader =
          new CRLFLineReader(new InputStreamReader(_input_,
                                                   __DEFAULT_ENCODING));
        __writer =
          new BufferedWriter(new OutputStreamWriter(_output_,
                                                    __DEFAULT_ENCODING));
        int tmo = getSoTimeout();
        if (tmo <= 0) { // none set currently
            setSoTimeout(connectTimeout); // use connect timeout to ensure we don't block forever
        }
        __getReply(false); // untagged response
        if (tmo <= 0) {
            setSoTimeout(tmo); // restore the original value
        }
        setState(IMAPState.NOT_AUTH_STATE);
    }

    /**
     * Sets IMAP client state.  This must be one of the
     * <code>_STATE</code> constants.
     *
     * @param state  The new state.
     */
    protected void setState(IMAP.IMAPState state)
    {
        __state = state;
    }


    /**
     * Returns the current IMAP client state.
     *
     * @return The current IMAP client state.
     */
    public IMAP.IMAPState getState()
    {
        return __state;
    }

    /**
     * Disconnects the client from the server, and sets the state to
     * <code> DISCONNECTED_STATE </code>.  The reply text information
     * from the last issued command is voided to allow garbage collection
     * of the memory used to store that information.
     *
     * @throws IOException  If there is an error in disconnecting.
     */
    @Override
    public void disconnect() throws IOException
    {
        super.disconnect();
        _reader = null;
        __writer = null;
        _replyLines.clear();
        setState(IMAPState.DISCONNECTED_STATE);
    }


    /**
     * Sends a command an arguments to the server and returns the reply code.
     *
     * @param commandID The ID (tag) of the command.
     * @param command  The IMAP command to send.
     * @param args     The command arguments.
     * @return  The server reply code (either IMAPReply.OK, IMAPReply.NO or IMAPReply.BAD).
     */
    private int sendCommandWithID(String commandID, String command, String args) throws IOException
    {
        StringBuilder __commandBuffer = new StringBuilder();
        if (commandID != null)
        {
            __commandBuffer.append(commandID);
            __commandBuffer.append(' ');
        }
        __commandBuffer.append(command);

        if (args != null)
        {
            __commandBuffer.append(' ');
            __commandBuffer.append(args);
        }
        __commandBuffer.append(SocketClient.NETASCII_EOL);

        String message = __commandBuffer.toString();
        __writer.write(message);
        __writer.flush();

        fireCommandSent(command, message);

        __getReply();
        return _replyCode;
    }

    /**
     * Sends a command an arguments to the server and returns the reply code.
     *
     * @param command  The IMAP command to send.
     * @param args     The command arguments.
     * @return  The server reply code (see IMAPReply).
     * @throws IOException on error
     */
    public int sendCommand(String command, String args) throws IOException
    {
        return sendCommandWithID(generateCommandID(), command, args);
    }

    /**
     * Sends a command with no arguments to the server and returns the
     * reply code.
     *
     * @param command  The IMAP command to send.
     * @return  The server reply code (see IMAPReply).
     * @throws IOException on error
     */
    public int sendCommand(String command) throws IOException
    {
        return sendCommand(command, null);
    }

    /**
     * Sends a command and arguments to the server and returns the reply code.
     *
     * @param command  The IMAP command to send
     *                  (one of the IMAPCommand constants).
     * @param args     The command arguments.
     * @return  The server reply code (see IMAPReply).
     * @throws IOException on error
     */
    public int sendCommand(IMAPCommand command, String args) throws IOException
    {
        return sendCommand(command.getIMAPCommand(), args);
    }

    /**
     * Sends a command and arguments to the server and return whether successful.
     *
     * @param command  The IMAP command to send
     *                  (one of the IMAPCommand constants).
     * @param args     The command arguments.
     * @return  {@code true} if the command was successful
     * @throws IOException on error
     */
    public boolean doCommand(IMAPCommand command, String args) throws IOException
    {
        return IMAPReply.isSuccess(sendCommand(command, args));
    }

    /**
     * Sends a command with no arguments to the server and returns the
     * reply code.
     *
     * @param command  The IMAP command to send
     *                  (one of the IMAPCommand constants).
     * @return  The server reply code (see IMAPReply).
     * @throws IOException on error
    **/
    public int sendCommand(IMAPCommand command) throws IOException
    {
        return sendCommand(command, null);
    }

    /**
     * Sends a command to the server and return whether successful.
     *
     * @param command  The IMAP command to send
     *                  (one of the IMAPCommand constants).
     * @return  {@code true} if the command was successful
     * @throws IOException on error
     */
    public boolean doCommand(IMAPCommand command) throws IOException
    {
        return IMAPReply.isSuccess(sendCommand(command));
    }

    /**
     * Sends data to the server and returns the reply code.
     *
     * @param command  The IMAP command to send.
     * @return  The server reply code (see IMAPReply).
     * @throws IOException on error
     */
    public int sendData(String command) throws IOException
    {
        return sendCommandWithID(null, command, null);
    }

    /**
     * Returns an array of lines received as a reply to the last command
     * sent to the server.  The lines have end of lines truncated.
     * @return The last server response.
     */
    public String[] getReplyStrings()
    {
        return _replyLines.toArray(new String[_replyLines.size()]);
    }

    /**
     * Returns the reply to the last command sent to the server.
     * The value is a single string containing all the reply lines including
     * newlines.
     *
     * @return The last server response.
     */
    public String getReplyString()
    {
        StringBuilder buffer = new StringBuilder(256);
        for (String s : _replyLines)
        {
            buffer.append(s);
            buffer.append(SocketClient.NETASCII_EOL);
        }

        return buffer.toString();
    }

    /**
     * Sets the current chunk listener.
     * If a listener is registered and the implementation returns true,
     * then any registered
     * {@link org.apache.commons.net.PrintCommandListener PrintCommandListener}
     * instances will be invoked with the partial response and a status of
     * {@link IMAPReply#PARTIAL} to indicate that the final reply code is not yet known.
     * @param listener the class to use, or {@code null} to disable
     * @see #TRUE_CHUNK_LISTENER
     * @since 3.4
     */
    public void setChunkListener(IMAPChunkListener listener) {
        __chunkListener = listener;
    }

    /**
     * Generates a new command ID (tag) for a command.
     * @return a new command ID (tag) for an IMAP command.
     */
    protected String generateCommandID()
    {
        String res = new String (_initialID);
        // "increase" the ID for the next call
        boolean carry = true; // want to increment initially
        for (int i = _initialID.length-1; carry && i>=0; i--)
        {
            if (_initialID[i] == 'Z')
            {
                _initialID[i] = 'A';
            }
            else
            {
                _initialID[i]++;
                carry = false; // did not wrap round
            }
        }
        return res;
    }

    /**
     * Quote an input string if necessary.
     * If the string is enclosed in double-quotes it is assumed
     * to be quoted already and is returned unchanged.
     * If it is the empty string, "" is returned.
     * If it contains a space
     * then it is enclosed in double quotes, escaping the
     * characters backslash and double-quote.
     *
     * @param input the value to be quoted, may be null
     * @return the quoted value
     */
    static String quoteMailboxName(String input) {
        if (input == null) { // Don't throw NPE here
            return null;
        }
        if (input.isEmpty()) {
            return "\"\""; // return the string ""
        }
        // Length check is necessary to ensure a lone double-quote is quoted
        if (input.length() > 1 && input.startsWith("\"") && input.endsWith("\"")) {
            return input; // Assume already quoted
        }
        if (input.contains(" ")) {
            // quoted strings must escape \ and "
            return "\"" + input.replaceAll("([\\\\\"])", "\\\\$1") + "\"";
        }
        return input;

    }
}
/* kate: indent-width 4; replace-tabs on; */
