/**
 * 
 */
package com.ampiere.web.struts.button;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;

import org.apache.ecs.AlignType;
import org.compiere.model.MInOut;
import org.compiere.model.MInOutLine;
import org.compiere.model.MInvoice;
import org.compiere.model.MInvoiceLine;
import org.compiere.model.MLocator;
import org.compiere.model.MLocatorLookup;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
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.NamePair;

import com.ampiere.dto.CodeValue;
import com.ampiere.search.ColBean;
import com.ampiere.util.AmpiereUtil;

/**
 * @author Shinjirito
 */
public class CreateFromShipmentForm extends CreateFromBaseForm {
	private static final long serialVersionUID = -2388216106087950733L;
	protected String locatorLabel;
	protected String locatorSelected;
	protected List<CodeValue> locatorList;

	/**
	 *	Static Setup - set field value
	 */
	public void statInit(Ctx ctx) {
		super.statInit(ctx);
		setTitle(Msg.getElement(ctx, "M_InOut_ID", false) + " .. " + Msg.translate(ctx, "CreateFrom"));
		setLocatorLabel(Msg.getElement(ctx, "M_Locator_ID"));

		//  load Locator
		locatorList = new ArrayList<CodeValue>();
		MLocatorLookup locator = new MLocatorLookup(ctx, getWindowNo());
		locator.setOnly_Warehouse_ID(AmpiereUtil.getOnly_Warehouse_ID(ctx, getWindowNo()));
		Collection col = locator.getData(true, true, true, false);
		Iterator it = col.iterator();
		while (it.hasNext()) {
//			MLocator loc = (MLocator)it.next();
//			String key = String.valueOf(loc.getM_Locator_ID());
//			String name = loc.getValue();
			NamePair loc = (NamePair)it.next(); //clmg 2009/03/06 3.0は全部NamePairになったため。
			String key = String.valueOf(loc.getID()); //clmg 2009/03/06
			String name = loc.getName();//clmg 2009/03/06
			locatorList.add(new CodeValue(key, name));
//			if (loc.isDefault()) {//clmg 2009/03/06
//				locatorSelected = key;
//			}
		}

		initBPartner(getBpartnerID(), false, ctx);
	}

	/**
	 *  Init Details - load invoices not shipped
	 *  @param C_BPartner_ID BPartner
	 */
	protected void initBPDetails(int C_BPartner_ID, Ctx ctx)
	{
		log.config("C_BPartner_ID=" + C_BPartner_ID);

		//  load AP Invoice closed or complete
		invoiceList = new ArrayList<CodeValue>();

		//	None
		CodeValue pp = new CodeValue("0", "");
		invoiceList.add(pp);

		StringBuffer display = new StringBuffer("i.DocumentNo||' - '||")
			.append(DB.TO_CHAR("DateInvoiced", DisplayType.Date, Env.getAD_Language(ctx)))
			.append("|| ' - ' ||")
			.append(DB.TO_CHAR("GrandTotal", DisplayType.Amount, Env.getAD_Language(ctx)));
		//
		StringBuffer sql = new StringBuffer("SELECT i.C_Invoice_ID,").append(display)
		   .append(" FROM C_Invoice i "
		   + "WHERE i.C_BPartner_ID=? AND i.IsSOTrx='N' AND i.DocStatus IN ('CL','CO')"
		   + " AND i.C_Invoice_ID IN "
			   + "(SELECT il.C_Invoice_ID FROM C_InvoiceLine il"
			   + " LEFT OUTER JOIN M_MatchInv mi ON (il.C_InvoiceLine_ID=mi.C_InvoiceLine_ID) "
			   + "GROUP BY il.C_Invoice_ID,mi.C_InvoiceLine_ID,il.QtyInvoiced "
			   + "HAVING (il.QtyInvoiced<>SUM(mi.Qty) AND mi.C_InvoiceLine_ID IS NOT NULL)"
			   + " OR mi.C_InvoiceLine_ID IS NULL) "
		   + "ORDER BY i.DateInvoiced");

		try
		{
			PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null);
			pstmt.setInt(1, C_BPartner_ID);
			ResultSet rs = pstmt.executeQuery();
			while (rs.next())
			{
				pp = new CodeValue(rs.getString(1), rs.getString(2));
				invoiceList.add(pp);
			}
			rs.close();
			pstmt.close();
		}
		catch (SQLException e)
		{
			log.log(Level.SEVERE, sql.toString(), e);
		}
		invoiceSelected = "0";
	}   //  initBPDetails

	/**
	 *  Load Data - Invoice
	 *  @param C_Invoice_ID Invoice
	 */
	public List loadInvoice (int C_Invoice_ID, Ctx ctx, int maxRecNo)
	{
		log.config("C_Invoice_ID=" + C_Invoice_ID);
/*
		m_invoice = new MInvoice (ctx, C_Invoice_ID, null);    //  save
		p_order = null;
*/

		StringBuffer sql = new StringBuffer("SELECT "	//	Entered UOM
			+ "l.QtyInvoiced-SUM(NVL(mi.Qty,0)),l.QtyEntered/l.QtyInvoiced,"
			+ " l.C_UOM_ID,COALESCE(uom.UOMSymbol,uom.Name),"			//  3..4
			+ " l.M_Product_ID,p.Name, l.C_InvoiceLine_ID,l.Line,"      //  5..8
			+ " l.C_OrderLine_ID ");                   					//  9
		if (Env.isBaseLanguage(ctx, "C_UOM"))
		{
			sql.append("FROM C_UOM uom, C_InvoiceLine l, M_Product p, M_MatchInv mi ");
			sql.append("WHERE l.C_UOM_ID=uom.C_UOM_ID");
		}
		else
		{
			sql.append("FROM C_UOM_Trl uom, C_InvoiceLine_v l, M_Product p, M_MatchInv mi ");
			sql.append("WHERE l.C_UOM_ID=uom.C_UOM_ID AND uom.AD_Language='").append(Env.getAD_Language(ctx)).append("'");
		}
		sql.append(" AND l.M_Product_ID=p.M_Product_ID"
			+ " AND l.C_InvoiceLine_ID=mi.C_InvoiceLine_ID(+)"
			+ " AND l.C_Invoice_ID=? " 									//  #1
			+ "GROUP BY l.QtyInvoiced,l.QtyEntered/l.QtyInvoiced,"
			+ "l.C_UOM_ID,COALESCE(uom.UOMSymbol,uom.Name),"
				+ "l.M_Product_ID,p.Name, l.C_InvoiceLine_ID,l.Line,l.C_OrderLine_ID "
			+ "ORDER BY l.Line");

		ArrayList<ColBean> resultList = new ArrayList<ColBean>();
		try
		{
			PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null);
			pstmt.setInt(1, C_Invoice_ID);
			ResultSet rs = pstmt.executeQuery();
			int lineCount = 0;
			while (rs.next())
			{
				ColBean colBean = new ColBean();
				colBean.setColId(Integer.toString(lineCount));
				int beanOffset = 0;

				if (++lineCount > maxRecNo) {
					break;
				}

				//  0-Selection
				colBean.setColData(beanOffset, "false");
				colBean.setColTitle(beanOffset, Msg.translate(ctx, "Select"));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.CENTER + ";");
				beanOffset++;

				//  1-Qty
				BigDecimal qtyInvoiced = rs.getBigDecimal(1);
				BigDecimal multiplier = rs.getBigDecimal(2);
				BigDecimal qtyEntered = qtyInvoiced.multiply(multiplier);
				colBean.setColData(beanOffset, qtyEntered);
				colBean.setColTitle(beanOffset, Msg.translate(ctx, "Quantity"));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.RIGHT + ";");
				beanOffset++;

				// 2-UOM
				KeyNamePair pp = new KeyNamePair(rs.getInt(3), rs.getString(4).trim());
				colBean.setColData(beanOffset, pp);
				colBean.setColTitle(beanOffset, Msg.translate(ctx, "C_UOM_ID"));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.LEFT + ";");
				beanOffset++;

				// 3-Product
				pp = new KeyNamePair(rs.getInt(5), rs.getString(6));
				colBean.setColData(beanOffset, pp);
				colBean.setColTitle(beanOffset, Msg.translate(ctx, "M_Product_ID"));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.LEFT + ";");
				beanOffset++;

				// 4-OrderLine
				int C_OrderLine_ID = rs.getInt(9);
				if (rs.wasNull())
					colBean.setColData(beanOffset, null);
				else
					colBean.setColData(beanOffset, new KeyNamePair(C_OrderLine_ID, "."));
				colBean.setColTitle(beanOffset, Msg.getElement(ctx, "C_Order_ID", false));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.LEFT + ";");
				beanOffset++;

				//  5-Ship
				colBean.setColData(beanOffset, null);
				colBean.setColTitle(beanOffset, Msg.getElement(ctx, "M_InOut_ID", false));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.LEFT + ";");
				beanOffset++;

				//  6-Invoice
				pp = new KeyNamePair(rs.getInt(7), rs.getString(8));
				colBean.setColData(beanOffset, null);
				colBean.setColTitle(beanOffset, Msg.getElement(ctx, "C_Invoice_ID", false));
				colBean.setStyle(beanOffset, "text-align: " + AlignType.LEFT + ";");
				beanOffset++;

				resultList.add(colBean);
			}
			rs.close();
			pstmt.close();
		}
		catch (SQLException e)
		{
			log.log(Level.SEVERE, sql.toString(), e);
		}

		return resultList;
	}   //  loadInvoice

	/**
	 *  Save - create Shipments
	 *  @return true if saved
	 */
	protected boolean save(Ctx ctx, int M_InOut_ID, List resultList)
	{
		log.config("");

		if (selectedIndex == null || selectedIndex.length() <= 0) {
			return false;
		}
		String ppp[] = selectedIndex.split("\\,");
		if (ppp == null || ppp.length <= 0) {
			return false;
		}

		//
		if (locatorSelected == null || locatorSelected.length() <= 0) {
			return false;
		}
		int M_Locator_ID = Integer.parseInt(locatorSelected);

		MInOut inout = new MInOut (ctx, M_InOut_ID, null);
		log.config(inout + ", C_Locator_ID=" + M_Locator_ID);

		MOrder p_order = null;
		int C_Invoice_ID = Integer.parseInt(invoiceSelected);
		MInvoice invoice = null;
		if (C_Invoice_ID != 0) {
			invoice = new MInvoice(ctx, C_Invoice_ID, null);
		} else {
			int C_Order_ID = Integer.parseInt(orderSelected);
			if (C_Order_ID != 0) {
				p_order = new MOrder (ctx, C_Order_ID, null);
			}
		}

		/**
		 *  Selected        - 0
		 *  QtyEntered      - 1
		 *  C_UOM_ID        - 2
		 *  M_Product_ID    - 3
		 *  OrderLine       - 4
		 *  ShipmentLine    - 5
		 *  InvoiceLine     - 6
		 */

		//  Lines
		for (int i = 0; i < ppp.length; i++)
		{
			int idx = Integer.parseInt(ppp[i]);
			ColBean colBean = (ColBean)resultList.get(idx);
			if (colBean != null)
			{
				//  variable values
				BigDecimal QtyEntered = (BigDecimal)colBean.getColData(1);//  1-Qty

				KeyNamePair pp = (KeyNamePair)colBean.getColData(2);   //  2-UOM
				int C_UOM_ID = pp.getKey();
				pp = (KeyNamePair)colBean.getColData(3);               //  3-Product
				int M_Product_ID = pp.getKey();
				int C_OrderLine_ID = 0;
				pp = (KeyNamePair)colBean.getColData(4);               //  4-OrderLine
				if (pp != null)
					C_OrderLine_ID = pp.getKey();
				int C_InvoiceLine_ID = 0;
				MInvoiceLine il = null;
				pp = (KeyNamePair)colBean.getColData(6);               //  6-InvoiceLine
				if (pp != null)
					C_InvoiceLine_ID = pp.getKey();
				if (C_InvoiceLine_ID != 0)
					il = new MInvoiceLine (ctx, C_InvoiceLine_ID, null);
//				boolean isInvoiced = (C_InvoiceLine_ID != 0);

				//
				log.fine("Line QtyEntered=" + QtyEntered
					+ ", Product=" + M_Product_ID 
					+ ", OrderLine=" + C_OrderLine_ID + ", InvoiceLine=" + C_InvoiceLine_ID);

				//	Credit Memo - negative Qty
				if (invoice != null && invoice.isCreditMemo() )
					QtyEntered = QtyEntered.negate();
				//
				MInOutLine iol = new MInOutLine (inout);
				iol.setM_Product_ID(M_Product_ID, C_UOM_ID);	//	Line UOM
				iol.setQty(QtyEntered);							//	Movement/Entered
				//
				MOrderLine ol = null;
				if (C_OrderLine_ID != 0)
				{
					iol.setC_OrderLine_ID(C_OrderLine_ID);
					ol = new MOrderLine (ctx, C_OrderLine_ID, null);
					if (ol.getQtyEntered().compareTo(ol.getQtyOrdered()) != 0)
					{
						iol.setMovementQty(QtyEntered
							.multiply(ol.getQtyOrdered())
							.divide(ol.getQtyEntered(), 12, BigDecimal.ROUND_HALF_UP));
						iol.setC_UOM_ID(ol.getC_UOM_ID());
					}
					iol.setM_AttributeSetInstance_ID(ol.getM_AttributeSetInstance_ID());
					iol.setDescription(ol.getDescription());
				}
				else if (il != null)
				{
					if (il.getQtyEntered().compareTo(il.getQtyInvoiced()) != 0)
					{
						iol.setQtyEntered(QtyEntered
							.multiply(il.getQtyInvoiced())
							.divide(il.getQtyEntered(), 12, BigDecimal.ROUND_HALF_UP));
						iol.setC_UOM_ID(il.getC_UOM_ID());
					}
					iol.setDescription(il.getDescription());
				}
				//	Charge
				if (M_Product_ID == 0)
				{
					if (ol != null && ol.getC_Charge_ID() != 0)			//	from order
						iol.setC_Charge_ID(ol.getC_Charge_ID());
					else if (il != null && il.getC_Charge_ID() != 0)	//	from invoice
						iol.setC_Charge_ID(il.getC_Charge_ID());
				}
				//
				iol.setM_Locator_ID(M_Locator_ID);
				if (!iol.save())
					log.log(Level.SEVERE, "Line NOT created #" + i);
				//	Create Invoice Line Link
				else if (il != null)
				{
					il.setM_InOutLine_ID(iol.getM_InOutLine_ID());
					il.save();
				}
			}   //   if selected
		}   //  for all rows

		/**
		 *  Update Header
		 *  - if linked to another order/invoice - remove link
		 *  - if no link set it
		 */
		if (p_order != null)
		{
			inout.setC_Order_ID (p_order.getC_Order_ID());
			inout.setAD_OrgTrx_ID(p_order.getAD_OrgTrx_ID());
			inout.setC_Project_ID(p_order.getC_Project_ID());
			inout.setC_Campaign_ID(p_order.getC_Campaign_ID());
			inout.setC_Activity_ID(p_order.getC_Activity_ID());
			inout.setUser1_ID(p_order.getUser1_ID());
			inout.setUser2_ID(p_order.getUser2_ID());
		}

		if (invoice != null && invoice.getC_Invoice_ID() != 0)
		{
			if (inout.getC_Order_ID() == 0)
				inout.setC_Order_ID (invoice.getC_Order_ID());
			inout.setC_Invoice_ID (invoice.getC_Invoice_ID());
			inout.setAD_OrgTrx_ID(invoice.getAD_OrgTrx_ID());
			inout.setC_Project_ID(invoice.getC_Project_ID());
			inout.setC_Campaign_ID(invoice.getC_Campaign_ID());
			inout.setC_Activity_ID(invoice.getC_Activity_ID());
			inout.setUser1_ID(invoice.getUser1_ID());
			inout.setUser2_ID(invoice.getUser2_ID());
		}
		inout.save();
		return true;
	}   //  save

	public String getLocatorLabel() {
		return locatorLabel;
	}

	public void setLocatorLabel(String locatorLabel) {
		this.locatorLabel = locatorLabel;
	}

	public List<CodeValue> getLocatorList() {
		return locatorList;
	}

	public void setLocatorList(List<CodeValue> locatorList) {
		this.locatorList = locatorList;
	}

	public String getLocatorSelected() {
		return locatorSelected;
	}

	public void setLocatorSelected(String locatorSelected) {
		this.locatorSelected = locatorSelected;
	}
}
