/*
 * The Kuali Financial System, a comprehensive financial management system for higher education.
 *
 * Copyright 2005-2016 The Kuali Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kuali.kfs.coa.document.validation.impl;

import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.coa.businessobject.A21IndirectCostRecoveryAccount;
import org.kuali.kfs.coa.businessobject.A21SubAccount;
import org.kuali.kfs.coa.businessobject.Account;
import org.kuali.kfs.coa.businessobject.IndirectCostRecoveryAccount;
import org.kuali.kfs.coa.businessobject.SubAccount;
import org.kuali.kfs.kns.document.MaintenanceDocument;
import org.kuali.kfs.kns.document.authorization.MaintenanceDocumentRestrictions;
import org.kuali.kfs.kns.service.BusinessObjectAuthorizationService;
import org.kuali.kfs.krad.util.GlobalVariables;
import org.kuali.kfs.krad.util.ObjectUtils;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.kim.api.identity.Person;

/**
 * PreRules checks for the {@link SubAccount} that needs to occur while still in the Struts processing. This includes defaults, confirmations,
 * etc.
 */
public class SubAccountPreRules extends MaintenancePreRulesBase {

    protected SubAccount newSubAccount;

    // protected SubAccount copyAccount;

    public SubAccountPreRules() {

    }

    /**
     * This checks to see if a continuation account is necessary and then copies the ICR data from the Account
     * associated with this SubAccount (if necessary)
     *
     * @see org.kuali.kfs.coa.document.validation.impl.MaintenancePreRulesBase#doCustomPreRules(org.kuali.rice.kns.document.MaintenanceDocument)
     */
    protected boolean doCustomPreRules(MaintenanceDocument document) {
        setupConvenienceObjects(document);
        checkForContinuationAccounts(document.getNewMaintainableObject().getMaintenanceAction()); // run this first to avoid side
        // effects

        LOG.debug("done with continuation account, proceeeding with remaining pre rules");

        copyICRFromAccount(document);

        return true;
    }

    /**
     * This looks for the SubAccount's account number and then sets the values to the continuation account value if it exists
     *
     * @param maintenanceAction
     */
    protected void checkForContinuationAccounts(String maintenanceAction) {
        LOG.debug("entering checkForContinuationAccounts()");

        /*
         * KULCOA-734 - The check for continuation account for main Account Number on sub-account has been modified to only occur
         * for a New and Copy Action. This cannot happen on an Edit as the primary key will change.
         */
        if (KFSConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction) || KFSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {

            if (StringUtils.isNotBlank(newSubAccount.getAccountNumber())) {
                Account account = checkForContinuationAccount("Account Number", newSubAccount.getChartOfAccountsCode(), newSubAccount.getAccountNumber(), "");
                if (ObjectUtils.isNotNull(account)) { // override old user inputs
                    newSubAccount.setAccountNumber(account.getAccountNumber());
                    newSubAccount.setChartOfAccountsCode(account.getChartOfAccountsCode());
                }
            }
        }
    }

    /**
     * This method sets the convenience objects like newSubAccount, so you have short and easy handles to the new and
     * old objects contained in the maintenance document. It also calls the BusinessObjectBase.refresh(), which will attempt to load
     * all sub-objects from the DB by their primary keys, if available.
     *
     * @param document
     */
    protected void setupConvenienceObjects(MaintenanceDocument document) {

        // setup newAccount convenience objects, make sure all possible sub-objects are populated
        newSubAccount = (SubAccount) document.getNewMaintainableObject().getBusinessObject();
        // copyAccount = (SubAccount) ObjectUtils.deepCopy(newAccount);
        // copyAccount.refresh();
    }

    /**
     * This copies the Indirect Cost Rate (ICR) from the account if the SubAccount is a specific type - determined
     * as "EX" from {@link SubAccountRule#CG_A21_TYPE_ICR}
     * <p>
     * If it is "EX" it will then copy over the ICR information from the Account specified for this SubAccount
     *
     * @param document
     */
    protected void copyICRFromAccount(MaintenanceDocument document) {
        Person user = GlobalVariables.getUserSession().getPerson();

        // get a new instance of MaintenanceDocumentAuthorizations for this context
        MaintenanceDocumentRestrictions auths = SpringContext.getBean(BusinessObjectAuthorizationService.class).getMaintenanceDocumentRestrictions(document, user);

        // don't need to copy if the user does not have the authority to edit the fields
        if (!auths.getFieldRestriction("a21SubAccount.financialIcrSeriesIdentifier").isReadOnly()) {
            // only need to do this of the account sub type is EX
            A21SubAccount a21SubAccount = newSubAccount.getA21SubAccount();
            Account account = newSubAccount.getAccount();
            if (KFSConstants.SubAccountType.EXPENSE.equals(a21SubAccount.getSubAccountTypeCode())) {
                if (ObjectUtils.isNull(account) || StringUtils.isBlank(account.getAccountNumber())) {
                    account = getAccountService().getByPrimaryId(newSubAccount.getChartOfAccountsCode(), newSubAccount.getAccountNumber());
                    if (ObjectUtils.isNotNull(account)) {
                        if (a21SubAccount.getA21ActiveIndirectCostRecoveryAccounts().isEmpty()) {
                            for (IndirectCostRecoveryAccount icrAccount : account.getActiveIndirectCostRecoveryAccounts()) {
                                a21SubAccount.getA21IndirectCostRecoveryAccounts().add(A21IndirectCostRecoveryAccount.copyICRAccount(icrAccount));
                            }
                        }
                        if (StringUtils.isBlank(a21SubAccount.getFinancialIcrSeriesIdentifier())) {
                            a21SubAccount.setFinancialIcrSeriesIdentifier(account.getFinancialIcrSeriesIdentifier());
                            a21SubAccount.setOffCampusCode(account.isAccountOffCampusIndicator());
                        }
                        if (StringUtils.isBlank(a21SubAccount.getIndirectCostRecoveryTypeCode())) {
                            a21SubAccount.setIndirectCostRecoveryTypeCode(account.getAcctIndirectCostRcvyTypeCd());
                        }
                    }
                }
            }
        }
    }
}
