package com.bocloud.ims.service.resource.azure;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.NetworkInterfaceDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.NetworkInterfaceModel;
import com.bocloud.cmp.model.NotifyMessage;
import com.bocloud.cmp.model.azure.network.NicIpConfigurationModel;
import com.bocloud.cmp.params.azure.NetworkInterfaceOperationParams;
import com.bocloud.cmp.params.azure.NicChangeSubnetParams;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.AzureIpRelationType;
import com.bocloud.ims.common.enums.AzureTaskStatus;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.azure.network.NicIpConfiguration;
import com.bocloud.ims.entity.resource.azure.network.PublicIPAddress;
import com.bocloud.ims.entity.resource.azure.network.ResourcePublicIPAddressRelation;
import com.bocloud.ims.interfaces.resource.azure.NetworkInterfaceService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.repository.resource.azure.network.NicIpConfigurationRepository;
import com.bocloud.ims.repository.resource.azure.network.PublicIPAddressRepository;
import com.bocloud.ims.repository.resource.azure.network.ResourcePublicIPAddressRelationRepository;
import com.bocloud.ims.service.internal.SmsProjectService;
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.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: NetworkInterfaceServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2019/9/29 15:08
 */
@Service("networkInterfaceService")
public class NetworkInterfaceServiceImpl implements NetworkInterfaceService {

	private static Logger logger = LoggerFactory.getLogger(NetworkInterfaceServiceImpl.class);

	private static OperateResult.OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;

	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private NetworkInterfaceRepository networkInterfaceRepository;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private NetworkInterfaceDriver networkInterfaceDriver;
	@Autowired
	private VpcRepository vpcRepository;
	@Autowired
	private CloudServerRepository cloudServerRepository;
	@Autowired
	private SubnetRepository subnetRepository;
	@Autowired
	private SecurityGroupRepository securityGroupRepository;
	@Autowired
	private ServerSgroupRepository serverSgroupRepository;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;
	@Autowired
	private ResourceEventRepository resourceEventRepository;
	@Autowired
	private SmsProjectService smsProjectService;
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;
	@Autowired
	private ResourceGroupRepository resourceGroupRepository;
	@Autowired
	private AmqpTemplate amqpTemplate;
	@Autowired
	private NicIpConfigurationRepository nicIpConfigurationRepository;
	@Autowired
	private PublicIPAddressRepository publicIPAddressRepository;
	@Autowired
	private ResourcePublicIPAddressRelationRepository resourcePublicIPAddressRelationRepository;

	@Override
	public BocloudResult<GridBean<NetworkInterface>> list(Pager pager, RequestContext context) {
		List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
		Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
		sorter.put("gmtCreate", Common.ONE);
		Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
		Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
		Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
		try {
			GridBean<NetworkInterface> gridBean;
			List<NetworkInterface> list;
			int total;
			Long tenantId = context.getTenant();
			Long projectId = context.getProject();
			if (null != tenantId && 0L != tenantId) {
				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);
				}
				total = this.networkInterfaceRepository.count(params, null, projectIds);
				list = this.networkInterfaceRepository.list(page, rows, params, sorter, null, projectIds);
			} else {
				total = networkInterfaceRepository.count(params);
				list = networkInterfaceRepository.list(page, rows, params, sorter);
			}
			for (NetworkInterface networkInterface : list) {
				if (!StringUtils.isEmpty(networkInterface.getSgroupUuid())) {
					List<String> awsGroupNames = new ArrayList<>();
					JSONArray sgroupsArray = JSONObject.parseArray(networkInterface.getSgroupUuid());
					if (null != sgroupsArray && sgroupsArray.size() > 0) {
						for (int i = 0; i < sgroupsArray.size(); i++) {
							SecurityGroup securityGroup = securityGroupRepository
									.getByGroupUuid(sgroupsArray.get(i).toString(), networkInterface.getVendorId());
							if (!ObjectUtils.isEmpty(securityGroup)) {
								awsGroupNames.add(securityGroup.getAwsGroupName());
							}
						}
						networkInterface.setAwsGroupNames(awsGroupNames);
					}
				}
			}
			gridBean = new GridBean<>(page, rows, total, list);
			return new BocloudResult<>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list networkInterface failure:", e);
			return new BocloudResult<>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<NetworkInterface> detail(Long id, RequestContext context) {
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(id);
			CloudVendor cloudVendor = cloudVendorRepository.query(networkInterface.getVendorId());
			Assert.notNull(cloudVendor, "云平台不存在");
			switch (CloudProvider.valueOf(cloudVendor.getType())) {
			case ALIYUN:
				if (!StringUtils.isEmpty(networkInterface.getSgroupUuid())) {
					List<String> groupNames = new ArrayList<>();
					JSONArray sgroupsArray = JSONObject.parseArray(networkInterface.getSgroupUuid());
					for (int i = 0; i < sgroupsArray.size(); i++) {
						SecurityGroup securityGroup = securityGroupRepository.getByGroupUuid(sgroupsArray.get(i).toString(),
								networkInterface.getVendorId());
						if (!ObjectUtils.isEmpty(securityGroup)) {
							groupNames.add(securityGroup.getName());
						}
					}
					networkInterface.setAwsGroupNames(groupNames);
				}
				break;
			default:
				if (!StringUtils.isEmpty(networkInterface.getSgroupUuid())) {
					List<String> awsGroupNames = new ArrayList<>();
					JSONArray sgroupsArray = JSONObject.parseArray(networkInterface.getSgroupUuid());
					for (int i = 0; i < sgroupsArray.size(); i++) {
						SecurityGroup securityGroup = securityGroupRepository.getByGroupUuid(sgroupsArray.get(i).toString(),
								networkInterface.getVendorId());
						if (!ObjectUtils.isEmpty(securityGroup)) {
							awsGroupNames.add(securityGroup.getAwsGroupName());
						}
					}
					networkInterface.setAwsGroupNames(awsGroupNames);
				}
				break;
			}
			return new BocloudResult<>(true, networkInterface, "查询详情成功");
		} catch (Exception e) {
			logger.error("query networkInterface fail:", e);
			return new BocloudResult<>(false, "查询详情失败");
		}
	}

	@Override
	public BocloudResult<Void> remove(Long id, RequestContext context) {
		String path = ResourceGroup.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			NetworkInterface entity = networkInterfaceRepository.query(id);
			Assert.notNull(entity, "数据不存在");
			CloudVendor vendor = cloudVendorRepository.query(entity.getVendorId());
			Assert.notNull(vendor, "平台验证失败");
			CloudProvider provider = CloudProvider.valueOf(vendor.getType());
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".networkInterface";
				String message = "删除网络接口失败";
				BocloudResult result = networkInterfaceDriver.remove(vendor.getUuid(), entity.getRegionId(),
						entity.getNetworkInterfaceUuid());
				try {
					if (result.isSuccess()) {
						message = "删除网络接口成功";
						networkInterfaceRepository.delete(id, context.getTarget());
						if (provider == CloudProvider.AZURE) {
							List<NicIpConfiguration> nicIpConfigurations = nicIpConfigurationRepository
									.listByNetworkInterfaceId(id);
							for (NicIpConfiguration nicIpConfiguration : nicIpConfigurations) {
								List<ResourcePublicIPAddressRelation> addressRelations = resourcePublicIPAddressRelationRepository
										.listByResourceId(nicIpConfiguration.getId(),
												AzureIpRelationType.NICIPCONFIGURATION.name());
								for (ResourcePublicIPAddressRelation relation : addressRelations) {
									PublicIPAddress publicIPAddress = publicIPAddressRepository
											.query(relation.getIpId());
									if (!ObjectUtils.isEmpty(publicIPAddress)) {
										// 重置状态
										publicIPAddress.setStatus(AzureTaskStatus.AVAILABLE.name());
										publicIPAddressRepository.update(publicIPAddress);
									}
								}
								// 删除绑定关系
								resourcePublicIPAddressRelationRepository.removeByResourceId(nicIpConfiguration.getId(),
										AzureIpRelationType.NICIPCONFIGURATION.name());
								nicIpConfigurationRepository.delete(nicIpConfiguration.getId());
							}
						}
					} else {
						logger.error("删除网络接口失败：" + result.getMessage());
						message = result.getMessage();
					}
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
					// 站内信推送
					NotifyMessage notifyMessage = new NotifyMessage(context, "提示:", message, null, true, false);
					amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
				} catch (Exception e) {
					logger.error("remove networkInterface fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult<>(true, "任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("remove networkInterface fail:", e);
			return new BocloudResult<>(false, "删除网络接口失败");
		}
	}

	@Override
	public BocloudResult<Void> create(NetworkInterface entityParams, RequestContext context) {
		try {
			CloudVendor vendor = cloudVendorRepository.query(entityParams.getVendorId());
			Assert.notNull(vendor, "平台验证失败");
			Vpc vpc = vpcRepository.query(entityParams.getVpcId());
			Assert.notNull(vpc, "网络不存在");
			// 开启个性化验证
			ResourceGroup resourceGroup = null;
			Subnet subnet = null;
			CloudProvider provider = CloudProvider.valueOf(vendor.getType());
			switch (provider) {
			case AWS:
			case ALIYUN:
				if (!StringUtils.isEmpty(entityParams.getResourceGroupUuid())) {
					resourceGroup = resourceGroupRepository.getByUuid(entityParams.getResourceGroupUuid(),
							vendor.getId());
					if (null == resourceGroup) {
						logger.error("get resourceGroup failure");
						return new BocloudResult(false, "资源组不存在");
					}
				} else {
					resourceGroup = resourceGroupRepository.getByName(vendor.getId(), "default");
					if (null != resourceGroup) {
						entityParams.setResourceGroupUuid(resourceGroup.getResourceGroupUuid());
					}
				}
				subnet = subnetRepository.query(entityParams.getSubnetUuid(), entityParams.getVendorId());
				Assert.notNull(subnet, "子网不存在");
				break;
			case AZURE:
				subnet = subnetRepository.query(entityParams.getSubnetId());
				Assert.notNull(subnet, "子网不存在");
				resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
				Assert.notNull(resourceGroup, "资源组不存在");
				break;
			default:
				break;
			}
			Subnet newSubnet = subnet;
			NetworkInterfaceModel model = new NetworkInterfaceModel();
			BeanUtils.copyProperties(entityParams, model);
			if (provider == CloudProvider.AZURE) {
				model.setAzureResourceGroupName(resourceGroup.getName());
			}
			model.setNetworkUuid(vpc.getVpcId());
			model.setSubnetName(newSubnet.getName());
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".networkInterface";
				String message = "创建网络接口失败";
				BocloudResult result = networkInterfaceDriver.create(vendor.getUuid(), entityParams.getRegionId(),
						model);
				try {
					if (result.isSuccess()) {
						message = "创建网络接口成功";
						NetworkInterfaceModel newModel = JSONObject
								.parseObject(JSONObject.toJSONString(result.getData()), NetworkInterfaceModel.class);
						BeanUtils.copyProperties(newModel, entityParams);
						entityParams.setVpcId(vpc.getId());
						entityParams.setVendorId(vendor.getId());
						entityParams.setCreatorId(context.getTarget());
						entityParams.setGmtCreate(new Date());
						entityParams.setTenantId(context.getTenant());
						entityParams.setProjectId(context.getProject());
						if (context.getCatalog() == RequestContext.Catalog.User) {
							entityParams.setUserId(context.getTarget());
						}
						entityParams.setNetworkInterfaceUuid(newModel.getNetworkInterfaceUuid());
						if ((CloudProvider.AWS.name().equals(vendor.getType())
								|| CloudProvider.ALIYUN.name().equals(vendor.getType())) && null != newSubnet) {
							entityParams.setSubnetName(newSubnet.getName());
							entityParams.setSubnetId(newSubnet.getId());
							entityParams.setSgroupUuid(JSONObject.toJSONString(newModel.getSecurityGroups()));
						}
						networkInterfaceRepository.save(entityParams);
						if (provider == CloudProvider.AZURE) {
							List<NicIpConfigurationModel> nicIpConfigurationModels = newModel
									.getNicIpConfigurationModels();
							for (NicIpConfigurationModel nicIpConfigurationModel : nicIpConfigurationModels) {
								NicIpConfiguration nicIpConfiguration = new NicIpConfiguration();
								BeanUtils.copyProperties(nicIpConfigurationModel, nicIpConfiguration);
								nicIpConfiguration.setNetworkInterfaceId(entityParams.getId());
								nicIpConfiguration.setVpcId(entityParams.getVpcId());
								nicIpConfiguration.setSubnetId(entityParams.getSubnetId());
								nicIpConfigurationRepository.save(nicIpConfiguration);
							}
						}
					} else {
						logger.error("创建网络接口失败：" + result.getMessage());
						message = result.getMessage();
					}
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
					// 站内信推送
					NotifyMessage notifyMessage = new NotifyMessage(context, "提示:", message, null, true, false);
					amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
				} catch (Exception e) {
					logger.error("create networkInterface fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult<>(true, "任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("networkInterface create fail:", e);
			return new BocloudResult<>(false, "创建网络接口失败 : " + e.getMessage());
		}
	}

	@Override
	public BocloudResult<Void> modify(NetworkInterface entityParams, RequestContext context) {
		String name = entityParams.getName();
		String remark = entityParams.getRemark();
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(entityParams.getId());
			Assert.notNull(networkInterface, "网络接口不存在");
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			Assert.notNull(vendor, "平台验证失败");
			NetworkInterfaceModel model = JSON.parseObject(JSON.toJSONString(entityParams),
					NetworkInterfaceModel.class);
			model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
			// 获取云平台类型
			CloudProvider type = CloudProvider.valueOf(vendor.getType());
			switch (type) {
			case AWS:
				model.setName(name);
				model.setRemark(remark);
				break;
			}
			BocloudResult result = networkInterfaceDriver.modify(vendor.getUuid(), networkInterface.getRegionId(),
					model);
			if (result.isFailed()) {
				return result;
			}
			networkInterface.setName(name);
			networkInterface.setRemark(remark);
			networkInterface.setMenderId(context.getTarget());
			networkInterface.setGmtModify(new Date());
			networkInterfaceRepository.update(networkInterface);
			return new BocloudResult<>(true, "编辑网络接口成功!");
		} catch (Exception e) {
			logger.error("networkInterface modify fail:", e);
			return new BocloudResult<>(false, "编辑网络接口失败: " + e.getMessage());
		}
	}

	@Override
	public BocloudResult operations(NetworkInterfaceOperationParams params, RequestContext context) {
		// 挂载 卸载主机
		String action = params.getAction();
		if ("attach".equals(action)) {
			return this.attach(params, context);
		}
		if ("detach".equals(action)) {
			return this.detach(params, context);
		}
		// 附加 分离 安全组
		if ("attachGroup".equals(action)) {
			return this.attachSecurityGroup(params, context);
		}
		if ("detachGroup".equals(action)) {
			return this.detachSecurityGroup(params, context);
		}
		return new BocloudResult(false, "Unknown Operation！");
	}

	public BocloudResult attach(NetworkInterfaceOperationParams params, RequestContext context) {
		Long serverId = params.getServerId();
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(params.getId());
			if (null == networkInterface) {
				logger.error("get networkInterface failure");
				return new BocloudResult(false, "网络接口不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			CloudServer server = cloudServerRepository.query(serverId);
			if (null == server) {
				logger.error("get server failure");
				return new BocloudResult(false, "实例不存在");
			}
			NetworkInterfaceModel model = new NetworkInterfaceModel();
			CloudProvider type = CloudProvider.valueOf(vendor.getType());
			switch (type) {
			case AWS:
				List<Param> sparams = Lists.newArrayList();
				Map<String, Object> simpleMap = MapTools.simpleMap("vendorId", vendor.getId());
				simpleMap.put("serverId", serverId);
				sparams.add(new Param(simpleMap, Sign.EQ));
				int count = networkInterfaceRepository.count(sparams);
				BeanUtils.copyProperties(networkInterface, model);
				model.setDeviceIndex(count);
				model.setVirtualMachineUuid(server.getInstanceId());
				break;
			case AZURE:
				model.setVirtualMachineUuid(server.getInstanceId());
				model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
				break;
			case ALIYUN:
				BeanUtils.copyProperties(networkInterface, model);
				model.setInstanceId(server.getInstanceId());
				break;
			}
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".nics";
				String message = "附加虚拟机失败";
				BocloudResult result = networkInterfaceDriver.attach(vendor.getUuid(), networkInterface.getRegionId(),
						model);
				try {
					ResourceEvent event;
					if (result.isSuccess()) {
						message = "附加虚拟机成功";
						NetworkInterfaceModel interfaceModel = JSONObject
								.parseObject(JSONObject.toJSONString(result.getData()), NetworkInterfaceModel.class);
						interfaceModel.setVendorId(networkInterface.getVendorId());
						interfaceModel.setVpcId(networkInterface.getVpcId());
						BeanUtils.copyProperties(interfaceModel, networkInterface);
						networkInterface.setServerId(server.getId());
						networkInterface.setMenderId(context.getTarget());
						networkInterface.setGmtModify(new Date());
						networkInterface.setRegionId(model.getRegionId());
						networkInterface.setSubnetName(model.getSubnetName());
						networkInterface.setResourceGroupUuid(model.getResourceGroupUuid());
						switch (type) {
						case AWS:
							List<String> ipList = JSONArray.parseArray(server.getPrivateIps(), String.class);
							ipList.add(networkInterface.getPrimaryPrivateIPAddress());
							server.setPrivateIps(JSON.toJSONString(ipList));
							cloudServerRepository.update(server);
							break;
						case ALIYUN:
							List<String> aliyunIpList = JSONArray.parseArray(server.getPrivateIps(), String.class);
							aliyunIpList.add(networkInterface.getPrimaryPrivateIPAddress());
							server.setPrivateIps(JSON.toJSONString(aliyunIpList));
							cloudServerRepository.update(server);
							networkInterface.setStatus("InUse");
							break;
						case AZURE:
							List<String> ipPrivateList = JSONArray.parseArray(server.getPrivateIps(), String.class);
							ipPrivateList.add(networkInterface.getPrimaryPrivateIPAddress());
							server.setPrivateIps(JSON.toJSONString(ipPrivateList));
							List<String> ipPublicList = JSONArray.parseArray(server.getPublicIps(), String.class);
							if (!org.springframework.util.StringUtils.isEmpty(networkInterface.getPublicIPAddress())) {
								ipPublicList.add(networkInterface.getPublicIPAddress());
							}
							server.setPublicIps(JSON.toJSONString(ipPublicList));
							cloudServerRepository.update(server);
							break;
						}
						networkInterfaceRepository.update(networkInterface);
						event = new ResourceEvent(server.getId(), "附加",
								"网络接口 【" + networkInterface.getName() + "】附加成功！虚拟机【" + server.getName() + "】",
								context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
					} else {
						logger.error("附加虚拟机失败：" + result.getMessage());
						message = result.getMessage();
						event = new ResourceEvent(server.getId(), "附加",
								"网络接口 【" + networkInterface.getName() + "】附加失败！虚拟机【" + server.getName() + "】",
								context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
					}
					resourceEventRepository.save(event);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("networkInterface attch fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "附加虚拟机任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("networkInterface attch fail:", e);
			return new BocloudResult(false, "网络接口附加失败 : " + e.getMessage());
		}
	}

	public BocloudResult detach(NetworkInterfaceOperationParams params, RequestContext context) {
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(params.getId());
			if (null == networkInterface) {
				logger.error("get networkInterface failure");
				return new BocloudResult(false, "网络接口不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			CloudServer server = cloudServerRepository.query(networkInterface.getServerId());
			if (null == server) {
				logger.error("get cloudServer failure");
				return new BocloudResult(false, "实例不存在");
			}
			CloudProvider type = CloudProvider.valueOf(vendor.getType());
			NetworkInterfaceModel model = new NetworkInterfaceModel();
			switch (type) {
			case AWS:
				BeanUtils.copyProperties(networkInterface, model);
				break;
			case ALIYUN:
				if (networkInterface.getInterfaceType().equalsIgnoreCase("Primary")) {
					return new BocloudResult(false, "主网卡不支持解绑操作");
				}
				if (!(networkInterface.getStatus().equalsIgnoreCase("Detaching")
						|| networkInterface.getStatus().equalsIgnoreCase("InUse"))) {
					return new BocloudResult(false, "网卡当前状态不支持解绑操作");
				}
				if (!(server.getStatus().equalsIgnoreCase(BocloudStatus.Server.RUNNING.name())
						|| server.getStatus().equalsIgnoreCase(BocloudStatus.Server.STOPPED.name()))) {
					return new BocloudResult(false, "虚拟机当前状态不支持解绑操作");
				}
				model.setInstanceId(server.getInstanceId());
				model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
				break;
			case AZURE:
				model.setVirtualMachineUuid(server.getInstanceId());
				model.setName(networkInterface.getName());
				model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
				break;
			default:
				break;
			}
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".nics";
				String message = "分离虚拟机失败";
				BocloudResult result = networkInterfaceDriver.detach(vendor.getUuid(), networkInterface.getRegionId(),
						model);
				try {
					ResourceEvent event;
					if (result.isSuccess()) {
						message = "分离虚拟机成功";
						networkInterface.setMenderId(context.getTarget());
						networkInterface.setGmtModify(new Date());
						networkInterface.setServerId(null);
						networkInterface.setAttachedTime(null);
						networkInterface.setAttachmentUuid(null);
						networkInterface.setDeviceIndex(-1);
						networkInterface.setDeleteOnTermination(false);
						networkInterface.setDetachedTime(new Date());
						// 被分离的网卡一定不是主网卡
						networkInterface.setNicsPrimary(false);
						switch (type) {
						case AWS:
							List<String> ipList = JSONArray.parseArray(server.getPrivateIps(), String.class);
							ipList.remove(networkInterface.getPrimaryPrivateIPAddress());
							server.setPrivateIps(JSON.toJSONString(ipList));
							cloudServerRepository.update(server);
							networkInterface.setStatus("available");
							break;
						case ALIYUN:
							List<String> aliyunIpList = JSONArray.parseArray(server.getPrivateIps(), String.class);
							aliyunIpList.remove(networkInterface.getPrimaryPrivateIPAddress());
							server.setPrivateIps(JSON.toJSONString(aliyunIpList));
							cloudServerRepository.update(server);
							networkInterface.setStatus("Available");
							break;
						case AZURE:
							List<String> ipPrivateList = JSONArray.parseArray(server.getPrivateIps(), String.class);
							ipPrivateList.remove(networkInterface.getPrimaryPrivateIPAddress());
							server.setPrivateIps(JSON.toJSONString(ipPrivateList));
							List<String> ipPublicList = JSONArray.parseArray(server.getPublicIps(), String.class);
							if (!org.springframework.util.StringUtils.isEmpty(networkInterface.getPublicIPAddress())) {
								ipPublicList.remove(networkInterface.getPublicIPAddress());
							}
							if (CollectionUtils.isEmpty(ipPublicList)) {
								server.setPublicIps(null);
							} else {
								server.setPublicIps(JSON.toJSONString(ipPublicList));
							}
							cloudServerRepository.update(server);
							break;
						}
						networkInterfaceRepository.update(networkInterface);
						event = new ResourceEvent(server.getId(), "分离",
								"网络接口 【" + networkInterface.getName() + "】分离成功！虚拟机【" + server.getName() + "】",
								context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());

					} else {
						logger.error("分离虚拟机失败：" + result.getMessage());
						message = result.getMessage();
						event = new ResourceEvent(server.getId(), "分离",
								"网络接口 【" + networkInterface.getName() + "】分离成功！虚拟机【" + server.getName() + "】",
								context.getTarget(), new Date(), "VM", vendor.getId(), context.getCatalog());
					}
					resourceEventRepository.save(event);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("networkInterface attch fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "分离虚拟机任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("networkInterface detach fail: ", e);
			return new BocloudResult(false, "网络接口分离失败 : " + e.getMessage());
		}
	}

	public BocloudResult attachSecurityGroup(NetworkInterfaceOperationParams params, RequestContext context) {
		Long groupId = params.getGroupId();
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(params.getId());
			if (null == networkInterface) {
				logger.error("get networkInterface failure");
				return new BocloudResult(false, "网络接口不存在");
			}
			SecurityGroup securityGroup = securityGroupRepository.query(groupId);
			if (null == securityGroup) {
				logger.error("get securityGroup failure");
				return new BocloudResult(false, "网络安全组不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			NetworkInterfaceModel model = new NetworkInterfaceModel();
			model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
			model.setSecurityGroupUuid(securityGroup.getGroupUuid());
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".nics";
				String message = "附加安全组失败";
				BocloudResult result = networkInterfaceDriver.attachSecurityGroup(vendor.getUuid(),
						networkInterface.getRegionId(), model);
				try {
					if (result.isSuccess()) {
						message = "附加安全组成功";
						networkInterface.setMenderId(context.getTarget());
						networkInterface.setGmtModify(new Date());
						networkInterface.setSecurityGroupId(securityGroup.getId());
						networkInterfaceRepository.update(networkInterface);
						if (null != networkInterface.getServerId()) {
							serverSgroupRepository.removeBySgid(securityGroup.getId());
							ServerSgroup serverSgroup = new ServerSgroup(networkInterface.getServerId(), groupId);
							serverSgroupRepository.save(serverSgroup);
						}

					} else {
						logger.error("附加安全组失败：" + result.getMessage());
						message = result.getMessage();
					}
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("networkInterface attachSecurityGroup fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "附加安全组任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("networkInterface attachSecurityGroup fail:", e);
			return new BocloudResult(false, "附加安全组失败 : " + e.getMessage());
		}
	}

	public BocloudResult detachSecurityGroup(NetworkInterfaceOperationParams params, RequestContext context) {
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(params.getId());
			if (null == networkInterface) {
				logger.error("get networkInterface failure");
				return new BocloudResult(false, "网络接口不存在");
			}
			SecurityGroup securityGroup = securityGroupRepository.query(networkInterface.getSecurityGroupId());
			if (null == securityGroup) {
				logger.error("get securityGroup failure");
				return new BocloudResult(false, "网络安全组不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			NetworkInterfaceModel model = new NetworkInterfaceModel();
			model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
			model.setSecurityGroupUuid(securityGroup.getGroupUuid());
			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".nics";
				String message = "分离安全组失败";
				BocloudResult result = networkInterfaceDriver.detachSecurityGroup(vendor.getUuid(),
						networkInterface.getRegionId(), model);
				try {
					if (result.isSuccess()) {
						message = "分离安全组成功";
						networkInterface.setMenderId(context.getTarget());
						networkInterface.setGmtModify(new Date());
						networkInterface.setSecurityGroupId(null);
						networkInterfaceRepository.update(networkInterface);
						if (null != networkInterface.getServerId()) {
							serverSgroupRepository.remove(securityGroup.getId(), networkInterface.getServerId());
						}
					} else {
						logger.error("分离安全组失败：" + result.getMessage());
						message = result.getMessage();
					}
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("networkInterface detachSecurityGroup fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "分离安全组任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("networkInterface detachSecurityGroup fail:", e);
			return new BocloudResult(false, "分离安全组失败 : " + e.getMessage());
		}
	}

	@Override
	public BocloudResult vmChangeInterface(String params, RequestContext context) {
		JSONObject object = JSONTools.isJSONObj(params);
		if (null == object) {
			return new BocloudResult(false, "参数格式不正确");
		}
		Long networkInterfaceId = object.getLong("networkInterfaceId");
		Long instanceId = object.getLong("instanceId");
		try {
			CloudServer cloudServer = cloudServerRepository.query(instanceId);
			if (null == cloudServer) {
				logger.warn("cloudServer data not exist");
				return new BocloudResult(false, "虚拟机不存在");
			}
			CloudVendor cloudVendor = cloudVendorRepository.query(cloudServer.getVendorId());
			if (null == cloudVendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			NetworkInterface networkInterface = networkInterfaceRepository.query(networkInterfaceId);
			if (null == networkInterface) {
				logger.warn("networkInterface data not exist");
				return new BocloudResult(false, "数据不存在");
			}

			BocloudResult bocloudResult = networkInterfaceDriver.vmChangeInterface(cloudVendor.getUuid(),
					cloudServer.getRegionId(), networkInterface.getNetworkInterfaceUuid(), cloudServer.getInstanceId());
			if (bocloudResult.isFailed()) {
				return bocloudResult;
			}
			return new BocloudResult(true, "更换网络接口成功");
		} catch (Exception e) {
			logger.error("networkInterface change vm  fail:", e);
			return new BocloudResult(false, "更换网络接口失败");
		}

	}

	@Override
	public BocloudResult changeSubnet(NicChangeSubnetParams params, RequestContext context) {
		Long id = params.getId();
		Long subnetId = params.getSubnetId();
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(id);
			if (null == networkInterface) {
				logger.warn("networkInterface data not exist");
				return new BocloudResult(false, "网络接口不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			Subnet subnet = subnetRepository.query(subnetId);
			if (null == subnet) {
				logger.error("get subnet failure");
				return new BocloudResult(false, "子网不存在");
			}
			CloudProvider type = CloudProvider.valueOf(vendor.getType());

			NetworkInterfaceModel model = new NetworkInterfaceModel();
			model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
			model.setSubnetName(subnet.getName());

			taskExecutor.execute(() -> {
				String operate = vendor.getType().toLowerCase() + ".nics";
				String message = "更换子网失败";
				BocloudResult result = networkInterfaceDriver.changeSubnet(vendor.getUuid(),
						networkInterface.getRegionId(), model);
				try {
					if (result.isSuccess()) {
						message = "更换子网成功";
						NetworkInterfaceModel interfaceModel = JSONObject
								.parseObject(JSONObject.toJSONString(result.getData()), NetworkInterfaceModel.class);
						networkInterface.setSubnetId(subnet.getId());
						networkInterface.setSubnetName(subnet.getName());
						networkInterface.setGmtModify(new Date());
						networkInterface.setMenderId(context.getTarget());
						networkInterface.setPrimaryPrivateIPAddress(interfaceModel.getPrimaryPrivateIPAddress());
						networkInterfaceRepository.update(networkInterface);
						CloudServer server = cloudServerRepository.get(networkInterface.getServerId());
						switch (type) {
						case AZURE:
							if (!ObjectUtils.isEmpty(server)
									&& !StringUtils.isEmpty(interfaceModel.getPrimaryPrivateIPAddress())) {
								server.setPrivateIps(
										JSON.toJSONString(Arrays.asList(interfaceModel.getPrimaryPrivateIPAddress())));
								cloudServerRepository.update(server);
							}
							break;
						default:
							break;
						}
					} else {
						logger.error("网络接口更换子网失败：" + result.getMessage());
						message = result.getMessage();
					}
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("networkInterface changeSubnet fail:", e);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "网络接口更换子网任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("networkInterface changeSubnet fail:", e);
			return new BocloudResult(false, "网络接口更换子网失败");
		}
	}

	@Override
	public BocloudResult distributionSecurityGroup(Long id, NetworkInterfaceModel model, RequestContext context) {
		try {
			NetworkInterface networkInterface = networkInterfaceRepository.query(id);
			if (null == networkInterface) {
				logger.error("get networkInterface failure");
				return new BocloudResult(false, "网络接口不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "平台验证失败");
			}
			List<String> securityGroups = model.getSecurityGroups();
			if (CollectionUtils.isEmpty(securityGroups)) {
				return new BocloudResult(false, "至少保留一个安全组");
			}
			List<Long> groupIds = new ArrayList<>();
			for (String securityGroup : securityGroups) {
				SecurityGroup group = securityGroupRepository.getByGroupUuid(securityGroup, vendor.getId());
				if (ObjectUtils.isEmpty(group)) {
					logger.error("get group failure");
					return new BocloudResult(false, "安全组不存在");
				}
				groupIds.add(group.getId());
			}
			model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
			BocloudResult result = networkInterfaceDriver.sgroups(vendor.getUuid(), networkInterface.getRegionId(),
					model);
			if (result.isFailed()) {
				return result;
			}
			networkInterface.setMenderId(context.getTarget());
			networkInterface.setGmtModify(new Date());
			if (CloudProvider.AWS.name().equals(vendor.getType())) {
				networkInterface.setSgroupUuid(JSONObject.toJSONString(securityGroups));
			}
			networkInterfaceRepository.update(networkInterface);
			if (CloudProvider.AWS.name().equals(vendor.getType())) {
				// 主网络接口
				if (0 == networkInterface.getDeviceIndex()) {
					serverSgroupRepository.removeBySid(networkInterface.getServerId());
					for (Long groupId : groupIds) {
						ServerSgroup serverSgroup = new ServerSgroup(networkInterface.getServerId(), groupId);
						serverSgroupRepository.save(serverSgroup);
					}
				}
			}

			return new BocloudResult(true, "分配安全组成功!");
		} catch (Exception e) {
			logger.error("networkInterface sgroups fail:", e);
			return new BocloudResult(false, "分配安全组失败 : " + e.getMessage());
		}
	}

	@Override
	public BocloudResult batchRemove(String params, RequestContext context) {
		try {
			// 获取资源ID
			List<Long> idArray = JSONArray.parseArray(params, Long.class);
			if (ListTool.isEmpty(idArray)) {
				return new BocloudResult(false, "请选择需要删除的网络接口！");
			}
			NetworkInterface networkInterface = networkInterfaceRepository.query(idArray.get(0));
			if (ObjectUtils.isEmpty(networkInterface)) {
				return new BocloudResult(false, "网络接口数据异常！");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (ObjectUtils.isEmpty(vendor)) {
				return new BocloudResult(false, "平台信息异常！");
			}
			taskExecutor.execute(new Runnable() {
				@Override
				public void run() {
					String operate = vendor.getType().toLowerCase() + ".nics";
					try {
						List<BocloudResult> succList = Lists.newArrayList();
						List<BocloudResult> failList = Lists.newArrayList();
						for (Long id : idArray) {
							BocloudResult bocloudResult = remove(id, context);
							if (bocloudResult.isSuccess()) {
								succList.add(bocloudResult);
							} else {
								failList.add(bocloudResult);
							}
						}
						// 删除成功的数量
						int success = succList.size();
						// 删除失败的数量
						int fail = failList.size();
						String content = null;
						if (fail == idArray.size()) {
							content = "网络接口批量删除失败，详情如下：\n";
							for (BocloudResult bocloudResult : failList) {
								content += bocloudResult.getMessage() + "\n";
							}
						} else if (success == idArray.size()) {
							content = "网络接口批量删除成功【" + success + "】个";
						} else {
							content = "网络接口批量删除成功【" + success + "】个,失败【" + fail + "】个，失败详情如下：\n";
							for (BocloudResult bocloudResult : failList) {
								content += bocloudResult.getMessage() + "\n";
							}
						}
						resourceEventPublisher.send(new OperateResult(fail == idArray.size() ? false : true, content,
								operate, MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
					} catch (Exception e) {
						logger.error("网络接口批量删除异常：" + e.getMessage());
						resourceEventPublisher.send(new OperateResult(false, "网络接口批量删除异常：" + e.getMessage(), operate,
								MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
					}
				}
			});
			return new BocloudResult(true, "删除任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("delete error ：", e);
			return new BocloudResult(false, "批量删除失败！");
		}
	}

	@Override
	public BocloudResult privateIpAddresses(Long id, NetworkInterfaceModel networkInterfaceModel,
			RequestContext context) {
		try {
			if (null == networkInterfaceModel) {
				return new BocloudResult(false, "参数格式不正确");
			}
			String action = networkInterfaceModel.getAction();
			NetworkInterface networkInterface = networkInterfaceRepository.query(id);
			if (null == networkInterface) {
				return new BocloudResult(false, "弹性网卡不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
			if (null == vendor) {
				return new BocloudResult(false, "平台不存在");
			}
			CloudProvider provider = CloudProvider.valueOf(vendor.getType());
			taskExecutor.execute(new Runnable() {
				@Override
				public void run() {
					String operate = vendor.getType().toLowerCase() + ".nics";
					try {
						BocloudResult result = null;
						switch (provider) {
						case ALIYUN:
							NetworkInterfaceModel model = new NetworkInterfaceModel();
							model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
							List<String> privateIps = networkInterfaceModel.getPrivateIpAddress();
							if ("assign".equalsIgnoreCase(action)) {
								model.setPrivateIpAddress(privateIps);
								result = networkInterfaceDriver.assignPrivateIpAddresses(vendor.getUuid(),
										networkInterface.getRegionId(), model);
								if (result.isFailed()) {
									resourceEventPublisher.send(new OperateResult(false, result.getMessage(), operate,
											MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
									return;
								}
								networkInterface.setPrivateIPAddress(JSON.toJSONString(privateIps));
								networkInterface.setMenderId(context.getTarget());
								networkInterface.setGmtModify(new Date());
								networkInterfaceRepository.update(networkInterface);
							}
							break;
						default:
							break;
						}
						resourceEventPublisher.send(new OperateResult(true, "辅助私网IP分配成功", operate,
								MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
					} catch (Exception e) {
						logger.error("辅助私网IP分配异常：" + e.getMessage());
						resourceEventPublisher.send(new OperateResult(false, "辅助私网IP分配异常：" + e.getMessage(), operate,
								MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
					}
				}
			});
			return new BocloudResult(true, "任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("辅助私网IP操作失败" + e);
			return new BocloudResult(false, "辅助私网IP操作失败:" + e.getMessage());
		}
	}

	@Override
	public BocloudResult list(Long vendorId, String regionId, Long vpcId, String interfaceType) {
		try {
			return new BocloudResult(true, networkInterfaceRepository.list(vendorId, regionId, vpcId, interfaceType),
					"查询成功");
		} catch (Exception e) {
			logger.error("Get error message:{}", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult listAvailableNics(Long vendorId, String regionId) {
		try {
			return new BocloudResult(true, networkInterfaceRepository.listAvailableNics(vendorId, regionId), "查询成功");
		} catch (Exception e) {
			logger.error("Get error message:{}", e);
			return new BocloudResult(false, "查询失败");
		}
	}

}
