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

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

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

import com.dev.swms.server.model.base.ItemKey;
import com.dev.swms.server.model.base.Location;
import com.dev.swms.server.model.base.LocationType;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.swms.server.model.base.SignFile;
import com.dev.swms.server.model.base.WarehouseArea;
import com.dev.swms.server.utils.DoubleUtils;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.model.VersionalEntity;

public class Inventory extends VersionalEntity {
	private static final long serialVersionUID = 3811918523040436872L;
	public static final String STATUS_QUALITY = "质检";
	public static final String STATUS_BAD = "报废";
	public static final String STATUS_VALID = "";
	public static final String STATUS_INVALID = "不可用";
	public static final String STATUS_FAILED = "质检不合格";
	public static final String COUNT_ADJUST = "盘点差异调整";
	public static final String COMPANY_TRANS_OUT = "货权转出";
	public static final String COMPANY_TRANS_IN = "货权转入";
	
	/** 所属库区 */
	private WarehouseArea zone;
	/** 所属库位 */
	private Location location;
	/** 所属具体商品库存 */
	private ItemKey itemKey;
	/** 所属具体商品库存 */
	private ItemKeyInventory itemKeyInventory;
	/** 库存数量(包装数量) */
	private double quantity;
	/** 已分配数量(基本单位数量) */
	private double queuedQuantity;
	/** 包装单位 */
	private PackageUnit masterPackUnit;
	/** 基本单位数量*/
	private double qtyOfMasterPack;
	/** CA系数*/
	private Double caCoefficient=0D;
	/** 包装单位 */
	private PackageUnit packageUnit;
	/** 托盘号 */
	private Stock LP;
	/** 锁定状态 */
	private String status;
	/** 存货日期 **/
	private Date storageDate;
	/** SOI **/
	private String SOI;
	/**条形码*/
	private String barCode;//线边=XB
	/**重量*/
	private double weight;
	/**体积*/
	private double volume;
	/** 是否贴标 **/
	private boolean Labeling;
	
	private Set<SignFile> files = new HashSet<SignFile>(); // 附件清单
	
	/** 是否锁定 **/
	private boolean beLock;
	
	/** 是否不良品 **/
	private boolean beReject;
	
	/**制造库位*/
	private Location zzkw;
	
	
	public Location getZzkw() {
		return zzkw;
	}

	public void setZzkw(Location zzkw) {
		this.zzkw = zzkw;
	}
	public ItemKey getItemKey() {
		return itemKey;
	}

	public void setItemKey(ItemKey itemKey) {
		this.itemKey = itemKey;
	}

	public WarehouseArea getZone() {
		return zone;
	}

	public void setZone(WarehouseArea zone) {
		this.zone = zone;
	}

	public boolean isBeLock() {
		return beLock;
	}

	public void setBeLock(boolean beLock) {
		this.beLock = beLock;
	}

	public boolean isBeReject() {
		return beReject;
	}

	public void setBeReject(boolean beReject) {
		this.beReject = beReject;
	}

	public Set<SignFile> getFiles() {
		return files;
	}

	public void setFiles(Set<SignFile> files) {
		this.files = files;
	}

	public boolean isLabeling() {
		return Labeling;
	}

	public void setLabeling(boolean labeling) {
		Labeling = labeling;
	}

	public String getBarCode() {
		return barCode;
	}

	public void setBarCode(String barCode) {
		this.barCode = barCode;
	}

	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 Double getCaCoefficient() {
		return caCoefficient;
	}

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

	@Override
	public boolean equals(final Object other) {
		if (!(other instanceof Inventory))
			return false;
		Inventory castOther = (Inventory) other;
		return new EqualsBuilder().append(location, castOther.location).append(
				itemKeyInventory, castOther.itemKeyInventory).append(
				packageUnit, castOther.packageUnit).append(LP, castOther.LP)
				.append(status, castOther.status).append(storageDate,
						castOther.storageDate).append(SOI, castOther.SOI)
				.isEquals();
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(location).append(itemKeyInventory)
				.append(packageUnit).append(LP).append(status).append(
						storageDate).append(SOI).toHashCode();
	}

	public Inventory(){
		
	}
	
	public Date getStorageDate() {
		return storageDate;
	}
	public void setStorageDate(Date storageDate) {
		this.storageDate = storageDate;
	}
	public String getSOI() {
		return SOI;
	}
	public void setSOI(String soi) {
		SOI = soi;
	}
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}
	public Stock getLP() {
		return LP;
	}
	public void setLP(Stock lp) {
		LP = lp;
	}
	public ItemKeyInventory getItemKeyInventory() {
		return itemKeyInventory;
	}
	public void setItemKeyInventory(ItemKeyInventory itemKeyInventory) {
		this.itemKeyInventory = itemKeyInventory;
	}
	public Location getLocation() {
		return location;
	}
	public void setLocation(Location location) {
		this.location = location;
	}
	public PackageUnit getPackageUnit() {
		return packageUnit;
	}
	public void setPackageUnit(PackageUnit packageUnit) {
		this.packageUnit = packageUnit;
	}
	public double getQuantity() {
		return quantity;
	}
	public void setQuantity(double quantity) {
		this.quantity = quantity;
	}
	public double getQueuedQuantity() {
		return queuedQuantity;
	}
	public void setQueuedQuantity(double queuedQuantity) {
		this.queuedQuantity = queuedQuantity;
	}
	public PackageUnit getMasterPackUnit() {
		return masterPackUnit;
	}
	public void setMasterPackUnit(PackageUnit masterPackUnit) {
		this.masterPackUnit = masterPackUnit;
	}
	public double getQtyOfMasterPack() {
		return qtyOfMasterPack;
	}
	public void setQtyOfMasterPack(double qtyOfMasterPack) {
		this.qtyOfMasterPack = qtyOfMasterPack;
	}
	
	/**
	 * 根据基本单位数量刷新包装数量
	 */
	private void refreshPackQty() {
		this.quantity=this.qtyOfMasterPack;
//		if (this.packageUnit.getPrecision() == 0) {
//			//向上取整，得到整包装数量
//			this.quantity = Math.ceil(this.qtyOfMasterPack / this.packageUnit.getConvertFigure());
//		} else {
//			//根据包装精度计算包装数量
//			this.quantity = DoubleUtils.formatByPrecision(this.qtyOfMasterPack / this.packageUnit.getConvertFigure(), 
//					this.packageUnit.getPrecision());
//		}
	}

	/**
	 * 增加商品库存数量
	 * @param quantity 待增加的商品数量(基本单位数量)
	 */
	public void add(double quantity,double weight,double volume) {
		this.qtyOfMasterPack += quantity;
		this.weight += weight;
		this.volume += volume;
//		if (this.LP != null) {
//			this.LP.addInventoryQty(quantity);
//			if (!this.LP.getLocation().equals(this.getLocation())) {
//				this.LP.setLocation(this.getLocation());
//			}
//		}
//		if (this.getLocation().getType().equals(LocationType.STORAGE)||this.getLocation().getType().equals(LocationType.TRANSIT)) {
//			this.getLocation().setStatus(Location.STORE);
//		}
//		if (this.getLocation().getInventories() == null) {
//			this.getLocation().setInventories(new HashSet<Inventory>());
//		}
//		this.getLocation().getInventories().add(this);
//		this.getLocation().setCurrentItem(this.getItemKeyInventory().getItemKey().getItem().getId());
//		this.getLocation().setCurrentLot(this.getItemKeyInventory().getItemKey().getId());

		refreshPackQty();
	}

	/**
	 * 减少库存可用数量
	 * @param quantity 待减少的数量（基本单位数量）
	 */
	public void remove(double quantity,double weight,double volume) {
//		if (DoubleUtils.compareByPrecision(this.qtyOfMasterPack - quantity, 
//				this.queuedQuantity, this.packageUnit.getPrecision())<0) {
		if ((this.qtyOfMasterPack - quantity) < this.queuedQuantity) {
			throw new BusinessException(this.itemKey.getItem().getCode()+"库存不足");
		}
		this.qtyOfMasterPack -= quantity;
		this.weight -= weight;
		this.volume -= volume;
//		if (this.LP != null) {
//			this.LP.removeInventoryQty(quantity);
//		}
//		if (this.getLocation().getType().equals(LocationType.STORAGE)||this.getLocation().getType().equals(LocationType.TRANSIT)) {
//			this.getLocation().setStatus(Location.PICK);
//		}
//		this.getLocation().setCurrentItem(this.getItemKey().getItem().getId());
//		this.getLocation().setCurrentLot(this.getItemKey().getId());

		refreshPackQty();
	}
	
	/**
	 * 库存调整－根据传入的参数直接修改库存数量
	 * @param quantity 调整后数量（基本单位数量）
	 */
	public void adjust(double quantity) {
		if (DoubleUtils.compareByPrecision(this.queuedQuantity, 
				quantity, this.packageUnit.getPrecision())>0) {
			//if (this.queuedQuantity>quantity) {
			throw new BusinessException("inventory.quantity.insufficient");
		}
		if (this.LP != null) {
			this.LP.removeInventoryQty(this.qtyOfMasterPack-quantity);
		}
		this.qtyOfMasterPack = quantity;
		this.getLocation().setCurrentItem(this.getItemKeyInventory().getItemKey().getItem().getId());
		this.getLocation().setCurrentLot(this.getItemKeyInventory().getItemKey().getId());

		refreshPackQty();
	}
	
	/**
	 * 获取当前库存的可用数量
	 * @return 可用库存数量(基本单位数量)
	 */
	public double getAvaliableQuantity() {
		return DoubleUtils.formatByPrecision(this.qtyOfMasterPack-this.queuedQuantity, 
				1);
	}
	
	/**
	 * 库存分配－只能对可用库存进行分配
	 * @param quantity 待分配数量(基本单位数量)
	 */
	public void allocate(double quantity, Location location, Stock LP) {
		if (DoubleUtils.compareByPrecision(this.queuedQuantity+quantity, 
				this.qtyOfMasterPack, 1)>0) {
			//if ((this.queuedQuantity+quantity) > this.qtyOfMasterPack) {
			throw new BusinessException("inventory.quantity.insufficient");
		}
		this.queuedQuantity += quantity;
		
		if (location != null && LocationType.STORAGE.equals(location.getType())) {
			double allocatePackQty = quantity;//this.getPackageUnit().getConvertFigure();
//			if (this.getPackageUnit().getPrecision() == 0) {
				allocatePackQty = Math.ceil(allocatePackQty);
//			} else {
//				allocatePackQty = DoubleUtils.formatByPrecision(allocatePackQty, this.getPackageUnit().getPrecision());
//			}
//			location.allocate(this.getItemKeyInventory().getItemKey(), 
//						allocatePackQty, this.getPackageUnit(), LP);
		}
	}
	
	/**
	 * 取消分配库存－不能取消超过已分配数量
	 * @param quantity 待取消分配数量(基本单位数量)
	 */
	public void unallocate(double quantity, Location location, Stock LP) {
		if (DoubleUtils.compareByPrecision(this.queuedQuantity, 
				quantity, 1)<0) {
			//if (this.queuedQuantity < quantity) {
			System.out.println("  "+this.getId()+"  "+this.queuedQuantity+" 数量  "+quantity);
			
			throw new BusinessException("inventory.quantity.insufficient");
		}
		this.queuedQuantity -= quantity;
		
		if (location != null && LocationType.STORAGE.equals(location.getType())) {
			double allocatePackQty = quantity;///this.getPackageUnit().getConvertFigure();
//			if (this.getPackageUnit().getPrecision() == 0) {
				allocatePackQty = Math.ceil(allocatePackQty);
//			} else {
//				allocatePackQty = DoubleUtils.formatByPrecision(allocatePackQty, this.getPackageUnit().getPrecision());
//			}
//			location.unAllocate(allocatePackQty, this.getPackageUnit(), LP);
		}
	}

	/**
	 * 判断库存是否被锁定
	 * @return true-不可用 false-可用
	 */
	public boolean isLocked() {
		return !StringUtils.isEmpty(this.status);
	}

	/**
	 * 锁定库存，设置库存状态为不可用
	 *
	 */
	public void lock(String status) {
		if (StringUtils.isEmpty(this.status)) {
			this.setStatus(status);
		}
	}
	
	/**
	 * 解锁库存，设置库存状态为可用
	 *
	 */
	public void unlock() {
		if (!StringUtils.isEmpty(this.status)) {
			this.setStatus(Inventory.STATUS_VALID);
		}
	}
	
	/**
	 * 移除和附件的关联关系
	 * 
	 * @author  dev
	 */
	public void removeFiles(SignFile signFile) {
		this.getFiles().remove(signFile);
	}

}
