/*
 * 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.examples.mail;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.net.imap.IMAPClient;

/**
 * This is an example program demonstrating how to use the IMAP[S]Client class.
 * This program connects to a IMAP[S] server and imports messages into the folder from an mbox file.
 * <p>
 * Usage: IMAPImportMbox imap[s]://user:password@host[:port]/folder/path <mboxfile> [selectors]
 * <p>
 * An example selector might be:
 * <ul>
 * <li>1,2,3,7-10</li>
 * <li>-142986- : this is useful for retrieving messages by apmail number, which appears as From xyz-return-142986-apmail-...</li>
 * </ul>
 * <p>
 * For example:<br>
 * IMAPImportMbox imaps://user:pass@imap.googlemail.com/imported_messages 201401.mbox 1-10,20 -142986-
 */
public final class IMAPImportMbox
{

    private static final String CRLF = "\r\n";
    private static final Pattern PATFROM = Pattern.compile(">+From "); // escaped From

    public static void main(String[] args) throws IOException
    {
        if (args.length < 2)
        {
            System.err.println("Usage: IMAPImportMbox imap[s]://user:password@host[:port]/folder/path <mboxfile> [selectors]");
            System.err.println("\tWhere: a selector is a list of numbers/number ranges - 1,2,3-10" +
                               " - or a list of strings to match in the initial From line");
            System.exit(1);
        }

        final URI uri      = URI.create(args[0]);
        final String file  = args[1];

        final File mbox = new File(file);
        if (!mbox.isFile() || !mbox.canRead()) {
            throw new IOException("Cannot read mailbox file: " + mbox);
        }

        String path = uri.getPath();
        if (path == null || path.length() < 1) {
            throw new IllegalArgumentException("Invalid folderPath: '" + path + "'");
        }
        String folder = path.substring(1); // skip the leading /

        List<String> contains = new ArrayList<String>(); // list of strings to find
        BitSet msgNums = new BitSet(); // list of message numbers

        for(int i = 2; i < args.length; i++) {
            String arg = args[i];
            if (arg.matches("\\d+(-\\d+)?(,\\d+(-\\d+)?)*")) { // number,m-n
                for(String entry : arg.split(",")) {
                    String []parts = entry.split("-");
                    if (parts.length == 2) { // m-n
                        int low = Integer.parseInt(parts[0]);
                        int high = Integer.parseInt(parts[1]);
                        for(int j=low; j <= high; j++) {
                            msgNums.set(j);
                        }
                    } else {
                        msgNums.set(Integer.parseInt(entry));
                    }
                }
            } else {
                contains.add(arg); // not a number/number range
            }
        }
//        System.out.println(msgNums.toString());
//        System.out.println(java.util.Arrays.toString(contains.toArray()));

        // Connect and login
        final IMAPClient imap = IMAPUtils.imapLogin(uri, 10000, null);

        int total = 0;
        int loaded = 0;
        try {
            imap.setSoTimeout(6000);

            final BufferedReader br = new BufferedReader(new FileReader(file)); // TODO charset?

            String line;
            StringBuilder sb = new StringBuilder();
            boolean wanted = false; // Skip any leading rubbish
            while((line=br.readLine())!=null) {
                if (line.startsWith("From ")) { // start of message; i.e. end of previous (if any)
                    if (process(sb, imap, folder, total)) { // process previous message (if any)
                        loaded++;
                    }
                    sb.setLength(0);
                    total ++;
                    wanted = wanted(total, line, msgNums, contains);
                } else if (startsWith(line, PATFROM)) { // Unescape ">+From " in body text
                    line = line.substring(1);
                }
                // TODO process first Received: line to determine arrival date?
                if (wanted) {
                    sb.append(line);
                    sb.append(CRLF);
                }
            }
            br.close();
            if (wanted && process(sb, imap, folder, total)) { // last message (if any)
                loaded++;
            }
        } catch (IOException e) {
            System.out.println("Error processing msg: " + total + " " + imap.getReplyString());
            e.printStackTrace();
            System.exit(10);
            return;
        } finally {
            imap.logout();
            imap.disconnect();
        }
        System.out.println("Processed " + total + " messages, loaded " + loaded);
    }

    private static boolean startsWith(String input, Pattern pat) {
        Matcher m = pat.matcher(input);
        return m.lookingAt();
    }

    private static String getDate(String msg) {
        final Pattern FROM_RE = Pattern.compile("From \\S+ +\\S+ (\\S+)  ?(\\S+) (\\S+) (\\S+)"); // From SENDER Fri Sep 13 17:04:01 2019
        //                                                 [Fri]   Sep      13     HMS   2019
        // output date: 13-Sep-2019 17:04:01 +0000
        String date = null;
        Matcher m = FROM_RE.matcher(msg);
        if (m.lookingAt()) {
            date = m.group(2)+"-"+m.group(1)+"-"+m.group(4)+" "+m.group(3)+" +0000";
        }
        return date;
    }

    private static boolean process(final StringBuilder sb, final IMAPClient imap, final String folder
            ,final int msgNum) throws IOException {
        final int length = sb.length();
        boolean haveMessage = length > 2;
        if (haveMessage) {
            System.out.println("MsgNum: " + msgNum +" Length " + length);
            sb.setLength(length-2); // drop trailing CRLF (mbox format has trailing blank line)
            String msg = sb.toString();
            if (!imap.append(folder, null, getDate(msg), msg)) {
                throw new IOException("Failed to import message: " + msgNum + " " + imap.getReplyString());
            }
        }
        return haveMessage;
    }

    /**
     * Is the message wanted?
     *
     * @param msgNum the message number
     * @param line the From line
     * @param msgNums the list of wanted message numbers
     * @param contains the list of strings to be contained
     * @return true if the message is wanted
     */
    private static boolean wanted(int msgNum, String line, BitSet msgNums, List<String> contains) {
        return (msgNums.isEmpty() && contains.isEmpty()) // no selectors
             || msgNums.get(msgNum) // matches message number
             || listContains(contains, line); // contains string
    }

    /**
     * Is at least one entry in the list contained in the string?
     * @param contains the list of strings to look for
     * @param string the String to check against
     * @return true if at least one entry in the contains list is contained in the string
     */
    private static boolean listContains(List<String> contains, String string) {
        for(String entry : contains) {
            if (string.contains(entry)) {
                return true;
            }
        }
        return false;
    }

}
