package com.ampiere.web.struts.form;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
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.MForm;
import org.compiere.model.MLookupFactory;
import org.compiere.model.MLookupInfo;
import org.compiere.util.CLogger;
import org.compiere.util.Ctx;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Language;
import org.compiere.util.Msg;
import org.compiere.util.WebSessionCtx;

import com.ampiere.util.Constants;

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

    /** Logger. */
    private CLogger log = CLogger.getCLogger(this.getClass());
    
    /** Payment List Forward. */
    private static final String PAYMENT_LIST = "paymentlist";

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

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

    /** Form ID. */
    private static final int FORM_ID = 106;

    /**
     * Action execute.
     * @param mapping mapping
     * @param actionForm actionForm
     * @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 actionForm,
            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);
        }

//        Env.setContext(wsc.ctx, 0, "IsSOTrx", "Y");
        wsc.ctx.setContext(0, "IsSOTrx", "Y");

        MForm form = getForm(wsc.ctx, FORM_ID);
//        Env.setContext(wsc.ctx, "FormName", form.getName());
        wsc.ctx.setContext("FormName", form.getName());

        PaymentPrintForm myForm =
            (PaymentPrintForm) request.getAttribute(ACTION_FORM);
        if (myForm == null) {
            myForm = (PaymentPrintForm) actionForm;
            if (myForm == null) {
                myForm = new PaymentPrintForm();
            }
        }
        
        // Main Window Title
        myForm.setMainWindowTitle(form.getName() + " - " + wsc.loginInfo);

        // Page title.
        myForm.setPageTitle(form.getName());

        // Payment selection
        loadPaymentList(wsc, myForm);

        // Load Bank Account
        loadBankAccount(wsc, myForm);

        // Load Payment Rule
        loadPaymentRule(wsc, myForm);

        // Load Payment rule info
        loadPaymentRuleInfo(wsc, myForm);

        // Button alt
        myForm.setExportLabel(Msg.translate(wsc.ctx, "Export"));
        myForm.setPrintLabel(Msg.translate(wsc.ctx, "Print"));
        myForm.setProcessLabel(Msg.translate(wsc.ctx, "Process"));

        
        // Save form to request.
        request.setAttribute(ACTION_FORM, myForm);

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

        return mapping.findForward(PAYMENT_LIST);

    }
    
    /**
     *  Get Form from Form ID.
     *  @param ctx Properties
     *  @param formId Form ID
     *  @return form
     */
    private MForm getForm(final Ctx ctx, final int formId) {

        // Get Form from Form ID
        MForm form = new MForm(ctx, formId, null);
        
        boolean trl = !Env.isBaseLanguage(ctx, "AD_Form");
        if (trl) {
            String sql = "SELECT t.Name, t.Description, t.Help "
                       + "FROM AD_Form f INNER JOIN AD_Form_Trl t"
                       + " ON (f.AD_Form_ID=t.AD_Form_ID AND AD_Language=?)"
                       + "WHERE f.AD_Form_ID=?";
            try {
                PreparedStatement pstmt = DB.prepareStatement(sql, null);
                if (trl) {
                    pstmt.setString(1, Env.getAD_Language(ctx));
                    pstmt.setInt(2, formId);

                    ResultSet rs = pstmt.executeQuery();
                    if (rs.next()) {
                        form.setName(rs.getString(1));
                        form.setDescription(rs.getString(2));
                        form.setHelp(rs.getString(3));
                    }
                    rs.close();
                    pstmt.close();
                }
            } catch (SQLException e) {
                log.log(Level.SEVERE, sql, e);
            }
        }

        return form;
    }   //  getForm

    /**
     * Get Payment List.
     * @param wsc Context
     * @param form Action form
     * @return Payment List
     */
    private void loadPaymentList(
            final WebSessionCtx wsc,
            final PaymentPrintForm form) {

        form.setPaymentSelectionLabel(Msg.translate(wsc.ctx, "C_PaySelection_ID"));

        ArrayList < HashMap > dataList = new ArrayList < HashMap > ();
        HashMap < String, Object > data = new HashMap < String, Object > ();

        log.config("");
//        int clientId = Env.getAD_Client_ID(wsc.ctx);
        int clientId = wsc.ctx.getAD_Client_ID();

        //  Load PaySelect
        String sql = "SELECT C_PaySelection_ID, Name || ' - ' || TotalAmt FROM C_PaySelection "
            + "WHERE AD_Client_ID=? AND Processed='Y' AND IsActive='Y'"
            + "ORDER BY PayDate DESC";
        try {
            PreparedStatement pstmt = DB.prepareStatement(sql, null);
            pstmt.setInt(1, clientId);
            ResultSet rs = pstmt.executeQuery();
            //
            while (rs.next())
            {
                data = new HashMap < String, Object > ();
                data.put("key", rs.getInt(1));
                data.put("value", rs.getString(2));
                dataList.add(data);
            }
            rs.close();
            pstmt.close();
        } catch (SQLException e) {
            log.log(Level.SEVERE, sql, e);
        }

        form.setPaymentSelectionList(dataList);

        if (dataList.size() == 0) { 
            form.setResultInfo("alert('" + Msg.getMsg(wsc.ctx, "VPayPrintNoRecords") + "');");
        } else {
            if (form.getPaymentSelectionId() == 0) {
                form.setPaymentSelectionId(Integer.valueOf(dataList.get(0).get("key").toString()));
            }
        }
    }
    
    /**
     * load Bank Account.
     * @param wsc Context
     * @param form Action form
     * @return Payment List
     */
    private void loadBankAccount(
            final WebSessionCtx wsc,
            final PaymentPrintForm form) {

        log.info( "VPayPrint.loadPaySelectInfo");

        form.setBankAccountLabel(Msg.translate(wsc.ctx, "C_BankAccount_ID"));
        form.setCurrentBalanceLabel(Msg.translate(wsc.ctx, "CurrentBalance"));
        form.setCurrentCurrencyLabel(Msg.translate(wsc.ctx, "C_Currency_ID"));

        //  load Banks from PaySelectLine
        String sql = "SELECT ps.C_BankAccount_ID, b.Name || ' ' || ba.AccountNo,"   //  1..2
            + " c.ISO_Code, CurrentBalance "                                        //  3..4
            + "FROM C_PaySelection ps"
            + " INNER JOIN C_BankAccount ba ON (ps.C_BankAccount_ID=ba.C_BankAccount_ID)"
            + " INNER JOIN C_Bank b ON (ba.C_Bank_ID=b.C_Bank_ID)"
            + " INNER JOIN C_Currency c ON (ba.C_Currency_ID=c.C_Currency_ID) "
            + "WHERE ps.C_PaySelection_ID=? AND ps.Processed='Y' AND ba.IsActive='Y'";
        try
        {
            PreparedStatement pstmt = DB.prepareStatement(sql, null);
            pstmt.setInt(1, form.getPaymentSelectionId());
            ResultSet rs = pstmt.executeQuery();
            if (rs.next())
            {
                form.setBankAccountId(rs.getInt(1));
                form.setBankAccountName(rs.getString(2));
                form.setCurrentCurrency(rs.getString(3));
                form.setCurrentBalance(wsc.amountFormat.format(rs.getBigDecimal(4)));
            }
            else
            {
                form.setBankAccountId(-1);
                form.setBankAccountName("");
                form.setCurrentCurrency("");
                form.setCurrentBalance(wsc.amountFormat.format(Env.ZERO));
                log.log(Level.SEVERE, "No active BankAccount for C_PaySelection_ID=" + form.getPaymentSelectionId());
            }
            rs.close();
            pstmt.close();
        }
        catch (SQLException e)
        {
            log.log(Level.SEVERE, sql, e);
        }
    }   //  loadBankAccount

    /**
     * Bank changed - load PaymentRule.
     * @param wsc Context
     * @param form Action form
     * @return Payment List
     */
    private void loadPaymentRule(
            final WebSessionCtx wsc,
            final PaymentPrintForm form) {

        log.info("");

        form.setPaymentRuleLabel(Msg.translate(wsc.ctx, "PaymentRule"));

        ArrayList < HashMap > dataList = new ArrayList < HashMap > ();
        HashMap < String, Object > data = new HashMap < String, Object > ();

        if (form.getBankAccountId() == -1)
            return;

        // load PaymentRule for Bank
        Language language = Language.getLanguage(Env.getAD_Language(wsc.ctx));
        MLookupInfo info = MLookupFactory.getLookup_List(language, 195);
        String sql = info.Query.substring(0, info.Query.indexOf(" ORDER BY"))
            + " AND " + info.KeyColumn
            + " IN (SELECT PaymentRule FROM C_PaySelectionCheck WHERE C_PaySelection_ID=?) "
            + info.Query.substring(info.Query.indexOf(" ORDER BY"));
        try {
            PreparedStatement pstmt = DB.prepareStatement(sql, null);
            pstmt.setInt(1, form.getPaymentSelectionId());
            ResultSet rs = pstmt.executeQuery();
            //
            while (rs.next())
            {
                data = new HashMap < String, Object > ();
                data.put("key", rs.getString(2));
                data.put("value", rs.getString(3));
                dataList.add(data);
            }
            rs.close();
            pstmt.close();
        }
        catch (SQLException e)
        {
            log.log(Level.SEVERE, sql, e);
        }
        
        form.setPaymentRuleList(dataList);
        
        if (dataList.size() == 0) {
            log.config("PaySel=" + form.getPaymentSelectionId() + ", BAcct=" + form.getBankAccountId() + " - " + sql);
        } else {
            if (form.getPaymentRule() == null || form.getPaymentRule() == "") {
                form.setPaymentRule(dataList.get(0).get("key").toString());
            }
        }
    }   //  loadPaymentRule

    /**
     * PaymentRule changed - load DocumentNo, NoPayments, enable/disable EFT, Print
     * @param wsc Context
     * @param form Action form
     * @return Payment List
     */
    private void loadPaymentRuleInfo(
            final WebSessionCtx wsc,
            final PaymentPrintForm form) {

        form.setDocumentNumberLabel(Msg.translate(wsc.ctx, "DocumentNo"));
        form.setPaymentNumberLabel(Msg.translate(wsc.ctx, "NoOfPayments"));

        if (form.getPaymentRule() == null || form.getPaymentRule() == "") {
            return;
        }

        log.info("PaymentRule=" + form.getPaymentRule());

        form.setPaymentNumber(0);

        String sql = "SELECT COUNT(*) "
            + "FROM C_PaySelectionCheck "
            + "WHERE C_PaySelection_ID=?";
        try
        {
            PreparedStatement pstmt = DB.prepareStatement(sql, null);
            pstmt.setInt(1, form.getPaymentSelectionId());
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                form.setPaymentNumber(rs.getInt(1));
            }
            rs.close();
            pstmt.close();
        } catch (SQLException e) {
            log.log(Level.SEVERE, sql, e);
        }

        //  DocumentNo
        sql = "SELECT CurrentNext "
            + "FROM C_BankAccountDoc "
            + "WHERE C_BankAccount_ID=? AND PaymentRule=? AND IsActive='Y'";
        try
        {
            PreparedStatement pstmt = DB.prepareStatement(sql, null);
            pstmt.setInt(1, form.getBankAccountId());
            pstmt.setString(2, form.getPaymentRule());
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                form.setDocumentNumber(rs.getInt(1));
            } else {
                log.log(Level.SEVERE, "VPayPrint.loadPaymentRuleInfo - No active BankAccountDoc for C_BankAccount_ID="
                    + form.getBankAccountId() + " AND PaymentRule=" + form.getPaymentRule());
                form.setResultInfo("alert('" + Msg.translate(wsc.ctx, "VPayPrintNoDoc") + "');");
            }
            rs.close();
            pstmt.close();
        }
        catch (SQLException e)
        {
            log.log(Level.SEVERE, sql, e);
        }
    }   //  loadPaymentRuleInfo
}
