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

import java.math.BigDecimal;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ServiceUtil;

public class GlEvents {

    private static final String MODULE = GlEvents.class.getName();

    public static String createReconcileAccount(HttpServletRequest request, HttpServletResponse response) {
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
        final Delegator delegator = (Delegator) request.getAttribute("delegator");
        GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
        Map<String, Object> ctx = UtilHttp.getParameterMap(request);
        String acctgTransId;
        String acctgTransEntrySeqId;
        String glAccountId = null;
        String organizationPartyId = null;
        BigDecimal reconciledBalance = BigDecimal.ZERO;
        boolean isSelected;
        String debitCreditFlag;
        // The number of multi form rows is retrieved
        int rowCount = UtilHttp.getMultiFormRowCount(ctx);
        for (int i = 0; i < rowCount; i++) {  //for calculating amount per glAccountId
            String suffix = UtilHttp.getMultiRowDelimiter() + i;
            isSelected = (ctx.containsKey("_rowSubmit" + suffix) && "Y".equalsIgnoreCase((String) ctx.get("_rowSubmit" + suffix)));
            if (!isSelected) {
                continue;
            }
            acctgTransId = (String) ctx.get("acctgTransId" + suffix);
            acctgTransEntrySeqId = (String) ctx.get("acctgTransEntrySeqId" + suffix);
            organizationPartyId = (String) ctx.get("organizationPartyId" + suffix);
            glAccountId = (String) ctx.get("glAccountId" + suffix);
            try {
                GenericValue acctgTransEntry = EntityQuery.use(delegator).from("AcctgTransEntry").where("acctgTransId", acctgTransId,
                        "acctgTransEntrySeqId", acctgTransEntrySeqId).queryOne();
                if (acctgTransEntry != null) {
                    //calculate amount for each AcctgTransEntry according to glAccountId based on debit and credit
                    debitCreditFlag = acctgTransEntry.getString("debitCreditFlag");
                    if ("D".equalsIgnoreCase(debitCreditFlag)) {
                        reconciledBalance = reconciledBalance.add(acctgTransEntry.getBigDecimal("amount"));  //total balance per glAccountId
                    } else {
                        reconciledBalance = reconciledBalance.subtract(acctgTransEntry.getBigDecimal("amount"));  //total balance per glAccountId
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, MODULE);
                return "error";
            }

        }
        Map<String, Object> fieldMap = UtilMisc.toMap("glReconciliationName", "Reconciliation at date " + UtilDateTime.nowTimestamp(), "glAccountId",
                glAccountId, "organizationPartyId", organizationPartyId, "reconciledDate", UtilDateTime.nowTimestamp(), "reconciledBalance",
                reconciledBalance, "userLogin", userLogin);
        Map<String, Object> glReconResult = null;
        try {
            glReconResult = dispatcher.runSync("createGlReconciliation", fieldMap); //create GlReconciliation for the glAccountId
            if (ServiceUtil.isError(glReconResult)) {
                return "error";
            }
        } catch (GenericServiceException e) {
            Debug.logError(e, MODULE);
            return "error";
        }
        String glReconciliationId = (String) glReconResult.get("glReconciliationId");
        String reconciledAmount;
        for (int i = 0; i < rowCount; i++) {
            String suffix = UtilHttp.getMultiRowDelimiter() + i;
            isSelected = (ctx.containsKey("_rowSubmit" + suffix) && "Y".equalsIgnoreCase((String) ctx.get("_rowSubmit" + suffix)));
            if (!isSelected) {
                continue;
            }
            acctgTransId = (String) ctx.get("acctgTransId" + suffix);
            acctgTransEntrySeqId = (String) ctx.get("acctgTransEntrySeqId" + suffix);
            try {
                GenericValue acctgTransEntry = EntityQuery.use(delegator).from("AcctgTransEntry").where("acctgTransId", acctgTransId,
                        "acctgTransEntrySeqId", acctgTransEntrySeqId).queryOne();
                if (acctgTransEntry != null) {
                    reconciledAmount = acctgTransEntry.getString("amount");
                    acctgTransId = acctgTransEntry.getString("acctgTransId");
                    acctgTransEntrySeqId = acctgTransEntry.getString("acctgTransEntrySeqId");
                    Map<String, Object> glReconEntryMap = UtilMisc.toMap("glReconciliationId", glReconciliationId, "acctgTransId", acctgTransId,
                            "acctgTransEntrySeqId", acctgTransEntrySeqId, "reconciledAmount", reconciledAmount, "userLogin", userLogin);
                    Map<String, Object> glReconEntryResult = null;
                    try {
                        glReconEntryResult = dispatcher.runSync("createGlReconciliationEntry", glReconEntryMap);
                        if (ServiceUtil.isError(glReconEntryResult)) {
                            return "error";
                        }
                    } catch (GenericServiceException e) {
                        Debug.logError(e, MODULE);
                        return "error";
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, MODULE);
                return "error";
            }
        }
        ctx.put("glReconciliationId", glReconciliationId);
        request.setAttribute("glReconciliationId", glReconciliationId);
        return "success";
    }
}
