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

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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

import com.dev.swms.server.model.abstractEntity.AbstractMoveDoc;
import com.dev.swms.server.model.abstractEntity.AbstractMoveDocDetail;
import com.dev.swms.server.model.base.BillType;
import com.dev.swms.server.model.base.ItemKey;
import com.dev.swms.server.model.base.Structure;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.swms.server.model.base.Warehouse;
import com.dev.swms.server.model.base.Worker;
import com.dev.swms.server.model.inventory.Inventory;
import com.dev.swms.server.model.inventory.Task;
import com.dev.swms.server.model.shipping.PickTicketStatus;
import com.dev.energy.server.web.security.UserHolder;

public class MoveDoc extends AbstractMoveDoc {
	private static final long serialVersionUID = -4584322735023407478L;
	/** 定义单据类型 */
	public static final String MV_ASN = "MV_ASN";
	public static final String MV_MOVE = "MV_MOVE";
	public static final String MV_PROCESS = "MV_PROCESS";
	public static final String MV_SUPPLY = "MV_SUPPLY";
	
	/** 仓库 */
	private Warehouse warehouse;
	/** 货主 */
	private Structure company;
	/** 单据编号 */
	private String code;
	/** 单据类型 */
	private BillType billType;
	/**收货单类型**/
	private BillType asnType;
	/** 创建日期 */
	private Date createDate;
	/** 移位计划状态 */
	private String status;
	/** 相关单号 */
	private String relateBillCode;
	/** 计划数量 */
	private double planQuantity;
	/** 分配数量 */
	private double allocateQuantity;
	/** 移位数量 */
	private double moveQuantity;
	/** 最后更新用户ID */
	private Long userID;
	/** 最后更新用户名 */
	private String userName;
	/** 最后更新时间 */
	private Date updateTime;
	/** 包含移位计划明细 */
	private Set<MoveDocDetail> details = new HashSet<MoveDocDetail>();
	/** 单据打印标志 */
	private int printCount = 0;
	
	private String shiftMethod;//位移方式
	
	/** 作业人员 */
	private Worker worker1;
	/** 作业人员 */
	private Worker worker2;
	/** 作业人员 */
	private Worker worker3;
	/** 作业人员 */
	private Worker worker4;
	
	private String relatedBill1;//客户订单号
	
	private String description;//备注
	
	
	

	public String getRelatedBill1() {
		return relatedBill1;
	}

	public void setRelatedBill1(String relatedBill1) {
		this.relatedBill1 = relatedBill1;
	}

	public String getDescription() {
		return description;
	}

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

	public Worker getWorker1() {
		return worker1;
	}

	public void setWorker1(Worker worker1) {
		this.worker1 = worker1;
	}

	public Worker getWorker2() {
		return worker2;
	}

	public void setWorker2(Worker worker2) {
		this.worker2 = worker2;
	}

	public Worker getWorker3() {
		return worker3;
	}

	public void setWorker3(Worker worker3) {
		this.worker3 = worker3;
	}

	public Worker getWorker4() {
		return worker4;
	}

	public void setWorker4(Worker worker4) {
		this.worker4 = worker4;
	}

	public String getShiftMethod() {
		return shiftMethod;
	}

	public void setShiftMethod(String shiftMethod) {
		this.shiftMethod = shiftMethod;
	}

	public int getPrintCount() {
		return printCount;
	}

	public void setPrintCount(int printCount) {
		this.printCount = printCount;
	}

	public Structure getCompany() {
		return company;
	}

	public void setCompany(Structure company) {
		this.company = company;
	}

	public double getAllocateQuantity() {
		return allocateQuantity;
	}

	public void setAllocateQuantity(double allocateQuantity) {
		this.allocateQuantity = allocateQuantity;
	}

	public BillType getBillType() {
		return billType;
	}

	public void setBillType(BillType billType) {
		this.billType = billType;
	}

	public BillType getAsnType() {
		return asnType;
	}

	public void setAsnType(BillType asnType) {
		this.asnType = asnType;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public Set<MoveDocDetail> getDetails() {
		return details;
	}

	public void setDetails(Set<MoveDocDetail> details) {
		this.details = details;
	}

	public double getMoveQuantity() {
		return moveQuantity;
	}

	public void setMoveQuantity(double moveQuantity) {
		this.moveQuantity = moveQuantity;
	}

	public double getPlanQuantity() {
		return planQuantity;
	}

	public void setPlanQuantity(double planQuantity) {
		this.planQuantity = planQuantity;
	}

	public String getRelateBillCode() {
		return relateBillCode;
	}

	public void setRelateBillCode(String relateBillCode) {
		this.relateBillCode = relateBillCode;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Date getUpdateTime() {
		return updateTime;
	}

	public void setUpdateTime(Date updateTime) {
		this.updateTime = updateTime;
	}

	public Long getUserID() {
		return userID;
	}

	public void setUserID(Long userID) {
		this.userID = userID;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Warehouse getWarehouse() {
		return warehouse;
	}

	public void setWarehouse(Warehouse warehouse) {
		this.warehouse = warehouse;
	}

	public void setUserTracking() {
		this.setUserID(UserHolder.getUser().getId());
		this.setUserName(UserHolder.getUser().getName());
		this.setUpdateTime(new Date());
	}

	public boolean cancel() {
		 if (MoveDocStatus.OPEN.equals(this.status)) {
			 this.setStatus(MoveDocStatus.CANCEL);
			 return true;
		 }
		return false;
	}

	public MoveDocDetail getDetailByConditionForProcess(ItemKey itemKey,
			String srcLP, String soi, Date storageDate, PackageUnit packageUnit) {
		if (this.getDetails() == null || this.getDetails().size() == 0) {
			return null;
		}
		for (MoveDocDetail detail : this.getDetails()) {
			if (detail.getItemKey().getId().equals(itemKey.getId())
					&& ((detail.getSrcLP() == null && srcLP == null) || (detail.getSrcLP() != null && detail.getSrcLP().equals(srcLP)))
					&& detail.getPackageUnit().getId().equals(packageUnit.getId())) {
				return detail;
			}
		}
		return null;
	}

	public void allocate(Double quantity) {
		this.allocateQuantity += quantity;
		if ((MoveDocStatus.OPEN.equals(this.getStatus()) 
				|| MoveDocStatus.ACTIVE.equals(this.getStatus()))
				&& this.allocateQuantity > 0) {
			this.setStatus(MoveDocStatus.ALLOCATE);
		}
	}

	public void unallocate(Double quantity) {
		this.allocateQuantity -= quantity;
		if (this.allocateQuantity == 0
				&& MoveDocStatus.ALLOCATE.equals(this.getStatus())) {
			this.setStatus(MoveDocStatus.OPEN);
		}
	}

	public void moveTo(Double moveQuantity) {
		this.moveQuantity += moveQuantity;
		if (MoveDocStatus.ACTIVE.equals(this.getStatus())
				|| MoveDocStatus.ALLOCATE.equals(this.getStatus())
				|| MoveDocStatus.MOVE.equals(this.getStatus())) {
			if (this.moveQuantity == this.planQuantity) {
				this.setStatus(MoveDocStatus.CLOSE);
			} else {
				this.setStatus(MoveDocStatus.MOVE);
			}
		}
	}

	public double getAllocatedQuantity() {
		return allocateQuantity;
	}

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

	public double getOrderQuantity() {
		return planQuantity;
	}

	public void setOrderQuantity(double orderQuantity) {
		this.planQuantity = orderQuantity;
	}

	public double getPickedQuantity() {
		return moveQuantity;
	}

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

	public double getShippedQuantity() {
		return 0;
	}

	public void setShippedQuantity(double shippedQuantity) {
		
	}

	public List<AbstractMoveDocDetail> getAbstractMoveDocDetails() {
		List<AbstractMoveDocDetail> details = new ArrayList<AbstractMoveDocDetail>();
		for(MoveDocDetail detail :this.details){
			details.add(detail);
		}
        return details;
	}
	/**
	 * 对指定的移位单明细分配
	 * 只能对打开、已分配或部分发运状态的发货单做拣货分配
	 * @param moveDocDetail 待分配的移位单明细
	 * @param inventory 待分配的库存
	 * @param quantity 分配数量
	 */
	public Task allocate(String bhCode,AbstractMoveDocDetail moveDocDetail, Inventory inventory, double quantity) {
		Task t=moveDocDetail.allocate(null,inventory, quantity);
		this.allocateQuantity += quantity;
		this.status = PickTicketStatus.ALLOCATE;
        setUserTracking();
        return t;
	}

	public void removeDetail(MoveDocDetail detail) {
		this.getDetails().remove(detail);
		this.planQuantity -= detail.getPlanQuantityOfMU();
	}

	public void add(double quantity) {
		this.planQuantity += quantity;
	}

	@Override
	public boolean equals(final Object other) {
		if (!(other instanceof MoveDoc))
			return false;
		MoveDoc castOther = (MoveDoc) other;
		return new EqualsBuilder().append(warehouse, castOther.warehouse)
				.append(company, castOther.company)
				.append(code, castOther.code).append(billType,
						castOther.billType).isEquals();
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(warehouse).append(company).append(
				code).append(billType).toHashCode();
	}

	@Override
	public void setApplyDoc(String code) {
	}

}
