package ink.wgink.module.menu.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.SearchException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.menu.IMongoMenuService;
import ink.wgink.module.menu.dao.IMenuDao;
import ink.wgink.module.menu.pojo.vos.MenuVO;
import ink.wgink.module.menu.service.IMenuService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.bos.menu.SaveMenuBO;
import ink.wgink.pojo.bos.menu.UpdateMenuBO;
import ink.wgink.pojo.dtos.ZTreeDTO;
import ink.wgink.pojo.dtos.menu.MenuDTO;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.ArrayListUtil;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.map.HashMapUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @ClassName: MenuServiceImpl
 * @Description: 菜单
 * @Author: wenc
 * @Date: 2018/12/27 10:18 PM
 * @Version: 1.0
 **/
@Service
public class MenuServiceImpl extends DefaultBaseService implements IMenuService {

    @Autowired
    private IMenuDao menuDao;
    @Autowired(required = false)
    private IMongoMenuService mongoMenuService;

    @Override
    public MenuDTO get(Map<String, Object> params) {
        return menuDao.get(params);
    }

    @Override
    public List<MenuDTO> list(Map<String, Object> params) {
        List<MenuDTO> srcMenuDTOs = menuDao.list(params);
        return ArrayListUtil.deepClone(srcMenuDTOs, MenuDTO.class);
    }

    @Override
    public List<MenuDTO> listByParentId(String menuParentId) {
        Map<String, Object> params = getHashMap(2);
        params.put("menuParentId", menuParentId);
        params.put("menuStatus", 0);
        return list(params);
    }

    @Override
    public List<MenuDTO> listByIds(List<String> menuIds) {
        Map<String, Object> params = getHashMap(2);
        params.put("menuIds", menuIds);
        return list(params);
    }

    @Override
    public List<MenuDTO> listByParentIdAndIds(String menuParentId, List<String> menuIds) {
        Map<String, Object> params = getHashMap(4);
        params.put("menuParentId", menuParentId);
        params.put("menuIds", menuIds);
        params.put("menuStatus", 0);
        return list(params);
    }

    @Override
    public List<MenuDTO> listAll(Map<String, Object> params) {
        List<MenuDTO> menuDTOs = list(params);
        listSub(menuDTOs);
        return menuDTOs;
    }

    @Override
    public List<MenuDTO> listAllByParentId(String menuParentId) {
        List<MenuDTO> menuDTOs = listByParentId(menuParentId);
        listSub(menuDTOs);
        return menuDTOs;
    }

    @Override
    public List<MenuDTO> listAllByParentIdAndIds(String menuParentId, List<String> menuIds) {
        List<MenuDTO> menuDTOs = listByParentIdAndIds(menuParentId, menuIds);
        listSubByIds(menuDTOs, menuIds);
        return menuDTOs;
    }

    @Override
    public List<ZTreeDTO> listZTree(Map<String, Object> params) {
        List<ZTreeDTO> zTreeDTOs = menuDao.listZTree(params);
        for (ZTreeDTO zTreeDTO : zTreeDTOs) {
            Integer subCount = menuDao.countByParentId(zTreeDTO.getId());
            setZTreeInfo(zTreeDTO, subCount);
        }
        return zTreeDTOs;
    }

    @Override
    public SuccessResultList<List<MenuDTO>> listPage(ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<MenuDTO> menuDTOs = menuDao.list(page.getParams());
        PageInfo<MenuDTO> pageInfo = new PageInfo<>(menuDTOs);
        return new SuccessResultList<>(menuDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public synchronized void save(MenuVO menuVO) {
        saveAndReturnId(menuVO);
    }

    @Override
    public void save(String token, MenuVO menuVO) {
        saveAndReturnId(token, menuVO);
    }

    @Override
    public String saveAndReturnId(MenuVO menuVO) {
        return saveAndReturnId(null, menuVO);
    }

    @Override
    public String saveAndReturnId(String token, MenuVO menuVO) {
        Map<String, Object> params = HashMapUtil.beanToMap(menuVO);
        String menuId = UUIDUtil.getUUID();
        String parentCode = null;
        String menuParentId = params.get("menuParentId").toString();
        if (!ISystemConstant.TREE_ROOT_ID.equals(menuParentId)) {
            params.put("menuId", menuParentId);
            MenuDTO menuDTO = menuDao.get(params);
            parentCode = menuDTO.getMenuCode();
        }
        String menuCode = getCode(parentCode, menuParentId);
        params.put("menuCode", menuCode);
        params.put("menuId", menuId);
        if (StringUtils.isBlank(token)) {
            setSaveInfo(params);
        } else {
            setAppSaveInfo(token, params);
        }
        menuDao.save(params);
        if (mongoMenuService != null) {
            mongoMenuService.update(menuId);
        }
        return menuId;
    }

    @Override
    public String saveAndReturnId(SaveMenuBO saveMenuBO) {
        MenuVO menuVO = new MenuVO();
        BeanUtils.copyProperties(saveMenuBO, menuVO);
        return saveAndReturnId(menuVO);
    }

    @Override
    public void remove(List<String> ids) {
        remove(null, ids);
    }

    @Override
    public void update(String menuId, UpdateMenuBO updateMenuBO) {
        MenuVO menuVO = new MenuVO();
        BeanUtils.copyProperties(updateMenuBO, menuVO);
        update(menuId, menuVO);
    }

    @Override
    public void remove(String token, List<String> ids) {
        Map<String, Object> params = getHashMap(2);
        params.put("menuIds", ids);
        if (StringUtils.isBlank(token)) {
            setUpdateInfo(params);
        } else {
            setAppUpdateInfo(token, params);
        }
        menuDao.remove(params);
        if (mongoMenuService != null) {
            mongoMenuService.delete(ids);
        }
    }

    @Override
    public MenuDTO get(String menuId) {
        Map<String, Object> params = getHashMap(2);
        params.put("menuId", menuId);
        return get(params);
    }

    @Override
    public MenuDTO getAll(String menuId) {
        MenuDTO menuDTO = get(menuId);
        if (menuDTO == null) {
            return null;
        }
        List<MenuDTO> menuDTOs = listAllByParentId(menuId);
        menuDTO.setSubMenus(menuDTOs);
        if (!menuDTOs.isEmpty()) {
            menuDTO.setParent(true);
        }
        return menuDTO;
    }

    @Override
    public void update(String menuId, MenuVO menuVO) {
        update(null, menuId, menuVO);
    }

    @Override
    public void update(String token, String menuId, MenuVO menuVO) {
        Map<String, Object> params = HashMapUtil.beanToMap(menuVO);
        params.put("menuId", menuId);
        if (StringUtils.isBlank(token)) {
            setUpdateInfo(params);
        } else {
            setAppUpdateInfo(token, params);
        }
        menuDao.update(params);
        if (mongoMenuService != null) {
            mongoMenuService.update(menuId);
        }
    }

    @Override
    public List<String> listMenuIdByUser(Map<String, Object> params) {
        return menuDao.listIdByUser(params);
    }

    @Override
    public List<MenuDTO> listSystemMenu(String systemMenuId) {
        if (mongoMenuService != null) {
            return mongoMenuService.listSystemSubMenus(systemMenuId);
        }
        return listAllByParentId(systemMenuId);
    }

    @Override
    public List<MenuDTO> listSystemMenu(String systemMenuId, List<String> selectedMenuIds) {
        if (mongoMenuService != null) {
            return mongoMenuService.listSystemSubMenus(systemMenuId, selectedMenuIds);
        }
        return listAllByParentIdAndIds(systemMenuId, selectedMenuIds);
    }

    /**
     * 递归查询子菜单
     *
     * @param menuDTOs
     */
    private void listSub(List<MenuDTO> menuDTOs) {
        if (menuDTOs.isEmpty()) {
            return;
        }
        for (MenuDTO menuDTO : menuDTOs) {
            List<MenuDTO> subMenuDTOs = listByParentId(menuDTO.getMenuId());
            menuDTO.setSubMenus(subMenuDTOs);
            if (!subMenuDTOs.isEmpty()) {
                menuDTO.setParent(true);
            }
            listSub(subMenuDTOs);
        }
    }

    private void listSubByIds(List<MenuDTO> menuDTOs, List<String> menuIds) {
        if (menuDTOs.isEmpty()) {
            return;
        }
        for (MenuDTO menuDTO : menuDTOs) {
            List<MenuDTO> subMenuDTOs = listByParentIdAndIds(menuDTO.getMenuId(), menuIds);
            menuDTO.setSubMenus(subMenuDTOs);
            if (!subMenuDTOs.isEmpty()) {
                menuDTO.setParent(true);
            }
            listSubByIds(subMenuDTOs, menuIds);
        }
    }

    /**
     * 获取code
     *
     * @param parentCode
     * @param parentId
     * @return
     * @throws SearchException
     */
    private String getCode(String parentCode, String parentId) {
        MenuDTO menuDTO = menuDao.getLastByParentId(parentId);
        String code = menuDTO != null ? menuDTO.getMenuCode() : "0000";
        return super.getNewCode(code, parentCode);
    }

}
