/**
 * 文件：MenuServiceImpl.java
 * 版本：1.0.0
 * 日期：
 * Copyright &reg;
 * All right reserved.
 */

package com.mortals.xhx.base.system.menu.service.impl;

import com.mortals.framework.common.code.YesNo;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.OrderCol;
import com.mortals.framework.service.IUser;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.menu.dao.MenuDao;
import com.mortals.xhx.base.system.menu.model.MenuEntity;
import com.mortals.xhx.base.system.menu.model.MenuQuery;
import com.mortals.xhx.base.system.menu.model.MenuTreeSelect;
import com.mortals.xhx.base.system.menu.service.MenuService;

import com.mortals.xhx.base.system.resource.model.ResourceEntity;
import com.mortals.xhx.base.system.resource.service.ResourceService;
import com.mortals.xhx.base.system.role.model.RoleAuthQuery;
import com.mortals.xhx.base.system.role.model.RoleUserQuery;
import com.mortals.xhx.base.system.role.service.RoleAuthService;
import com.mortals.xhx.base.system.role.service.RoleUserService;
import com.mortals.xhx.common.code.YesNoEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

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

/**
 * <p>Title: 菜单信息</p>
 * <p>Description: MenuServiceImpl service接口 </p>
 * <p>Copyright: Copyright &reg;  </p>
 * <p>Company: </p>
 *
 * @author
 * @version 1.0.0
 */
@Service("menuService")
public class MenuServiceImpl extends AbstractCRUDServiceImpl<MenuDao, MenuEntity, Long> implements MenuService {

    @Override
    public List<MenuEntity> findAllEnable() throws AppException {
        MenuQuery params = new MenuQuery();
        params.setStatus(YesNo.YES.getValue());
        params.setMenuType(0);//主菜单
        List<OrderCol> orderColList = new ArrayList<OrderCol>();
        orderColList.add(new OrderCol("parentId"));
        orderColList.add(new OrderCol("orderId"));
        params.setOrderColList(orderColList);
        return dao.getList(params);
    }

    @Override
    public List<MenuEntity> findTreeMenu(IUser user) throws AppException {
        //todo 重新写 菜单树 通过角色获取菜单
        if (user.isAdmin()) {
            //全菜单列表获取
            MenuQuery menuQuery = new MenuQuery();
            List<OrderCol> orderColList = new ArrayList<>();
            orderColList.add(new OrderCol("parentId"));
            orderColList.add(new OrderCol("orderId"));
            menuQuery.setOrderColList(orderColList);
            List<MenuEntity> list = this.find(menuQuery);
            List<MenuEntity> returnTreeList = this.buildMenuTree(list);
            return returnTreeList;
        }
        List<MenuEntity> menuEntities = this.getDao().getListByUserId(user.getId()).stream().distinct().collect(Collectors.toList());
        List<MenuEntity> returnTreeList = this.buildMenuTree(menuEntities);
        return returnTreeList;

    }


    @Override
    public void upOrDown(Long id, Integer type) {
        MenuQuery query = new MenuQuery();
        query.setOrderColList(Arrays.asList(new OrderCol("orderId")));
        query.setOrderKind(OrderCol.ASCENDING);
        //判断移动的是一级菜单还是二级菜单
        MenuEntity menuEntity = this.get(id);
        if (menuEntity.getParentId() == 0) {
            //一级菜单
            query.setParentId(0L);
        } else {
            //二级菜单
            query.setParentId(menuEntity.getParentId());
        }

        List<MenuEntity> list = this.find(query);
        MenuEntity preEntity = null;
        MenuEntity curEntity = null;
        if (type == YesNoEnum.NO.getValue()) {
            //up
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getId().equals(id) && i > 0) {
                    curEntity = list.get(i);
                    preEntity = list.get(i - 1);
                    break;
                }
            }

        } else {
            //down
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getId().equals(id) && i + 1 < list.size()) {
                    curEntity = list.get(i);
                    preEntity = list.get(i + 1);
                    break;
                }
            }
        }

        if (preEntity != null && curEntity != null) {
            //交换
            int temp = preEntity.getOrderId();
            preEntity.setOrderId(curEntity.getOrderId());
            curEntity.setOrderId(temp);

            this.update(preEntity);
            this.update(curEntity);
        }

    }

    @Override
    protected void saveBefore(MenuEntity entity, Context context) throws AppException {
        MenuEntity parentMenuEntity = this.get(entity.getParentId());
        if (!ObjectUtils.isEmpty(parentMenuEntity)) {
            entity.setAncestors(parentMenuEntity.getAncestors() + "," + entity.getParentId());
        }
        MenuQuery query = new MenuQuery();
        query.setParentId(entity.getParentId());
        Comparator<Integer> comparator = Comparator.comparing(Integer::intValue);
        Optional<Integer> maxOptional = this.find(query).stream().map(MenuEntity::getOrderId).filter(f -> f != 9999).max(comparator);
        maxOptional.ifPresent(e -> {
            e = e + 1;
            entity.setOrderId(e);
        });
        super.saveBefore(entity, context);
    }

    @Override
    protected void updateBefore(MenuEntity entity, Context context) throws AppException {
        MenuEntity newParentEntity = this.get(entity.getParentId());
        MenuEntity oldEntity = this.get(entity.getId());
        if (!ObjectUtils.isEmpty(newParentEntity) && !ObjectUtils.isEmpty(oldEntity)) {
            String newAncestors = newParentEntity.getAncestors() + "," + newParentEntity.getId();
            String oldAncestors = oldEntity.getAncestors();
            entity.setAncestors(newAncestors);
            updateMenuChildren(entity.getId(), newAncestors, oldAncestors, context);
        }
        super.updateBefore(entity, context);
    }



    /**
     * 修改子元素关系
     *
     * @param menuId       被修改的菜单信息业务ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateMenuChildren(Long menuId, String newAncestors, String oldAncestors, Context context) {
        List<MenuEntity> children =  getDao().selectChildrenMenuById(menuId.toString());
        for (MenuEntity child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            this.updateAfter(children, context);
        }
    }

    @Override
    public boolean hasChildByMenuId(Long menuId) {
        List<MenuEntity> list = this.find(new MenuQuery().parentId(menuId));
        return list.size() > 0 ? true : false;
    }

    @Override
    public List<MenuEntity> buildMenuTree(List<MenuEntity> list) {
        List<MenuEntity> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(MenuEntity::getId).collect(Collectors.toList());

        for (Iterator<MenuEntity> iterator = list.iterator(); iterator.hasNext(); ) {
            MenuEntity menuEntity = iterator.next();
            if (!tempList.contains(menuEntity.getParentId())) {
                recursionFn(list, menuEntity, new HashSet<>());
                returnList.add(menuEntity);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList;
    }

    @Override
    public List<MenuTreeSelect> buildMenuTreeSelect(List<MenuEntity> list) {
        List<MenuEntity> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(MenuEntity::getId).collect(Collectors.toList());

        for (Iterator<MenuEntity> iterator = list.iterator(); iterator.hasNext(); ) {
            MenuEntity menuEntity = iterator.next();
            if (!tempList.contains(menuEntity.getParentId())) {
                recursionFn(list, menuEntity, new HashSet<>());
                returnList.add(menuEntity);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList.stream().map(MenuTreeSelect::new).collect(Collectors.toList());
    }

    @Override
    public List<MenuTreeSelect> buildMenuTreeChecked(List<MenuEntity> allMenuList, Set<Long> menuIdsChecked) {

        List<MenuEntity> returnList = new ArrayList<>();
        List<Long> tempList = allMenuList.stream().map(MenuEntity::getId).collect(Collectors.toList());

        for (Iterator<MenuEntity> iterator = allMenuList.iterator(); iterator.hasNext(); ) {
            MenuEntity menuEntity = iterator.next();
            if (!tempList.contains(menuEntity.getParentId())) {
                recursionFn(allMenuList, menuEntity, menuIdsChecked);
                returnList.add(menuEntity);
            }
        }

        if (returnList.isEmpty()) {
            returnList = allMenuList;
        }
        return returnList.stream().map(MenuTreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<MenuEntity> list, MenuEntity t, Set<Long> menuIdsChecked) {
        // 得到子节点列表
        updateChecked(menuIdsChecked, t);
        List<MenuEntity> childList = getChildList(list, t);
        t.setChildren(childList);
        for (MenuEntity tChild : childList) {
            updateChecked(menuIdsChecked, tChild);
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild, menuIdsChecked);
            }
        }
    }

    private  void updateChecked(Set<Long> menuIdsChecked, MenuEntity menu) {
        if (menuIdsChecked.contains(menu.getId())) {
            menu.setChecked(YesNoEnum.YES.getValue());
        } else {
            menu.setChecked(YesNoEnum.NO.getValue());
        }
    }

    @Override
    protected void removeBefore(Long[] ids, Context context) throws AppException {
        //有子节点 禁止删除
        if (hasChildByMenuId(ids[0])) {
            throw new AppException("存在下级菜单信息业务,不允许删除");
        }
        super.removeBefore(ids, context);
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<MenuEntity> list, MenuEntity t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    /**
     * 得到子节点列表
     */
    private List<MenuEntity> getChildList(List<MenuEntity> list, MenuEntity t) {
        return list.stream().map(item -> {
            if (!ObjectUtils.isEmpty(item.getParentId()) && item.getParentId() == t.getId()) {
                return item;
            }
            return null;
        }).filter(f -> f != null).collect(Collectors.toList());
    }

    @Override
    public List<MenuTreeSelect> getListByParentId(Long parentId, Context context) {
        if (ObjectUtils.isEmpty(parentId)) {
            parentId = 0L;
        }
        //只做一层
        List<MenuTreeSelect> collect = this.find(new MenuQuery().parentId(parentId), context).stream().map(item -> new MenuTreeSelect(item)
        ).collect(Collectors.toList());
        return collect;
    }


}