/**
 * 文件：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.service.MenuService;

import com.mortals.xhx.common.code.YesNoEnum;
import org.springframework.stereotype.Service;

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, Set<String> urls) throws AppException {
        Set<Long> authIds = new HashSet<>();
        Map<Long, MenuEntity> menuMap = new HashMap<Long, MenuEntity>();
        List<MenuEntity> userModuleList = this.findAllEnable();
        for (MenuEntity sysModule : userModuleList) {
            if (sysModule == null) {
                continue;
            }
            menuMap.put(sysModule.getId(), sysModule);
            if (!user.isAdmin() && urls.contains(StringUtils.trim(sysModule.getUrl()))) {
                authIds.add(sysModule.getId());
            }
        }
        if (!user.isAdmin()) {
            Long[] ids = authIds.toArray(new Long[authIds.size()]);
            for (Long id : ids) {
                MenuEntity menu = menuMap.get(id);
                while (menu != null) {
                    authIds.add(menu.getId());
                    menu = menuMap.get(menu.getParentId());
                }
            }
        }
        List<MenuEntity> outlookBar = new ArrayList<MenuEntity>();
        List<MenuEntity> norightList = new ArrayList<MenuEntity>();
        for (MenuEntity sysModule : userModuleList) {
            if (!user.isAdmin() && !authIds.contains(sysModule.getId())) {
                norightList.add(sysModule);
                continue;
            }
            if (sysModule.getParentId() == null || sysModule.getParentId().longValue() == 0) {
                outlookBar.add(sysModule);
                continue;
            }
            MenuEntity sysModuleParent = menuMap.get(sysModule.getParentId());
            if (sysModuleParent != null) {
                sysModuleParent.getChildList().add(sysModule);
            }
        }
        return outlookBar;
    }

    public List<MenuEntity> findTreeMenu() throws AppException {
        Map<Long, MenuEntity> menuMap = new HashMap<Long, MenuEntity>();
        List<MenuEntity> userModuleList = this.findAllEnable();
        for (MenuEntity sysModule : userModuleList) {
            if (sysModule == null) {
                continue;
            }
            menuMap.put(sysModule.getId(), sysModule);
        }
        List<MenuEntity> outlookBar = new ArrayList<MenuEntity>();
        for (MenuEntity sysModule : userModuleList) {
            if (sysModule.getParentId() == null || sysModule.getParentId().longValue() == 0) {
                outlookBar.add(sysModule);
                continue;
            }
            MenuEntity sysModuleParent = menuMap.get(sysModule.getParentId());
            if (sysModuleParent != null) {
                sysModuleParent.getChildList().add(sysModule);
            }
        }
        return outlookBar;
    }

    @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 {
        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);
    }
}