package com.ampiere.web.struts.form;

import java.util.Iterator;
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.framework.Lookup;
import org.compiere.model.MLookupFactory;
import org.compiere.model.MPInstance;
import org.compiere.model.MPInstancePara;
import org.compiere.model.MProcess;
import org.compiere.process.ProcessInfo;
import org.compiere.process.ProcessInfoUtil;
import org.compiere.util.CLogger;
import org.compiere.util.Ctx;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.compiere.util.Trx;
import org.compiere.util.WebSessionCtx;

import com.ampiere.util.Constants;

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

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

    /** Shipment List Forward. */
    private static final String INVOICE_LIST = "invoicelist";

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

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

    /** C_OrderLine.M_Warehouse_ID. */
    private static final int ORDER_BUSINESS_PARTNER_COLUMN_ID = 2762;

    /**
     * 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(ORDER_LIST);
        
        GenerateInvoiceFromOrderForm myForm =
            (GenerateInvoiceFromOrderForm) request.getAttribute(ACTION_FORM);

        String column = myForm.getChangedColumn();
        if (column.equals("organizationId")) {
            // Ware house selection changed.
            actionForward = mapping.findForward(ORDER_LIST);
        } else if (column.equals("businessPartnerId")) {
            // Business Partner ID chenged.
            actionForward = mapping.findForward(ORDER_LIST);
        } else if (column.equals("businessPartnerName")) {
            // Business Partner Name chenged.

            //  C_Order.C_BPartner_ID
            Lookup lookup = null;
            try {
                lookup = MLookupFactory.get(
                        wsc.ctx,
                        0,
                        ORDER_BUSINESS_PARTNER_COLUMN_ID,
                        DisplayType.TableDir,
                        wsc.language,
                        "C_BPartner_ID",
                        0,
                        false,
                        "UPPER(NAME) LIKE '" + myForm.getBusinessPartnerName().toUpperCase() + "%' ");

                Iterator keyNames = lookup.getData(true, false, true, false).iterator();
                KeyNamePair keyName;
                if (keyNames.hasNext()) {
                    keyName = (KeyNamePair) keyNames.next();
                    myForm.setBusinessPartnerId(keyName.getKey());
                    myForm.setBusinessPartnerName(keyName.getName());
                } else {
                    myForm.setBusinessPartnerId(999999999);
                }
            } catch (Exception e) {
                log.log(Level.SEVERE, "MLookupFactory.get AD_Column_ID=" + ORDER_BUSINESS_PARTNER_COLUMN_ID, e);
            }

            actionForward = mapping.findForward(ORDER_LIST);
        } else {
            // Genarate shipments.
            if (myForm.getOrderIdList()!=null && myForm.getOrderIdList().length > 0) {
//                myForm.setMainWindowTitle(Env.getContext(wsc.ctx, "FormName") + " - " + wsc.loginInfo);
//                myForm.setPageTitle(Env.getContext(wsc.ctx, "FormName"));
                myForm.setMainWindowTitle(wsc.ctx.getContext("FormName") + " - " + wsc.loginInfo);
                myForm.setPageTitle(wsc.ctx.getContext("FormName"));
                
                generateInvoices(wsc.ctx, myForm);

                actionForward = mapping.findForward(INVOICE_LIST);
            } else {
                actionForward = mapping.findForward(ORDER_LIST);
            }
        }
        
        // Save form to request.
        request.setAttribute(ACTION_FORM, myForm);

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

        return actionForward;
    }
    
    /**
     *  Generate Shipments.
     *  @param ctx Compiere Context
     *  @param form Action Form
     */
    private void generateInvoices(
            final Ctx ctx,
            final GenerateInvoiceFromOrderForm form) {

        String whereClause = getWhereClause(form.getOrderIdList());

        //  Reset Selection
        String sql  = "UPDATE C_Order SET IsSelected = 'N' "
                    + "WHERE IsSelected='Y'"
//                    + " AND AD_Client_ID=" + Env.getAD_Client_ID(ctx);
                    + " AND AD_Client_ID=" + ctx.getAD_Client_ID();
        int no = DB.executeUpdate(sql, null);

        //  Set Selection
        sql = "UPDATE C_Order SET IsSelected='Y' WHERE " + whereClause;
        no = DB.executeUpdate(sql, null);

        if (no == 0) {
            form.setResultInfo("No Invoices"); //  not translated
            return;
        }

        // M_InOutCreate - org.compiere.process.InOutGenerate
        int processId = 134; 
        MProcess process = MProcess.get(ctx, processId);
        MPInstance instance = new MPInstance(ctx, processId, 0);
        if (!instance.save()) {
            form.setResultInfo(Msg.getMsg(Env.getCtx(), "ProcessNoInstance"));
            return;
        }

        ProcessInfo pi = new ProcessInfo("VInOutGen", processId);
        pi.setAD_PInstance_ID(instance.getAD_PInstance_ID());
//        pi.setAD_User_ID(Env.getAD_User_ID(ctx));
//        pi.setAD_Client_ID(Env.getAD_Client_ID(ctx));
        pi.setAD_User_ID(ctx.getAD_User_ID());
        pi.setAD_Client_ID(ctx.getAD_Client_ID());

        //  Add Parameter - Selection=Y
        MPInstancePara ip = new MPInstancePara(instance, 10);
        ip.setParameter("Selection", "Y");
        if (!ip.save()) {
            form.setResultInfo("No Parameter added"); //  not translated
            return;
        }

        //  Add Parameter - M_Warehouse_ID=x
        ip = new MPInstancePara(instance, 20);
        ip.setParameter("DocAction", "CO");
        if (!ip.save()) {
            form.setResultInfo("No Parameter added"); //  not translated
            return;
        }

        //  Start
        boolean processOK = false;
        if (process.isJavaProcess()) {
            Trx trx = Trx.get(Trx.createTrxName("WebPrc"), true);
            try {
                processOK = process.processIt(pi, trx);
                trx.commit();
                trx.close();
            } catch (Throwable t) {
                trx.rollback();
                trx.close();
            }

            if (!processOK || pi.isError()) {
                processOK = false;
            }
            
            if (processOK) {
                ProcessInfoUtil.setLogFromDB(pi);
                StringBuffer iText = new StringBuffer();
                iText.append("<b>").append(pi.getSummary())
                    .append("</b><br>(")
                    .append(Msg.getMsg(ctx, "InvGenerateInfo"))
                    //  Shipments are generated depending on the Delivery Rule selection in the Order
                    .append(")<br>")
                    .append(pi.getLogInfo(true))
                    .append("<br><br>");
                form.setResultInfo(iText.toString());

                //  Reset Selection
                sql = "UPDATE C_Order SET IsSelected='N' WHERE " + whereClause;
                no = DB.executeUpdate(sql, null);
                log.config("Reset=" + no);

            } else {
                log.log(Level.SEVERE, "Error:" + pi.getSummary());
            }
        }

    }   //  generateShipments
    
    /**
     * Get Where Clause.
     * @param orderIds Order ID's
     * @return Where Clause
     */
    private String getWhereClause(final int [] orderIds) {

        //  Query String
        StringBuffer sb = new StringBuffer("");
        if (orderIds.length > 0) {
            sb.append("C_Order_ID");
            if (orderIds.length > 1) {
                sb.append(" IN (");
            } else {
                sb.append("=");
            }
            //  Add elements
            for (int i = 0; i < orderIds.length; i++) {
                if (i > 0) {
                    sb.append(",");
                }
                sb.append(String.valueOf(orderIds[i]));
            }

            if (orderIds.length > 1) {
                sb.append(")");
            }

        }
        
        return sb.toString();
    }
}
