package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.RouterDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.PortModel;
import com.bocloud.cmp.model.RouterBean;
import com.bocloud.cmp.model.RouterModel;
import com.bocloud.cmp.provider.utils.IPAddress;
import com.bocloud.common.model.*;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.utils.*;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.entity.resource.manageone.ManageOneAccount;
import com.bocloud.ims.interfaces.manageone.ManageOneAccountService;
import com.bocloud.ims.interfaces.resource.RouterService;
import com.bocloud.ims.interfaces.resource.SubnetService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.transportor.OpenstackTransportor;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * 路由Service接口实现
 *
 * @author weiwei
 */
@Service("routerService")
public class RouterServiceImpl implements RouterService {

	private static Logger logger = LoggerFactory.getLogger(RouterServiceImpl.class);
	@Autowired
	private RouterRepository routerRepository;
	@Autowired
	private SubnetRepository subnetRepository;
	@Autowired
	private PortRepository portRepository;
	@Autowired
	private IpRepository ipRepository;
	@Autowired
	private IpPoolRepository ipPoolRepository;
	@Autowired
	private NetworkRepository networkRepository;
	@Autowired
	private VpcRepository vpcRepository;
	@Autowired
	private FloatingIpRepository floatingIpRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private RouterDriver routerDriver;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private PortFixedIpRepository portFixedIpRepository;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;
	@Autowired
	private ObjectRelationRepository objectRelationRepository;
	@Autowired
	private RouterSubnetRepository routerSubnetRepository;
	@Autowired
	private SmsProjectService smsProjectService;
	@Autowired
	private SubnetService subnetService;
	@Autowired
	private OSTenantRepository osTenantRepository;
	@Autowired
	private ManageOneAccountService accountService;
	@Autowired
	private AmqpTemplate amqpTemplate;

	@Override
	public BocloudResult<GridBean<Router>> list(Pager pager, RequestContext context) {
		GridBean gridBean = null;
		List<Router> list = Lists.newArrayList();
		int total = 0;
		try {

			int page = pager.getPage();
			int rows = pager.getRows();
			List<Param> params = pager.getParams();
			Map<String, String> sorter = pager.getSorter();
			boolean simple = pager.getSimple();

			if (null == params) {
				params = new ArrayList<>();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			Long tenantId = context.getTenant();
			String type = null;
			params = Optional.ofNullable(params).orElse(new ArrayList<>());
			for (Param param : params) {
				Map<String, Object> paramMap = param.getParam();
				if (paramMap.containsKey("type")) {
					type = paramMap.get("type") == null ? null : paramMap.get("type").toString();
					paramMap.remove("type");
				}
			}
			Catalog catalog = context.getCatalog();
			// 为租户下的用户
			if (Catalog.Tenant == catalog || Catalog.User == catalog) {
				String vendorType = null;
				for (Param param : params) {
					Map<String, Object> paramMap = param.getParam();
					if (paramMap.containsKey("vendorType")) {
						vendorType = String.valueOf(paramMap.get("vendorType"));
						paramMap.remove("vendorType");
					}
				}
				total = this.routerRepository.count(params, tenantId, null, vendorType);
				list = this.routerRepository.list(page, rows, params, sorter, tenantId, null, vendorType);
				gridBean = GridHelper.getBean(page, rows, total, list);
			} else {
				total = routerRepository.count(params);
				if (simple) {
					if (0 == context.getTenant()) {
						params.add(new Param(MapTools.simpleMap(Common.TENANTID, 0), Sign.EQ));
					}
					List<SimpleBean> beans = routerRepository.list(params, sorter);
					gridBean = new GridBean(1, 1, total, beans);
				} else {
					list = this.routerRepository.list(page, rows, params, sorter);
					gridBean = GridHelper.getBean(page, rows, total, list);
				}
			}
			return new BocloudResult<>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list router fail:", e);
			return new BocloudResult<>(false, "查询失败", null, null);
		}
	}

	@Override
	public BocloudResult<Router> create(Router router, RequestContext context) {
		try {
			Long tenantId = context.getTenant();
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null == vendor) {
				logger.error("get cloud vendor failure!");
				return new BocloudResult<>(false, "平台不存在");
			}
			if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
					|| CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
				Router routerByName = routerRepository.getByName(router.getVendorId(), router.getName());
				if (routerByName != null) {
					return new BocloudResult<>(false, "该名称已存在");
				}
			}
			RouterModel model = JSONObject.parseObject(JSONObject.toJSONString(router), RouterModel.class);
			Long networkId = null;
			if (null != router.getNetworkId()) {
				Network network = networkRepository.query(router.getNetworkId());
				if (null != network) {
					networkId = network.getId();
					model.setNetworkUuid(network.getNetworkUuid());
				}
			}
			if (null != router.getVpcId()) {
				Vpc vpc = vpcRepository.query(router.getVpcId());
				if (null != vpc) {
					model.setVpcUuid(vpc.getVpcId());
				}
			}
			if (0 != tenantId) {
				model.setAdminStateup(true);
			}
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.create(model, vendor.getUuid(), account.getUsername(), account.getPassword(),
						account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.create(model, vendor.getUuid(), router.getOsTenantName(), router.getRegionId());
			}
			if (result.isFailed()) {
				return new BocloudResult<>(false, result.getMessage());
			}
			model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), RouterModel.class);
			BeanUtils.copyProperties(model, router);
			router.setRegionId(router.getRegionId());
			router.preSave(context.getTarget(), context.getTarget(), vendor.getId(), networkId, tenantId,
					context.getProject());
			routerRepository.save(router);
			// 发送给云平台统计队列对云平台重新统计
			JSONObject jsonObject = new JSONObject();
			jsonObject.put(Common.VENDORID, vendor.getId());
			amqpTemplate.convertAndSend("vendor.statistics.queue", jsonObject);
			return new BocloudResult<>(true, router, "创建成功!");
		} catch (Exception e) {
			logger.error("create router failure:", e);
			return new BocloudResult<>(false, "创建失败!");
		}
	}

	@Override
	public BocloudResult<String> remove(Long id, RequestContext context) {
		String path = Router.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			Router router = routerRepository.query(id);
			if (null == router) {
				logger.warn("router data not exist");
				return new BocloudResult<>(false, "数据不存在");
			}
			List<Subnet> subnets = subnetRepository.listByRouterId(id);
			if (!subnets.isEmpty()) {
				return new BocloudResult<>(false, "删除失败：存在子网!");
			}
			// 云供应商
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null == vendor) {
				logger.error("get cloud vendor failure");
				return new BocloudResult<>(false, "平台不存在");
			}
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.remove(router.getRouterUuid(), vendor.getUuid(), account.getUsername(),
						account.getPassword(), account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.remove(router.getRouterUuid(), vendor.getUuid(), router.getRegionId());
			}
			if (result.isFailed()) {
				return new BocloudResult<>(false, "删除失败：" + result.getMessage());
			}
			ObjectRelation objectRelation = objectRelationRepository.get(id, ResourceCategory.Router.name());
			if (null != objectRelation && router.getTenantId() > 0L) {
				objectRelationRepository.deleteByRid(id, ResourceCategory.Router.name());
			}
			routerRepository.remove(id, context.getTarget());
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType())) {
				vpcRepository.deleteByRouterId(router.getId(), vendor.getId(), context.getTarget());
			}
			// 发送给云平台统计队列对云平台重新统计
			JSONObject jsonObject = new JSONObject();
			jsonObject.put(Common.VENDORID, vendor.getId());
			amqpTemplate.convertAndSend("vendor.statistics.queue", jsonObject);
			return new BocloudResult<>(true, "删除成功");
		} catch (Exception e) {
			logger.error("remove router fail:", e);
			return new BocloudResult<>(false, "删除失败");
		}
	}

	@Override
	public BocloudResult<Router> detail(Long id) {
		try {
			Router router = routerRepository.query(id);
			if (null == router) {
				return new BocloudResult<>(false, "查询详情失败!");
			}
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null != vendor) {
				router.setVendorName(vendor.getName());
			}
			if (!StringUtils.isEmpty(router.getTenantUuid())) {
				OSTenant osTenant = osTenantRepository.getByTenantUuid(router.getTenantUuid(), router.getVendorId());
				if (null != osTenant) {
					router.setOsTenantName(osTenant.getName());
				}
			}
			return new BocloudResult<>(true, router, "查询成功!");
		} catch (Exception e) {
			logger.error("query router detail failure:", e);
			return new BocloudResult<>(false, "查询详情失败!");
		}
	}

	@Override
	public BocloudResult<Router> modify(RouterBean bean, RequestContext context) {
		String path = Router.class.getSimpleName() + "_" + bean.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			Router router = routerRepository.query(bean.getId());
			if (null == router) {
				logger.warn("router data not exist");
				return new BocloudResult<>(false, "数据不存在");
			}
			// 云供应商
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult<>(false, "修改失败");
			}
			if (CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())) {
				if (!bean.getName().equals(router.getName())) {
					Router routerByName = routerRepository.getByName(vendor.getId(), bean.getName());
					if (routerByName != null) {
						return new BocloudResult<>(false, "该路由名称已存在");
					}
				}
			}
			RouterModel model = new RouterModel();
			model.setRouterUuid(router.getRouterUuid());
			model.setName(bean.getName());
			if (0 == context.getTenant()) {
				model.setAdminStateup(bean.getAdminStateup());
			} else {
				model.setAdminStateup(router.getAdminStateup());
			}
			model.setRemark(bean.getRemark());
			if (null != bean.getVpcId()) {
				Vpc vpc = vpcRepository.query(bean.getVpcId());
				if (null != vpc) {
					model.setVpcUuid(vpc.getVpcId());
				}
			}
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.modify(model, vendor.getUuid(), account.getUsername(), account.getPassword(),
						account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.modify(model, vendor.getUuid(), router.getRegionId());
			}
			if (result.isFailed()) {
				return new BocloudResult<>(false, "修改失败");
			}
			BeanUtils.copyProperties(bean, router);
			router.setMenderId(context.getTarget());
			routerRepository.update(router);
			return new BocloudResult<>(true, router, "修改路由成功");
		} catch (Exception e) {
			logger.error("modify router fail:", e);
			return new BocloudResult<>(false, "修改路由失败");
		}
	}

	@Override
	public BocloudResult<String> attach(Long id, Long subnetId, String address, Long portId, RequestContext context) {
		try {
			Router router = routerRepository.query(id);
			if (null == router) {
				return new BocloudResult<>(false, "路由不存在");
			}
			Subnet subnet = subnetRepository.query(subnetId);
			if (null == subnet) {
				return new BocloudResult<>(false, "子网不存在");
			}
			RouterModel model = new RouterModel();
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null == vendor) {
				logger.error("get cloud vendor failure");
				return new BocloudResult<>(false, "平台不存在");
			}
			CloudProvider provider = CloudProvider.valueOf(vendor.getType());
			switch (provider) {
			case OPENSTACK:
				if (StringUtils.isEmpty(subnet.getGateway())) {
					return new BocloudResult<>(false, "子网网关不存在");
				}
				// 指定了IP地址
				if (!StringUtils.isEmpty(address)) {
					Network network = networkRepository.query(subnet.getNetworkId());
					if (null == network) {
						return new BocloudResult<>(false, "连接子网所在网络不存在");
					}
					model.setAttachNetworkUuid(network.getNetworkUuid());
					Ip ip = ipRepository.checkExist(address, subnetId, subnet.getVendorId());
					if (null != ip) {
						return new BocloudResult<>(false, "连接子网失败：该IP已被其他资源使用");
					}
					// 校验IP是否在子网范围内
//                        IpPool ipPool = ipPoolRepository.queryBySubnet(subnetId, subnet.getVendorId());
//                        if (null == ipPool) {
//                            ipPool = new IpPool(subnet.getGateway(), subnet.getCidr(), subnet.getIpPools(),
//                                    subnet.getDnsNames(), subnetId, network.getId(), subnet.getVendorId());
//                            ipPool.setCreatorId(context.getTarget());
//                            ipPool.setMenderId(context.getTarget());
//                            ipPool.setVersion(IPAddress.getVersion(subnet.getGateway()));
//                            ipPoolRepository.save(ipPool);
//                        }
					List<String> pools = JSONArray.parseArray(subnet.getIpPools(), String.class);
					if (ListTool.isEmpty(pools)) {
						return new BocloudResult<>(false, "连接子网失败：该子网IP地址池分配有误");
					}
					IPAddress ipAddress = IPAddress.getIPAddress(address);
					boolean flag = ipAddress.isInPools(address, pools);
					if (!flag) {
						return new BocloudResult<>(false, "连接子网失败：该IP不在该子网的网段内");
					}
					ip = new Ip(address, ipAddress.getMask(subnet.getCidr()), subnet.getGateway(), subnet.getDnsNames(),
							subnet.getVendorId(), IDFactory.instance().uuid(), null, IpStatus.used);
					ip.setCatalog("PORT");
					ip.setNetworkId(subnet.getNetworkId());
					ip.setSubnetId(subnet.getId());
					ipRepository.save(ip);
				}
				model.setRouterUuid(router.getRouterUuid());
				model.setSubnetUuid(subnet.getSubnetUuid());
				model.setAddress(address);
				break;
			case FUSIONCLOUD:
			case MANAGEONE:
				if (null != portId && 0L != portId) {
					Port port = portRepository.query(portId);
					if (null == port) {
						return new BocloudResult<>(false, "端口不存在");
					}
					List<PortFixedIp> portFixedIps = portFixedIpRepository.listByPortId(portId);
					if (ListTool.isEmpty(portFixedIps)) {
						return new BocloudResult<>(false, "端口Ip地址为空");
					}
					if (portFixedIps.size() > 1) {
						return new BocloudResult<>(false, "连接子网的端口只能有一个IP地址");
					}
					model.setPortUuid(port.getPortUuid());
				} else {
					if (StringUtils.isEmpty(subnet.getGateway())) {
						return new BocloudResult<>(false, "子网网关地址不存在");
					}
					model.setSubnetUuid(subnet.getSubnetUuid());
				}
				model.setRouterUuid(router.getRouterUuid());
				break;
			case HUAWEI:
				if (null != portId && 0L != portId) {
					Port port = portRepository.query(portId);
					if (null == port) {
						return new BocloudResult<>(false, "端口不存在");
					}
					List<PortFixedIp> portFixedIps = portFixedIpRepository.listByPortId(portId);
					if (ListTool.isEmpty(portFixedIps)) {
						return new BocloudResult<>(false, "端口Ip地址为空");
					}
					if (portFixedIps.size() > 1) {
						return new BocloudResult<>(false, "连接子网的端口只能有一个IP地址");
					}
					model.setPortUuid(port.getPortUuid());
				} else {
					if (StringUtils.isEmpty(subnet.getGateway())) {
						return new BocloudResult<>(false, "子网网关地址不存在");
					}
					model.setSubnetUuid(subnet.getSubnetUuid());
				}
				model.setRouterUuid(router.getRouterUuid());
				break;
			default:
				break;
			}
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.attach(model, vendor.getUuid(), account.getUsername(), account.getPassword(),
						account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.attach(model, vendor.getUuid(), null);
			}
			if (result.isFailed()) {
				if (!StringUtils.isEmpty(address)) {
					ipRepository.delete(address, subnetId, subnet.getVendorId());
				}
				return new BocloudResult<>(false, result.getMessage());
			}
			PortModel portModel = (PortModel) result.getData();
			Port port = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), Port.class);
			Long userId = context.getTarget();
			port.preSave(userId, userId, router.getVendorId(), subnet.getNetworkId());
			port.setStatus(BocloudStatus.Network.RUNNING.name());
			portRepository.save(port);
			// 保存固定IP
			OpenstackTransportor toolOS = new OpenstackTransportor(ipRepository, ipPoolRepository, subnetRepository,
					portFixedIpRepository);
			toolOS.batchSavePortFixedIp(portModel.getPortFixedIps(), port.getPortUuid(), port.getId(), vendor.getId());
			subnet.setMenderId(userId);
			subnetRepository.update(subnet);
			RouterSubnet routerSubnet = new RouterSubnet(router.getId(), subnet.getId(), vendor.getId());
			routerSubnetRepository.save(routerSubnet);

			return new BocloudResult<>(true, "连接子网成功");
		} catch (Exception e) {
			logger.error("Attach subnet to router failure:", e);
			return new BocloudResult<>(false, "连接子网失败");
		}
	}

	@Override
	public BocloudResult<String> detach(Long id, Long subnetId, RequestContext context) {
		try {
			Router router = routerRepository.query(id);
			Assert.notNull(router, "路由不存在");
			Subnet subnet = subnetRepository.query(subnetId);
			Assert.notNull(subnet, "子网不存在");
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			Assert.notNull(vendor, "平台不存在");
			RouterModel model = new RouterModel();
			model.setRouterUuid(router.getRouterUuid());
			model.setSubnetUuid(subnet.getSubnetUuid());
			String device = "network:router_interface";
			if (CloudProvider.HUAWEI.name().equals(vendor.getType())) {
				device = "network:router_interface_distributed";
			}
			List<Port> ports = portRepository.listBySubnetId(subnetId, device);
			Long portId = null;
			String portUuid = null;
			if (!ListTool.isEmpty(ports)) {
				for (Port port : ports) {
					if (router.getRouterUuid().equals(port.getDeviceUuid())) {
						portId = port.getId();
						portUuid = port.getPortUuid();
						break;
					}
				}
			}
			model.setPortUuid(portUuid);
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.detach(model, vendor.getUuid(), account.getUsername(), account.getPassword(),
						account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.detach(model, vendor.getUuid(), null);
			}
			if (result.isFailed()) {
				return new BocloudResult<>(false, "断开子网失败：" + result.getMessage());
			}
			subnet.setMenderId(context.getTarget());
			subnetRepository.update(subnet);
			routerSubnetRepository.remove(router.getId(), subnetId, router.getVendorId());
			// 删除端口
			if (null != portId) {
				List<PortFixedIp> fixedIps = portFixedIpRepository.listByPortId(portId);
				for (PortFixedIp fixedIp : fixedIps) {
					// 释放IP
					ipRepository.delete(fixedIp.getIpAddress(), fixedIp.getSubnetId(), vendor.getId());
				}
				portFixedIpRepository.deleteByPortId(portId);
				portRepository.remove(portId, context.getTarget());
			}
			return new BocloudResult<>(true, "断开子网成功");
		} catch (Exception e) {
			logger.error("Detach subnet from router failure:", e);
			return new BocloudResult<>(false, "断开子网失败");
		}
	}

	@Override
	public BocloudResult<String> config(Long id, Long networkId, RequestContext context, String params) {
		String path = Router.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			Router router = routerRepository.query(id);
			if (null == router) {
				logger.warn("router data not exist");
				return new BocloudResult<>(false, "路由不存在");
			}
			if (null == networkId) {
				JSONObject object = JSONObject.parseObject(params);
				networkId = object.getLong("networkId");
			}
			Network network = networkRepository.query(networkId);
			if (null == network) {
				logger.warn("network data not exist");
				return new BocloudResult<>(false, "网络不存在");
			}
			// 云供应商
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null == vendor) {
				logger.error("get cloud vendor failure");
				return new BocloudResult<>(false, "平台不存在");
			}
			RouterModel model = new RouterModel();
			model.setRouterUuid(router.getRouterUuid());
			model.setNetworkUuid(network.getNetworkUuid());
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.config(model, vendor.getUuid(), account.getUsername(), account.getPassword(),
						account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.config(model, vendor.getUuid(), "");
			}
			if (result.isFailed()) {
				return new BocloudResult<>(false, "设置网关失败");
			}
			model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), RouterModel.class);
			router.setEnableSnat(model.getEnableSnat());
			router.setNetworkUuid(model.getNetworkUuid());
			router.setNetworkId(networkId);
			router.setMenderId(context.getTarget());
			routerRepository.update(router);
			return new BocloudResult<>(true, "设置网关成功");
		} catch (Exception e) {
			logger.error("Config router's gateway fail:", e);
			return new BocloudResult<>(false, "设置网关失败");
		}
	}

	@Override
	public BocloudResult<String> clear(Long id, RequestContext context) {
		String path = Router.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			Router router = routerRepository.query(id);
			if (null == router) {
				logger.warn("router data not exist");
				return new BocloudResult<>(false, "数据不存在");
			}
			List<FloatingIp> fIps = floatingIpRepository.listByRouterId(id);
			for (FloatingIp fIp : fIps) {
				if (null != fIp.getPortId()) {
					return new BocloudResult<>(false, "该路由连接的子网下有端口和浮动IP关联，无法清除网关");
				}
			}
			// 云供应商
			CloudVendor vendor = cloudVendorRepository.query(router.getVendorId());
			if (null == vendor) {
				logger.error("get cloud vendor failure");
				return new BocloudResult<>(false, "平台不存在");
			}
			BocloudResult result = null;
			if (CloudProvider.MANAGEONE.name().equals(vendor.getType()) && null != context.getTenant()
					&& 0L != context.getTenant()) {
				ManageOneAccount account = accountService.queryAccount(vendor.getId(), context.getTenant());
				Assert.notNull(account, "认证失败！");
				result = routerDriver.clear(router.getRouterUuid(), vendor.getUuid(), account.getUsername(),
						account.getPassword(), account.getProjectId(), account.getDomainName());
			} else {
				result = routerDriver.clear(router.getRouterUuid(), vendor.getUuid(), "");
			}
			if (result.isFailed()) {
				return new BocloudResult<>(false, "清除网关失败");
			}
			router.setEnableSnat(null);
			router.setNetworkUuid(null);
			router.setNetworkId(null);
			router.setMenderId(context.getTarget());
			routerRepository.update(router);
			return new BocloudResult<>(true, "清除网关成功");
		} catch (Exception e) {
			logger.error("Clear router's gateway fail:", e);
			return new BocloudResult<>(false, "清除网关失败");
		}
	}

	@Override
	public BocloudResult<String> batchRemove(List<Long> ids, RequestContext context) {
		if (ListTool.isEmpty(ids)) {
			return new BocloudResult<>(false, "没有需要删除的路由！");
		}
		try {
			List<BocloudResult> succList = Lists.newArrayList();
			List<BocloudResult> failList = Lists.newArrayList();
			Long vendorId = null;
			for (Long id : ids) {
				Router router = routerRepository.query(id);
				if (null != router) {
					if (null == vendorId) {
						vendorId = router.getVendorId();
					}
					BocloudResult result = remove(id, context);
					if (result.isSuccess()) {
						succList.add(new BocloudResult<>(true, "【" + router.getName() + "】删除成功"));
					} else {
						failList.add(
								new BocloudResult<>(false, "【" + router.getName() + "】删除失败：" + result.getMessage()));
					}
				}
			}
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			String operate = vendor.getType().toLowerCase() + ".router";
			// 删除成功的数量
			int success = succList.size();
			// 删除失败的数量
			int fail = failList.size();
			String content = null;
			if (fail == ids.size()) {
				content = "云路由批量删除失败，详情如下：\n";
				for (BocloudResult bocloudResult : failList) {
					content += bocloudResult.getMessage() + "\n";
				}
				resourceEventPublisher.send(
						new OperateResult(false, content, operate, MapTools.simpleMap(Common.VENDORID, vendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
			} else {
				content = "云路由批量删除成功【" + success + "】个,失败【" + fail + "】个，详情如下：\n";
				for (BocloudResult bocloudResult : succList) {
					content += bocloudResult.getMessage() + "\n";
				}
				for (BocloudResult bocloudResult : failList) {
					content += bocloudResult.getMessage() + "\n";
				}
				resourceEventPublisher.send(
						new OperateResult(true, content, operate, MapTools.simpleMap(Common.VENDORID, vendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
			}
		} catch (Exception e) {
			logger.error("batch remove router fail:", e);
			return new BocloudResult<>(false, "批量删除任务下发失败");
		}
		return new BocloudResult<>(true, "批量删除任务已下发，正在执行...");
	}

	@Override
	public BocloudResult<Integer> count(Long userId, Long projectId, Long tenantId) {
		try {
			List<Param> params = Lists.newArrayList();
			Catalog catalog = Catalog.Tenant;
			Long target = tenantId;
			if (null != userId) {
				target = userId;
				catalog = Catalog.User;
			}
			List<Project> projects = smsProjectService.projectsByCondition(target, catalog);
			List<Long> projectIds = new ArrayList<>();
			// 此时查询的是全部用户全部项目的信息
			if (null != projectId && 0L != projectId) {
				projectIds.add(projectId);
			} else if (!ListTool.isEmpty(projects)) {
				projects.forEach(project -> projectIds.add(project.getId()));
			} else {
				// 当前用户不属于任何项目，则登录之后查看不到任何信息
				projectIds.add(-1L);
			}
			Integer total = this.routerRepository.count(params, null, projectIds);
			return new BocloudResult<>(true, total, "查询成功");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult<>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<List<Router>> listNetAndSubNet(String params, RequestContext context) {
		try {
			JSONObject object = JSONObject.parseObject(params);
			// 云平台ID
			Long vendorId = object.getLong(Common.VENDORID);
			String regionId = object.getString("regionId");
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			List<Router> routerList = new ArrayList<>();
			switch (CloudProvider.valueOf(vendor.getType())) {
			case HUAWEI:
				routerList = routerRepository.listByVid(vendorId, regionId);
				if (ListTool.isEmpty(routerList)) {
					return new BocloudResult<>(false, "该云平台下没有可用网络");
				}
				List<Long> subList = null;
				for (Router router : routerList) {
					List<RouterSubnet> byRouter = routerSubnetRepository.listByRouter(router.getId());
					subList = new ArrayList<>();
					for (RouterSubnet routerSubnet : byRouter) {
						Long subnetId = routerSubnet.getSubnetId();
						subList.add(subnetId);
					}
					List<Subnet> subnetList = subnetRepository.listByIds(buildParam(subList));
					if (null != subList && subnetList.size() > 0) {
						router.setSubnets(subnetList);
					}
				}
				break;
			default:
				break;
			}
			return new BocloudResult<>(true, routerList, "查询成功");
		} catch (Exception e) {
			logger.error("list network and subnet error：", e);
			return new BocloudResult<>(false, "查询网络失败");
		}
	}

	private String buildParam(List<Long> subList) {
		StringBuilder builder = new StringBuilder("(");
		if (null != subList && subList.size() > 0) {
			for (Long id : subList) {
				builder.append(id).append(",");
			}
			builder.append(" -1 )");
		}
		return builder.toString();
	}

	@Override
	public BocloudResult routers(String condition, RequestContext context) {
		JSONObject object = JSONObject.parseObject(condition);

		String action = object.getString("condition");
		if ("count".equalsIgnoreCase(action)) {
			Long projectId = object.getLong("projectId");
			Long tenantId = object.getLong("tenantId");
			return this.count(context.getTarget(), projectId, tenantId);
		} else if ("listNetAndSubNet".equalsIgnoreCase(action)) {
			return this.listNetAndSubNet(condition, context);
		} else if ("firewall".equalsIgnoreCase(action)) {
			return listByFirewall(condition, context);
		} else {
			return ResultTools.formatErrResult();
		}
	}

	private BocloudResult<List<Router>> listByFirewall(String condition, RequestContext context) {
		try {
			JSONObject object = JSONObject.parseObject(condition);
			Long vendorId = object.getLong("vendorId");
			Long projectId = context.getProject();
			List<Project> projects = smsProjectService.projectsByCondition(context.getTarget(), context.getCatalog());
			List<Long> projectIds = new ArrayList<>();
			// 此时查询的是全部用户全部项目的信息
			if (null != projectId && 0L != projectId) {
				projectIds.add(projectId);
			} else if (!ListTool.isEmpty(projects)) {
				projects.forEach(project -> projectIds.add(project.getId()));
			} else {
				// 当前用户不属于任何项目，则登录之后查看不到任何信息
				projectIds.add(-1L);
			}
			List<Router> routers = routerRepository.listUnBingFirewall(vendorId, projectIds);
			return new BocloudResult<>(true, routers, "查询成功！");
		} catch (Exception e) {
			logger.error("查询VPC失败：" + e.getMessage());
			return new BocloudResult<>(false, "查询失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult<String> operation(Long id, Long networkId, String action, String params,
			RequestContext context) {
		if ("config".equalsIgnoreCase(action)) { // 设置网关
			return this.config(id, networkId, context, params);
		}
		if ("clear".equalsIgnoreCase(action)) {
			return this.clear(id, context);
		}
		return new BocloudResult<>(false, "未知类型");
	}

	@Override
	public BocloudResult<List<Subnet>> listSubnets(Pager pager, String condition, RequestContext context) {
		JSONObject object = JSONObject.parseObject(condition);
		if (null == object) {
			return new BocloudResult<>(false, "未知类型！");
		}
		String action = object.getString("condition");
		if ("listattachbyrouter".equalsIgnoreCase(action)) { // 查询指定路由连接的子网
			return subnetService.listAttachByRouter(object.getLong(Common.VENDORID), object.getLong("routerId"));
		} else if ("listdetachbyrouter".equals(action)) { // 查询未连接该路由的子网
			return subnetService.listDetachByRouter(object.getLong(Common.VENDORID), object.getLong("routerId"),
					object.getLong("networkId"), object.getString("tenantUuid"));
		} else if ("listbyvendor".equals(action)) { // 查询云平台下子网
			return subnetService.listByVendorId(object.getLong(Common.VENDORID), object.getLong("networkId"),
					object.getString("tenantUuid"));
		} else {
			return ResultTools.formatErrResult();
		}
	}

}
