package com.lightinit.hsdataplatform.impl.admin;

import com.lightinit.hsdataplatform.entity.*;
import com.lightinit.hsdataplatform.mapper.*;
import com.lightinit.hsdataplatform.model.admin.*;
import com.lightinit.hsdataplatform.service.admin.ICommonService;
import com.lightinit.hsdataplatform.service.admin.TreeDataBuilder;
import com.lightinit.hsdataplatform.spring.DynamicDataContextHolder;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import static java.util.stream.Collectors.reducing;
import static java.util.stream.Collectors.toList;

/**
 * Created by WangYao on 2018/5/23.
 */
@Service
public class CommonServiceImpl implements ICommonService {

    @Autowired
    private SectorMapper sectorMapper;
    @Autowired
    private ResourceCatelogMapper resourceCatelogMapper;
    @Autowired
    private SentryRoleMapper sentryRoleMapper;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private ModuleActionMapper moduleActionMapper;

    public List<TreeModel> querySectorTreeData(Long selectedId) {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);

        SectorExample example1 = new SectorExample();
        SectorExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andDeletedAtIsNull();
        final List<Sector> dataList = sectorMapper.selectByExample(example1);

        Function<Sector,TreeModel> mapFunction = (q) -> {
            TreeModel treeModel = new TreeModel(q.getId().toString(), null, q.getSectorName(), q.getSectorLevel());
            if (q.getId().equals(selectedId)){
                treeModel.setState(treeModel.new State(false, false, false, true));
            }
            return treeModel;
        };
        List<TreeModel> treeModelList = dataList.stream().filter(q -> q.getParentId() == null).map(mapFunction).collect(toList());
        TreeDataBuilder.buildTreeModelRecursively(treeModelList, dataList, (pCurrentTreeModel, pDataList) -> {
            return pDataList.stream()
                    .filter(q -> q.getParentId() != null && q.getParentId().toString().equals(pCurrentTreeModel.getId()))
                    .map(mapFunction)
                    .collect(toList());
        });
        return treeModelList;
    }

    public List<TreeModel> queryResourceCatelogTreeData(String resourceCatelogType, Long selectedId) {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);

        ResourceCatelogExample example = new ResourceCatelogExample();
        if (StringUtils.isNotEmpty(resourceCatelogType)){
            ResourceCatelogExample.Criteria criteria1 = example.createCriteria();
            criteria1.andCatelogTypeEqualTo(resourceCatelogType);
        }
        final List<ResourceCatelog> dataList = resourceCatelogMapper.selectByExample(example);

        Function<ResourceCatelog,TreeModel> mapFunction = (q) -> {
            TreeModel treeModel =  new TreeModel(q.getId().toString(), null, q.getCatelogName(), null);
            if (q.getId().equals(selectedId)){
                treeModel.setState(treeModel.new State(false, false, false, true));
            }
            return treeModel;
        };
        List<TreeModel> treeModelList = dataList.stream().filter(q -> q.getParentId() == null).map(mapFunction).collect(toList());
        TreeDataBuilder.buildTreeModelRecursively(treeModelList, dataList, (pCurrentTreeModel, pDataList) -> {
            return pDataList.stream()
                    .filter(q -> q.getParentId() != null && q.getParentId().toString().equals(pCurrentTreeModel.getId()))
                    .map(mapFunction)
                    .collect(toList());
        });
        return treeModelList;
    }

    public List<TreeModel> queryRoleTreeData(Long selectedId) {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);

        SentryRoleExample example = new SentryRoleExample();
        final List<SentryRole> dataList = sentryRoleMapper.selectByExample(example);

        Function<SentryRole,TreeModel> mapFunction = (q) -> {
            TreeModel treeModel =  new TreeModel(q.getId().toString(), null, q.getRolename(), null);
            if (q.getId().equals(selectedId)){
                treeModel.setState(treeModel.new State(false, false, false, true));
            }
            return treeModel;
        };
        List<TreeModel> treeModelList = dataList.stream().filter(q -> q.getParentid() == null).map(mapFunction).collect(toList());
        TreeDataBuilder.buildTreeModelRecursively(treeModelList, dataList, (pCurrentTreeModel, pDataList) -> {
            return pDataList.stream()
                    .filter(q -> q.getParentid() != null && q.getParentid().toString().equals(pCurrentTreeModel.getId()))
                    .map(mapFunction)
                    .collect(toList());
        });
        return treeModelList;
    }


    public List<TreeModel> queryModuleTreeData(List<Long> moduleIds, List<Long> selectedModuleIds, List<Long> selectedActionIds) {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);

        MenuExample example1 = new MenuExample();
        MenuExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andMenushowEqualTo(1);
        if (moduleIds != null && moduleIds.size() > 0){
            criteria1.andIdIn(moduleIds);
        }
        List<Menu> moduleList = menuMapper.selectByExample(example1);

        ModuleActionExample example2 = new ModuleActionExample();
        ModuleActionExample.Criteria criteria2 = example2.createCriteria();
        List<ModuleAction> allActionList = moduleActionMapper.selectByExample(example2);

        List<ModuleWithActionListModel> dataList = new ArrayList<>();
        for (Menu module : moduleList) {
            ModuleWithActionListModel moduleWithAction = new ModuleWithActionListModel();
            BeanUtils.copyProperties(module, moduleWithAction);
            dataList.add(moduleWithAction);
            if (allActionList != null && allActionList.size() > 0) {
                moduleWithAction.setModuleActionList(allActionList.stream().filter(q -> q.getModuleId().equals(moduleWithAction.getId())).collect(toList()));
            }
        }

        Function<ModuleAction,TreeModel> actionMapFunction = (q) -> {
            TreeModel treeModel =  new TreeModel(q.getId().toString(), null, q.getActionName(), null);
            treeModel.setSelectable(false);
            if (selectedActionIds != null && selectedActionIds.contains(q.getId())){
                treeModel.setState(treeModel.new State(true, false, false, false));
            }
            List<String> tags = new ArrayList<>();
            tags.add(String.valueOf("功能"));
            treeModel.setTags(tags);
            return treeModel;
        };

        Function<ModuleWithActionListModel,TreeModel> moduleMapFunction = (q) -> {
            // 模块
            TreeModel treeModel =  new TreeModel(q.getId().toString(), null, q.getMenuname(), null);
            treeModel.setSelectable(false);
            treeModel.setState(treeModel.new State(false, false, false, false));
            if (selectedModuleIds != null && selectedModuleIds.contains(q.getId())){
//                treeModel.setState(treeModel.new State(true, false, true, false));
                treeModel.getState().setChecked(true);
            }
            List<String> tags = new ArrayList<>();
            tags.add(String.valueOf("模块"));
            treeModel.setTags(tags);
            // Action
            if (q.getModuleActionList() != null && q.getModuleActionList().size() > 0){
                List<TreeModel> childNodes = q.getModuleActionList().stream().map(actionMapFunction).collect(toList());
                if (childNodes != null && childNodes.size() > 0){
                    treeModel.getState().setExpanded(false);
                }
                treeModel.setNodes(childNodes);
            }
            return treeModel;
        };
        List<TreeModel> treeModelList = dataList.stream().filter(q -> q.getParentmenu() == null).map(moduleMapFunction).collect(toList());
        TreeDataBuilder.buildTreeModelRecursively(treeModelList, dataList, (pCurrentTreeModel, pDataList) -> {
            return pDataList.stream()
                    .filter(q -> q.getParentmenu() != null && q.getParentmenu().toString().equals(pCurrentTreeModel.getId()))
                    .map(moduleMapFunction)
                    .collect(toList());
        });
        return treeModelList;
    }
}
