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

import java.text.SimpleDateFormat;
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.base.ItemKey;
import com.dev.swms.server.model.base.Location;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.swms.server.model.base.Warehouse;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.model.Entity;
import com.dev.energy.server.model.EntityFactory;

public class ItemKeyInventory extends Entity {
	private static final long serialVersionUID = 106811359477944143L;
	/** 仓库 */
	private Warehouse warehouse;
	/** 具体商品 */
	private ItemKey itemKey;
	/** 包含库存 */
	private Set<Inventory> inventories = new HashSet<Inventory>();
	
	public ItemKeyInventory(){
		
	}
	
	public boolean equals(final Object other) {
		if (!(other instanceof ItemKeyInventory))
			return false;
		ItemKeyInventory castOther = (ItemKeyInventory) other;
		return new EqualsBuilder().append(warehouse, castOther.getWarehouse())
				.append(itemKey, castOther.getItemKey()).isEquals();
	}
	public int hashCode() {
		return new HashCodeBuilder().append(warehouse).append(itemKey)
				.toHashCode();
	}
	
	public ItemKey getItemKey() {
		return itemKey;
	}
	public void setItemKey(ItemKey itemKey) {
		this.itemKey = itemKey;
	}
	public Warehouse getWarehouse() {
		return warehouse;
	}
	public void setWarehouse(Warehouse warehouse) {
		this.warehouse = warehouse;
	}	
	public Set<Inventory> getInventories() {
		return inventories;
	}
	public void setInventories(Set<Inventory> inventories) {
		this.inventories = inventories;
	}
	
	/**
	 * 检查商品库存是否存在，如不存在则返回null
	 * @param location 存货库位
	 * @param packageUnit 包装单位
	 * @return null－未找到；inventory－找到
	 */
	public Inventory getInventory(Location location, PackageUnit packageUnit, Stock LP,String barCode, String status, 
			Date storageDate, String soi) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		if(soi==null){
			soi="";
		}
		for (Inventory inventory : this.inventories) {
			if (inventory.getLocation().getId().equals(location.getId()) 
//					&& inventory.getPackageUnit().getId().equals(packageUnit.getId()) 
				) {
				return inventory;
			}
		}
		return null;
	}
	
	public Inventory getInventoryWithNew(Location location, PackageUnit packageUnit, 
			Stock LP,String barCode,String status, Date storageDate, String soi,Boolean lock,Boolean reject) {
		if (LP != null) {
			//放置的托盘数不能超过承载类型限制
			if (location.getStowage()!=null&&location.getStowage().getLpLimit()>0 && location.getTotalLP()==location.getStowage().getLpLimit()) {
				boolean isSameLp = false;
				for (Inventory inv : location.getInventories()) {
					if (inv.getLP()!=null && inv.getLP().getId().equals(LP.getId())) {
						isSameLp = true;
						break;
					}
				}
				if (!isSameLp) {
					throw new BusinessException("location.stock.full");
				}
			}
		}
		
		Inventory dbInv = getInventory(location, packageUnit, LP, barCode, status, storageDate, soi);
		if (dbInv == null) {
			dbInv = new Inventory();//EntityFactory.getEntity(Inventory.class);
			dbInv.setLocation(location);
			dbInv.setItemKeyInventory(this);
			location.setCurrentItem(this.getItemKey().getItem().getId());
			location.setCurrentLot(this.getItemKey().getId());
			dbInv.setPackageUnit(packageUnit);
			dbInv.setCaCoefficient(this.getItemKey().getItem().getCAcoefficient()==null?0:this.getItemKey().getItem().getCAcoefficient());
			dbInv.setLP(LP);
			dbInv.setStatus(status);
			dbInv.setStorageDate(storageDate);
			dbInv.setSOI(soi == null ? "" : soi);
			dbInv.setMasterPackUnit(this.getItemKey().getItem().getMinPackageUnit());
			dbInv.setBeLock(lock);
			dbInv.setBeReject(reject);
			this.inventories.add(dbInv);
		}
		
		return dbInv;
	}
	
	public Inventory isInventoryNew(Location location, PackageUnit packageUnit, 
			Stock LP,String barCode,String status, Date storageDate, String soi,Boolean lock,Boolean reject) {
		Inventory dbInv = getInventory(location, packageUnit, LP, barCode, status, storageDate, soi);
		if (dbInv != null) {
			return dbInv;
		}else{
			return null;
		}
		
		
	}
	
	/**
	 * 检查商品库存是否存在，如果不存在则抛出异常
	 * @param location 存货库位
	 * @param packageUnit 包装单位
	 * @return 返回找到的inventory或抛出BusinessException
	 */
	public Inventory getInventoryWithException(Location location, 
			PackageUnit packageUnit, Stock LP, String barCode, String status, Date storageDate, String soi) {
		Inventory dbInv = getInventory(location, packageUnit, LP, barCode,status, storageDate, soi);
		if (dbInv == null) {
			throw new BusinessException("inventory.not.found");
		}
		return dbInv;
	}
	
	/**
	 * 库存调整---增加库存
	 * @param location 调整库位
	 * @param quantity 待增加数量（基本单位数量）
	 * @param packageUnit 商品包装
	 * @return 调整后的库存Inventory
	 */
	public Inventory adjustInventoryAdd(Location location, double quantity, PackageUnit packageUnit, 
			Stock LP, String barCode,double weight,double volume,String status, Date storageDate, String soi,Boolean lock,Boolean reject) {
		Inventory inventory = getInventoryWithNew(location, packageUnit, LP, barCode, status, storageDate, soi,lock,reject);
		inventory.add(quantity,weight,volume);
		if (inventory.isNew()) {
			this.getInventories().add(inventory);
		} else {
			if (inventory.getQtyOfMasterPack() == 0 && inventory.getQueuedQuantity() == 0) {
				this.getInventories().remove(inventory);
			}
		}
		return inventory;
	}
	
	/**
	 * 库存调整－减少库存
	 * @param location 调整库位
	 * @param quantity 调整数量（基本单位数量）
	 * @param packageUnit 库存包装
	 * @return 返回调整后的inventory或抛出BusinessException
	 */
	public Inventory adjustInventoryRemove(Location location, double quantity, 
			PackageUnit packageUnit, Stock LP, String barCode,double weight,double volume,String status, Date storageDate, String soi) {
		Inventory inventory = getInventoryWithException(location, packageUnit, LP, barCode,status, storageDate, soi);
		inventory.remove(quantity,weight,volume);
		if (inventory.getQtyOfMasterPack() == 0 && inventory.getQueuedQuantity() == 0) {
			this.getInventories().remove(inventory);
		}
		return inventory;
	}
	
	/**
	 * 库存调整---数量替换
	 * @param inventory 待调整库存
	 * @param quantity 调整后数量（基本单位数量）
	 */
	public void adjustInventoryUpdate(Inventory inventory, double quantity) {
		inventory.adjust(quantity);
		if (inventory.getQtyOfMasterPack() == 0 && inventory.getQueuedQuantity() == 0) {
			this.getInventories().remove(inventory);
		}
	}
	
	/**
	 * 库内移位---将指定库存的可用数量移到指定库位
	 * @param srcInventory 待移位库存
	 * @param destLocation 目标库位
	 * @param quantity 移位数量（基本单位数量）
	 * @return 目标库位inventory
	 */
	public Inventory moveInventory(Inventory srcInventory, Location destLocation, Stock destLP, String barCode,
			double quantity,double weight,double volume) {
		removeInventory(srcInventory, quantity,weight,volume);
		Inventory destInventory = getInventoryWithNew(destLocation, srcInventory.getPackageUnit(), 
				destLP,barCode, srcInventory.getStatus(), srcInventory.getStorageDate(), srcInventory.getSOI(),srcInventory.isBeLock(),srcInventory.isBeReject());
		destInventory.add(quantity,weight,volume);
		this.getInventories().add(destInventory);
		
		return destInventory;
	}
	
	/**
	 * 减少库存数
	 * @param inventory 待减少库存
	 * @param quantity 减少数量（基本单位数量）
	 */
	public void removeInventory(Inventory inventory, double quantity,double weight,double volume) {
		inventory.remove(quantity,weight,volume);
		if (inventory.getQtyOfMasterPack() == 0 && inventory.getQueuedQuantity() == 0) {
			this.getInventories().remove(inventory);
		}
	}
	
	/**
	 * 发货确认
	 * @param location 库位
	 * @param quantity 发货数量（基本单位数量）
	 * @param packageUnit 商品包装 
	 */
	public Inventory ship(Location location, double quantity, PackageUnit packageUnit, Stock LP, String barCode, double weight, double volume,
			String status, Date storageDate, String soi) {
		Inventory inventory = getInventoryWithException(location, packageUnit, LP, barCode,status, storageDate, soi);
		inventory.remove(quantity,weight,volume);
		if (inventory.getQtyOfMasterPack() == 0 && inventory.getQueuedQuantity() == 0) {
			this.getInventories().remove(inventory);
		}
		return inventory;
	}

	public List<Inventory> getInventories(Location location, Stock LP, Date storageDate, String soi,
			String status) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		List<Inventory> results = new ArrayList<Inventory>();
		if(soi==null){
			soi="";
		}
		for (Inventory inventory : this.inventories) {
			if (inventory.getLocation().getId().equals(location.getId()) 
					&& ((LP == null && inventory.getLP() == null) || (inventory.getLP() != null && LP != null && inventory.getLP().getId().equals(LP.getId())))
					&& sdf.format(inventory.getStorageDate()).equals(sdf.format(storageDate)) 
					&& soi.equals(inventory.getSOI())
					&& inventory.getStatus().equals(status)) {
				results.add(inventory);
			}
		}
		return results;
	}

	public List<Inventory> getInventories(Location location, Stock LP, String status) {
		List<Inventory> results = new ArrayList<Inventory>();
		for (Inventory inventory : this.inventories) {
			if (inventory.getLocation().getId().equals(location.getId()) 
					&& ((LP == null && inventory.getLP() == null) 
							|| (inventory.getLP() != null && LP != null && inventory.getLP().getId().equals(LP.getId())))
					&& inventory.getStatus().equals(status)) {
				results.add(inventory);
			}
		}
		return results;
	}

}
