/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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 com.queplix.core.modules.inbox.utils;

import com.queplix.core.modules.inbox.Account;
import com.queplix.core.utils.DateHelper;
import com.queplix.core.utils.log.AbstractLogger;

import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.MessagingException;
import java.util.Date;

/**
 * This is defaul message filter.
 *
 * @author Konstantin Mironov
 * @since 8 Dec 2006
 */
public class DefaultMessageFilter extends AbstractLogger
        implements MessageFilter {

    private Date lastReceiveDate;
    private Long maxMsgSize;
    private Long maxTotalSize;
    private boolean skeepSeenMsgFlag;
    private InboxProvider provider;

    private int processedMsgSize = 0;
    private String info;
    private Account account;

    /**
     * Constructor.
     *
     * @param lastReceiveDate  skip messages with date less than given
     * @param maxMsgSize       skip messages with size more than given
     * @param maxTotalSize     skip messages if total size more than given
     * @param skeepSeenMsgFlag skip messages if message has SEEN flag
     * @param provider         InboxProvider
     */
    public DefaultMessageFilter(Date lastReceiveDate,
                                Long maxMsgSize,
                                Long maxTotalSize,
                                boolean skeepSeenMsgFlag,
                                InboxProvider provider) {

        this.lastReceiveDate = lastReceiveDate;
        this.maxMsgSize = maxMsgSize;
        this.maxTotalSize = maxTotalSize;
        this.skeepSeenMsgFlag = skeepSeenMsgFlag;
        this.provider = provider;
    }

    /**
     * Constructor.
     *
     * @param account  mail account
     * @param provider InboxProvider
     */
    public DefaultMessageFilter(Account account, InboxProvider provider) {

        this(account.getLastReceiveDate(),
                account.getMaxMessageSize(),
                account.getMaxMailboxSize(),
                false,
                provider);
        this.account = account;
    }

    /*
     * No javadoc.
     * @see MessageFilter#filter
     */
    public boolean filter(Message message) throws MessagingException {

        int id = message.getMessageNumber();

        // 1. Seen flag.
        if(skeepSeenMsgFlag && message.isSet(Flags.Flag.SEEN)) {
            // .. no log msg
            return false;
        }

        // 2. Last received date.
        Date serverDate = provider.getServerDate(message);
        if(serverDate == null || (lastReceiveDate != null
                && serverDate.compareTo(lastReceiveDate) <= 0)) {
            return reportProblem(
                    "Message #" + id
                            + " skipped - server date is before Last Received date. "
                            +
                            "Message server date: " + DateHelper.formatDate(
                            serverDate) +
                            ". Last receive date: " + DateHelper.formatDate(
                            lastReceiveDate));
        }

        // 3. Last meesage UID.
        String messageUID = account.getMessageUID();
        String currentUID = provider.getUID(message);
        if(messageUID != null && currentUID != null) {
            if(messageUID.compareTo(currentUID) == 0) {
                return reportProblem(
                        "Message #" + id
                                + " skipped - message UID is the same as the Last UID. "
                                +
                                "Message server date: " + DateHelper.formatDate(
                                serverDate) +
                                ". Last receive date: " + DateHelper.formatDate(
                                lastReceiveDate) +
                                ". Message UID: " + currentUID +
                                ". Last UID: " + messageUID);
            }
        } // if (messageUID != null && currentUID != null)

        // 4. Max message size.
        int messageSize = message.getSize();
        if(maxMsgSize != null && messageSize > maxMsgSize.longValue()) {
            return reportProblem(
                    "Message #" + id + " (size = " + messageSize
                            + " bytes) skipped - exceeds the size quota (" +
                            maxMsgSize + " bytes).");
        }

        // 5. Max total size.
        if(maxTotalSize != null
                && (processedMsgSize + messageSize) > maxTotalSize
                .longValue()) {
            return reportProblem(
                    "Message #" + id + " (size = " + messageSize
                            + " bytes) skipped - account exceeds the size quota ("
                            +
                            maxTotalSize + " bytes).");
        }

        // 6. 'From' addr.
        Address[] froms = message.getFrom();
        if(froms == null) {
            return reportProblem(
                    "Message #" + id + " skipped - 'From' address not found.");
        }

        // 7. 'To' addr.
        Address[] tos = message.getRecipients(Message.RecipientType.TO);
        if(tos == null) {
            return reportProblem(
                    "Message #" + id + " skipped - 'To' address not found.");
        }

        // Ok.
        processedMsgSize += messageSize;
        return true;
    } // filter(Message message) : boolean

    /*
     * No javadoc.
     * @see MessageFilter#getInfo
     */
    public String getInfo() {
        return info;
    }

    /**
     * Resets filter state.
     */
    public void reset() {
        processedMsgSize = 0;
        info = null;
    }

    //
    // Remembers info message and returns false.
    //
    protected boolean reportProblem(String info) {
        this.info = info;
        return false;
    }
} // class DefaultMessageFilter
