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

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Quota;
import javax.mail.UIDFolder;

import javax.mail.search.AddressTerm;
import javax.mail.search.AndTerm;
import javax.mail.search.BodyTerm;
import javax.mail.search.ComparisonTerm;
import javax.mail.search.DateTerm;
import javax.mail.search.FlagTerm;
import javax.mail.search.FromTerm;
import javax.mail.search.FromStringTerm;
import javax.mail.search.HeaderTerm;
import javax.mail.search.MessageIDTerm;
import javax.mail.search.MessageNumberTerm;
import javax.mail.search.NotTerm;
import javax.mail.search.OrTerm;
import javax.mail.search.ReceivedDateTerm;
import javax.mail.search.RecipientTerm;
import javax.mail.search.RecipientStringTerm;
import javax.mail.search.SearchException;
import javax.mail.search.SearchTerm;
import javax.mail.search.SentDateTerm;
import javax.mail.search.SizeTerm;
import javax.mail.search.StringTerm;
import javax.mail.search.SubjectTerm;

import org.apache.geronimo.javamail.store.imap.ACL;
import org.apache.geronimo.javamail.store.imap.IMAPFolder;
import org.apache.geronimo.javamail.store.imap.Rights;
import org.apache.geronimo.javamail.store.imap.connection.IMAPResponseTokenizer.Token;

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


/**
 * Utility class for building up what might be complex arguments
 * to a command.  This includes the ability to directly write out
 * binary arrays of data and have them constructed as IMAP
 * literals.
 */
public class IMAPCommand {

    // digits table for encoding IMAP modified Base64.  Note that this differs
    // from "normal" base 64 by using ',' instead of '/' for the last digit.
    public static final char[] encodingTable = {
        'A', 'B', 'C', 'D', 'E', 'F', 'G',
        'H', 'I', 'J', 'K', 'L', 'M', 'N',
        'O', 'P', 'Q', 'R', 'S', 'T', 'U',
        'V', 'W', 'X', 'Y', 'Z',
        'a', 'b', 'c', 'd', 'e', 'f', 'g',
        'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u',
        'v', 'w', 'x', 'y', 'z',
        '0', '1', '2', '3', '4', '5', '6',
        '7', '8', '9',
        '+', ','
    };

    protected boolean needWhiteSpace = false;

    // our utility writer stream
    protected DataOutputStream out;
    // the real output target
    protected ByteArrayOutputStream sink;
    // our command segment set.  If the command contains literals, then the literal
    // data must be sent after receiving an continue response back from the server.
    protected List segments = null;
    // the append tag for the response
    protected String tag;

    // our counter used to generate command tags.
    static protected int tagCounter = 0;

    /**
     * Create an empty command.
     */
    public IMAPCommand() {
        try {
            sink = new ByteArrayOutputStream();
            out = new DataOutputStream(sink);

            // write the tag data at the beginning of the command.
            out.writeBytes(getTag());
            // need a blank separator
            out.write(' ');
        } catch (IOException e ) {
        }
    }

    /**
     * Create a command with an initial command string.
     *
     * @param command The command string used to start this command.
     */
    public IMAPCommand(String command) {
        this();
        append(command);
    }

    public String getTag() {
        if (tag == null) {
            // the tag needs to be non-numeric, so tack a convenient alpha character on the front.
            tag = "a" + tagCounter++;
        }
        return tag;
    }


    /**
     * Save the current segment of the command we've accumulated.  This
     * generally occurs because we have a literal element in the command
     * that's going to require a continuation response from the server before
     * we can send it.
     */
    private void saveCurrentSegment()
    {
        try {
            out.flush();     // make sure everything is written
                             // get the data so far and reset the sink
            byte[] segment = sink.toByteArray();
            sink.reset();
            // most commands don't have segments, so don't create the list until we do.
            if (segments == null) {
                segments = new ArrayList();
            }
            // ok, we need to issue this command as a conversation.
            segments.add(segment);
        } catch (IOException e) {
        }
    }


    /**
     * Write all of the command data to the stream.  This includes the
     * leading tag data.
     *
     * @param outStream
     * @param connection
     *
     * @exception IOException
     * @exception MessagingException
     */
    public void writeTo(OutputStream outStream, IMAPConnection connection) throws IOException, MessagingException
    {

        // just a simple, single string-encoded command?
        if (segments == null) {
            // make sure the output stream is flushed
            out.flush();
            // just copy the command data to the output stream
            sink.writeTo(outStream);
            // we need to end the command with a CRLF sequence.
            outStream.write('\r');
            outStream.write('\n');
        }
        // multiple-segment mode, which means we need to deal with continuation responses at
        // each of the literal boundaries.
        else {
            // at this point, we have a list of command pieces that must be written out, then a
            // continuation response checked for after each write.  Once each of these pieces is
            // written out, we still have command stuff pending in the out stream, which we'll tack
            // on to the end.
            for (int i = 0; i < segments.size(); i++) {
                outStream.write((byte [])segments.get(i));
                // now wait for a response from the connection.  We should be getting a
                // continuation response back (and might have also received some asynchronous
                // replies, which we'll leave in the queue for now.  If we get some status back
                // other than than a continue, we've got an error in our command somewhere.
                IMAPTaggedResponse response = connection.receiveResponse();
                if (!response.isContinuation()) {
                    throw new CommandFailedException("Error response received on a IMAP continued command:  " + response);
                }
            }
            out.flush();
            // all leading segments written with the appropriate continuation received in reply.
            // just copy the command data to the output stream
            sink.writeTo(outStream);
            // we need to end the command with a CRLF sequence.
            outStream.write('\r');
            outStream.write('\n');
        }
    }


    /**
     * Directly append a value to the buffer without attempting
     * to insert whitespace or figure out any format encodings.
     *
     * @param value  The value to append.
     */
    public void append(String value) {
        try {
            // add the bytes direcly
            out.writeBytes(value);
            // assume we're needing whitespace after this (pretty much unknown).
            needWhiteSpace = true;
        } catch (IOException e) {
        }
    }


    /**
     * Append a string value to a command buffer.  This sorts out
     * what form the string needs to be appended in (LITERAL, QUOTEDSTRING,
     * or ATOM).
     *
     * @param target The target buffer for appending the string.
     * @param value  The value to append.
     */
    public void appendString(String value) {
        try {
            // work off the byte values
            appendString(value.getBytes("ISO8859-1"));
        } catch (UnsupportedEncodingException e) {
        }
    }


    /**
     * Append a string value to a command buffer.  This always appends as
     * a QUOTEDSTRING
     *
     * @param value  The value to append.
     */
    public void appendQuotedString(String value) {
        try {
            // work off the byte values
            appendQuotedString(value.getBytes("ISO8859-1"));
        } catch (UnsupportedEncodingException e) {
        }
    }


    /**
     * Append a string value to a command buffer, with encoding.  This sorts out
     * what form the string needs to be appended in (LITERAL, QUOTEDSTRING,
     * or ATOM).
     *
     * @param target The target buffer for appending the string.
     * @param value  The value to append.
     */
    public void appendEncodedString(String value) {
        // encode first.
        value = encode(value);
        try {
            // work off the byte values
            appendString(value.getBytes("ISO8859-1"));
        } catch (UnsupportedEncodingException e) {
        }
    }


    /**
     * Encode a string using the modified UTF-7 encoding.
     *
     * @param original The original string.
     *
     * @return The original string encoded with modified UTF-7 encoding.
     */
    public String encode(String original) {

        // buffer for encoding sections of data
        byte[] buffer = new byte[4];
        int bufferCount = 0;

        StringBuffer result = new StringBuffer();

        // state flag for the type of section we're in.
        boolean encoding = false;

        for (int i = 0; i < original.length(); i++) {
            char ch = original.charAt(i);

            // processing an encoded section?
            if (encoding) {
                // is this a printable character?
                if (ch > 31 && ch < 127) {
                    // encode anything in the buffer
                    encode(buffer, bufferCount, result);
                    // add the section terminator char
                    result.append('-');
                    encoding = false;
                    // we now fall through to the printable character section.
                }
                // still an unprintable
                else {
                    // add this char to the working buffer?
                    buffer[++bufferCount] = (byte)(ch >> 8);
                    buffer[++bufferCount] = (byte)(ch & 0xff);
                    // if we have enough to encode something, do it now.
                    if (bufferCount >= 3) {
                        bufferCount = encode(buffer, bufferCount, result);
                    }
                    // go back to the top of the loop.
                    continue;
                }
            }
            // is this the special printable?
            if (ch == '&') {
                // this is the special null escape sequence
                result.append('&');
                result.append('-');
            }
            // is this a printable character?
            else if (ch > 31 && ch < 127) {
                // just add to the result
                result.append(ch);
            }
            else {
                // write the escape character
                result.append('&');

                // non-printable ASCII character, we need to switch modes
                // both bytes of this character need to be encoded.  Each
                // encoded digit will basically be a "character-and-a-half".
                buffer[0] = (byte)(ch >> 8);
                buffer[1] = (byte)(ch & 0xff);
                bufferCount = 2;
                encoding = true;
            }
        }
        // were we in a non-printable section at the end?
        if (encoding) {
            // take care of any remaining characters
            encode(buffer, bufferCount, result);
            // add the section terminator char
            result.append('-');
        }
        // convert the encoded string.
        return result.toString();
    }


    /**
     * Encode a single buffer of characters.  This buffer will have
     * between 0 and 4 bytes to encode.
     *
     * @param buffer The buffer to encode.
     * @param count  The number of characters in the buffer.
     * @param result The accumulator for appending the result.
     *
     * @return The remaining number of bytes remaining in the buffer (return 0
     *         unless the count was 4 at the beginning).
     */
    protected static int encode(byte[] buffer, int count, StringBuffer result) {
        byte b1 = 0;
        byte b2 = 0;
        byte b3 = 0;

        // different processing based on how much we have in the buffer
        switch (count) {
            // ended at a boundary.  This is cool, not much to do.
            case 0:
                // no residual in the buffer
                return 0;

            // just a single left over byte from the last encoding op.
            case 1:
                b1 = buffer[0];
                result.append(encodingTable[(b1 >>> 2) & 0x3f]);
                result.append(encodingTable[(b1 << 4) & 0x30]);
                return 0;

            // one complete char to encode
            case 2:
                b1 = buffer[0];
                b2 = buffer[1];
                result.append(encodingTable[(b1 >>> 2) & 0x3f]);
                result.append(encodingTable[((b1 << 4) & 0x30) + ((b2 >>>4) & 0x0f)]);
                result.append(encodingTable[((b2 << 2) & (0x3c))]);
                return 0;

            // at least a full triplet of bytes to encode
            case 3:
            case 4:
                b1 = buffer[0];
                b2 = buffer[1];
                b3 = buffer[2];
                result.append(encodingTable[(b1 >>> 2) & 0x3f]);
                result.append(encodingTable[((b1 << 4) & 0x30) + ((b2 >>>4) & 0x0f)]);
                result.append(encodingTable[((b2 << 2) & 0x3c) + ((b3 >>> 6) & 0x03)]);
                result.append(encodingTable[b3 & 0x3f]);

                // if we have more than the triplet, we need to move the extra one into the first
                // position and return the residual indicator
                if (count == 4) {
                    buffer[0] = buffer[4];
                    return 1;
                }
                return 0;
        }
        return 0;
    }


    /**
     * Append a string value to a command buffer.  This sorts out
     * what form the string needs to be appended in (LITERAL, QUOTEDSTRING,
     * or ATOM).
     *
     * @param target The target buffer for appending the string.
     * @param value  The value to append.
     */
    public void appendString(String value, String charset) throws MessagingException {
        if (charset == null) {
            try {
                // work off the byte values
                appendString(value.getBytes("ISO8859-1"));
            } catch (UnsupportedEncodingException e) {
            }
        }
        else {
            try {
                // use the charset to extract the bytes
                appendString(value.getBytes(charset));
                throw new MessagingException("Invalid text encoding");
            } catch (UnsupportedEncodingException e) {
            }
        }
    }


    /**
     * Append a value in a byte array to a command buffer.  This sorts out
     * what form the string needs to be appended in (LITERAL, QUOTEDSTRING,
     * or ATOM).
     *
     * @param target The target buffer for appending the string.
     * @param value  The value to append.
     */
    public void appendString(byte[] value) {
        // sort out how we need to append this
        switch (IMAPResponseTokenizer.getEncoding(value)) {
            case Token.LITERAL:
                appendLiteral(value);
                break;
            case Token.QUOTEDSTRING:
                appendQuotedString(value);
                break;
            case Token.ATOM:
                appendAtom(value);
                break;
        }
    }


    /**
     * Append an integer value to the command, converting
     * the integer into string form.
     *
     * @param value  The value to append.
     */
    public void appendInteger(int value) {
        appendAtom(Integer.toString(value));
    }


    /**
     * Append a long value to the command, converting
     * the integer into string form.
     *
     * @param value  The value to append.
     */
    public void appendLong(long value) {
        appendAtom(Long.toString(value));
    }


    /**
     * Append an atom value to the command.  Atoms are directly
     * appended without using literal encodings.
     *
     * @param value  The value to append.
     */
    public void appendAtom(String value) {
        try {
            appendAtom(value.getBytes("ISO8859-1"));
        } catch (UnsupportedEncodingException e) {
        }
    }



    /**
     * Append an atom to the command buffer.  Atoms are directly
     * appended without using literal encodings.  White space is
     * accounted for with the append operation.
     *
     * @param value  The value to append.
     */
    public void appendAtom(byte[] value) {
        try {
            // give a token separator
            conditionalWhitespace();
            // ATOMs are easy
            out.write(value);
        } catch (IOException e) {
        }
    }


    /**
     * Append an IMAP literal values to the command.
     * literals are written using a header with the length
     * specified, followed by a CRLF sequence, followed
     * by the literal data.
     *
     * @param value  The literal data to write.
     */
    public void appendLiteral(byte[] value) {
        try {
            appendLiteralHeader(value.length);
            out.write(value);
        } catch (IOException e) {
        }
    }

    /**
     * Add a literal header to the buffer.  The literal
     * header is the literal length enclosed in a
     * "{n}" pair, followed by a CRLF sequence.
     *
     * @param size   The size of the literal value.
     */
    protected void appendLiteralHeader(int size) {
        try {
            conditionalWhitespace();
            out.writeByte('{');
            out.writeBytes(Integer.toString(size));
            out.writeBytes("}\r\n");
            // the IMAP client is required to send literal data to the server by
            // writing the command up to the header, then waiting for a continuation
            // response to send the rest.
            saveCurrentSegment();
        } catch (IOException e) {
        }
    }


    /**
     * Append literal data to the command where the
     * literal sourcd is a ByteArrayOutputStream.
     *
     * @param value  The source of the literal data.
     */
    public void appendLiteral(ByteArrayOutputStream value) {
        try {
            appendLiteralHeader(value.size());
            // have this output stream write directly into our stream
            value.writeTo(out);
        } catch (IOException e) {
        }
    }

    /**
     * Write out a string of literal data, taking into
     * account the need to escape both '"' and '\'
     * characters.
     *
     * @param value  The bytes of the string to write.
     */
    public void appendQuotedString(byte[] value) {
        try {
            conditionalWhitespace();
            out.writeByte('"');

            // look for chars requiring escaping
            for (int i = 0; i < value.length; i++) {
                byte ch = value[i];

                if (ch == '"' || ch == '\\') {
                    out.writeByte('\\');
                }
                out.writeByte(ch);
            }

            out.writeByte('"');
        } catch (IOException e) {
        }
    }

    /**
     * Mark the start of a list value being written to
     * the command.  A list is a sequences of different
     * tokens enclosed in "(" ")" pairs.  Lists can
     * be nested.
     */
    public void startList() {
        try {
            conditionalWhitespace();
            out.writeByte('(');
            needWhiteSpace = false;
        } catch (IOException e) {
        }
    }

    /**
     * Write out the end of the list.
     */
    public void endList() {
        try {
            out.writeByte(')');
            needWhiteSpace = true;
        } catch (IOException e) {
        }
    }


    /**
     * Add a whitespace character to the command if the
     * previous token was a type that required a
     * white space character to mark the boundary.
     */
    protected void conditionalWhitespace() {
        try {
            if (needWhiteSpace) {
                out.writeByte(' ');
            }
            // all callers of this are writing a token that will need white space following, so turn this on
            // every time we're called.
            needWhiteSpace = true;
        } catch (IOException e) {
        }
    }


    /**
     * Append a body section specification to a command string.  Body
     * section specifications are of the form "[section]<start.count>".
     *
     * @param section  The section numeric identifier.
     * @param partName The name of the body section we want (e.g. "TEST", "HEADERS").
     */
    public void appendBodySection(String section, String partName) {
        try {
            // we sometimes get called from the top level
            if (section == null) {
                appendBodySection(partName);
                return;
            }

            out.writeByte('[');
            out.writeBytes(section);
            if (partName != null) {
                out.writeByte('.');
                out.writeBytes(partName);
            }
            out.writeByte(']');
            needWhiteSpace = true;
        } catch (IOException e) {
        }
    }


    /**
     * Append a body section specification to a command string.  Body
     * section specifications are of the form "[section]".
     *
     * @param partName The partname we require.
     */
    public void appendBodySection(String partName) {
        try {
            out.writeByte('[');
            out.writeBytes(partName);
            out.writeByte(']');
            needWhiteSpace = true;
        } catch (IOException e) {
        }
    }


    /**
     * Append a set of flags to a command buffer.
     *
     * @param flags  The flag set to append.
     */
    public void appendFlags(Flags flags) {
        startList();

        Flags.Flag[] systemFlags = flags.getSystemFlags();

        // process each of the system flag names
        for (int i = 0; i < systemFlags.length; i++) {
            Flags.Flag flag = systemFlags[i];

            if (flag == Flags.Flag.ANSWERED) {
                appendAtom("\\Answered");
            }
            else if (flag == Flags.Flag.DELETED) {
                appendAtom("\\Deleted");
            }
            else if (flag == Flags.Flag.DRAFT) {
                appendAtom("\\Draft");
            }
            else if (flag == Flags.Flag.FLAGGED) {
                appendAtom("\\Flagged");
            }
            else if (flag == Flags.Flag.RECENT) {
                appendAtom("\\Recent");
            }
            else if (flag == Flags.Flag.SEEN) {
                appendAtom("\\Seen");
            }
        }

        // now process the user flags, which just get appended as is.
        String[] userFlags = flags.getUserFlags();

        for (int i = 0; i < userFlags.length; i++) {
            appendAtom(userFlags[i]);
        }

        // close the list off
        endList();
    }


    /**
     * Format a date into the form required for IMAP commands.
     *
     * @param d      The source Date.
     */
    public void appendDate(Date d) {
        // get a formatter to create IMAP dates.  Use the US locale, as the dates are not localized.
        IMAPDateFormat formatter = new IMAPDateFormat();
        // date_time strings need to be done as quoted strings because they contain blanks.
        appendString(formatter.format(d));
    }


    /**
     * Format a date into the form required for IMAP search commands.
     *
     * @param d      The source Date.
     */
    public void appendSearchDate(Date d) {
        // get a formatter to create IMAP dates.  Use the US locale, as the dates are not localized.
        IMAPSearchDateFormat formatter = new IMAPSearchDateFormat();
        // date_time strings need to be done as quoted strings because they contain blanks.
        appendString(formatter.format(d));
    }


    /**
     * append an IMAP search sequence from a SearchTerm.  SearchTerms
     * terms can be complex sets of terms in a tree form, so this
     * may involve some recursion to completely translate.
     *
     * @param term    The search term we're processing.
     * @param charset The charset we need to use when generating the sequence.
     *
     * @exception MessagingException
     */
    public void appendSearchTerm(SearchTerm term, String charset) throws MessagingException {
        // we need to do this manually, by inspecting the term object against the various SearchTerm types
        // defined by the javamail spec.

        // Flag searches are used internally by other operations, so this is a good one to check first.
        if (term instanceof FlagTerm) {
            appendFlag((FlagTerm)term, charset);
        }
        // after that, I'm not sure there's any optimal order to these.  Let's start with the conditional
        // modifiers (AND, OR, NOT), then just hit each of the header types
        else if (term instanceof AndTerm) {
            appendAnd((AndTerm)term, charset);
        }
        else if (term instanceof OrTerm) {
            appendOr((OrTerm)term, charset);
        }
        else if (term instanceof NotTerm) {
            appendNot((NotTerm)term, charset);
        }
        // multiple forms of From: search
        else if (term instanceof FromTerm) {
            appendFrom((FromTerm)term, charset);
        }
        else if (term instanceof FromStringTerm) {
            appendFrom((FromStringTerm)term, charset);
        }
        else if (term instanceof HeaderTerm) {
            appendHeader((HeaderTerm)term, charset);
        }
        else if (term instanceof RecipientTerm) {
            appendRecipient((RecipientTerm)term, charset);
        }
        else if (term instanceof RecipientStringTerm) {
            appendRecipient((RecipientStringTerm)term, charset);
        }
        else if (term instanceof SubjectTerm) {
            appendSubject((SubjectTerm)term, charset);
        }
        else if (term instanceof BodyTerm) {
            appendBody((BodyTerm)term, charset);
        }
        else if (term instanceof SizeTerm) {
            appendSize((SizeTerm)term, charset);
        }
        else if (term instanceof SentDateTerm) {
            appendSentDate((SentDateTerm)term, charset);
        }
        else if (term instanceof ReceivedDateTerm) {
            appendReceivedDate((ReceivedDateTerm)term, charset);
        }
        else if (term instanceof MessageIDTerm) {
            appendMessageID((MessageIDTerm)term, charset);
        }
        else {
            // don't know what this is
            throw new SearchException("Unsupported search type");
        }
    }

    /**
     * append IMAP search term information from a FlagTerm item.
     *
     * @param term    The source FlagTerm
     * @param charset target charset for the search information (can be null).
     * @param out     The target command buffer.
     */
    protected void appendFlag(FlagTerm term, String charset) {
        // decide which one we need to test for
        boolean set = term.getTestSet();

        Flags flags = term.getFlags();
        Flags.Flag[] systemFlags = flags.getSystemFlags();

        String[] userFlags = flags.getUserFlags();

        // empty search term?  not sure if this is an error.  The default search implementation would
        // not consider this an error, so we'll just ignore this.
        if (systemFlags.length == 0 && userFlags.length == 0) {
            return;
        }

        if (set) {
            for (int i = 0; i < systemFlags.length; i++) {
                Flags.Flag flag = systemFlags[i];

                if (flag == Flags.Flag.ANSWERED) {
                    appendAtom("ANSWERED");
                }
                else if (flag == Flags.Flag.DELETED) {
                    appendAtom("DELETED");
                }
                else if (flag == Flags.Flag.DRAFT) {
                    appendAtom("DRAFT");
                }
                else if (flag == Flags.Flag.FLAGGED) {
                    appendAtom("FLAGGED");
                }
                else if (flag == Flags.Flag.RECENT) {
                    appendAtom("RECENT");
                }
                else if (flag == Flags.Flag.SEEN) {
                    appendAtom("SEEN");
                }
            }
        }
        else {
            for (int i = 0; i < systemFlags.length; i++) {
                Flags.Flag flag = systemFlags[i];

                if (flag == Flags.Flag.ANSWERED) {
                    appendAtom("UNANSWERED");
                }
                else if (flag == Flags.Flag.DELETED) {
                    appendAtom("UNDELETED");
                }
                else if (flag == Flags.Flag.DRAFT) {
                    appendAtom("UNDRAFT");
                }
                else if (flag == Flags.Flag.FLAGGED) {
                    appendAtom("UNFLAGGED");
                }
                else if (flag == Flags.Flag.RECENT) {
                    // not UNRECENT?
                    appendAtom("OLD");
                }
                else if (flag == Flags.Flag.SEEN) {
                    appendAtom("UNSEEN");
                }
            }
        }


        // User flags are done as either "KEYWORD name" or "UNKEYWORD name"
        for (int i = 0; i < userFlags.length; i++) {
            appendAtom(set ? "KEYWORD" : "UNKEYWORD");
            appendAtom(userFlags[i]);
        }
    }


    /**
     * append IMAP search term information from an AndTerm item.
     *
     * @param term    The source AndTerm
     * @param charset target charset for the search information (can be null).
     * @param out     The target command buffer.
     */
    protected void appendAnd(AndTerm term, String charset) throws MessagingException {
        // ANDs are pretty easy.  Just append all of the terms directly to the
        // command as is.

        SearchTerm[] terms = term.getTerms();

        for (int i = 0; i < terms.length; i++) {
            appendSearchTerm(terms[i], charset);
        }
    }


    /**
     * append IMAP search term information from an OrTerm item.
     *
     * @param term    The source OrTerm
     * @param charset target charset for the search information (can be null).
     * @param out     The target command buffer.
     */
    protected void appendOr(OrTerm term, String charset) throws MessagingException {
        SearchTerm[] terms = term.getTerms();

        // OrTerms are a bit of a pain to translate to IMAP semantics.  The IMAP OR operation only allows 2
        // search keys, while OrTerms can have n keys (including, it appears, just one!  If we have more than
        // 2, it's easiest to convert this into a tree of OR keys and let things generate that way.  The
        // resulting IMAP operation would be OR (key1) (OR (key2) (key3))

        // silly rabbit...somebody doesn't know how to use OR
        if (terms.length == 1) {
            // just append the singleton in place without the OR operation.
            appendSearchTerm(terms[0], charset);
            return;
        }

        // is this a more complex operation?
        if (terms.length > 2) {
            // have to chain these together (shazbat).
            SearchTerm current = terms[0];

            for (int i = 1; i < terms.length; i++) {
                current = new OrTerm(current, terms[i]);
            }

            // replace the term array with the newly generated top array
            terms = ((OrTerm)current).getTerms();
        }

        // we're going to generate this with parenthetical search keys, even if it is just a simple term.
        appendAtom("OR");
        startList();
        // generated OR argument 1
        appendSearchTerm(terms[0], charset);
        endList();
        startList();
        // generated OR argument 2
        appendSearchTerm(terms[0], charset);
        // and the closing parens
        endList();
    }


    /**
     * append IMAP search term information from a NotTerm item.
     *
     * @param term    The source NotTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendNot(NotTerm term, String charset) throws MessagingException {
        // we're goint to generate this with parenthetical search keys, even if it is just a simple term.
        appendAtom("NOT");
        startList();
        // generated the NOT expression
        appendSearchTerm(term.getTerm(), charset);
        // and the closing parens
        endList();
    }


    /**
     * append IMAP search term information from a FromTerm item.
     *
     * @param term    The source FromTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendFrom(FromTerm term, String charset) throws MessagingException {
        appendAtom("FROM");
        // this may require encoding
        appendString(term.getAddress().toString(), charset);
    }


    /**
     * append IMAP search term information from a FromStringTerm item.
     *
     * @param term    The source FromStringTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendFrom(FromStringTerm term, String charset) throws MessagingException {
        appendAtom("FROM");
        // this may require encoding
        appendString(term.getPattern(), charset);
    }


    /**
     * append IMAP search term information from a RecipientTerm item.
     *
     * @param term    The source RecipientTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendRecipient(RecipientTerm term, String charset) throws MessagingException {
        appendAtom(recipientType(term.getRecipientType()));
        // this may require encoding
        appendString(term.getAddress().toString(), charset);
    }


    /**
     * append IMAP search term information from a RecipientStringTerm item.
     *
     * @param term    The source RecipientStringTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendRecipient(RecipientStringTerm term, String charset) throws MessagingException {
        appendAtom(recipientType(term.getRecipientType()));
        // this may require encoding
        appendString(term.getPattern(), charset);
    }


    /**
     * Translate a recipient type into it's string name equivalent.
     *
     * @param type   The source recipient type
     *
     * @return A string name matching the recipient type.
     */
    protected String recipientType(Message.RecipientType type) throws MessagingException {
        if (type == Message.RecipientType.TO) {
            return "TO";
        }
        if (type == Message.RecipientType.CC) {
            return "CC";
        }
        if (type == Message.RecipientType.BCC) {
            return "BCC";
        }

        throw new SearchException("Unsupported RecipientType");
    }


    /**
     * append IMAP search term information from a HeaderTerm item.
     *
     * @param term    The source HeaderTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendHeader(HeaderTerm term, String charset) throws MessagingException {
        appendAtom("HEADER");
        appendString(term.getHeaderName());
        appendString(term.getPattern(), charset);
    }



    /**
     * append IMAP search term information from a SubjectTerm item.
     *
     * @param term    The source SubjectTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendSubject(SubjectTerm term, String charset) throws MessagingException {
        appendAtom("SUBJECT");
        appendString(term.getPattern(), charset);
    }


    /**
     * append IMAP search term information from a BodyTerm item.
     *
     * @param term    The source BodyTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendBody(BodyTerm term, String charset) throws MessagingException {
        appendAtom("BODY");
        appendString(term.getPattern(), charset);
    }


    /**
     * append IMAP search term information from a SizeTerm item.
     *
     * @param term    The source SizeTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendSize(SizeTerm term, String charset) throws MessagingException {

        // these comparisons can be a real pain.  IMAP only supports LARGER and SMALLER.  So comparisons
        // other than GT and LT have to be composed of complex sequences of these.  For example, an EQ
        // comparison becomes NOT LARGER size NOT SMALLER size

        if (term.getComparison() == ComparisonTerm.GT) {
            appendAtom("LARGER");
            appendInteger(term.getNumber());
        }
        else if (term.getComparison() == ComparisonTerm.LT) {
            appendAtom("SMALLER");
            appendInteger(term.getNumber());
        }
        else if (term.getComparison() == ComparisonTerm.EQ) {
            appendAtom("NOT");
            appendAtom("LARGER");
            appendInteger(term.getNumber());

            appendAtom("NOT");
            appendAtom("SMALLER");
            // it's just right <g>
            appendInteger(term.getNumber());
        }
        else if (term.getComparison() == ComparisonTerm.NE) {
            // this needs to be an OR comparison
            appendAtom("OR");
            appendAtom("LARGER");
            appendInteger(term.getNumber());

            appendAtom("SMALLER");
            appendInteger(term.getNumber());
        }
        else if (term.getComparison() == ComparisonTerm.LE) {
            // just the inverse of LARGER
            appendAtom("NOT");
            appendAtom("LARGER");
            appendInteger(term.getNumber());
        }
        else if (term.getComparison() == ComparisonTerm.GE) {
            // and the reverse.
            appendAtom("NOT");
            appendAtom("SMALLER");
            appendInteger(term.getNumber());
        }
    }


    /**
     * append IMAP search term information from a MessageIDTerm item.
     *
     * @param term    The source MessageIDTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendMessageID(MessageIDTerm term, String charset) throws MessagingException {

        // not directly supported by IMAP, but we can compare on the header information.
        appendAtom("HEADER");
        appendString("Message-ID");
        appendString(term.getPattern(), charset);
    }


    /**
     * append IMAP search term information from a SendDateTerm item.
     *
     * @param term    The source SendDateTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendSentDate(SentDateTerm term, String charset) throws MessagingException {
        Date date = term.getDate();

        switch (term.getComparison()) {
            case ComparisonTerm.EQ:
                appendAtom("SENTON");
                appendSearchDate(date);
                break;
            case ComparisonTerm.LT:
                appendAtom("SENTBEFORE");
                appendSearchDate(date);
                break;
            case ComparisonTerm.GT:
                appendAtom("SENTSINCE");
                appendSearchDate(date);
                break;
            case ComparisonTerm.GE:
                appendAtom("OR");
                appendAtom("SENTSINCE");
                appendSearchDate(date);
                appendAtom("SENTON");
                appendSearchDate(date);
                break;
            case ComparisonTerm.LE:
                appendAtom("OR");
                appendAtom("SENTBEFORE");
                appendSearchDate(date);
                appendAtom("SENTON");
                appendSearchDate(date);
                break;
            case ComparisonTerm.NE:
                appendAtom("NOT");
                appendAtom("SENTON");
                appendSearchDate(date);
                break;
            default:
                throw new SearchException("Unsupported date comparison type");
        }
    }


    /**
     * append IMAP search term information from a ReceivedDateTerm item.
     *
     * @param term    The source ReceivedDateTerm
     * @param charset target charset for the search information (can be null).
     */
    protected void appendReceivedDate(ReceivedDateTerm term, String charset) throws MessagingException {
        Date date = term.getDate();

        switch (term.getComparison()) {
            case ComparisonTerm.EQ:
                appendAtom("ON");
                appendSearchDate(date);
                break;
            case ComparisonTerm.LT:
                appendAtom("BEFORE");
                appendSearchDate(date);
                break;
            case ComparisonTerm.GT:
                appendAtom("SINCE");
                appendSearchDate(date);
                break;
            case ComparisonTerm.GE:
                appendAtom("OR");
                appendAtom("SINCE");
                appendSearchDate(date);
                appendAtom("ON");
                appendSearchDate(date);
                break;
            case ComparisonTerm.LE:
                appendAtom("OR");
                appendAtom("BEFORE");
                appendSearchDate(date);
                appendAtom("ON");
                appendSearchDate(date);
                break;
            case ComparisonTerm.NE:
                appendAtom("NOT");
                appendAtom("ON");
                appendSearchDate(date);
                break;
            default:
                throw new SearchException("Unsupported date comparison type");
        }
    }


    /**
     * Run the tree of search terms, checking for problems with
     * the terms that may require specifying a CHARSET modifier
     * on a SEARCH command sent to the server.
     *
     * @param term   The term to check.
     *
     * @return True if there are 7-bit problems, false if the terms contain
     *         only 7-bit ASCII characters.
     */
    static public boolean checkSearchEncoding(SearchTerm term) {
        // StringTerm is the basis of most of the string-valued terms, and are most important ones to check.
        if (term instanceof StringTerm) {
            return checkStringEncoding(((StringTerm)term).getPattern());
        }
        // Address terms are basically string terms also, but we need to check the string value of the
        // addresses, since that's what we're sending along.  This covers a lot of the TO/FROM, etc. searches.
        else if (term instanceof AddressTerm) {
            return checkStringEncoding(((AddressTerm)term).getAddress().toString());
        }
        // the NOT contains a term itself, so recurse on that.  The NOT does not directly have string values
        // to check.
        else if (term instanceof NotTerm) {
            return checkSearchEncoding(((NotTerm)term).getTerm());
        }
        // AND terms and OR terms have lists of subterms that must be checked.
        else if (term instanceof AndTerm) {
            return checkSearchEncoding(((AndTerm)term).getTerms());
        }
        else if (term instanceof OrTerm) {
            return checkSearchEncoding(((OrTerm)term).getTerms());
        }

        // non of the other term types (FlagTerm, SentDateTerm, etc.) pose a problem, so we'll give them
        // a free pass.
        return false;
    }


    /**
     * Run an array of search term items to check each one for ASCII
     * encoding problems.
     *
     * @param terms  The array of terms to check.
     *
     * @return True if any of the search terms contains a 7-bit ASCII problem,
     *         false otherwise.
     */
    static public boolean checkSearchEncoding(SearchTerm[] terms) {
        for (int i = 0; i < terms.length; i++) {
            if (checkSearchEncoding(terms[i])) {
                return true;
            }
        }
        return false;
    }


    /**
     * Check a string to see if this can be processed using just
     * 7-bit ASCII.
     *
     * @param s      The string to check
     *
     * @return true if the string contains characters outside the 7-bit ascii range,
     *         false otherwise.
     */
    static public boolean checkStringEncoding(String s) {
        for (int i = 0; i < s.length(); i++) {
            // any value greater that 0x7f is a problem char.  We're not worried about
            // lower ctl chars (chars < 32) since those are still expressible in 7-bit.
            if (s.charAt(i) > 127) {
                return true;
            }
        }

        return false;
    }


    /**
     * Append a FetchProfile information to an IMAPCommand
     * that's to be issued.
     *
     * @param profile The fetch profile we're using.
     *
     * @exception MessagingException
     */
    public void appendFetchProfile(FetchProfile profile) throws MessagingException {
        // the fetch profile items are a parenthtical list passed on a
        // FETCH command.
        startList();
        if (profile.contains(UIDFolder.FetchProfileItem.UID)) {
            appendAtom("UID");
        }
        if (profile.contains(FetchProfile.Item.ENVELOPE)) {
            // fetching the envelope involves several items
            appendAtom("ENVELOPE");
            appendAtom("INTERNALDATE");
            appendAtom("RFC822.SIZE");
        }
        if (profile.contains(FetchProfile.Item.FLAGS)) {
            appendAtom("FLAGS");
        }
        if (profile.contains(FetchProfile.Item.CONTENT_INFO)) {
            appendAtom("BODYSTRUCTURE");
        }
        if (profile.contains(IMAPFolder.FetchProfileItem.SIZE)) {
            appendAtom("RFC822.SIZE");
        }
        // There are two choices here, that are sort of redundant.
        // if all headers have been requested, there's no point in
        // adding any specifically requested one.
        if (profile.contains(IMAPFolder.FetchProfileItem.HEADERS)) {
            appendAtom("BODY.PEEK[HEADER]");
        }
        else {
            String[] headers = profile.getHeaderNames();
            // have an actual list to retrieve?  need to craft this as a sublist
            // of identified fields.
            if (headers.length > 0) {
                appendAtom("BODY.PEEK[HEADER.FIELDS]");
                startList();
                for (int i = 0; i < headers.length; i++) {
                    appendAtom(headers[i]);
                }
                endList();
            }
        }
        // end the list.
        endList();
    }


    /**
     * Append an ACL value to a command.  The ACL is the writes string name,
     * followed by the rights value.  This version uses no +/- modifier.
     *
     * @param acl    The ACL to append.
     */
    public void appendACL(ACL acl) {
        appendACL(acl, null);
    }

    /**
     * Append an ACL value to a command.  The ACL is the writes string name,
     * followed by the rights value.  A +/- modifier can be added to the
     * // result.
     *
     * @param acl      The ACL to append.
     * @param modifier The modifer string (can be null).
     */
    public void appendACL(ACL acl, String modifier) {
        appendString(acl.getName());
        String rights = acl.getRights().toString();

        if (modifier != null) {
            rights = modifier + rights;
        }
        appendString(rights);
    }


    /**
     * Append a quota specification to an IMAP command.
     *
     * @param quota  The quota value to append.
     */
    public void appendQuota(Quota quota) {
        appendString(quota.quotaRoot);
        startList();
        for (int i = 0; i < quota.resources.length; i++) {
            appendQuotaResource(quota.resources[i]);
        }
        endList();
    }

    /**
     * Append a Quota.Resource element to an IMAP command.  This converts as
     * the resoure name, the usage value and limit value).
     *
     * @param resource The resource element we're appending.
     */
    public void appendQuotaResource(Quota.Resource resource) {
        appendAtom(resource.name);
        // NB:  For command purposes, only the limit is used.
        appendLong(resource.limit);
    }
}

