/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.service.sysmgr.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.crunii.micro.common.constants.LockConstants;
import com.crunii.micro.common.dto.OrderProp;
import com.crunii.micro.common.exception.BusinessException;
import com.crunii.micro.common.utils.StreamUtils;
import com.crunii.micro.domain.dto.sys.MenuExtend;
import com.crunii.micro.domain.entity.main.TsmMenu;
import com.crunii.micro.domain.entity.main.TsmUrl;
import com.crunii.micro.domain.repo.main.TsmMenuRepo;
import com.crunii.micro.domain.repo.main.TsmUrlRepo;
import com.crunii.micro.platform.components.Locker;
import com.crunii.micro.service.sysmgr.dto.sysmgr.MenuC;
import com.crunii.micro.service.sysmgr.dto.sysmgr.MenuU;
import com.crunii.micro.service.sysmgr.jdbc.MenuJdbcDao;
import com.crunii.micro.service.sysmgr.service.MenuService;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 田平 create 2019年2月19日下午3:57:34
 */
@Service(value = "menuService")
public class MenuServiceImpl implements MenuService {
	@Autowired
	private TsmMenuRepo tsmMenuRepo;

	@Autowired
	private MenuJdbcDao menuJdbcDao;

	@Autowired
	private TsmUrlRepo tsmUrlRepo;

	@Autowired
	private Locker locker;

	@Override
	public List<MenuExtend> getChildren(String parentMenuCode,Integer menuType) {
		Map<String, Object> props = new HashMap<>();
		props.put("parentMenuCode", parentMenuCode);
		if (menuType!=null){
			props.put("menuType", menuType);
		}
		OrderProp order = new OrderProp("sortId");
		List<TsmMenu> menus = tsmMenuRepo.findByProps(props, order);

		List<MenuExtend> mes = menus.stream().map(m -> {
			MenuExtend menuExtend = new MenuExtend();
			BeanUtils.copyProperties(m, menuExtend, "terminal");
			menuExtend.setLeaf(menuJdbcDao.findIsLeaf(m.getMenuCode()));
			//取按钮对应url
			if (menuExtend.getButtonUrlId() > 0) {
				//取菜单所有的按钮，不管状态
				TsmUrl url = tsmUrlRepo.getOne(menuExtend.getButtonUrlId());
				if (url != null) {
					menuExtend.setUrlPath(url.getUrlPath());
					menuExtend.setUrlName(url.getUrlName());
				}
			}
			if(StrUtil.isNotBlank(m.getTerminal())) {
				menuExtend.setTerminal(StrUtil.split(m.getTerminal(), StrUtil.C_COMMA));
			}
			return menuExtend;
		}).sorted(Comparator.comparingInt(MenuExtend::getSortId)).collect(Collectors.toList());

		if(ObjectUtil.isNotEmpty(mes)){
			List<String> parentCodeList = StreamUtils.toList(mes, MenuExtend::getParentMenuCode);
			List<TsmMenu> parentList = tsmMenuRepo.findAllById(parentCodeList);
			if(ObjectUtil.isNotEmpty(parentList)) {
				Map<String, TsmMenu> parentMap = StreamUtils.toIdentityMap(parentList, TsmMenu::getMenuCode);
				for (MenuExtend item : mes) {
					TsmMenu parent = parentMap.get(item.getParentMenuCode());
					if (parent != null) {
						item.setParentMenuName(parent.getMenuName());
					}
				}
			}
		}

		return mes;
	}

	@Override
	public void createMenu(MenuC menuC) {
		locker.lock(LockConstants.LOCK_MENU, menuC.getParentMenuCode());
		try {
			Date curr = new Date();
			TsmMenu menu = new TsmMenu();
			BeanUtils.copyProperties(menuC, menu);
			menu.setCreateTime(curr);
			menu.setUpdateTime(curr);
			menu.setState(menuC.getState());

			setAllParentNamePinyinCode(menu);
			setTerminal(menuC.getTerminal(), menu);
			menu.setMenuCode(menuJdbcDao.getNextMenuCode(menuC.getParentMenuCode()));
			tsmMenuRepo.save(menu);
			tsmMenuRepo.flush();
		} finally {
			locker.unlock();
		}
	}

	private static void setTerminal(List<String> terminal, TsmMenu menu) {
		if(ObjectUtil.isNotEmpty(terminal)) {
			String fixTerminal = String.join(",", terminal);
			menu.setTerminal(fixTerminal);
		}
	}

	private void setAllParentNamePinyinCode(TsmMenu menu) {
		List<TsmMenu> parents = Lists.newArrayList();
		String parentMenuCode = menu.getParentMenuCode();
		while(menu.getParentMenuCode() != null){
			Optional<TsmMenu> parentOptional = tsmMenuRepo.findById(parentMenuCode);
			if(parentOptional.isPresent()){
				TsmMenu parent = parentOptional.get();
				parents.add(parent);
				parentMenuCode = parent.getParentMenuCode();
			} else {
				break;
			}
		}
		String parentCode = "";
		for (int i = parents.size()-1; i >= 0; i--) {
			TsmMenu tsmMenu = parents.get(i);
			parentCode += PinyinUtil.getFirstLetter(tsmMenu.getMenuName(), "") + "-";
		}
		menu.setCode(parentCode + PinyinUtil.getFirstLetter(menu.getMenuName(), ""));
	}

	@Override
	public void recursiveParents(String menuCode, Set<String> parents) {
		TsmMenu menu = tsmMenuRepo.getOne(menuCode);
		if (menu != null) {
			parents.add(menu.getParentMenuCode());
			recursiveParents(menu.getParentMenuCode(), parents);
		} else {
			return;
		}
	}

	@Override
	public void updateMenu(MenuU menuU) {
		if(StrUtil.equals(menuU.getMenuCode(), menuU.getParentMenuCode())){
			throw new BusinessException("父级菜单不能是当前菜单!");
		}
		//菜单更新加锁
		locker.lock(LockConstants.LOCK_MENU, menuU.getMenuCode());
		try {
			Date curr = new Date();
			TsmMenu menu = tsmMenuRepo.getOne(menuU.getMenuCode());
			BeanUtils.copyProperties(menuU, menu);
			setAllParentNamePinyinCode(menu);
			setTerminal(menuU.getTerminal(), menu);
			menu.setUpdateTime(curr);
			tsmMenuRepo.save(menu);
		} finally {
			locker.unlock();
		}
	}



}
