package com.dev.swms.server.model.inventory;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import com.dev.swms.server.model.base.BOMComponent;
import com.dev.swms.server.model.base.Item;
import com.dev.swms.server.model.base.LotInfo;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.model.Entity;

public class ProcessDocDetail extends Entity {

	private ProcessDoc processDoc; //加工单

	private Item item; //货品(BOM)

	private LotInfo lotInfo; //批次属性

	private Double quantity; //待加工数量(BOM)

	private Double allocatedQuantity; //分配数量(BOM)

	private Double pickedQuantity; //拣货数量(BOM)

	private Double processQuantity; //加工数量(BOM)

	private PackageUnit packageUnit; //包装单位

	private String description; //描述
	
	/** 关联上架计划号 */
	private String moveDocCode;

	public int hashCode() {
		return new HashCodeBuilder().append(processDoc).append(item).append(
				lotInfo).append(packageUnit).toHashCode();
	}

	public boolean equals(final Object other) {
		if (!(other instanceof ProcessDocDetail))
			return false;
		ProcessDocDetail castOther = (ProcessDocDetail) other;
		return new EqualsBuilder().append(processDoc, castOther.processDoc)
				.append(item, castOther.item)
				.append(lotInfo, castOther.lotInfo).append(packageUnit,
						castOther.packageUnit).isEquals();
	}

	public String getMoveDocCode() {
		return moveDocCode;
	}

	public void setMoveDocCode(String moveDocCode) {
		this.moveDocCode = moveDocCode;
	}

	public Double getAllocatedQuantity() {
		return allocatedQuantity;
	}

	public void setAllocatedQuantity(Double allocatedQuantity) {
		this.allocatedQuantity = allocatedQuantity;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Item getItem() {
		return item;
	}

	public void setItem(Item item) {
		this.item = item;
	}

	public LotInfo getLotInfo() {
		return lotInfo;
	}

	public void setLotInfo(LotInfo lotInfo) {
		this.lotInfo = lotInfo;
	}

	public PackageUnit getPackageUnit() {
		return packageUnit;
	}

	public void setPackageUnit(PackageUnit packageUnit) {
		this.packageUnit = packageUnit;
	}

	public Double getPickedQuantity() {
		return pickedQuantity;
	}

	public void setPickedQuantity(Double pickedQuantity) {
		this.pickedQuantity = pickedQuantity;
	}

	public ProcessDoc getProcessDoc() {
		return processDoc;
	}

	public void setProcessDoc(ProcessDoc processDoc) {
		this.processDoc = processDoc;
	}

	public Double getProcessQuantity() {
		return processQuantity;
	}

	public void setProcessQuantity(Double processQuantity) {
		this.processQuantity = processQuantity;
	}

	public Double getQuantity() {
		return quantity;
	}

	public void setQuantity(Double quantity) {
		this.quantity = quantity;
	}
	
	/**
	 * 增加加工单明细的待加工数量
	 * @param quantity 待增加的期待数量
	 */
	public void addQuantity(double quantity) {
		this.quantity += quantity;
	}
	
	/** 
	 * 明细预分配
	 * @param lot 预分配批次号
	 * @param quantity 预分配数量
	 */
	public void preAllocate(Double quantity) {
		this.allocatedQuantity += quantity;
		if (this.allocatedQuantity > this.getQuantity()) {
			throw new BusinessException("preAlloate.quantity.error");
		}
		this.getProcessDoc().preAllocate(quantity);
	}
	
	/**
	 * 明细取消预分配
	 * @param quantity
	 */
	public void unPreAllocate() {
		this.allocatedQuantity = 0.0;
		if (this.allocatedQuantity < 0) {
			throw new BusinessException("unPreAlloate.quantity.error");
		}
		this.getProcessDoc().unPreAllocate();
	}
	
	//捡货的时候根据ProcessDocDetail对应的ProcessRecord得到捡货数量
	public void pick(){
		double pickQty = getBOMQuantity();
		double oldQty = this.pickedQuantity;
		if(pickQty>this.pickedQuantity)
			this.pickedQuantity=pickQty;
		this.getProcessDoc().pick(oldQty,pickQty);
	}
	
	//当捡货的时候,根据record的数量得到套件数量
	private double getBOMQuantity(){
		double quantity = -1;
		List<BOMMap> maps = getBOMMap(this.getItem(),1);
		for(BOMMap map:maps){
			double pickedQty = 0.0;
/*			for(ProcessRecord record:this.getProcessRecords()){
				if(record.getItem().getId()==map.getItem().getId()){
					pickedQty+=record.getPickedQuantity()==null?0.0:record.getPickedQuantity();
				}
			}
*/			Double tempQty = (Double)pickedQty/map.getQuantity();
			if(quantity<0){
				quantity = tempQty.intValue();
			}else{
				if(tempQty.intValue()<quantity){
					quantity = tempQty.intValue();
				}
			}
		}
		return quantity;
	}
	
	private List<BOMMap> getBOMMap(Item item, double beishu) {
		List<BOMMap> map = new ArrayList<BOMMap>();
		for (BOMComponent bomc : item.getComponents()) {
			if (bomc.getComponent().isBOM()) {
				List<BOMMap> tempmaps = getBOMMap(bomc.getComponent(), bomc.getQuantity());
				map.addAll(tempmaps);
			} else {
				BOMMap mp = new BOMMap();
				mp.setItem(bomc.getComponent());
				mp.setQuantity(bomc.getQuantity() * beishu);
				map.add(mp);
			}
		}
		return map;
	}
	
	public void process(double quantity){
		double oldProcessQty = this.processQuantity;
		this.processQuantity = quantity;
		this.processDoc.process(oldProcessQty,quantity);
		this.processDoc.addProcessFee(item.getPrice()*(quantity-oldProcessQty));
		processBOMDetail(quantity-oldProcessQty);
	}
	
	
	/**
	 * 扣减子件加工数量
	 */
	private void processBOMDetail(double quantity) {
		for (BOMComponent component : this.getItem().getComponents()) {
			ProcessDocBOMDetail bomDetail = this.processDoc.getProcessDocBOMDetailByItem(component.getComponent());
			bomDetail.setProcessQuantity(bomDetail.getProcessQuantity()+quantity*component.getQuantity());
		}
	}
}
