package com.dev.swms.server.service.base.pojo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.dev.swms.client.ui.constant.CT_IV;
import com.dev.swms.client.ui.javabean.JB_IV;
import com.dev.swms.client.ui.javabean.JB_Location_IV;
import com.dev.swms.client.ui.javabean.JB_Location_IV_List;
import com.dev.swms.client.ui.javabean.JB_Location_Inventory;
import com.dev.swms.client.ui.javabean.JB_Location_RC_IV;
import com.dev.swms.client.ui.javabean.JB_Location_RC_IV_List;
import com.dev.swms.client.ui.javabean.JB_Zone_IV;
import com.dev.swms.server.model.base.Location;
import com.dev.swms.server.model.base.LocationType;
import com.dev.swms.server.model.base.ModelType;
import com.dev.swms.server.model.base.RackType;
import com.dev.swms.server.model.base.UserGroupWarehouse;
import com.dev.swms.server.model.base.Warehouse;
import com.dev.swms.server.model.base.WarehouseArea;
import com.dev.swms.server.model.inventory.Inventory;
import com.dev.swms.server.service.base.WarehouseManager;
import com.dev.swms.server.utils.DoubleUtils;
import com.dev.swms.server.web.filter.WarehouseHolder;
import com.dev.energy.client.ui.table.RowData;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.model.EntityFactory;
import com.dev.energy.server.model.security.Group;
import com.dev.energy.server.model.security.User;
import com.dev.energy.server.service.pojo.DefaultBaseManager;
import com.dev.energy.server.service.security.UserManager;
import com.dev.energy.server.util.LocalizedMessage;
import com.dev.energy.server.web.security.UserHolder;

@SuppressWarnings("unchecked")
public class DefaultWarehouseManager extends DefaultBaseManager implements
		WarehouseManager {
	protected final UserManager userManager;

	public DefaultWarehouseManager(UserManager userManager) {
		super();
		this.userManager = userManager;
	}

	public void deleteAll(List<Long> warehouseIds) {
		String errMsg = "";
		for (Long id : warehouseIds) {
			Warehouse warehouse = commonDao.load(Warehouse.class, id);
			if (warehouse.getLocations() == null
					|| warehouse.getLocations().size() == 0) {
				warehouse.setDisabled(true);
				errMsg+=warehouse.getCode()+" 仓库失效成功;";
			}
			else
				errMsg+=warehouse.getCode()+" 仓库失效失败;";
		}
		
		LocalizedMessage.addLocalizedMessage(errMsg);
	}

	/**
	 * 供登录页面调用
	 */
	public Warehouse getWarehouseByCode(String code) {
		Warehouse result = (Warehouse) commonDao.findByNamedQueryUniqueResult("getWarehouseByCode",
				new String[] { "code" }, new String[] { code });
		return result;
	}
	
	public Warehouse getWarehouseByLoginName(String loginName) {	
		User user = (User) commonDao.findByQueryUniqueResult("from User u where u.loginName = '"+loginName+"'",new String[] {}, new Long[] {});
	    if(userManager.isAdmin(user)){
	    	List result = commonDao.findByQuery("from Warehouse w where w.disabled = false");
			if (result.size() >= 1) {
				return (Warehouse) result.get(0);
			}
	    }
	    List result = commonDao.findByNamedQuery("getWarehouseByGroupID",
				new String[] {"loginName"}, new Object[] {loginName});
	    if (result.size() >= 1) {
			return (Warehouse) result.get(0);
		}
		return null;
	}

	public void invokeUsersToWarehouse(List<Long> userGroupIds, Long warehouseId) {
		UserGroupWarehouse userWarehouse = null;
		if (userGroupIds.size() == 0 || userGroupIds == null) {
			throw new BusinessException("user.id.isnull");
		}
		for (Long userGroupId : userGroupIds) {
			userWarehouse = getUserWarehouse(userGroupId, warehouseId);
			this.commonDao.store(userWarehouse);
		}
		LocalizedMessage.addMessage("invoke.userwarehouse.success",
				new String[] { String.valueOf(userGroupIds.size()),String.valueOf(warehouseId) });
	}

	public void revokeUsersToWarehouse(List<Long> userWarehouseIds,
			Long warehouseId) {
		Warehouse warehouse = commonDao.load(Warehouse.class,warehouseId);
		List<UserGroupWarehouse> userWarehouseList = commonDao.loadAll(UserGroupWarehouse.class, userWarehouseIds
				.toArray(new Long[0]));
		if(userWarehouseList == null || userWarehouseList.size()== 0){
			throw new BusinessException("warehouse.userwarehouse.isnull");
		}
		warehouse.getUserGroupWarehouses().removeAll(userWarehouseList);
		commonDao.store(warehouse);
		LocalizedMessage.addMessage("revoke.userwarehouse.success",
				new String[] { String.valueOf(userWarehouseIds.size()),
						String.valueOf(warehouseId) });
	}

	private UserGroupWarehouse getUserWarehouse(Long userGroupId, Long warehouseId) {
		UserGroupWarehouse userGroupWarehouse = (UserGroupWarehouse) commonDao
				.findByNamedQueryUniqueResult("getUserWarehouseByUniqueKey",
						new String[] { "userGroupId", "warehouseId" }, new Object[] {
						userGroupId, warehouseId });
		if (userGroupWarehouse == null) {
			Group userGroup = commonDao.load(Group.class, userGroupId);
			Warehouse warehouse = commonDao.load(Warehouse.class, warehouseId);
			return new UserGroupWarehouse(userGroup, warehouse, "");
		}
		return userGroupWarehouse;
	}

	public void storeWarehouse(Warehouse warehouse) {
		boolean newWarehouse = false;
		if (warehouse.isNew()) {
			newWarehouse = true;
		}
		warehouse.setReferenceModel(ModelType.origen);
		this.store(warehouse);
		
		if(newWarehouse){
			//自动创建虚拟库区
			WarehouseArea zone = EntityFactory.getEntity(WarehouseArea.class);
			zone.setWarehouse(warehouse);
			zone.setCode("VIRTUAL");
			zone.setName("虚拟库区");
			zone.setDescription("");
			zone.setDisabled(false);
			
			this.commonDao.store(zone);
			
			//为虚拟库区创建盘点库位
			Location location = EntityFactory.getEntity(Location.class);
			location.setWarehouse(warehouse);
			location.setZone(zone);
			location.setCode("COUNT");
			location.setType(LocationType.COUNT);
			location.setName("盘点调整");
			location.setRackType(RackType.NORMAL);
			
			this.commonDao.store(location);
		}
		
	}

	public void storeZone(WarehouseArea zone) {
       if(zone.isNew()){
    	   zone.setWarehouse(WarehouseHolder.getWarehouse());
       }
	   this.commonDao.store(zone);
	}
	
	public void storeZoneKams(WarehouseArea zone,String code) {
	       if(zone.isNew()){
	    	   zone.setWarehouse(WarehouseHolder.getWarehouse());
	       }
	       Location l=null;
		    if(code!=null&&!code.equals("")){
		       List<Location> ls=this.commonDao.findByQuery("from Location l where l.code='"+code+"' and l.type!='SHIP' ");
				if(ls.size()<=0){
					l=EntityFactory.getEntity(Location.class);
					l.setCode(code);
					l.setType(LocationType.STORAGE);
					l.setWarehouse(WarehouseHolder.getWarehouse());
					l.setZone(zone);
					this.commonDao.store(l);
				}else{
					l=ls.get(0);
				}
				zone.setHckw(l);
			}else{
				zone.setHckw(null);
			}
	       //库位
		   this.commonDao.store(zone);
//		   if(l!=null){
//			   //更改线边库存
//			   List<Inventory> invs =this.commonDao.findByQuery("from Inventory inv where inv.barCode='XB' and inv.zone.id="+zone.getId() +" and inv.location.id!="+l.getId());
//			   for(Inventory inv:invs){
//				   inv.setLocation(l);
//				   this.commonDao.store(inv);
//			   }
//		   }
		}


	public void deleteZoneAll(List<Long> zoneIds) {
		String errMsg = "";
		for (Long id : zoneIds) {
			WarehouseArea zone = commonDao.load(WarehouseArea.class, id);
			try {
				this.commonDao.delete(zone);
			} catch (Exception e) {
				zone.setDisabled(true);
			}
//			if (!zone.inUse()) {
//				zone.setDisabled(true);
//				errMsg+=zone.getCode()+" 库区失效成功;";
//				
//			}
//			else
//				errMsg+=zone.getCode()+" 库区失效失败;";
		
		}
//		LocalizedMessage.addLocalizedMessage(errMsg);
	}

	public void activeZone(List<Long> zoneIds) {
		for (Long id : zoneIds) {
			WarehouseArea zone = this.commonDao.load(WarehouseArea.class,id);
			zone.setDisabled(false);
		}
		
	}

	public void activeAll(List<Long> warehouseIds) {
		for (Long id : warehouseIds) {
			Warehouse warehouse = this.commonDao.load(Warehouse.class,id);
			warehouse.setDisabled(false);
		}
		
	}

	public Map getThisWarehouse(Map m) {
		Map map = new HashMap();
	    map.put("1",WarehouseHolder.getWarehouse().getShortName());
	    map.put("userId",UserHolder.getUser().getId());
	    map.put("userName",UserHolder.getUser().getName());
		return map;
	}
	
	@SuppressWarnings("unchecked")
	public List<Warehouse> getAvailableWarehousesByUserId(Long userId) {
		User user = commonDao.load(User.class,userId);
		if(userManager.isAdmin(user)){
	    	List<Warehouse> result = commonDao.findByQuery("select w from Warehouse w where w.disabled=false",
					new String[] {}, new Long[] {});	
	    	return result;
	    }
		Set<Warehouse> warehouses = new HashSet<Warehouse>();
		for(Group group : user.getGroups()){
			List<Warehouse> temp = commonDao.findByNamedQuery("getAvailableWarehouseByUserGroupId",
					new String[] { "userGroupId" }, new Long[] { group.getId()});
			if(temp != null && temp.size()!=0){
				warehouses.addAll(temp);
			}
		}
		List<Warehouse> results = new ArrayList<Warehouse>();
		results.addAll(warehouses);
		return results;
	}
	
	public Map getWareHousesForenergy(Map map){
		Map result = new HashMap();
		List<Warehouse> warehouses = getAvailableWarehousesByUserId(Long.parseLong(map.get("user.id").toString()));		
		List rowDatas = new ArrayList();
		for (Warehouse warehouse : warehouses) {
			RowData rowData = new RowData();
			rowData.addColumnValue(warehouse.getId());
			rowData.addColumnValue(warehouse.getName());
			rowDatas.add(rowData);
		}
		result.put("wareHouses.list",rowDatas);
		return result;
	}
	
	public Map init_WM_IV(Map params) {
		String hql = "SELECT new com.dev.swms.client.ui.javabean.JB_IV(" +
				"w.id , w.name," +
				"(SELECT avg(lc.usedRate/lc.stowage.fullRate) FROM Location lc " +
				"WHERE lc.type=:type AND lc.disabled=false AND lc.warehouse.id=w.id Group By lc.warehouse.id)" +
				",w.x_Pos,w.y_Pos,w.image_url) " +
				"FROM Warehouse w WHERE w.disabled=false Order By w.id";
		List<JB_IV> ivs = commonDao.findByQuery(hql , new String[]{"type"} , new Object[]{LocationType.STORAGE});
		Map<String ,List> result = new HashMap<String,List>();
		result.put(CT_IV.IV_RESULT , ivs);
		return result;
	}
   
	//update WM_IV
	
	public Map update_WM_IV(Map params) {
		Long wh_id = (Long)params.get(CT_IV.IV_WH_ID);
		Long wh_xPos = (Long)params.get(CT_IV.IV_WH_XPOS);
		Long wh_yPos = (Long)params.get(CT_IV.IV_WH_YPOS);
		Warehouse wh = commonDao.load(Warehouse.class,wh_id);
		wh.setX_Pos(wh_xPos.intValue());
		wh.setY_Pos(wh_yPos.intValue());
		commonDao.store(wh);
		Map result = new HashMap();
		//result.put(CT_IV.IV_WH_ID,wh.getId());
		return result;
		
	}
	
	public Map update_WM_ZIV(Map params){
		Long wh_zone_id = (Long)params.get(CT_IV.IV_ZONE_ID);
		Long wh_zone_xPos = (Long)params.get(CT_IV.IV_ZONE_XPOS);
		Long wh_zone_yPos = (Long)params.get(CT_IV.IV_ZONE_YPOS);
		WarehouseArea zone = commonDao.load(WarehouseArea.class,wh_zone_id);
		zone.setX_Pos(wh_zone_xPos.intValue());
		zone.setY_Pos(wh_zone_yPos.intValue());
		commonDao.store(zone);
		Map result = new HashMap();
		//result.put(CT_IV.IV_WH_ID,wh.getId());
		return result;
	}
    	
	
	public Map init_Zone_IV(Map params) {
		Long wh_id = (Long)params.get(CT_IV.IV_WH_ID);
		String hql = "SELECT new com.dev.swms.client.ui.javabean.JB_Zone_IV(" +
				"zone.id," +
				"zone.code," +
				"zone.name," +
				"(SELECT avg(lc.usedRate/lc.stowage.fullRate) FROM Location lc " +
				"WHERE lc.type=:type AND lc.disabled=false AND lc.zone.id=zone.id Group By lc.zone.id)," +
				"zone.x_Pos," +
				"zone.y_Pos ) " +
				"FROM WarehouseArea zone " +
				"WHERE zone.warehouse.id=:id " +
				"Order By zone.id";
		List<JB_Zone_IV> zivs = commonDao.findByQuery(hql , 
				new String[]{"type" , "id"} , new Object[]{LocationType.STORAGE , wh_id});
		Map<String ,List> result = new HashMap<String,List>();
		result.put(CT_IV.IV_RESULT , zivs);
		return result;
	}

	public Map init_Location_IV(Map params) {
		Long zone_id = (Long)params.get(CT_IV.IV_ZONE_ID);
		String hql = "SELECT new com.dev.swms.client.ui.javabean.JB_Location_IV(" +
				"lc.line,lc.aisle,avg(lc.usedRate/lc.stowage.fullRate)) " +
				"FROM Location lc " +
				"WHERE lc.type=:type AND lc.disabled=false AND lc.zone.id=:id AND lc.line > 0 AND lc.aisle > 0 " +
				"Group By lc.line,lc.aisle " +
				"Order By lc.line ASC,lc.aisle ASC ";
		List<JB_Location_IV> livs = commonDao.findByQuery(hql , 
				new String[]{"type" , "id"} , new Object[]{LocationType.STORAGE , zone_id});
		
		Map<String ,List> result = new HashMap<String,List>();
		List<JB_Location_IV_List> ivls = new ArrayList<JB_Location_IV_List>();
		for(int i = 1; i <= CT_IV.DEFAULT_LINE ; i++) {
			JB_Location_IV_List ivl = new JB_Location_IV_List();
			ivls.add(ivl);
			for(int j = 1 ; j <= CT_IV.DEFAULT_AISLE ; j++) {
				JB_Location_IV iv = queryIVByLineAndAisle( i , j ,livs);
				if(iv != null) {
					ivl.add(iv);
				}else{
					ivl.add(new JB_Location_IV(i,j,-1D));
				}
			}
		}
		result.put(CT_IV.IV_RESULT , ivls);
		return result;
	}
	
	public Map init_Location_RC_IV(Map params) {
		Long zone_id = (Long)params.get(CT_IV.IV_ZONE_ID);
		Integer aisle = (Integer)params.get(CT_IV.IV_AISLE);
		Integer line = (Integer)params.get(CT_IV.IV_LINE);
		
		String hql = "SELECT lc " +
				"FROM Location lc " +
				"WHERE lc.type=:type AND lc.disabled=false AND lc.zone.id=:id AND lc.aisle=:aisle AND lc.line=:line AND lc.row>0 AND lc.col>0 " +
				"Order By lc.row DESC , lc.col ASC";
		List<Location> lcs = commonDao.findByQuery(hql , 
				new String[]{"type" , "id" , "aisle" , "line"} , new Object[]{LocationType.STORAGE , zone_id , aisle , line});
		
		List<JB_Location_RC_IV> lrcivs = new ArrayList<JB_Location_RC_IV>();
		
		for(Location lc : lcs) {
			lrcivs.add(lc.construct_JB_Location());
		}
		
		List<JB_Location_RC_IV_List> lrcivls = new ArrayList<JB_Location_RC_IV_List>();
		for(int i = CT_IV.DEFAULT_ROW ; i >= 1 ; i--) {
			JB_Location_RC_IV_List lrcivl = new JB_Location_RC_IV_List();
			lrcivls.add(lrcivl);
			for(int j = 1 ; j <= CT_IV.DEFAULT_COL ; j++) {
				JB_Location_RC_IV iv = queryIVByRowAndCol( i , j ,lrcivs);
				if(iv != null) {
					lrcivl.add(iv);
				}else{
					lrcivl.add(new JB_Location_RC_IV(i,j,-1D));
				}
			}
		}
		
		Map<String ,List> result = new HashMap<String,List>();
		result.put(CT_IV.IV_RESULT , lrcivls);
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public Map init_Inventory_Data(Map params) {
		Long loc_id = (Long)params.get(CT_IV.IV_LOCATION_ID);
		String hql = "SELECT new com.dev.swms.client.ui.javabean.JB_Location_Inventory(" +
				"inventory.id," +
				"inventory.itemKeyInventory.itemKey.item.company.name," +
				"inventory.location.code," +
				"inventory.itemKeyInventory.itemKey.item.code," +
				"inventory.itemKeyInventory.itemKey.item.name," +
				"inventory.itemKeyInventory.itemKey.lot," +
				"inventory.packageUnit.unit," +
				"inventory.quantity," +
				"inventory.quantity*inventory.packageUnit.weight," +
				"inventory.quantity*inventory.packageUnit.volume," +
				"inventory.storageDate,lp.LP) " +
				"FROM Inventory inventory Left Join inventory.LP lp " +
				"WHERE inventory.location.id="+loc_id;
		List<JB_Location_Inventory> lis = commonDao.findByQuery(hql);
		
		//构造合计行记录
		double totalQuantity = 0D;
		double totalWeight = 0D;
		double totalVolume = 0D;
		int totalAges = 0;
		for(JB_Location_Inventory li : lis) {
			li.setQuantity(DoubleUtils.format2Fraction(li.getQuantity()));
			li.setWeight(DoubleUtils.format2Fraction(li.getWeight()));
			li.setVolume(DoubleUtils.format2Fraction(li.getVolume()));
			totalQuantity += li.getQuantity();
			totalWeight += li.getWeight();
			totalVolume += li.getVolume();
			totalAges += li.getAge();
		}
		if(lis.size() > 0 ) {
			JB_Location_Inventory l = new JB_Location_Inventory(0L," "," "," "," "," " +
					"","<font color='red' style='font-weight:bold;'>总计:</font>"
					,DoubleUtils.format2Fraction(totalQuantity) 
					,DoubleUtils.format2Fraction(totalWeight)
					,DoubleUtils.format2Fraction(totalVolume));
			l.setAge(totalAges);
			l.setLp(" ");
			lis.add(l);
		}
		
		Map<String ,List> result = new HashMap<String,List>();
		result.put(CT_IV.IV_RESULT , lis);
		return result;
	}
	
	private JB_Location_RC_IV queryIVByRowAndCol(int row,int col , List<JB_Location_RC_IV> lrcivs) {
		for(JB_Location_RC_IV lrciv : lrcivs) {
			if(lrciv.getRow() == row && lrciv.getCol() == col) {
				return lrciv;
			}
		}
		return null;
	}
	
	private JB_Location_IV queryIVByLineAndAisle( int line ,int aisle , List<JB_Location_IV> livs) {
		for(JB_Location_IV liv : livs) {
			if(liv.getLoc_line() == line && liv.getLoc_aisle() == aisle) {
				return liv;
			}
		}
		return null;
	}

}
