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

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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

import com.dev.swms.server.model.base.Item;
import com.dev.swms.server.model.base.ItemKey;
import com.dev.swms.server.model.base.Location;
import com.dev.swms.server.model.base.LotInfo;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.swms.server.model.base.WarehouseArea;
import com.dev.swms.server.model.base.Worker;
import com.dev.swms.server.model.inventory.Stock;
import com.dev.swms.server.utils.DoubleUtils;
import com.dev.energy.server.model.Entity;
import com.dev.energy.server.model.EntityFactory;
import com.dev.energy.server.web.security.UserHolder;

public class ASNDetail extends Entity {
	private static final long serialVersionUID = -5729670330105759423L;
	/** 所属收货单 */
	private ASN asn;
	/** 商品 */
	private Item item;
	/** 商品属性 */
	private LotInfo lotInfo;
	/** 期望包装数量 */
	private double expectedQuantity;
	/** 期望基本单位数量 */
	private double expectedQtyOfMasterUnit;
	/** 已收数量 */
	private double receivedQuantity;
	/** 包装单位 */
	private PackageUnit packageUnit;
	/** 收货记录 */
	private Set<ReceivedRecord> receivedRecords = new HashSet<ReceivedRecord>();
	/** PO */
	private String PO;
	/** 行号 */
	private Integer lineNo;
	/** 月台	 */
	private Location dock;
	/** CA系数*/
	private Double caCoefficient=0D;
	/** 温度 */
	private String temperature;
	private double weight;//重量--净重
	private double volume;//体积
	private double receivedWeight;//收货重量--毛重
	
	private double receivedVolume;//收货体积
	/**  */
	private String sourceId;
	/**  未关联标识*/
	private String myfs;
	/** 备注 */
	private String remark;
	
	private Location zzkw;
	
	private Date operDate;
	
	private String operBy;
	
	public Location getZzkw() {
		return zzkw;
	}

	public void setZzkw(Location zzkw) {
		this.zzkw = zzkw;
	}

	private Date chTate;
	
	public Date getChTate() {
		return chTate;
	}

	public void setChTate(Date chTate) {
		this.chTate = chTate;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public String getSourceId() {
		return sourceId;
	}

	public void setSourceId(String sourceId) {
		this.sourceId = sourceId;
	}

	public String getMyfs() {
		return myfs;
	}

	public void setMyfs(String myfs) {
		this.myfs = myfs;
	}

	public double getReceivedWeight() {
		return receivedWeight;
	}

	public void setReceivedWeight(double receivedWeight) {
		this.receivedWeight = receivedWeight;
	}

	public double getReceivedVolume() {
		return receivedVolume;
	}

	public void setReceivedVolume(double receivedVolume) {
		this.receivedVolume = receivedVolume;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}

	public double getVolume() {
		return volume;
	}

	public void setVolume(double volume) {
		this.volume = volume;
	}

	
	

	public Date getOperDate() {
		return operDate;
	}

	public void setOperDate(Date operDate) {
		this.operDate = operDate;
	}

	public String getOperBy() {
		return operBy;
	}

	public void setOperBy(String operBy) {
		this.operBy = operBy;
	}

	public Double getCaCoefficient() {
		return caCoefficient;
	}

	public void setCaCoefficient(Double caCoefficient) {
		this.caCoefficient = caCoefficient;
	}

	public String getTemperature() {
		return temperature;
	}

	public void setTemperature(String temperature) {
		this.temperature = temperature;
	}

	public Location getDock() {
		return dock;
	}

	public void setDock(Location dock) {
		this.dock = dock;
	}

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

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

	public ASNDetail() {
	}

	public Integer getLineNo() {
		return lineNo;
	}
	public void setLineNo(Integer lineNo) {
		this.lineNo = lineNo;
	}
	public String getPO() {
		return PO;
	}
	public void setPO(String po) {
		PO = po;
	}
	public double getExpectedQuantity() {
		return expectedQuantity;
	}
	public void setExpectedQuantity(double expectedQuantity) {
		this.expectedQuantity = expectedQuantity;
	}
	public double getExpectedQtyOfMasterUnit() {
		return expectedQtyOfMasterUnit;
	}
	public void setExpectedQtyOfMasterUnit(double expectedQtyOfMasterUnit) {
		this.expectedQtyOfMasterUnit = expectedQtyOfMasterUnit;
	}
	public PackageUnit getPackageUnit() {
		return packageUnit;
	}
	public void setPackageUnit(PackageUnit packageUnit) {
		this.packageUnit = packageUnit;
	}
	public double getReceivedQuantity() {
		return receivedQuantity;
	}
	public void setReceivedQuantity(double receivedQuantity) {
		this.receivedQuantity = receivedQuantity;
	}
	public Set<ReceivedRecord> getReceivedRecords() {
		return receivedRecords;
	}
	public void setReceivedRecords(Set<ReceivedRecord> receivedRecords) {
		this.receivedRecords = receivedRecords;
	}
	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 ASN getAsn() {
		return asn;
	}
	public void setAsn(ASN asn) {
		this.asn = asn;
	}
	

	/**
	 * 增加收货单明细的期待数量
	 * @param quantity 待增加的期待数量
	 */
	public void addExpectedQuantity(double quantity) {
		this.expectedQuantity += quantity;
		this.expectedQtyOfMasterUnit = this.expectedQuantity*this.packageUnit.getConvertFigure();
	}

	/**
	 * 对明细进行收货处理,增加收货记录;
	 * @param itemKey     收货商品
	 * @param quantity    收取数量(基本单位数量)
	 * @param location    收货库位
	 * @param packageUnit 收货包装
	 * @param LP 
	 */
	public ReceivedRecord receiving(Location location, ItemKey itemKey, double quantity,
			PackageUnit packageUnit,Stock stock, String barCode,double weight,double volume,ReceivedDoc receivedDoc, Date receiveDate, Worker worker, String qualityCode) {
		if (quantity != 0) {
			this.receivedQuantity += quantity;
			ReceivedRecord r=addReceivedRecord(location, itemKey, quantity, packageUnit, stock,barCode,weight,volume,receiveDate, null, receivedDoc, worker, qualityCode);
			return r;
		}else{
			return null;
		}
	}
	
	public ReceivedRecord addReceivedRecord(WarehouseArea zone,Location location, ItemKey itemKey,
			double quantity,String barCode,Date receiveDate, String description,
			 Worker worker, String oper) {
		this.receivedQuantity += quantity;
		ReceivedRecord recRecord = EntityFactory.getEntity(ReceivedRecord.class);
		recRecord.setAsn(this.asn);
		recRecord.setAsnDetail(this);
		recRecord.setItemKey(itemKey);
		recRecord.setZone(zone);
		recRecord.setLocation(location);
		recRecord.setReceiveDate(receiveDate);
		recRecord.setReceivedQuantityMU(quantity);
		recRecord.setBarCode(barCode);
		recRecord.setReceivedQuantity(quantity);
		recRecord.setOccurTime(new Date());
		recRecord.setOperator(oper);
		recRecord.setDescription(description);
		recRecord.setWorker(worker);
//		this.receivedRecords.add(recRecord);
		this.setOperBy(oper);
		this.setOperDate(new Date());
		return recRecord;

	}

	/**
	 * 增加收货日志
	 * @param location    收货库位
	 * @param itemKey     商品属性
	 * @param quantity    收取数量(基本单位数量)
	 * @param packageUnit 收货包装
	 * @param description 备注
	 * @param LP 托盘
	 */
	private ReceivedRecord addReceivedRecord(Location location, ItemKey itemKey,
			double quantity, PackageUnit packageUnit, Stock stock,String barCode,double weight,double volume,Date receiveDate, String description,
			ReceivedDoc receivedDoc, Worker worker, String qualityCode) {
		ReceivedRecord recRecord = EntityFactory.getEntity(ReceivedRecord.class);
		recRecord.setAsn(this.asn);
		recRecord.setAsnDetail(this);
		recRecord.setItemKey(itemKey);
		if(stock!=null){
			recRecord.setSrcLPCode(stock.getLP());
			recRecord.setSrcLP(stock);
		}
		recRecord.setLocation(location);
		recRecord.setPackageUnit(packageUnit);
		recRecord.setReceiveDate(receiveDate);
		recRecord.setReceivedQuantityMU(quantity);
		recRecord.setBarCode(barCode);
		recRecord.setWeight(weight);
		recRecord.setVolume(volume);
		recRecord.setReceivedQuantity(quantity);
//		if (packageUnit.getPrecision() == 0) {
//			recRecord.setReceivedQuantity(Math.ceil(quantity/packageUnit.getConvertFigure()));
//		} else {
//			recRecord.setReceivedQuantity(DoubleUtils.formatByPrecision(
//					quantity/packageUnit.getConvertFigure(), packageUnit.getPrecision()));
//		}
		recRecord.setOccurTime(new Date());
		recRecord.setOperator(UserHolder.getUser() == null ? "admin" : UserHolder.getUser().getLoginName());
		recRecord.setDescription(description);
		recRecord.setReceivedDoc(receivedDoc);
		recRecord.setWorker(worker);
		recRecord.setQualityCode(qualityCode);
		this.setOperBy(recRecord.getOperator());
		this.setOperDate(new Date());
//		this.getAsn().getReceivedRecords().add(recRecord);
		this.receivedRecords.add(recRecord);
		return recRecord;

	}

	public void addReceivedQuantity(double quantity) {
		this.receivedQuantity += quantity;
		this.asn.addReceivedQuantity(quantity);
	}

	public void receiveBack(ReceivedRecord receivedRecord, MoveDoc moveDoc) {
		double backQty = receivedRecord.getReceivedQuantityMU() - receivedRecord.getQualityQty();
		receivedRecord.receiveBack(backQty);
		if (receivedRecord.getReceivedQuantityMU() == 0) {
			this.receivedRecords.remove(receivedRecord);
		}
		
		this.receivedQuantity -= backQty;
		this.asn.receiveBack(backQty, moveDoc);
	}
	
	public Map<Integer,String> getLotInfoValue(){
		Map<Integer,String> lotInfoValue = new HashMap<Integer, String>();
		Map<Integer,String> lotInfo = this.lotInfo.getLotInfoMap();
		Map<Integer,Boolean> lotRule = item.getLotRuleMap();
		for(int i = 1; i <= 18; i++){
			if(lotRule.get(i)){
				lotInfoValue.put(i, lotInfo.get(i));
			}
		}
		return lotInfoValue;
	}

	public double getUnReceivedQuantity() {
		return this.expectedQtyOfMasterUnit - this.receivedQuantity;
	}

}
