package com.bocloud.ims.service.transporter.vendor;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.ModuleCode;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.ElasticIpModel;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.KeypairModel;
import com.bocloud.cmp.model.LbListenerModel;
import com.bocloud.cmp.model.LbListenerRuleModel;
import com.bocloud.cmp.model.LbMemberModel;
import com.bocloud.cmp.model.LbModel;
import com.bocloud.cmp.model.LbPoolModel;
import com.bocloud.cmp.model.NetworkCardModel;
import com.bocloud.cmp.model.RegionModel;
import com.bocloud.cmp.model.RouteModel;
import com.bocloud.cmp.model.RouteTableModel;
import com.bocloud.cmp.model.SecurityGroupModel;
import com.bocloud.cmp.model.SecurityGroupRuleModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.ServerVolumeModel;
import com.bocloud.cmp.model.SubnetModel;
import com.bocloud.cmp.model.VolcengineSyncModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.model.VpcModel;
import com.bocloud.cmp.model.ZoneModel;
import com.bocloud.common.enums.OSCategory;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ElasticIp;
import com.bocloud.ims.entity.resource.Flavor;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Keypair;
import com.bocloud.ims.entity.resource.LbListener;
import com.bocloud.ims.entity.resource.LbListenerRule;
import com.bocloud.ims.entity.resource.LbMember;
import com.bocloud.ims.entity.resource.LbPool;
import com.bocloud.ims.entity.resource.LoadBalancer;
import com.bocloud.ims.entity.resource.NetworkCard;
import com.bocloud.ims.entity.resource.Region;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.Route;
import com.bocloud.ims.entity.resource.RouteTable;
import com.bocloud.ims.entity.resource.SecurityGroup;
import com.bocloud.ims.entity.resource.SecurityGroupRule;
import com.bocloud.ims.entity.resource.ServerSgroup;
import com.bocloud.ims.entity.resource.Subnet;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.Vpc;
import com.bocloud.ims.entity.resource.Zone;
import com.bocloud.ims.repository.resource.LbListenerRuleRepository;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.model.cmdb.CmdbRelation;
import com.bocloud.ims.service.transporter.AbstractTransporter;
import com.bocloud.ims.service.utils.CmdbInfoConvertor;
import com.bocloud.ims.service.utils.ListUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * @ClassName: VolcengineTransportor
 * @Description: 火山云同步工具类
 * @Author lxy
 * @Date 2021/9/15 15:06
 */
@Component
public class VolcengineTransporter extends AbstractTransporter {

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

	@Autowired
	private LbListenerRuleRepository lbListenerRuleRepository;

	@Override
	public Result transport(CloudVendor vendor, Long operator) {
		return this.syncCloudResource(vendor, operator);
	}

	@Override
	public BocloudResult process(CloudVendor vendor, Object data, Region region, Long userId, List<CmdbInfo> infos) {
		try {
			if (null != data) {
				if (cloudServerRepository.hasBuilding(vendor.getId())) {
					return new BocloudResult(false, "该平台下有云主机正在创建，请稍后进行同步操作");
				}
				Long vendorId = vendor.getId();
				String content = JSONObject.toJSONString(data);
				VolcengineSyncModel model = JSONObject.parseObject(content, VolcengineSyncModel.class);
				// 同步可用区域
				logger.info("Starting sync region......");
				this.syncRegions(model.getRegions(), vendor, userId, region.getRegionId());
				List<Zone> zoneList = zoneRepository.listByRegionId(region.getRegionId(), vendorId);
				Map<String, Long> zoneMap = new HashMap<>(8);
				for (Zone zone : zoneList) {
					zoneMap.put(zone.getZoneId(), zone.getId());
				}
				logger.info("End sync region......");

				// 同步vpc
				logger.info("Starting sync vpc......");
				this.syncVpc(model.getVpcModels(), vendor.getId(), userId, region.getRegionId());
				Map<String, Long> vpcMap = new HashMap<>(8);
				List<Vpc> vpcList = vpcRepository.list(vendorId, region.getRegionId());
				for (Vpc vpc : vpcList) {
					vpcMap.put(vpc.getVpcId(), vpc.getId());
				}
				Map<String, Long> subnetMap = new HashMap<>(8);
				Map<String, Subnet> subnetMapObject = new HashMap<>(8);
				List<Subnet> subnetList = subnetRepository.listByRegion(vendorId, region.getRegionId());
				for (Subnet subnet : subnetList) {
					subnetMap.put(subnet.getSubnetUuid(), subnet.getId());
					subnetMapObject.put(subnet.getSubnetUuid(), subnet);
				}
				logger.info("End sync vpc......");
				// 同步安全组
				logger.info("Starting sync security group......");
				this.syncSecurityGroup(model.getSecgModels(), vpcMap, vendorId, userId, region.getRegionId());
				logger.info("End sync security group......");
				// 同步规格
				logger.info("Starting sync flavor......");
				this.syncFlavor(model.getFlavorModels(), vendorId, userId, region.getRegionId());
				logger.info("End sync flavor......");
				List<Flavor> flavors = flavorRepository.listByVendorId(vendorId, region.getRegionId());
				Map<String, Flavor> flavorMap = new HashMap<String, Flavor>(8);
				for (Flavor flavor : flavors) {
					flavorMap.put(flavor.getFlavorUuid(), flavor);
				}
				// 同步镜像
				Map<String, Image> imageMap = Maps.newHashMap();
				logger.info("Starting sync image......");
				this.syncImage(model.getImageModels(), vendorId, region.getRegionId(), userId, vendor.getType(),
						imageMap);
				logger.info("End sync image......");
				// 同步云主机
				logger.info("Starting sync server......");
				Map<String, CloudServer> serverMap = new HashMap<>(8);
				this.syncServer(model.getServerModels(), vendor, userId, region, vendor.getType(), serverMap, flavorMap,
						infos);
				Map<String, CloudServer> sMap = new HashMap<>(8);
				List<CloudServer> serverByVid = cloudServerRepository.listByVid(vendor.getId(), region.getRegionId());
				for (CloudServer cloudServer : serverByVid) {
					sMap.put(cloudServer.getInstanceId(), cloudServer);
				}
				logger.info("End sync server......");
				// 弹性网卡
				logger.info("start sync networkcard...");
				this.syncNetworkCard(model.getNetworkCardModels(), vendor.getId(), userId, region.getRegionId());
				logger.info("end sync networkcard...");
				Map<String, NetworkCard> networkCardMap = new HashMap<>(8);
				List<NetworkCard> networkCards = networkCardRepository.listByVendor(vendor.getId());
				for (NetworkCard networkCard : networkCards) {
					networkCardMap.put(networkCard.getNetworkcardUuid(), networkCard);
				}
				// 同步弹性IP
				logger.info("Starting sync elastic ip......");
				this.syncElasticIp(model.getElasticIpModels(), region.getRegionId(), vendorId, userId, sMap,
						networkCardMap);
				Map<String, ElasticIp> elasticIpMap = new HashMap<>(8);
				List<ElasticIp> elasticIps = elasticIpRepository.listByVid(vendor.getId());
				for (ElasticIp elasticIp : elasticIps) {
					elasticIpMap.put(elasticIp.getElasticIpUuid(), elasticIp);
				}
				logger.info("End sync elastic ip...");
				// 同步路由表
				logger.info("Starting sync route tables......");
				this.syncRouteTable(model.getRouteTableModels(), vendor.getId(), userId, vpcMap, region.getRegionId(),
						subnetMapObject);
				logger.info("End sync route tables......");
				// 同步云硬盘类型
//                logger.info("Starting sync volume type......");
//                this.syncVolumeType(model.getVolumeTypeModels(), vendorId, region.getRegionId(), userId, zoneMap);
//                logger.info("End sync volume type......");
				// 同步云硬盘
				logger.info("Starting sync volume......");
				this.syncVolume(model.getVolumeModels(), vendorId, region.getRegionId(), userId, sMap);
				logger.info("End sync volume......");
				// 获取云硬盘信息
				Map<String, Volume> volumeMap = Maps.newHashMap();
				List<Volume> volumes = volumeRepository.listByVendorId(vendorId);
				for (Volume volume : volumes) {
					volumeMap.put(volume.getVolumeUuid(), volume);
				}
				// 同步快照
//                logger.info("Starting sync snapshot......");
//                this.syncSnapshot(model.getSnapshotModels(), vendorId, userId, region.getRegionId(), volumeMap);
//                logger.info("End sync snapshot......");
				// 同步密钥
				logger.info("Starting sync keypair......");
				this.syncKeypair(model.getKeypairModels(), region.getRegionId(), vendorId, userId);
				logger.info("End sync keypair...");

				// 同步负载均衡
				logger.info("Starting sync lb......");
				this.syncLoadBalancer(model.getLbModels(), vpcMap, subnetMapObject, vendor.getId(), userId,
						region.getRegionId(), elasticIpMap);
				List<LoadBalancer> balancers = loadBalancerRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> balancerMap = Maps.newHashMap();
				for (LoadBalancer balancer : balancers) {
					balancerMap.put(balancer.getLbUuid(), balancer.getId());
				}
				logger.info("End sync lb......");

				// 同步侦听器
				logger.info("Starting sync listener......");
				this.syncLbListener(model.getLbListenerModels(), balancerMap, vendor.getId(), userId,
						region.getRegionId(), true);
				List<LbListener> lbListeners = lbListenerRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> listenerMap = Maps.newHashMap();

				for (LbListener listener : lbListeners) {
					listenerMap.put(listener.getListenerUuid(), listener.getId());
				}
				logger.info("End sync lb listener......");

				// 后端云服务器组
				logger.info("Starting sync lb pool......");
				this.syncLbPool(model.getLbPoolModels(), listenerMap, balancerMap, vendor.getId(), userId,
						region.getRegionId());
				List<LbPool> targetGroups = lbPoolRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> tgMap = Maps.newHashMap();

				Map<String, LbPool> lbPoolMap = Maps.newHashMap();
				for (LbPool group : targetGroups) {
					tgMap.put(group.getPoolUuid(), group.getId());
					lbPoolMap.put(group.getPoolUuid(), group);
				}
				logger.info("End sync lb pool......");
				// 后端云服务器
				logger.info("Starting sync lb member......");
				this.syncLbMember(model.getLbMemberModels(), lbPoolMap, subnetMapObject, vendor.getId(), userId,
						region.getRegionId());
				logger.info("End sync lb member......");

			}
			return new BocloudResult(true, "云平台【" + vendor.getName() + "】平台数据同步成功");
		} catch (Exception e) {
			logger.error("Sync VolcengineTransportor error:{}", e);
			return new BocloudResult(false, "云平台【" + vendor.getName() + "】平台数据同步失败:" + e.getMessage());
		}
	}

	/**
	 * 同步负载均衡
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLoadBalancer(List<LbModel> models, Map<String, Long> vpcMap, Map<String, Subnet> subnetMap,
			Long vendorId, Long userId, String region, Map<String, ElasticIp> elasticIpMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			loadBalancerRepository.removeByVid(vendorId, region, userId);
			return;
		}
		List<LoadBalancer> balancers = loadBalancerRepository.listByVid(vendorId, region);
		Map<String, LoadBalancer> balancerMap = Maps.newHashMap();
		for (LoadBalancer balancer : balancers) {
			balancerMap.put(balancer.getLbUuid(), balancer);
		}
		for (LbModel model : models) {
			LoadBalancer balancer = new LoadBalancer();
			if (balancerMap.containsKey(model.getLbUuid())) {
				balancer = balancerMap.get(model.getLbUuid());
				BeanUtils.copyProperties(model, balancer);
				balancer.setVpcId(vpcMap.get(balancer.getVpcUuid()));
				Subnet subnet = subnetMap.get(balancer.getVipSubnetUuid());
				if (null != subnet) {
					balancer.setSubnetId(subnet.getId());
					balancer.setSubnetUuid(subnet.getSubnetUuid());
					balancer.setVpcId(subnet.getVpcId());
					balancer.setVpcUuid(subnet.getVpcUuid());
				}
				balancer.setMenderId(userId);
				balancer.setVendorId(vendorId);
				balancer.setGmtModify(new Date());
				balancer.setRegion(region);
				ElasticIp elasticIp = elasticIpMap.get(model.getEipUuid());
				if (null != elasticIp) {
					balancer.setEipId(elasticIp.getId());
					// 同步设置eip绑定实例
					if ("ClbInstance".equalsIgnoreCase(elasticIp.getInstanceType())) {
						elasticIp.setBandwidthName(balancer.getName());
						elasticIpRepository.update(elasticIp);
					}
				}
				loadBalancerRepository.update(balancer);
				balancerMap.remove(balancer.getLbUuid());
				continue;
			}
			BeanUtils.copyProperties(model, balancer);
			balancer.setVpcId(vpcMap.get(balancer.getVpcUuid()));
			Subnet subnet = subnetMap.get(balancer.getVipSubnetUuid());
			if (null != subnet) {
				balancer.setSubnetId(subnet.getId());
				balancer.setSubnetUuid(subnet.getSubnetUuid());
				balancer.setVpcId(subnet.getVpcId());
				balancer.setVpcUuid(subnet.getVpcUuid());
			}
			balancer.setCreatorId(userId);
			balancer.setVendorId(vendorId);
			balancer.setGmtCreate(new Date());
			balancer.setRegion(region);
			ElasticIp elasticIp = elasticIpMap.get(model.getEipUuid());
			if (null != elasticIp) {
				balancer.setEipId(elasticIp.getId());
				// 同步设置eip绑定实例
				if ("ClbInstance".equalsIgnoreCase(elasticIp.getInstanceType())) {
					elasticIp.setBandwidthName(balancer.getName());
					elasticIpRepository.update(elasticIp);
				}
			}
			loadBalancerRepository.save(balancer);
			balancerMap.remove(balancer.getLbUuid());
		}
		for (Map.Entry<String, LoadBalancer> entry : balancerMap.entrySet()) {
			loadBalancerRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步监听器
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	public void syncLbListener(List<LbListenerModel> models, Map<String, Long> balancerMap, Long vendorId, Long userId,
			String region, Boolean isRules) throws Exception {
		if (ListTool.isEmpty(models)) {
			lbListenerRepository.removeByVid(vendorId, userId, region);
			lbListenerRuleRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbListener> listenerList = lbListenerRepository.listByVid(vendorId, region);
		Map<String, LbListener> listenerMap = Maps.newHashMap();
		for (LbListener lbListener : listenerList) {
			listenerMap.put(lbListener.getListenerUuid(), lbListener);
		}
		for (LbListenerModel model : models) {
			LbListener lbListener = new LbListener();
			if (listenerMap.containsKey(model.getListenerUuid())) {
				lbListener = listenerMap.get(model.getListenerUuid());
				BeanUtils.copyProperties(model, lbListener);
				lbListener.setLbId(balancerMap.get(lbListener.getLbUuid()));
				lbListener.setVendorId(vendorId);
				lbListener.setGmtModify(new Date());
				lbListener.setRegionId(region);
				Object certificates = lbListener.getCertificates();
				if (null != certificates) {
					lbListener.setCertificates(JSONObject.toJSONString(certificates));
				}
				Object configuration = lbListener.getConfiguration();
				if (null != configuration) {
					lbListener.setConfiguration(JSONObject.toJSONString(configuration));
				}
				lbListenerRepository.update(lbListener);
				if (isRules) {
					syncLbListenerRule(model.getListenerRuleModels(), vendorId, userId, region,
							lbListener.getListenerUuid());
				}
				listenerMap.remove(model.getListenerUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbListener);
			lbListener.setLbId(balancerMap.get(lbListener.getLbUuid()));

			lbListener.setVendorId(vendorId);
			lbListener.setRegionId(region);
			Object certificates = lbListener.getCertificates();
			if (null != certificates) {
				lbListener.setCertificates(JSONObject.toJSONString(certificates));
			}
			Object configuration = lbListener.getConfiguration();
			if (null != configuration) {
				lbListener.setConfiguration(JSONObject.toJSONString(configuration));
			}
			lbListenerRepository.save(lbListener);
			if (isRules) {
				syncLbListenerRule(model.getListenerRuleModels(), vendorId, userId, region,
						lbListener.getListenerUuid());
			}
			listenerMap.remove(model.getListenerUuid());
		}
		for (Map.Entry<String, LbListener> entry : listenerMap.entrySet()) {
			lbListenerRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncLbListenerRule(List<LbListenerRuleModel> models, Long vendorId, Long userId, String region,
			String listenerUuid) throws Exception {
		if (ListTool.isEmpty(models)) {
			lbListenerRuleRepository.removeByVid(vendorId, userId, region, listenerUuid);
			return;
		}

		List<LbListenerRule> listenerList = lbListenerRuleRepository.listByVid(vendorId, region, listenerUuid);
		Map<String, LbListenerRule> listenerRuleMap = Maps.newHashMap();
		for (LbListenerRule lbListenerRule : listenerList) {
			listenerRuleMap.put(lbListenerRule.getRuleUuid(), lbListenerRule);
		}
		for (LbListenerRuleModel model : models) {
			LbListenerRule lbListenerRule = new LbListenerRule();
			if (listenerRuleMap.containsKey(model.getRuleUuid())) {
				lbListenerRule = listenerRuleMap.get(model.getRuleUuid());
				BeanUtils.copyProperties(model, lbListenerRule);
				lbListenerRule.setVendorId(vendorId);
				lbListenerRule.setGmtModify(new Date());
				lbListenerRule.setRegionId(region);
				lbListenerRuleRepository.update(lbListenerRule);
				listenerRuleMap.remove(model.getRuleUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbListenerRule);
			lbListenerRule.setVendorId(vendorId);
			lbListenerRule.setRegionId(region);
			lbListenerRule.setCreatorId(userId);
			lbListenerRule.setGmtCreate(new Date());
			lbListenerRuleRepository.save(lbListenerRule);
			listenerRuleMap.remove(model.getListenerUuid());
		}
		for (Map.Entry<String, LbListenerRule> entry : listenerRuleMap.entrySet()) {
			lbListenerRuleRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 后端云服务器组
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLbPool(List<LbPoolModel> models, Map<String, Long> listenerMap, Map<String, Long> balancerMap,
			Long vendorId, Long userId, String region) throws Exception {
		if (ListTool.isEmpty(models)) {
			lbPoolRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbPool> lbTargetGroups = lbPoolRepository.listByVid(vendorId, region);
		Map<String, LbPool> targetGroupMap = Maps.newHashMap();
		for (LbPool lbTargetGroup : lbTargetGroups) {
			targetGroupMap.put(lbTargetGroup.getPoolUuid(), lbTargetGroup);
		}
		for (LbPoolModel model : models) {
			LbPool lbTargetGroup = new LbPool();
			if (targetGroupMap.containsKey(model.getPoolUuid())) {
				lbTargetGroup = targetGroupMap.get(model.getPoolUuid());
				BeanUtils.copyProperties(model, lbTargetGroup);
				lbTargetGroup.setListenerId(listenerMap.get(lbTargetGroup.getListenerUuid()));
				lbTargetGroup.setLbId(balancerMap.get(lbTargetGroup.getLbUuid()));
				lbTargetGroup.setMenderId(userId);
				lbTargetGroup.setVendorId(vendorId);
				lbTargetGroup.setGmtModify(new Date());
				lbTargetGroup.setRegionId(region);
				lbPoolRepository.update(lbTargetGroup);
				targetGroupMap.remove(lbTargetGroup.getPoolUuid());
				continue;
			}
			BeanUtils.copyProperties(model, lbTargetGroup);
			lbTargetGroup.setListenerId(listenerMap.get(lbTargetGroup.getListenerUuid()));
			lbTargetGroup.setLbId(balancerMap.get(lbTargetGroup.getLbUuid()));
			lbTargetGroup.setCreatorId(userId);
			lbTargetGroup.setVendorId(vendorId);
			lbTargetGroup.setGmtCreate(new Date());
			lbTargetGroup.setRegionId(region);
			lbPoolRepository.save(lbTargetGroup);
			targetGroupMap.remove(lbTargetGroup.getPoolUuid());
		}
		for (Map.Entry<String, LbPool> entry : targetGroupMap.entrySet()) {
			lbPoolRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 后端云服务器
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncLbMember(List<LbMemberModel> models, Map<String, LbPool> tgMap, Map<String, Subnet> subnetMap,
			Long vendorId, Long userId, String region) throws Exception {
		if (ListTool.isEmpty(models)) {
			lbMemberRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<LbMember> lbTargets = lbMemberRepository.listByVid(vendorId, region);
		Map<String, LbMember> targetMap = Maps.newHashMap();
		for (LbMember lbTarget : lbTargets) {
			targetMap.put(lbTarget.getPoolUuid() + lbTarget.getMemberUuid(), lbTarget);
		}
		for (LbMemberModel model : models) {
			LbMember lbTarget = new LbMember();
			String uuid = model.getPoolUuid() + model.getMemberUuid();
			if (targetMap.containsKey(uuid)) {
				lbTarget = targetMap.get(uuid);
				BeanUtils.copyProperties(model, lbTarget);
				LbPool pool = tgMap.get(lbTarget.getPoolUuid());
				if (null != pool) {
					lbTarget.setPoolId(pool.getId());
					lbTarget.setListenerId(pool.getListenerId());
				}
				Subnet subnet = subnetMap.get(lbTarget.getSubnetUuid());
				if (null != subnet) {
					lbTarget.setSubnetId(subnet.getId());
				}
				CloudServer cloudServer = cloudServerRepository.get(vendorId, lbTarget.getInstanceId());
				if (null != cloudServer) {
					lbTarget.setName(cloudServer.getName());
					lbTarget.setStatus(cloudServer.getStatus());
					lbTarget.setInstanceId(cloudServer.getInstanceId());
				} else {
					continue;
				}
				lbTarget.setVendorId(vendorId);
				lbTarget.setGmtModify(new Date());
				lbTarget.setRegionId(region);
				lbMemberRepository.update(lbTarget);
				targetMap.remove(uuid);
				continue;
			}
			BeanUtils.copyProperties(model, lbTarget);
			LbPool pool = tgMap.get(lbTarget.getPoolUuid());
			if (null != pool) {
				lbTarget.setPoolId(pool.getId());
				lbTarget.setListenerId(pool.getListenerId());
			}
			Subnet subnet = subnetMap.get(lbTarget.getSubnetUuid());
			if (null != subnet) {
				lbTarget.setSubnetId(subnet.getId());
			}

			CloudServer cloudServer = cloudServerRepository.get(vendorId, lbTarget.getInstanceId());
			if (null != cloudServer) {
				lbTarget.setName(cloudServer.getName());
				lbTarget.setStatus(cloudServer.getStatus());
				lbTarget.setInstanceId(cloudServer.getInstanceId());
			} else {
				continue;
			}
			lbTarget.setCreatorId(0L);
			lbTarget.setVendorId(vendorId);
			lbTarget.setGmtCreate(new Date());
			lbTarget.setRegionId(region);
			lbMemberRepository.save(lbTarget);
			targetMap.remove(lbTarget.getPoolUuid() + lbTarget.getMemberUuid());
		}
		for (Map.Entry<String, LbMember> entry : targetMap.entrySet()) {
			lbMemberRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncRouteTable(List<RouteTableModel> models, Long vendorId, Long userId, Map<String, Long> vpcMap,
			String region, Map<String, Subnet> subnetMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			routeTableRepository.removeByVid(vendorId, region, userId);
			routeRepository.removeByVid(vendorId, region, userId);
			return;
		}
		List<RouteTable> routeTables = routeTableRepository.listByVid(vendorId, region);
		Map<String, RouteTable> routeTableMap = Maps.newHashMap();
		routeTables.forEach((RouteTable routeTable) -> {
			routeTableMap.put(routeTable.getUuid(), routeTable);
		});
		for (RouteTableModel model : models) {
			RouteTable routeTable = new RouteTable();
			if (routeTableMap.containsKey(model.getUuid())) {
				routeTable = routeTableMap.get(model.getUuid());
				BeanUtils.copyProperties(model, routeTable);
				// 关联vpc
				if (!org.apache.commons.lang3.StringUtils.isEmpty(model.getVpcUuid())
						&& null != vpcMap.get(model.getVpcUuid())) {
					routeTable.setVpcId(vpcMap.get(model.getVpcUuid()));
				}
				routeTable.setMenderId(userId);
				routeTable.setGmtModify(new Date());
				routeTable.setVendorId(vendorId);
				routeTable.setRegionId(region);
				routeTableRepository.update(routeTable);
				List<String> subnetUuids = routeTable.getSubnetUuids();
				if (!ListTool.isEmpty(subnetUuids)) {
					List<Subnet> subnets = Lists.newArrayList();
					for (String subnetUuid : subnetUuids) {
						Subnet subnet = subnetMap.get(subnetUuid);
						subnet.setRouteTableId(routeTable.getUuid());
						subnet.setRouteTableType(routeTable.getType());
						subnets.add(subnet);
					}
					subnetRepository.batchUpdate(subnets, subnets.size());
				}
				routeTableMap.remove(model.getUuid());
			} else {
				BeanUtils.copyProperties(model, routeTable);
				// 关联vpc
				if (!org.apache.commons.lang3.StringUtils.isEmpty(model.getVpcUuid())
						&& null != vpcMap.get(model.getVpcUuid())) {
					routeTable.setVpcId(vpcMap.get(model.getVpcUuid()));
				}
				routeTable.setCreatorId(userId);
				routeTable.setGmtCreate(new Date());
				routeTable.setVendorId(vendorId);
				routeTable.setRegionId(region);
				routeTableRepository.save(routeTable);
				List<String> subnetUuids = routeTable.getSubnetUuids();
				if (!ListTool.isEmpty(subnetUuids)) {
					List<Subnet> subnets = Lists.newArrayList();
					for (String subnetUuid : subnetUuids) {
						Subnet subnet = subnetMap.get(subnetUuid);
						subnet.setRouteTableId(routeTable.getUuid());
						subnet.setRouteTableType(routeTable.getType());
						subnets.add(subnet);
					}
					subnetRepository.batchUpdate(subnets, subnets.size());
				}
				routeTableMap.remove(model.getUuid());
			}
			syncRouteEntry(model.getRouteModels(), routeTable.getId(), vendorId, userId, region);
		}
		for (Map.Entry<String, RouteTable> entry : routeTableMap.entrySet()) {
			routeTableRepository.remove(entry.getValue().getId(), userId);
			routeRepository.removeByVid(vendorId, region, userId, entry.getValue().getId());
		}
	}

	private void syncRouteEntry(List<RouteModel> models, Long routeTableId, Long vendorId, Long userId, String region)
			throws Exception {
		if (ListTool.isEmpty(models)) {
			routeRepository.removeByVid(vendorId, region, userId, routeTableId);
			return;
		}
		List<Route> routes = routeRepository.listByVid(vendorId, region, routeTableId);
		Map<String, Route> routeMap = Maps.newHashMap();
		routes.forEach((Route route) -> {
			routeMap.put(route.getUuid() + route.getName() + route.getDestination() + route.getType(), route);
		});
		for (RouteModel model : models) {
			Route route = new Route();
			String key = model.getUuid() + model.getName() + model.getDestination() + model.getType();
			if (routeMap.containsKey(key)) {
				route = routeMap.get(key);
				BeanUtils.copyProperties(model, route);
				route.setRouteTableId(routeTableId);
				route.setMenderId(userId);
				route.setGmtModify(new Date());
				route.setVendorId(vendorId);
				route.setRegionId(region);
				routeRepository.update(route);
				routeMap.remove(key);
			} else {
				BeanUtils.copyProperties(model, route);
				route.setRouteTableId(routeTableId);
				route.setCreatorId(userId);
				route.setGmtCreate(new Date());
				route.setVendorId(vendorId);
				route.setRegionId(region);
				routeRepository.save(route);
				routeMap.remove(key);
			}
		}
		for (Map.Entry<String, Route> entry : routeMap.entrySet()) {
			routeRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncNetworkCard(List<NetworkCardModel> networkCardModels, Long vendorId, Long userId, String regionId)
			throws Exception {
		if (ListTool.isEmpty(networkCardModels)) {
			networkCardRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<NetworkCard> networkList = networkCardRepository.listByVendor(vendorId, regionId);
		Map<String, NetworkCard> networkCardMap = Maps.newHashMap();
		for (NetworkCard card : networkList) {
			networkCardMap.put(card.getNetworkcardUuid(), card);
		}
		NetworkCard networkCard = null;
		for (NetworkCardModel model : networkCardModels) {
			if (networkCardMap.containsKey(model.getNetworkcardUuid())) {
				networkCard = networkCardMap.get(model.getNetworkcardUuid());
				BeanUtils.copyProperties(model, networkCard);
				networkCard.setMenderId(userId);
				networkCard.setRegionId(regionId);
				networkCard.setGmtModify(new Date());
				networkCard.setCreatorId(userId);
				networkCard.setVendorId(vendorId);
				if (networkCard.getUsed() && !StringUtils.isEmpty(networkCard.getInstanceId())) {
					networkCard.setCategory("VM");
				} else {
					// 说明是创建负载均衡时直接创建的网卡
					if (networkCard.getName().startsWith("clb-") && networkCard.getName().endsWith("eni")) {
						networkCard.setCategory("LB");
					} else {
						networkCard.setCategory(null);
					}
				}
				networkCardRepository.update(networkCard);
				networkCardMap.remove(model.getNetworkcardUuid());
				continue;
			}
			networkCard = new NetworkCard();
			BeanUtils.copyProperties(model, networkCard);
			networkCard.setMenderId(userId);
			networkCard.setRegionId(regionId);
			if (networkCard.getUsed() && !StringUtils.isEmpty(networkCard.getInstanceId())) {
				networkCard.setCategory("VM");
			} else {
				// 说明是创建负载均衡时直接创建的网卡
				if (networkCard.getName().startsWith("clb-") && networkCard.getName().endsWith("eni")) {
					networkCard.setCategory("LB");
				}
			}
			networkCard.setGmtModify(new Date());
			networkCard.setVendorId(vendorId);
			networkCardRepository.save(networkCard);
		}
		for (Map.Entry<String, NetworkCard> entry : networkCardMap.entrySet()) {
			networkCardRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncElasticIp(List<ElasticIpModel> models, String region, Long vendorId, Long userId,
			Map<String, CloudServer> serverMap, Map<String, NetworkCard> networkCardMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			elasticIpRepository.removeByVid(vendorId, userId, region);
			return;
		}
		List<ElasticIp> elasticIps = elasticIpRepository.listByVid(vendorId, region);
		Map<String, ElasticIp> elasticIpMap = Maps.newHashMap();
		for (ElasticIp elasticIp : elasticIps) {
			elasticIpMap.put(elasticIp.getElasticIpUuid(), elasticIp);
		}
		for (ElasticIpModel model : models) {
			ElasticIp elasticIp = new ElasticIp();
			if (elasticIpMap.containsKey(model.getElasticIpUuid())) {
				elasticIp = elasticIpMap.get(model.getElasticIpUuid());
				BeanUtils.copyProperties(model, elasticIp);
				elasticIp.setInstanceId(model.getInstanceId());
				elasticIp.setVendorId(vendorId);
				elasticIp.setGmtModify(new Date());
				elasticIp.setRegionId(region);
				if (!StringUtils.isEmpty(elasticIp.getInstanceId())) {
					if ("EcsInstance".equalsIgnoreCase(elasticIp.getInstanceType())) {
						elasticIp.setBandwidthName(serverMap.get(elasticIp.getInstanceId()).getName());
					} else if ("NetworkInterface".equalsIgnoreCase(elasticIp.getInstanceType())) {
						elasticIp.setBandwidthName(networkCardMap.get(elasticIp.getInstanceId()).getName());
					}
				}
				elasticIpRepository.update(elasticIp);
				elasticIpMap.remove(elasticIp.getElasticIpUuid());
				continue;
			}
			BeanUtils.copyProperties(model, elasticIp);
			elasticIp.setInstanceId(model.getInstanceId());
			elasticIp.setCreatorId(0L);
			elasticIp.setMenderId(0L);
			elasticIp.setVendorId(vendorId);
			elasticIp.setGmtCreate(new Date());
			elasticIp.setRegionId(region);
			if (!StringUtils.isEmpty(elasticIp.getInstanceId())) {
				if ("EcsInstance".equalsIgnoreCase(elasticIp.getInstanceType())) {
					elasticIp.setBandwidthName(serverMap.get(elasticIp.getInstanceId()).getName());
				} else if ("NetworkInterface".equalsIgnoreCase(elasticIp.getInstanceType())) {
					elasticIp.setBandwidthName(networkCardMap.get(elasticIp.getInstanceId()).getName());
				}
			}
			elasticIpRepository.save(elasticIp);
			elasticIpMap.remove(model.getElasticIpUuid());
		}
		for (Map.Entry<String, ElasticIp> entry : elasticIpMap.entrySet()) {
			elasticIpRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncKeypair(List<KeypairModel> models, String regionId, Long vendorId, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			keypairRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Keypair> keypairs = keypairRepository.listByVid(vendorId, regionId);
		Map<String, Keypair> keypairMap = Maps.newHashMap();
		for (Keypair keypair : keypairs) {
			keypairMap.put(keypair.getName(), keypair);
		}
		for (KeypairModel model : models) {
			Keypair keypair = new Keypair();
			if (keypairMap.containsKey(model.getName())) {
				keypair = keypairMap.get(model.getName());
				BeanUtils.copyProperties(model, keypair);
				model.setGmtCreate(keypair.getGmtCreate());
				model.setUserUuid(keypair.getUserUuid());
				keypair.setMenderId(userId);
				keypair.setGmtModify(new Date());
				keypairRepository.update(keypair);
				keypairMap.remove(keypair.getName());
				continue;
			}
			BeanUtils.copyProperties(model, keypair);
			keypair.setCreatorId(userId);
			keypair.setGmtCreate(model.getGmtCreate());
			keypair.setVendorId(vendorId);
			keypair.setTenantId(0L);
			keypair.setProjectId(0L);
			keypairRepository.save(keypair);
		}
		for (Map.Entry<String, Keypair> entry : keypairMap.entrySet()) {
			keypairRepository.remove(entry.getValue().getId(), userId);
		}

	}

	/**
	 * 同步云硬盘
	 *
	 * @param volumeModels
	 * @param vendorId
	 * @param regionId
	 * @param userId
	 * @param serverMap
	 * @throws Exception
	 */
	private void syncVolume(List<VolumeModel> volumeModels, Long vendorId, String regionId, Long userId,
			Map<String, CloudServer> serverMap) throws Exception {
		if (ListTool.isEmpty(volumeModels)) {
			volumeRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Volume> volumes = volumeRepository.listByVendorId(vendorId, regionId);
		Map<String, Volume> volumeMap = Maps.newHashMap();
		for (Volume volume : volumes) {
			volumeMap.put(volume.getVolumeUuid(), volume);
		}
		Volume volume = null;
		for (VolumeModel volumeModel : volumeModels) {
			if (volumeMap.containsKey(volumeModel.getVolumeUuid())) {
				volume = volumeMap.get(volumeModel.getVolumeUuid());
				BeanUtils.copyProperties(volumeModel, volume);
				volume.setRegionId(regionId);
				volume.setVendorId(vendorId);
				volume.setStatus(volumeModel.getStatus().toUpperCase());
				volume.setCreateTime(volumeModel.getCreateTime());
				List<ServerVolumeModel> models = volumeModel.getModels();
				if (null != models && models.size() > 0) {
					ServerVolumeModel serverVolumeModel = models.get(0);
					volume.setDevice(serverVolumeModel.getDevice());
					volume.setInstanceId(serverVolumeModel.getInstanceId());
					CloudServer cloudServer = serverMap.get(serverVolumeModel.getInstanceId());
					if (null != cloudServer) {
						volume.setServerId(cloudServer.getId());
					}
				} else {
					volume.setServerId(null);
				}
				volumeRepository.update(volume);
				volumeMap.remove(volumeModel.getVolumeUuid());
				continue;
			}
			volume = new Volume();
			BeanUtils.copyProperties(volumeModel, volume);
			volume.setMenderId(0L);
			volume.setOwnerId(0L);
			volume.setRegionId(regionId);
			volume.setVendorId(vendorId);
			volume.setProjectId(0L);
			volume.setTenantId(0L);
			volume.setCreatorId(0L);
			volume.setStatus(volumeModel.getStatus().toUpperCase());
			volume.setCreateTime(volumeModel.getCreateTime());
			List<ServerVolumeModel> models = volumeModel.getModels();
			if (null != models && models.size() > 0) {
				ServerVolumeModel serverVolumeModel = models.get(0);
				volume.setDevice(serverVolumeModel.getDevice());
				volume.setInstanceId(serverVolumeModel.getInstanceId());
				CloudServer cloudServer = serverMap.get(serverVolumeModel.getInstanceId());
				if (null != cloudServer) {
					volume.setServerId(cloudServer.getId());
				}
			}
			volumeRepository.save(volume);

		}
		// 删除异常数据
		for (Map.Entry<String, Volume> entry : volumeMap.entrySet()) {
			volumeRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步镜像
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param type
	 * @param imageMap
	 * @throws Exception
	 */
	private void syncImage(List<ImageModel> models, Long vendorId, String regionId, Long userId, String type,
			Map<String, Image> imageMap) throws Exception {
		if (ListTool.isEmpty(models)) {
			imageRepository.removeByVid(vendorId, regionId, userId);
			return;
		}
		List<Image> images = imageRepository.listByVendorId(vendorId, regionId);
		Map<String, Image> imagesMap = Maps.newConcurrentMap();
		for (Image image : images) {
			if (null != image.getImageUuid()) {
				if (imagesMap.containsKey(image.getImageUuid())) {
					imageRepository.remove(image.getId(), userId);
				} else {
					imagesMap.put(image.getImageUuid(), image);
				}
			} else {
				imageRepository.remove(image.getId(), userId);
			}
		}
		List<Image> updateList = new ArrayList<Image>();
		List<Image> instertList = new ArrayList<Image>();
		for (ImageModel model : models) {
			Image image = new Image();
			// 过滤掉非active的镜像
			if ("AVAILABLE".equalsIgnoreCase(model.getStatus())) {
				if (imagesMap.containsKey(model.getImageUuid())) {
					image = imagesMap.get(model.getImageUuid());
					BeanUtils.copyProperties(model, image);
					image.setMenderId(userId);
					image.setVendorType(type);
					image.setVendorId(vendorId);
					image.setRegionId(regionId);
					image.setDefaultUser(model.getDefaultUser());
					updateList.add(image);
					imagesMap.remove(model.getImageUuid());
					continue;
				}
				BeanUtils.copyProperties(model, image);
				image.setVendorId(vendorId);
				image.setCreatorId(userId);
				image.setVendorType(type);
				image.setRegionId(regionId);
				image.setMenderId(userId);
				image.setTenantId(0L);
				image.setProjectId(0L);
				if (!StringUtils.hasText(image.getOsCategory())) {
					image.setOsCategory(image.getOsCategory());
				} else {
					image.setOsCategory("Linux");
				}
				image.setCatalog("VM");
				instertList.add(image);
			} else {
				image = imagesMap.get(model.getImageUuid());
				if (null != image) {
					imageRepository.remove(image.getId(), userId);
				}
			}
		}
		if (!updateList.isEmpty()) {
			imageRepository.batchUpdate(updateList, updateList.size());
		}
		if (!instertList.isEmpty()) {
			imageRepository.batchSave(instertList, instertList.size());
		}
		for (Map.Entry<String, Image> set : imagesMap.entrySet()) {
			imageRepository.remove(set.getValue().getId(), userId);
		}
	}

	/**
	 * 同步云主机
	 *
	 * @param serverModels
	 * @param vendor
	 * @param userId
	 * @param region
	 * @param type
	 * @param serverMap
	 * @param infos
	 * @param infos
	 * @throws Exception
	 */
	private void syncServer(List<ServerModel> serverModels, CloudVendor vendor, Long userId, Region region, String type,
			Map<String, CloudServer> serverMap, Map<String, Flavor> flavorMap, List<CmdbInfo> infos) throws Exception {
		if (ListTool.isEmpty(serverModels)) {
			List<CloudServer> servers = cloudServerRepository.listByVendorId(vendor.getId(), region.getRegionId());
			for (CloudServer server : servers) {
				serverSgroupRepository.removeBySid(server.getId());
				volumeRepository.detachVolumes(server.getId(), userId);
				// cmdb：删除云主机
				infos.add(CmdbInfoConvertor.getInfo(server, "delete", null));
			}
			cloudServerRepository.removeByVid(vendor.getId(), region.getRegionId(), userId);
			// 删除资源表
			resourceRepository.removeByVidReg(vendor.getId(), region.getRegionId(), userId);
			return;
		}
		// 获取平台云主机信息
		List<CloudServer> servers = cloudServerRepository.listByVendorId(vendor.getId(), region.getRegionId());
		Map<String, CloudServer> cloudSeverMap = Maps.newHashMap();
		for (CloudServer server : servers) {
			cloudSeverMap.put(server.getInstanceId(), server);
		}
		// 获取平台安全组信息
		List<SecurityGroup> securityGroups = securityGroupRepository.listByVendorId(vendor.getId(),
				region.getRegionId());
		Map<String, Long> groupMap = Maps.newHashMap();
		for (SecurityGroup group : securityGroups) {
			groupMap.put(group.getGroupUuid(), group.getId());
		}
		CloudServer vm = null;
		for (ServerModel server : serverModels) {
			List<CmdbRelation> relations = new ArrayList<>();
			relations.add(new CmdbRelation(ModuleCode.REGION.name(), 1L, ListUtils.getList(region.getGuid())));
			Flavor flavor = flavorMap.get(server.getFlavorUuid());
			// 更新已创建的云主机
			if (cloudSeverMap.containsKey(server.getInstanceId())) {
				vm = cloudSeverMap.get(server.getInstanceId());

				String account = vm.getAccount();
				if (StringUtils.hasText(account)) {
					Image image = imageRepository.getByImageUuid(server.getImageUuid());
					if (null != image) {
						account = image.getDefaultUser();
					}
				}
				server.setAccount(account);
				server.setPassword(vm.getPassword());
				BeanUtils.copyProperties(server, vm);

				vm.setOsCategory(server.getOsCategory());
				vm.setOsName(server.getOsName());
				vm.setOsVersion(server.getOsVersion());
				if ("error".equalsIgnoreCase(server.getStatus())) {
					vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
				} else {
					vm.setStatus(server.getStatus());
				}

				List<Long> sgIds = null;
				String groups = server.getGroups();
				if (!StringUtils.hasText(groups)) {
					List<String> groupList = JSONArray.parseArray(groups, String.class);
					if (null != groupList && groupList.size() > 0) {
						sgIds = new ArrayList<Long>();
						for (String sgUuid : groupList) {
							sgIds.add(groupMap.get(sgUuid));
						}
					}
				}

				vm.setHostId(0L);
				vm.setPassword(server.getPassword());
				vm.setIsTemplate(false);
				vm.setGmtVmCreate(server.getGmtVmCreate());
				vm.setPrivateIps(server.getPrivateIps());
				if (null != flavor) {
					vm.setCpu(flavor.getCpu());
					vm.setMemory(flavor.getMemory());
				}
				vm.setRegionId(region.getRegionId());
				vm.setVendorId(vendor.getId());
				cloudServerRepository.update(vm);
				// CMDB更新集群数据
				infos.add(CmdbInfoConvertor.getInfo(vm, null, relations));
				// 更新资源表
				updateResource(vm, vendor, region.getRegionId(), userId);
				cloudSeverMap.remove(vm.getInstanceId());
				// 更新云主机绑定的安全组
				serverSgroupRepository.removeBySid(vm.getId());
				updateSGroup(vm.getId(), server.getGroups(), groupMap);
				serverMap.remove(vm.getInstanceId());
				continue;
			}
			vm = new CloudServer();
			BeanUtils.copyProperties(server, vm);
			if ("error".equalsIgnoreCase(server.getStatus())) {
				vm.setStatus(BocloudStatus.Server.EXCEPTION.name());
			} else {
				vm.setStatus(server.getStatus());
			}
			vm.setVendorId(vendor.getId());
			vm.setRegionId(region.getRegionId());
			vm.setIsTemplate(false);
			vm.setResourceId(IDFactory.instance().uuid());
			vm.setVendorType(type);
			vm.setGmtVmCreate(server.getGmtVmCreate());
			vm.setPrivateIps(server.getPrivateIps());
			vm.setMenderId(0L);
			vm.setOwnerId(0L);
			vm.setTenantId(0L);
			vm.setProjectId(0L);

			List<Long> sgIds = null;
			String groups = server.getGroups();
			if (!StringUtils.hasText(groups)) {
				List<String> groupList = JSONArray.parseArray(groups, String.class);
				if (null != groupList && groupList.size() > 0) {
					sgIds = new ArrayList<Long>();
					for (String sgUuid : groupList) {
						sgIds.add(groupMap.get(sgUuid));
					}
				}
			}
			vm.setRecycle(false);
			vm.preSave(userId, userId, vendor.getId(), 0L, null, null, 0L, 0L);
			if (StringUtils.hasText(vm.getOsCategory())) {
				vm.setOsCategory(OSCategory.LINUX.name());
			}
			String account = vm.getAccount();
			if (StringUtils.hasText(account)) {
				Image image = imageRepository.getByImageUuid(vm.getImageUuid());
				if (null != image) {
					account = image.getDefaultUser();
				}
			}
			server.setAccount(account);
			if (null != flavor) {
				vm.setCpu(flavor.getCpu());
				vm.setMemory(flavor.getMemory());
			}
			cloudServerRepository.save(vm);
			// CMDB更新集群数据
			infos.add(CmdbInfoConvertor.getInfo(vm, null, relations));
			// 更新资源表
			updateResource(vm, vendor, region.getRegionId(), userId);
			serverSgroupRepository.removeBySid(vm.getId());
			updateSGroup(vm.getId(), server.getGroups(), groupMap);

		}
		for (Map.Entry<String, CloudServer> entry : cloudSeverMap.entrySet()) {
			CloudServer server = entry.getValue();
			resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
					userId);
			// cmdb：删除云主机
			infos.add(CmdbInfoConvertor.getInfo(entry.getValue(), "delete", null));
			volumeRepository.detachVolumes(server.getId(), userId);
			serverSgroupRepository.removeBySid(server.getId());
			cloudServerRepository.remove(server.getId(), userId);
		}
	}

	private void updateSGroup(Long serverId, String groups, Map<String, Long> groupMap) throws Exception {
		if (!StringUtils.hasText(groups)) {
			return;
		}
		List<String> groupList = JSONArray.parseArray(groups, String.class);
		if (ListTool.isEmpty(groupList)) {
			return;
		}
		for (String group : groupList) {
			Long groupId = groupMap.get(group);
			ServerSgroup serverSgroupInfo = serverSgroupRepository.getByServerGroup(serverId, groupId);
			if (null == serverSgroupInfo) {
				ServerSgroup serverSgroup = new ServerSgroup(serverId, groupMap.get(group));
				serverSgroupRepository.save(serverSgroup);
			}
		}
	}

	/**
	 * 更新资源表相关信息
	 *
	 * @param server
	 * @param vendor
	 * @param userId
	 * @throws Exception
	 */
	private void updateResource(CloudServer server, CloudVendor vendor, String region, Long userId) throws Exception {
		// 更新资源表
		Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
				server.getId());
		// 保存资源
		List<String> ips = Lists.newArrayList();
		if (!StringUtils.hasText(server.getPrivateIps())) {
			List<JSONObject> objects = JSONObject.parseArray(server.getPrivateIps(), JSONObject.class);
			for (JSONObject object : objects) {
				ips.add(object.getString("address"));
			}
		}
		if (null != resource) {
			resource.setStatus(server.getStatus());
			resource.setPrivateIps(JSONObject.toJSONString(ips));
			resource.setRegionId(region);
			resource.setMenderId(userId);
			resource.setAccurated(false);
			resource.setAuthed(false);
			resourceRepository.update(resource);
			server.setResource(resource);
		} else {
			resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(), server.getId(),
					null, server.getOsCategory(), vendor.getId());
			resource.preSave(server.getName(), server.getStatus(), userId, 0L, 0L);
			resource.setInventory(JSONObject.toJSONString(server));
			resource.setRegionId(region);
			resource.setPrivateIps(JSONObject.toJSONString(ips));
			resource.setOwnerId(userId);
			resource.setAccurated(false);
			resource.setAuthed(false);
			resourceRepository.save(resource);
			server.setResource(resource);
		}
	}

	/**
	 * 同步规格
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @param regionId
	 * @throws Exception
	 */
	private void syncFlavor(List<FlavorModel> models, Long vendorId, Long userId, String regionId) throws Exception {
		if (ListTool.isEmpty(models)) {
			flavorRepository.removeByVid(vendorId, regionId);
			return;
		}
		List<Flavor> flavors = flavorRepository.listByVendorId(vendorId, regionId);
		Map<String, Flavor> flavorMap = new HashMap<String, Flavor>(8);
		for (Flavor flavor : flavors) {
			flavorMap.put(flavor.getFlavorUuid(), flavor);
		}
		List<Flavor> updateList = new ArrayList<Flavor>();
		List<Flavor> instertList = new ArrayList<Flavor>();
		for (FlavorModel model : models) {
			Flavor flavor = new Flavor();
			if (flavorMap.containsKey(model.getFlavorUuid())) {
				flavor = flavorMap.get(model.getFlavorUuid());
				BeanUtils.copyProperties(model, flavor);
				flavor.setOsExtraSpecs(JSONObject.toJSONString(model.getOsExtraSpecs()));
				flavor.setAttachableQuantity(JSONObject.toJSONString(model.getAttachableQuantity()));
				flavor.setVendorId(vendorId);
				flavor.setRegionId(regionId);
				flavorRepository.update(flavor);
				flavorMap.remove(model.getName());
				continue;
			}
			BeanUtils.copyProperties(model, flavor);
			flavor.setOsExtraSpecs(JSONObject.toJSONString(model.getOsExtraSpecs()));
			flavor.setAttachableQuantity(JSONObject.toJSONString(model.getAttachableQuantity()));
			flavor.setVendorId(vendorId);
			flavor.setRegionId(regionId);
			flavorRepository.save(flavor);
		}

		for (Map.Entry<String, Flavor> entry : flavorMap.entrySet()) {
			flavorRepository.delete(entry.getValue().getId());
		}
	}

	/**
	 * 同步安全组和规则
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	private void syncSecurityGroup(List<SecurityGroupModel> models, Map<String, Long> vpcMap, Long vendorId,
			Long userId, String region) throws Exception {
		// 当安全组为空时,删除数据库残留数据
		if (ListTool.isEmpty(models)) {
			securityGroupRepository.removeByVid(vendorId, region, userId);
			securityGroupRuleRepository.removeByVid(vendorId, userId);
			return;
		}
		List<SecurityGroup> groups = securityGroupRepository.listByVendorId(vendorId, region);
		Map<String, SecurityGroup> groupMap = Maps.newHashMap();
		for (SecurityGroup group : groups) {
			groupMap.put(group.getGroupUuid(), group);
		}
		for (SecurityGroupModel model : models) {
			SecurityGroup group = new SecurityGroup();
			if (groupMap.containsKey(model.getGroupUuid())) {
				group = groupMap.get(model.getGroupUuid());
				BeanUtils.copyProperties(model, group);
				group.setVpcId(vpcMap.get(group.getVpcUuid()));
				group.setMenderId(userId);
				securityGroupRepository.update(group);
				securityGroupRuleRepository.removeBySgId(group.getId(), userId);
				for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
					SecurityGroupRule securityGroupRule = new SecurityGroupRule();
					BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
					securityGroupRule.setCreatorId(userId);
					securityGroupRule.setVendorId(vendorId);
					securityGroupRule.setGroupId(group.getId());
					securityGroupRule.setGroupUuid(group.getGroupUuid());
					securityGroupRuleRepository.save(securityGroupRule);
				}
				groupMap.remove(model.getGroupUuid());
				continue;
			}
			group = JSONObject.parseObject(JSONObject.toJSONString(model), SecurityGroup.class);
			group.setVpcId(vpcMap.get(group.getVpcUuid()));
			group.preSave(userId, userId, vendorId, 0L, 0L);
			securityGroupRepository.save(group);
			for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
				SecurityGroupRule securityGroupRule = new SecurityGroupRule();
				BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
				securityGroupRule.setCreatorId(userId);
				securityGroupRule.setVendorId(vendorId);
				securityGroupRule.setGroupId(group.getId());
				securityGroupRule.setGroupUuid(group.getGroupUuid());
				securityGroupRuleRepository.save(securityGroupRule);
			}
		}
		// 删除不存在的安全组
		for (Map.Entry<String, SecurityGroup> entry : groupMap.entrySet()) {
			securityGroupRepository.remove(entry.getValue().getId(), userId);
			securityGroupRuleRepository.removeBySgId(entry.getValue().getId(), userId);
		}
	}

	private void syncVpc(List<VpcModel> models, Long vendorId, Long userId, String region) throws Exception {
		if (ListTool.isEmpty(models)) {
			vpcRepository.deleteByVid(vendorId, region, userId);
			return;
		}
		List<Vpc> vpcs = vpcRepository.list(vendorId, region);
		Map<String, Vpc> vpcMap = Maps.newHashMap();
		for (Vpc vpc : vpcs) {
			vpcMap.put(vpc.getVpcId(), vpc);
		}
		for (VpcModel model : models) {
			Vpc vpc = new Vpc();
			if (vpcMap.containsKey(model.getVpcId())) {
				vpc = vpcMap.get(model.getVpcId());
				BeanUtils.copyProperties(model, vpc);
				vpc.setRegionId(region);
				vpcRepository.update(vpc);
				// 同步子网
				this.syncSubnet(model.getSubnetModels(), vendorId, userId, region, vpc.getVpcId(), vpc.getId());
				vpcMap.remove(model.getVpcId());
				continue;
			}
			BeanUtils.copyProperties(model, vpc);
			vpc.setCreatorId(userId);
			vpc.setVendorId(vendorId);
			vpc.setMenderId(userId);
			vpc.setRegionId(region);
			vpc.setTenantId(0L);
			vpc.setProjectId(0L);
			vpcRepository.save(vpc);
			// 同步子网
			this.syncSubnet(model.getSubnetModels(), vendorId, userId, region, vpc.getVpcId(), vpc.getId());
			vpcMap.remove(model.getVpcId());
		}
		for (Map.Entry<String, Vpc> entry : vpcMap.entrySet()) {
			vpcRepository.delete(entry.getValue().getId(), userId);
		}
	}

	private void syncSubnet(List<SubnetModel> models, Long vendorId, Long userId, String region, String vpcUuid,
			Long vpcId) throws Exception {
		if (ListTool.isEmpty(models)) {
			subnetRepository.deleteByVpcId(vendorId, vpcUuid, userId);
			return;
		}
		List<Subnet> subnetList = subnetRepository.listByVpcId(vendorId, vpcUuid);
		Map<String, Subnet> subnetMap = Maps.newHashMap();
		for (Subnet subnet : subnetList) {
			subnetMap.put(subnet.getSubnetUuid(), subnet);
		}
		for (SubnetModel model : models) {
			Subnet subnet = new Subnet();
			if (subnetMap.containsKey(model.getSubnetUuid())) {
				subnet = subnetMap.get(model.getSubnetUuid());
				BeanUtils.copyProperties(model, subnet);
				subnet.setMenderId(userId);
				subnet.setRegionId(region);
				subnet.setVpcId(vpcId);
				subnetRepository.update(subnet);
				subnetMap.remove(model.getSubnetUuid());
				continue;
			}
			BeanUtils.copyProperties(model, subnet);
			subnet.setMenderId(userId);
			subnet.setGmtModify(new Date());
			subnet.setCreatorId(userId);
			subnet.setVendorId(vendorId);
			subnet.setRegionId(region);
			subnet.setVpcId(vpcId);
			subnetRepository.save(subnet);
			subnetMap.remove(model.getSubnetUuid());
		}
		for (Map.Entry<String, Subnet> entry : subnetMap.entrySet()) {
			subnetRepository.remove(entry.getValue().getId(), userId);
		}
	}

	private void syncRegions(List<RegionModel> regionModels, CloudVendor vendor, Long userId, String regionId)
			throws Exception {
		if (ListTool.isEmpty(regionModels)) {
			regionRepository.deleteByVid(vendor.getId(), regionId);
			zoneRepository.deleteByRegionId(regionId, vendor.getId());
			return;
		}
		for (RegionModel model : regionModels) {
			// 同步区
			syncZone(model.getZones(), model.getCode(), vendor, userId);
		}
	}

	private void syncZone(List<ZoneModel> models, String regionId, CloudVendor vendor, Long userId) throws Exception {
		if (ListTool.isEmpty(models)) {
			zoneRepository.deleteByRegionId(regionId, vendor.getId());
			return;
		}
		List<Zone> zones = zoneRepository.listByRegionId(regionId, vendor.getId());
		Map<String, Zone> zoneMap = Maps.newHashMap();
		for (Zone zone : zones) {
			zoneMap.put(zone.getZoneId(), zone);
		}
		Zone zone = null;
		for (ZoneModel model : models) {
			zone = new Zone();
			if (zoneMap.containsKey(model.getZoneId())) {
				zone = zoneMap.get(model.getZoneId());
				BeanUtils.copyProperties(model, zone);
				zone.setVendorId(vendor.getId());
				zone.setRegionId(regionId);
				zoneRepository.update(zone);
				zoneMap.remove(model.getZoneId());
				continue;
			}
			BeanUtils.copyProperties(model, zone);
			zone.setVendorId(vendor.getId());
			zone.setRegionId(regionId);
			zoneRepository.save(zone);
			zoneMap.remove(model.getZoneId());
		}
		for (Map.Entry<String, Zone> entry : zoneMap.entrySet()) {
			zoneRepository.delete(entry.getValue().getId());
		}

	}

	@Override
	protected void register() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void beforeTransport() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void afterTransport() {
		// TODO Auto-generated method stub

	}

}
