package cn.ibizlab.core.extensions.service;

import cn.ibizlab.core.extensions.domain.DeptMap;
import cn.ibizlab.core.extensions.domain.DeptNode;
import cn.ibizlab.core.extensions.domain.OrgMap;
import cn.ibizlab.core.extensions.domain.OrgNode;
import cn.ibizlab.core.extensions.mapping.IBZDept2NodeMapping;
import cn.ibizlab.core.extensions.mapping.IBZOrg2NodeMapping;
import cn.ibizlab.core.ou.domain.IBZDepartment;
import cn.ibizlab.core.ou.domain.IBZEmployee;
import cn.ibizlab.core.ou.domain.IBZOrganization;
import cn.ibizlab.core.ou.service.IIBZEmployeeService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class OUCoreService
{


	@Autowired
	@Lazy
	private OUModelService ouModelService;

	@Autowired
	@Lazy
	private IIBZEmployeeService iibzEmployeeService;


	public List<IBZEmployee> getEmpByOrg(String orgid)
	{
		if(StringUtils.isEmpty(orgid) || "nullorgid".equals(orgid))
			return new ArrayList<>();
		return iibzEmployeeService.list(new QueryWrapper<IBZEmployee>().eq("orgid",orgid).orderByAsc("showorder"));
	}

	public List<IBZEmployee> getEmpByDept(String deptid)
	{
		if(StringUtils.isEmpty(deptid) || "nulldeptid".equals(deptid))
			return new ArrayList<>();
		return iibzEmployeeService.list(new QueryWrapper<IBZEmployee>().eq("mdeptid",deptid).orderByAsc("showorder"));
	}

	public List<IBZEmployee> getSubEmpByOrg(String orgid)
	{
		if(StringUtils.isEmpty(orgid) || "nullorgid".equals(orgid))
			return new ArrayList<>();
		Map<String, OrgMap> store=ouModelService.getOrgModel();
		OrgMap orgmodel=this.getOrgModel(orgid);
		if(orgmodel.getSub().size()==store.size())
			return iibzEmployeeService.list();
		return iibzEmployeeService.list(new QueryWrapper<IBZEmployee>().in("orgid",orgmodel.getSub()));
	}

	public List<IBZEmployee> getSubEmpByDept(String deptid)
	{
		if(StringUtils.isEmpty(deptid) || "nulldeptid".equals(deptid))
			return new ArrayList<>();
		DeptMap deptmodel=this.getDeptModel(deptid);
		return iibzEmployeeService.list(new QueryWrapper<IBZEmployee>().in("mdeptid",deptmodel.getSub()));
	}

	public List<IBZEmployee> getParentEmpByOrg(String orgid,boolean bRecurrence)
	{
		if(StringUtils.isEmpty(orgid) || "nullorgid".equals(orgid))
			return new ArrayList<>();
		OrgMap orgmodel=this.getOrgModel(orgid);
		List<String> parent=new ArrayList<>();
		for(String str:orgmodel.getParent())
		{
			parent.add(str);
			if(!bRecurrence)
				break;
		}
		if(parent.size()==0)
			return new ArrayList<>();
		return iibzEmployeeService.list(new QueryWrapper<IBZEmployee>().in("orgid",parent));
	}

	public List<IBZEmployee> getParentEmpByDept(String deptid,boolean bRecurrence)
	{
		if(StringUtils.isEmpty(deptid) || "nulldeptid".equals(deptid))
			return new ArrayList<>();
		DeptMap deptmodel=this.getDeptModel(deptid);
		List<String> parent=new ArrayList<>();
		for(String str:deptmodel.getParent())
		{
			parent.add(str);
			if(!bRecurrence)
				break;
		}
		if(parent.size()==0)
			return new ArrayList<>();
		return iibzEmployeeService.list(new QueryWrapper<IBZEmployee>().in("mdeptid",parent));
	}

	public OrgMap getOrgModel(String orgid)
	{
		Map<String, OrgMap> store=ouModelService.getOrgModel();
		if(store.containsKey(orgid))
		{
			OrgMap map = store.get(orgid);
			return map;
		}
		else
		{
			OrgMap map = new OrgMap();
			map.setOrgid(orgid);
			return map;
		}
	}

	public DeptMap getDeptModel(String deptid)
	{
		Map<String, DeptMap> store=ouModelService.getDeptModel(ouModelService.getOrgModel());
		if(store.containsKey(deptid))
		{
			DeptMap map = store.get(deptid);
			return map;
		}
		else
		{
			DeptMap map = new DeptMap();
			map.setDeptid(deptid);
			return map;
		}
	}


	@Autowired
	private IBZOrg2NodeMapping org2NodeMapping;

	public List<OrgNode> getOrgNode(String root)
	{
		if(StringUtils.isEmpty(root))
			root="alls";
		List<OrgNode> list=new ArrayList<>();
		Map<String,OrgMap> store=ouModelService.getOrgModel();
		for(OrgMap map:store.values())
		{
			IBZOrganization org=map.getOrg();
			String parent=org.getParentorgid();
			if(StringUtils.isEmpty(parent))
				parent="alls";
			if(parent.equals(root)||root.equals(org.getOrgid()))
			{
				OrgNode node=org2NodeMapping.toDto(org);
				node.getFilter().addAll(map.getParent());
				node.getFilter().add(node.getOrgid());
				if(root.equals(org.getOrgid())) {
					list.add(0,node);
				}
				else {
					looporg(node, store);
					list.add(node);
				}
			}
		}
		return list;
	}

	private void looporg(OrgNode node,Map<String,OrgMap> store)
	{
		Set<String> children=store.get(node.getOrgid()).getChildren();
		for(String child:children)
		{
			OrgMap childMap=store.get(child);
			OrgNode sub=org2NodeMapping.toDto(childMap.getOrg());
			sub.getFilter().addAll(childMap.getParent());
			sub.getFilter().add(sub.getOrgid());
			node.getChildren().add(sub);
			looporg(sub,store);
		}
	}


	@Autowired
	private IBZDept2NodeMapping dept2NodeMapping;

	public List<DeptNode> getDeptNode(String orgid)
	{
		List<DeptNode> list=new ArrayList<>();
		if(StringUtils.isEmpty(orgid))
			return list;

		Map<String,DeptMap> store=ouModelService.getDeptModel(ouModelService.getOrgModel());
		for(DeptMap map:store.values())
		{
			IBZDepartment dept=map.getDept();
			if(StringUtils.isEmpty(dept.getParentdeptid())&&orgid.equals(dept.getOrgid()))
			{
				DeptNode node=dept2NodeMapping.toDto(dept);
				loopdept(node,store);
				list.add(node);
			}
		}
		return list;
	}


	public List<DeptNode> getOrgDeptNode(String orgid)
	{
		List<DeptNode> list=new ArrayList<>();
		if(StringUtils.isEmpty(orgid))
			orgid="alls";

		Map<String,DeptNode> parentNode=new HashMap<>();

		List<OrgNode> listOrg=getOrgNode(orgid);
		for(OrgNode org:listOrg)
		{
			DeptNode node = changeOrgNode2DeptNode(org,parentNode);
			list.add(node);
		}

		Map<String,DeptMap> store=ouModelService.getDeptModel(ouModelService.getOrgModel());
		for(DeptMap map:store.values())
		{
			IBZDepartment dept=map.getDept();
			if(StringUtils.isEmpty(dept.getParentdeptid()))
			{
				DeptNode node=dept2NodeMapping.toDto(dept);
				if(parentNode.containsKey(dept.getOrgid())) {
					node.setFilter(parentNode.get(dept.getOrgid()).getFilter());
					parentNode.get(dept.getOrgid()).getChildren().add(node);
					loopdept(node,store);
				}

			}
		}
		return list;
	}

	private void loopdept(DeptNode node,Map<String,DeptMap> store)
	{
		Set<String> children=store.get(node.getDeptid()).getChildren();
		for(String child:children)
		{
			DeptMap childMap=store.get(child);
			DeptNode sub=dept2NodeMapping.toDto(childMap.getDept());
			sub.setFilter(node.getFilter());
			node.getChildren().add(sub);
			loopdept(sub,store);
		}
	}

	private DeptNode  changeOrgNode2DeptNode(OrgNode orgnode,Map<String,DeptNode> parentNode)
	{
		DeptNode node = new DeptNode();
		node.setDeptid(orgnode.getOrgid());
		node.setDeptname(orgnode.getOrgname());
		node.setFilter(orgnode.getFilter());
		node.setDisabled(true);
		parentNode.put(orgnode.getOrgid(),node);
		for(OrgNode org:orgnode.getChildren())
		{
			node.getChildren().add(changeOrgNode2DeptNode(org,parentNode));
		}
		return node;
	}

}
