package org.txh.autobuild.service.system.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.txh.autobuild.basic.BasicSupportMapper;
import org.txh.autobuild.basic.system.mapper.TRRoleMenuMapper;
import org.txh.autobuild.basic.system.mapper.TSRoleMapper;
import org.txh.autobuild.basic.system.model.TRRoleMenu;
import org.txh.autobuild.basic.system.model.TSRole;
import org.txh.autobuild.service.AbstractBasicSupportService;
import org.txh.autobuild.service.system.MenuService;
import org.txh.autobuild.service.system.RoleService;
import org.txh.autobuild.service.system.UserService;
import org.txh.autobuild.service.system.dto.Menu;
import org.txh.autobuild.service.system.dto.Role;
import org.txh.autobuild.service.system.enums.MenuTypeEnum;
import org.txh.autobuild.service.system.enums.SysStatusEnum;

@Service
public class RoleServiceImpl extends AbstractBasicSupportService<Role, TSRole> implements RoleService {

	@Resource
	private TSRoleMapper tsRoleMapper;

	@Resource
	private TRRoleMenuMapper trRoleMenuMapper;

	@Resource
	private UserService userService;

	@Resource
	private MenuService menuService;

	@Override
	public BasicSupportMapper<TSRole> getMapper() {
		return tsRoleMapper;
	}

	@Override
	public TSRole toModel(Role dto) {
		TSRole model = null;
		if (dto != null) {
			model = new TSRole();
			model.setName(dto.getName());
			model.setDescription(dto.getDescription());
			model.setStatus(dto.getStatus() == null ? null : dto.getStatus().name());
			super.fillModel(model, dto);
		}
		return model;
	}

	@Override
	public Role toDTO(TSRole model) {
		Role dto = null;
		if (model != null) {
			dto = new Role();
			dto.setName(model.getName());
			dto.setDescription(model.getDescription());
			dto.setStatus(SysStatusEnum.valueOf(model.getStatus()));
			super.fillDTO(dto, model);
			dto.setCreator(userService.findById(model.getCreateBy()));
			dto.setModifier(userService.findById(model.getModifyBy()));
		}
		return dto;
	}

	@Override
	public boolean hasMenu(Long roleId, Long menuId) {
		long count = tsRoleMapper.hasMenu(roleId, menuId);
		return count > 0;
	}

	@Override
	public List<Role> findUserAuthorizedRoles(Long userId) {
		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("status", SysStatusEnum.Activity.name());
		paramMap.put("userId", String.valueOf(userId));
		List<TSRole> list = tsRoleMapper.selectUserAuthorizedRoles(paramMap);
		return toDTO(list);
	}

	@Override
	public List<Menu> findMenus(Long roleId) {
		if (roleId == null) {
			return null;
		}
		// 查询并过滤掉未授权的菜单组
		List<Menu> list = menuService.findMenus(MenuTypeEnum.Group);
		filterUnauthorized(roleId, list);
		// 查询并过滤掉未授权的菜单组的子菜单
		List<Menu> submenuList = new ArrayList<Menu>();
		Menu filter = new Menu();
		for (Menu menu : list) {
			filter.setParentId(menu.getId());
			submenuList = menuService.findMenus(filter, true);
			filterUnauthorized(roleId, submenuList);
			for (Menu submenu : submenuList) {
				filterUnauthorized(roleId, submenu.getSubmenuList());
			}
			menu.setSubmenuList(submenuList);
		}
		return list;
	}

	/**
	 * 过滤用户未授权的菜单
	 * 
	 * @param roleId
	 * @param list
	 */
	private void filterUnauthorized(Long roleId, List<Menu> list) {
		Iterator<Menu> it = list.iterator();
		while (it.hasNext()) {
			if (!this.hasMenu(roleId, it.next().getId())) {
				it.remove();
			}
		}
	}

	@Override
	@Transactional(isolation = Isolation.READ_COMMITTED)
	public void addMenus(Long roleId, Menu... menus) {
		Long[] menuIds = new Long[menus.length];
		for (int i = 0; i < menus.length; i++) {
			menuIds[i] = menus[i].getId();
		}
		this.addMenus(roleId, menuIds);
	}

	@Override
	@Transactional(isolation = Isolation.READ_COMMITTED)
	public void addMenus(Long roleId, Long... menuIds) {
		TRRoleMenu trRoleMenu = new TRRoleMenu();
		trRoleMenu.setRoleId(roleId);

		for (Long menuId : menuIds) {
			Menu menu = menuService.findById(menuId);
			if (menu == null) {
				continue;
			}
			trRoleMenu.setMenuId(menuId);
			trRoleMenu.setCreateBy(userService.getCurrentUser().getId());
			trRoleMenu.setCreateTime(Calendar.getInstance().getTime());
			trRoleMenuMapper.insert(trRoleMenu);
			trRoleMenu.setId(null);
		}
	}

	@Override
	@Transactional(isolation = Isolation.READ_COMMITTED)
	public void removeMenus(Long roleId, Menu... menus) {
		for (Menu menu : menus) {
			trRoleMenuMapper.deleteBy(roleId, menu.getId());
		}
	}

	@Override
	@Transactional(isolation = Isolation.READ_COMMITTED)
	public void removeMenus(Long roleId, Long... menuIds) {
		for (Long menuId : menuIds) {
			trRoleMenuMapper.deleteBy(roleId, menuId);
		}
	}

	@Override
	@Transactional(isolation = Isolation.READ_COMMITTED)
	public void updateRoleMenus(Long roleId, Long... menuIds) {
		trRoleMenuMapper.deleteBy(roleId, null);
		this.addMenus(roleId, menuIds);
	}

	@Override
	public List<Map<String, Object>> easyuiTreeFormat(List<Role> roleList) {
		if (roleList == null) {
			return null;
		}
		List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
		for (Role role : roleList) {
			Map<String, Object> dataMap = new HashMap<String, Object>();
			dataMap.put("id", role.getId());
			dataMap.put("text", role.getName());
			dataList.add(dataMap);
		}
		return dataList;
	}
}
