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

import com.queplix.core.error.IncorrectParameterException;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.modules.inbox.Account;
import com.queplix.core.modules.inbox.utils.AccountDAO;
import com.queplix.core.modules.inbox.utils.InboxPropertyFactory;
import com.queplix.core.modules.inbox.utils.log.SystemLogPublisher;
import com.queplix.core.modules.services.Action;
import com.queplix.core.modules.services.ActionContext;
import com.queplix.core.modules.services.ActionRunner;
import com.queplix.core.modules.services.XAActionContext;
import com.queplix.core.utils.DateHelper;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * The class is a inbox manager action. The perform method processes all email accounts.
 *
 * @author Konstantin Mironov
 * @since 8 Dec 2006
 */
public class InboxManagerAction extends Action {

    // ------------------------------------------------------- Constants

    // Parameters names.
    private static final String BATCH_SIZE_PARAM = "messages-batch-size";
    private static final String UPDATE_ACCOUNT_PARAM = "update-account";

    // ------------------------------------------------------- Fields

    // Action objects.
    private SystemLogPublisher log;

    // XA action context for the child action to run.
    private XAActionContext xa;

    // ------------------------------------------------------- Parameters data

    // Messages process-at-once batch size.
    private Integer batchSize;

    // Whether to update account status after check?
    private boolean updateAccount;

    // ------------------------------------------------------- API methods

    /*
     * No javadoc
     * @see Action#perform
     */

    public java.io.Serializable perform() {

        long time = System.currentTimeMillis();
        boolean error = false;
        int accountsCount = 0;

        // Initialization.
        init();

        // Go!
        try {
            Date nextCheckDate = DateHelper.getNowDate();
            AccountDAO dao = InboxPropertyFactory.getInstance().getAccountDAO();
            Collection accounts = dao.loadAllActiveAccountVO(nextCheckDate);

            if(accounts != null) {
                for(Iterator it = accounts.iterator(); it.hasNext();) {

                    // Get next account.
                    Account account = (Account) it.next();
                    Long accountID = new Long(account.getAccountID());

                    // Preparing the Inbox action parameters.
                    Map params = new HashMap();
                    params.put("account", account);
                    params.put("batchSize", batchSize);
                    params.put("updateAccount",
                            (updateAccount) ? Boolean.TRUE:Boolean.FALSE);

                    // Starting Inbox service.
                    String msg = "Starting a new inbox service";
                    log.DEBUG(msg, accountID);
                    DEBUG(msg + ". Account #" + accountID);

                    try {
                        InboxAction inboxAction = new InboxAction();
                        xa.addParameters(params);
                        ActionRunner.runAsXA(inboxAction, xa);

                        // Updating the next check time.
                        Integer delay = account.getDelayInMinutes();
                        if(delay != null) {
                            long delayInMillis = delay.intValue() * 60 * 1000;
                            long nextCheckDateInMillis =
                                    DateHelper.currentTimeMillis()
                                            + delayInMillis;
                            account.setNextCheckDate(new Date(
                                    nextCheckDateInMillis));

                            msg = "The next check time updated";
                            DEBUG(msg + ". Account #" + accountID);
                            log.DEBUG(msg, accountID);
                        } // if (delay != null)
                    } catch (Exception ex) {
                        // Catch exception and continue cycle.
                        ERROR(ex.getMessage());
                        log.ERROR("Unknown exception: " + ex.getMessage(),
                                accountID);
                        continue;
                    } // try
                    accountsCount++;
                } // for (Iterator it = accounts.iterator(); it.hasNext();)
            } // if (accounts != null)
        } catch (Throwable t) {
            // Write error log.
            error = true;
            ERROR(log, "Unknown exception: " + t.getMessage(), t);

        } finally {

            // The end.
            time = (System.currentTimeMillis() - time) / 1000;
            if(error) {
                WARN(log, "Inbox Manager service completed with errors. Time = "
                        + time + " sec.");
            } else {
                INFO(log, "Inbox Manager service finished. " + accountsCount
                        + " account(s) checked. Time = " + time + " sec.");
            }
        } // try

        return null;

    } // perform() : java.io.Serializable

    // ------------------------------------------------------- Private methods

    //
    // Initialize action
    //

    private void init() {
        ActionContext context = getContext();
        LogonSession ls = context.getLogonSession();
        log = new SystemLogPublisher(ls);
        xa = new XAActionContext(ls, log);

        INFO(log, "Inbox Manager service started.");

        // Getting the messages batch size.
        try {
            batchSize = getContext().getParamAsInt(BATCH_SIZE_PARAM);
            if(batchSize != null && batchSize.intValue() <= 0) {
                throw new IncorrectParameterException(BATCH_SIZE_PARAM,
                        "" + batchSize, "Must be > 0.");
            }
            DEBUG("Batch size = " + batchSize);

        } catch (Exception ex) {
            batchSize = null;
            WARN("Messages batching is disabled. " + ex.getMessage());
        } // try

        // Getting the accounts update flag.
        try {
            updateAccount = getContext().getParamAsBoolean(UPDATE_ACCOUNT_PARAM)
                    .booleanValue();
            DEBUG("Update account? - " + updateAccount);
        } catch (Exception ex) {
            updateAccount = false;
            WARN("Account updating is disabled. " + ex.getMessage());
        } // try
    } // init()

} // class InboxManagerAction extends Action
