package com.ampiere.web.struts.form;

import java.util.Properties;
import java.util.logging.Level;

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

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.compiere.model.MAccount;
import org.compiere.model.MAcctSchema;
import org.compiere.model.MCharge;
import org.compiere.util.CLogger;
import org.compiere.util.Ctx;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.WebSessionCtx;

import com.ampiere.util.Constants;

/**
 * @author siqinbilige
 */
public class ChargeAccountAction extends Action {

    /** Logger. */
    private CLogger log = CLogger.getCLogger(this.getClass());
    
    /** Order List Forward. */
    private static final String ACCOUNT_LIST = "accountlist";

    /** Action Form. */
    private static final String ACTION_FORM = "ChargeAccountForm";

    /** Global Error Forward. */
    private static final String ERROR_FORWARD = "error";

    /**
     * Action execute.
     * @param mapping mapping
     * @param form form
     * @param request request
     * @param response response
     * @throws Exception Exception
     * @return ActionForward
     * @see org.apache.struts.action.Action#execute(
     *      org.apache.struts.action.ActionMapping,
     *      org.apache.struts.action.ActionForm,
     *      javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    public final ActionForward execute(
            final ActionMapping mapping,
            final ActionForm form,
            final HttpServletRequest request,
            final HttpServletResponse response)
    throws Exception {
    	
		//201001 
        WebSessionCtx wscTest = WebSessionCtx.get(request); 
        if (wscTest == null) {
            log.log(Level.SEVERE, "Session Time Out.");
            request.setAttribute(Constants.SESSION_TIMEOUT_INFO, "Session Time Out. Please login again.");
            return mapping.findForward(Constants.SESSION_TIMEOUT);
        }
        //--201001    	

        log.fine("Begin " + this.getClass().getName() + ";execute");

        WebSessionCtx wsc = WebSessionCtx.get(request); 
        if (wsc == null) {
            log.log(Level.SEVERE, "Session Time Out.");
            return mapping.findForward(ERROR_FORWARD);
        }

        ActionForward actionForward = mapping.findForward(ACCOUNT_LIST);
        
        ChargeAccountForm myForm =
            (ChargeAccountForm) request.getAttribute(ACTION_FORM);

        String column = myForm.getChangedColumn();
        if (column.equals("new")) {
            // Append new element.

            int elementValueId = createElementValue(
                    wsc.ctx,
                    myForm.getKeyValue(),
                    myForm.getKeyName(),
                    "on".equals(myForm.getExpense()));
            if (elementValueId == 0) {
                myForm.setResultInfo(Msg.translate(wsc.ctx, "ChargeNotCreated") + ":" + myForm.getKeyName());
            } else {
                int chargeId = createCharge(wsc.ctx, myForm.getKeyName(), elementValueId);
                if (chargeId == 0) {
                    myForm.setResultInfo(Msg.translate(wsc.ctx, "ChargeNotCreated") + ":" + myForm.getKeyName());
                } else {
                    myForm.setKeyValue("");
                    myForm.setKeyName("");
                    myForm.setExpense("on");
                    myForm.setResultInfo("");
                }
            }

            actionForward = mapping.findForward(ACCOUNT_LIST);
        } else {
            createAccount(wsc.ctx, myForm);
            myForm.setKeyList(null);
            actionForward = mapping.findForward(ACCOUNT_LIST);
        }
        
        // Save form to request.
        request.setAttribute(ACTION_FORM, myForm);

        log.fine("End " + this.getClass().getName() + ";execute");

        return actionForward;
    }
    
    /**
     *  Create Charges from Accounts.
     *  @param ctx Context
     *  @param form Acction form
     */
    private void createAccount(final Ctx ctx, final ChargeAccountForm form) {
        //
        StringBuffer listCreated = new StringBuffer();
        StringBuffer listRejected = new StringBuffer();
        //
        String [] accounts = form.getKeyList();
        int rows = accounts.length;
        for (int i = 0; i < rows; i++) {
            String [] keyname = accounts[i].split("\\|");
            int elementValueId = Integer.valueOf(keyname[0]);
            String name = keyname[1];
            //
            int chargeId = createCharge(ctx, name, elementValueId);
            if (chargeId == 0) {
                if (listRejected.length() > 0) {
                    listRejected.append(", ");
                }
                listRejected.append(name);
            } else {
                if (listCreated.length() > 0) {
                    listCreated.append(", ");
                }
                listCreated.append(name);
            }
        }
        
        String result = "";
        if (listCreated.length() > 0) {
            result += Msg.translate(ctx, "ChargeCreated") + " : " + listCreated.toString();
        }

        if (listRejected.length() > 0) {
            result += Msg.translate(ctx, "ChargeNotCreated") + " : " + listRejected.toString();
        }
        
        form.setResultInfo(result);
    }   //  createAccount
   

    
    /**
     *  Create ElementValue for primary AcctSchema.
     *  @param ctx Context
     *  @param value value
     *  @param name name
     *  @param isExpenseType is expense
     *  @return element value
     */
    private int createElementValue(
            final Ctx ctx,
            final String value,
            final String name,
            final boolean isExpenseType) {

        int elementValueId = DB.getNextID(ctx, "C_ElementValue", null);
//        int accountElementId = Env.getContextAsInt(ctx, 0, "AccountElementId");
//        int clientId = Env.getAD_Client_ID(ctx);
//        int organizationId = Env.getAD_Org_ID(ctx);
//        int userId = Env.getAD_User_ID(ctx);
        int accountElementId = ctx.getContextAsInt(0, "AccountElementId");
        int clientId = ctx.getAD_Client_ID();
        int organizationId = ctx.getAD_Org_ID();
        int userId = ctx.getAD_User_ID();

        StringBuffer sql = new StringBuffer("INSERT INTO C_ElementValue "
            + "(C_ElementValue_ID, C_Element_ID,"
            + " AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,"
            + " Value, Name, Description,"
            + " AccountType, AccountSign,"
            + " IsDocControlled, IsSummary,"
            + " ValidFrom, ValidTo,"
            + " PostActual, PostBudget, PostEncumbrance, PostStatistical,"
            + " IsBankAccount, C_BankAccount_ID, IsForeignCurrency, C_Currency_ID"
            + ") VALUES (");
        //  C_ElementValue_ID, C_Element_ID,
        sql.append(elementValueId).append(",").append(accountElementId).append(",");
        //  AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,
        sql.append(clientId).append(",").append(organizationId);
        sql.append(",'Y',SysDate,").append(userId).append(",SysDate,").append(userId).append(",");
        //  Value, Name, Description,
        sql.append("'").append(value).append("','").append(name).append("',NULL,");
        //  AccountType, AccountSign,
        sql.append(isExpenseType ? "'E'" : "'R'").append(", 'N', ");
        //  IsDocControlled, IsSummary,
        sql.append("'N','N',");
        //  ValidFrom, ValidTo,
        sql.append("TO_DATE('01-JAN-1970'),NULL,");
        //  PostActual, PostBudget, PostEncumbrance, PostStatistical,
        sql.append("'Y','Y','Y','Y',");
        //  IsBankAccount, C_BankAccount_ID, IsForeignCurrency, C_Currency_ID
        sql.append("'N',NULL,'N',NULL)");
        //
        int no = DB.executeUpdate(sql.toString(), null);
        if (no != 1) {
            log.log(Level.SEVERE, "#" + no + "\n" + sql.toString());
            elementValueId = 0;
        } else {
            log.config("C_ElementValue_ID=" + elementValueId + " " + value + "=" + name);
        }
        return elementValueId;
    }   //  create_ElementValue

    /**
     *  Create Charge and account entries for primary AcctSchema.
     *  @param ctx Context
     *  @param name name
     *  @param elementValueId element value
     *  @return charge
     */
    private int createCharge(final Ctx ctx, final String name, final int elementValueId) {
        //
        MCharge charge = new MCharge(ctx, 0, null);
        charge.setName(name);
//        int taxCategoryId = Env.getContextAsInt(ctx, 0, "TaxCategoryID");
        int taxCategoryId = ctx.getContextAsInt(0, "TaxCategoryID");
        charge.setC_TaxCategory_ID(taxCategoryId);
        if (!charge.save()) {
            log.log(Level.SEVERE, name + " not created");
            return 0;
        }

//        int accountSchemaId = Env.getContextAsInt(ctx, "$C_AcctSchema_ID");
        int accountSchemaId = ctx.getContextAsInt("$C_AcctSchema_ID");
        MAcctSchema acctSchema = new MAcctSchema(ctx, accountSchemaId, null);

        if (acctSchema == null || acctSchema.getC_AcctSchema_ID() == 0) {
            return 0;
        }

        //  Target Account
        MAccount defaultAcct = MAccount.getDefault(acctSchema, true); //  optional null
        MAccount acct = MAccount.get(
                ctx,
                charge.getAD_Client_ID(),
                charge.getAD_Org_ID(), 
                acctSchema.getC_AcctSchema_ID(), 
                elementValueId,
                defaultAcct.getC_SubAcct_ID(),
                defaultAcct.getM_Product_ID(),
                defaultAcct.getC_BPartner_ID(),
                defaultAcct.getAD_OrgTrx_ID(), 
                defaultAcct.getC_LocFrom_ID(),
                defaultAcct.getC_LocTo_ID(),
                defaultAcct.getC_SalesRegion_ID(), 
                defaultAcct.getC_Project_ID(),
                defaultAcct.getC_Campaign_ID(),
                defaultAcct.getC_Activity_ID(),
                defaultAcct.getUser1_ID(),
                defaultAcct.getUser2_ID(), 
                defaultAcct.getUserElement1_ID(),
                defaultAcct.getUserElement2_ID()); 
        if (acct == null) {
            return 0;
        }

        //  Update Accounts
        StringBuffer sql = new StringBuffer("UPDATE C_Charge_Acct ");
        sql.append("SET CH_Expense_Acct=").append(acct.getC_ValidCombination_ID());
        sql.append(", CH_Revenue_Acct=").append(acct.getC_ValidCombination_ID());
        sql.append(" WHERE C_Charge_ID=").append(charge.getC_Charge_ID());
        sql.append(" AND C_AcctSchema_ID=").append(accountSchemaId);
        //
        int no = DB.executeUpdate(sql.toString(), null);
        if (no != 1) {
            log.log(Level.SEVERE, "Update #" + no + "\n" + sql.toString());
        }
        //
        return charge.getC_Charge_ID();
    }   //  create_Charge

}
