package com.bocloud.ims.service.transportor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.ModuleCode;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.FloatingIpModel;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.KeypairModel;
import com.bocloud.cmp.model.QcloudSyncModel;
import com.bocloud.cmp.model.RegionModel;
import com.bocloud.cmp.model.SecurityGroupModel;
import com.bocloud.cmp.model.SecurityGroupRuleModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.cmp.model.SubnetModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.model.VpcModel;
import com.bocloud.cmp.model.ZoneModel;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
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.Flavor;
import com.bocloud.ims.entity.resource.FloatingIp;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Keypair;
import com.bocloud.ims.entity.resource.Region;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.SecurityGroup;
import com.bocloud.ims.entity.resource.SecurityGroupRule;
import com.bocloud.ims.entity.resource.ServerKeypair;
import com.bocloud.ims.entity.resource.ServerSgroup;
import com.bocloud.ims.entity.resource.Snapshot;
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.CloudServerRepository;
import com.bocloud.ims.repository.resource.FlavorRepository;
import com.bocloud.ims.repository.resource.FloatingIpRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.KeypairRepository;
import com.bocloud.ims.repository.resource.NetworkCardRepository;
import com.bocloud.ims.repository.resource.ObjectRelationRepository;
import com.bocloud.ims.repository.resource.RegionRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRuleRepository;
import com.bocloud.ims.repository.resource.ServerKeypairRepository;
import com.bocloud.ims.repository.resource.ServerSgroupRepository;
import com.bocloud.ims.repository.resource.SnapshotRepository;
import com.bocloud.ims.repository.resource.SubnetRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.ims.repository.resource.VpcRepository;
import com.bocloud.ims.repository.resource.ZoneRepository;
import com.bocloud.ims.service.model.cmdb.CmdbInfo;
import com.bocloud.ims.service.model.cmdb.CmdbRelation;
import com.bocloud.ims.service.utils.ListUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
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.apache.commons.lang3.StringUtils;

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

/**
 * qcloud
 *
 * @时间 2019年10月24日
 */
@Component
public class QcloudTransportor implements Transportor {

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

	@Autowired
	private ImageRepository imageRepository;
	@Autowired
	private FlavorRepository flavorRepository;
	@Autowired
	private VolumeRepository volumeRepository;
	@Autowired
	private SnapshotRepository snapshotRepository;
	@Autowired
	private SecurityGroupRepository securityGroupRepository;
	@Autowired
	private SecurityGroupRuleRepository securityGroupRuleRepository;
	@Autowired
	private ServerSgroupRepository serverSgroupRepository;
	@Autowired
	private CloudServerRepository cloudServerRepository;
	@Autowired
	private RegionRepository regionRepository;
	@Autowired
	private ZoneRepository zoneRepository;
	@Autowired
	private ResourceRepository resourceRepository;
	@Autowired
	private VpcRepository vpcRepository;
	@Autowired
	private KeypairRepository keypairRepository;
	@Autowired
	private FloatingIpRepository floatingIpRepository;
	@Autowired
	private SubnetRepository subnetRepository;
	@Autowired
	private ServerKeypairRepository serverKeyPairRepository;
	@Autowired
	private ObjectRelationRepository objectRelationRepository;

	@Override
	public BocloudResult sync(CloudVendor vendor, Object data, Region region, Long userId, List<CmdbInfo> infos) {
		try {
			if (null != data) {
				if (cloudServerRepository.hasBuilding(vendor.getId())) {
					return new BocloudResult(false, "该平台下有虚拟机正在创建，请稍后进行同步操作");
				}
				String content = JSONObject.toJSONString(data);
				QcloudSyncModel model = JSONObject.parseObject(content, QcloudSyncModel.class);

				// 同步安全组
				logger.info("start sync security.... ");
				this.syncSecurityGroup(model.getGroupModels(), vendor, userId, region.getRegionId());
				logger.info("End sync security group......");
				List<SecurityGroup> groups = securityGroupRepository.listByVendorId(vendor.getId(),
						region.getRegionId(), null);
				Map<String, Long> groupMap = Maps.newHashMap();
				for (SecurityGroup group : groups) {
					groupMap.put(group.getGroupUuid(), group.getId());
				}
				// 同步密钥
				logger.info("Starting sync keyPairs.....");
				this.syncKeyPairs(model.getKeypairModels(), vendor.getId(), userId, region.getRegionId());
				logger.info("End sync keyPairs......");
				// 获取秘钥数据
				List<Keypair> keyPairList = keypairRepository.listByVid(vendor.getId(), region.getRegionId());
				Map<String, Long> keyPairMap = new HashMap<>();
				for (Keypair keypair : keyPairList) {
					keyPairMap.put(keypair.getFingerprint(), keypair.getId());
				}
				// 同步镜像
				logger.info("Starting sync image......");
				this.syncImage(model.getImageModels(), vendor, userId, region.getRegionId());
				logger.info("End sync image......");
				List<Image> imageList = imageRepository.listByVendorId(vendor.getId(), region.getRegionId());
				Map<String, Image> imageMap = Maps.newHashMap();
				for (Image image : imageList) {
					imageMap.put(image.getImageUuid(), image);
				}
				// 同步虚拟机
				logger.info("Starting sync server......");
				this.syncServer(model.getServerModels(), vendor, userId, groupMap, region, keyPairMap, imageMap);
				logger.info("End sync server......");
				List<CloudServer> cloudServers = cloudServerRepository.listByVendorId(vendor.getId(),
						region.getRegionId());
				Map<String, Long> serverMap = Maps.newHashMap();
				for (CloudServer cloudServer : cloudServers) {
					serverMap.put(cloudServer.getInstanceId(), cloudServer.getId());
				}
				// 同步云硬盘
				logger.info("Starting sync volume......");
				this.syncVolume(model.getVolumeModels(), vendor, userId, serverMap, region.getRegionId());
				logger.info("End sync volume......");
				// 获取云硬盘信息
				Map<String, Long> volumeMap = Maps.newHashMap();
				List<Volume> volumes = volumeRepository.listByVendorId(vendor.getId(), region.getRegionId());
				for (Volume volume : volumes) {
					volumeMap.put(volume.getVolumeUuid(), volume.getId());
				}
				// 同步云快照
				logger.info("Starting sync snapshot......");
				this.syncSnapshot(model.getSnapshotModels(), vendor, userId, volumeMap, region.getRegionId());
				logger.info("End sync snapshot......");
				// 同步虚拟机规格
				logger.info("Starting sync instance type......");
				this.syncInstanceType(model.getFlavorModels(), vendor.getId(), region.getRegionId());
				logger.info("End sync instance type......");
				// 同步域
				logger.info("Starting sync region and zone......");
				this.syncRegion(model.getRegionModels(), vendor, region.getRegionId());
				logger.info("End sync region and zone......");
				// 同步vpc
				logger.info("Starting sync vpc......");
				this.syncVpc(model.getVpcModels(), vendor.getId(), userId, region.getRegionId());
				logger.info("End sync vpc......");
				List<Vpc> list = vpcRepository.list(vendor.getId(), region.getRegionId());
				Map<String, Long> vpcMap = Maps.newHashMap();
				for (Vpc vpc : list) {
					vpcMap.put(vpc.getVpcId(), vpc.getId());
				}
				// 同步子网
				logger.info("Starting sync subnet.....");
				this.syncSubnet(model.getSubnetModels(), vendor.getId(), userId, region.getRegionId(), vpcMap);
				logger.info("Starting sync subnet.....END ");
				List<Subnet> subnetList = subnetRepository.listByRegion(vendor.getId(), region.getRegionId());
				Map<String, Long> subnetMap = Maps.newHashMap();
				for (Subnet subnet : subnetList) {
					subnetMap.put(subnet.getSubnetUuid(), subnet.getId());
				}
				// 浮动IP
				logger.info("statr sync floatingIP...");
				this.syncFloatingIp(model.getFloatingIpModels(), vendor.getId(), userId, region.getRegionId());
				logger.info("statr sync floatingIP... END");
			}
			return new BocloudResult(true, null, "云平台【 " + vendor.getName() + " 】数据同步成功");
		} catch (Exception e) {
			logger.error("云平台【 " + vendor.getName() + " 】数据同步失败");
			return new BocloudResult(false, e.getMessage(), "云平台【 " + vendor.getName() + " 】数据同步失败:" + e.getMessage());
		}
	}

	private void syncSubnet(List<SubnetModel> models, Long id, Long userId, String region, Map<String, Long> vpcMap)
			throws Exception {
		subnetRepository.removeByVid(id, region, userId);
		Subnet subnet = null;
		List<Subnet> subList = new ArrayList<Subnet>();
		for (SubnetModel subnetModel : models) {
			subnet = new Subnet();
			BeanUtils.copyProperties(subnetModel, subnet);
			subnet.setSubnetUuid(subnetModel.getSubnetUuid());
			subnet.setMenderId(userId);
			subnet.setGmtModify(new Date());
			subnet.setCreatorId(userId);
			subnet.setVendorId(id);
			subnet.setRegionId(region);
			if (org.apache.commons.lang3.StringUtils.isNotEmpty(subnetModel.getVpcUuid())) {
				subnet.setNetworkId(vpcMap.get(subnetModel.getVpcUuid()));
			}
			subList.add(subnet);
		}
		if (subList.size() > 0) {
			subnetRepository.batchSave(subList, subList.size() + 1);
		}
	}

	private void syncFloatingIp(List<FloatingIpModel> models, Long vendorId, Long userId, String region)
			throws Exception {
		// 当浮动IP为空时，清空数据库
		if (ListTool.isEmpty(models)) {
			floatingIpRepository.removeByVid(vendorId, region, userId);
			return;
		}
		List<FloatingIp> listByVid = floatingIpRepository.listByVid(vendorId, region);
		Map<String, FloatingIp> ipMap = Maps.newHashMap();
		for (FloatingIp ip : listByVid) {
			ipMap.put(ip.getFloatingIpUuid(), ip);
		}
		FloatingIp floating = null;
		for (FloatingIpModel model : models) {
			if (ipMap.containsKey(model.getFloatingIpUuid())) {
				floating = ipMap.get(model.getFloatingIpUuid());
				BeanUtils.copyProperties(model, floating);
				floating.setRegionId(region);
				floating.setGmtModify(new Date());
				floating.setVendorId(vendorId);
				floatingIpRepository.update(floating);
				ipMap.remove(model.getFloatingIpUuid());
				continue;
			}
			floating = new FloatingIp();
			BeanUtils.copyProperties(model, floating);
			floating.setMenderId(userId);
			floating.setRegionId(region);
			floating.setGmtModify(new Date());
			floating.setTenantId(0L);
			floating.setProjectId(0L);
			floating.setCreatorId(userId);
			floating.setVendorId(vendorId);
			floatingIpRepository.save(floating);
		}
		for (Map.Entry<String, FloatingIp> entry : ipMap.entrySet()) {
			floatingIpRepository.remove(entry.getValue().getId(), userId);
		}
	}

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

	/**
	 * 同步vpc专用网络
	 *
	 * @param models
	 * @param vendorId
	 * @param userId
	 * @throws Exception
	 */
	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.setMenderId(userId);
				vpc.setRegionId(region);
				vpcRepository.update(vpc);
				vpcMap.remove(model.getVpcId());
				continue;
			}
			BeanUtils.copyProperties(model, vpc);
			vpc.setCreatorId(userId);
			vpc.setTenantId(0L);
			vpc.setProjectId(0L);
			vpc.setVendorId(vendorId);
			vpc.setRegionId(region);
			vpcRepository.save(vpc);
			vpcMap.remove(model.getVpcId());
		}
		for (Entry<String, Vpc> entry : vpcMap.entrySet()) {
			vpcRepository.delete(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步云硬盘
	 *
	 * @param models
	 * @param vendor
	 * @param userId
	 * @param serverMap
	 * @throws Exception
	 */
	private void syncVolume(List<VolumeModel> models, CloudVendor vendor, Long userId, Map<String, Long> serverMap,
			String region) throws Exception {
		// 删除 脏数据
		volumeRepository.deleteRegionNull(vendor.getId());
		if (ListTool.isEmpty(models)) {
			volumeRepository.removeByVid(vendor.getId(), region, userId);
			return;
		}
		List<Volume> volumes = volumeRepository.listByVendorId(vendor.getId(), region);
		Map<String, Volume> volumeMap = Maps.newHashMap();
		for (Volume volume : volumes) {
			volumeMap.put(volume.getVolumeUuid(), volume);
		}
		for (VolumeModel model : models) {
			Volume volume = new Volume();
			if (volumeMap.containsKey(model.getVolumeUuid())) {
				volume = volumeMap.get(model.getVolumeUuid());
				BeanUtils.copyProperties(model, volume);
				volume.setMenderId(userId);
				volume.setGmtModify(new Date());
				volume.setRegionId(region);
				volume.setVendorType(vendor.getType());
				if (!StringUtils.isEmpty(model.getInstanceId())) {
					volume.setServerId(serverMap.get(model.getInstanceId()));
				}
				volumeRepository.update(volume);
				volumeMap.remove(volume.getVolumeUuid());
				continue;
			}
			BeanUtils.copyProperties(model, volume);
			volume.setCreatorId(userId);
			volume.setGmtCreate(new Date());
			volume.setVendorId(vendor.getId());
			volume.setRegionId(region);
			volume.setVendorType(vendor.getType());
			volume.setProjectId(0L);
			volume.setTenantId(0L);
			if (!StringUtils.isEmpty(model.getInstanceId())) {
				volume.setServerId(serverMap.get(model.getInstanceId()));
			}
			volumeRepository.save(volume);
			volumeMap.remove(volume.getVolumeUuid());
		}
		for (Entry<String, Volume> entry : volumeMap.entrySet()) {
			volumeRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步域
	 *
	 * @param regionModels
	 * @param vendor
	 * @param reg
	 * @throws Exception
	 */
	private void syncRegion(List<RegionModel> regionModels, CloudVendor vendor, String reg) throws Exception {
		if (ListTool.isEmpty(regionModels)) {
			regionRepository.deleteByVid(vendor.getId(), reg);
			zoneRepository.deleteByRegionId(reg, vendor.getId());
			return;
		}
		for (RegionModel model : regionModels) {
			syncZone(model.getZones(), model.getCode(), vendor.getId());
		}
	}

	/**
	 * 同步域下面的区
	 *
	 * @param models
	 * @param vendorId
	 * @throws Exception
	 */
	private void syncZone(List<ZoneModel> models, String regionId, Long vendorId) throws Exception {
		zoneRepository.deleteByRegionId(regionId, vendorId);
		if (null != models && models.size() > 0) {
			Zone zone = null;
			List<Zone> zoneList = Lists.newArrayList();
			for (ZoneModel model : models) {
				zone = new Zone();
				BeanUtils.copyProperties(model, zone);
				zone.setVendorId(vendorId);
				zone.setRegionId(regionId);
				zoneList.add(zone);
			}
			if (zoneList.size() > 0) {
				zoneRepository.batchSave(zoneList);
			}
		}
	}

	/**
	 * 同步镜像
	 *
	 * @param models
	 * @param vendor
	 * @param userId
	 * @throws Exception
	 */
	private void syncImage(List<ImageModel> models, CloudVendor vendor, Long userId, String region) throws Exception {
		if (ListTool.isEmpty(models)) {
			imageRepository.removeByVid(vendor.getId(), region, userId);
			return;
		}
		List<Image> images = imageRepository.listByVendorId(vendor.getId(), region);
		Map<String, Image> imageMap = Maps.newHashMap();
		for (Image image : images) {
			imageMap.put(image.getImageUuid(), image);
		}
		for (ImageModel model : models) {
			Image image = new Image();
			if (imageMap.containsKey(model.getImageUuid())) {
				image = imageMap.get(model.getImageUuid());
				BeanUtils.copyProperties(model, image);
				image.setMenderId(userId);
				image.setGmtModify(new Date());
				image.setRegionId(region);
				image.setVendorType(vendor.getType());
				imageRepository.update(image);
				imageMap.remove(image.getImageUuid());
				continue;
			}
			BeanUtils.copyProperties(model, image);
			image.setCreatorId(userId);
			image.setGmtCreate(new Date());
			image.setVendorId(vendor.getId());
			image.setVendorType(vendor.getType());
			image.setTenantId(0L);
			image.setProjectId(0L);
			image.setRegionId(region);
			image.setCatalog("VM");
			imageRepository.save(image);
			imageMap.remove(image.getImageUuid());
		}
		for (Entry<String, Image> entry : imageMap.entrySet()) {
			imageRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步虚拟机规格
	 *
	 * @param models
	 * @param vendorId
	 * @throws Exception
	 */
	private void syncInstanceType(List<FlavorModel> models, Long vendorId, String region) throws Exception {
		flavorRepository.removeByVid(vendorId, region);
		List<Flavor> flavorList = Lists.newArrayList();
		Flavor flavor = null;
		for (FlavorModel flavorModel : models) {
			flavor = new Flavor();
			BeanUtils.copyProperties(flavorModel, flavor);
			flavor.setRegionId(region);
			flavor.setVendorId(vendorId);
			flavorList.add(flavor);
		}
		if (flavorList.size() > 0) {
			flavorRepository.batchSave(flavorList);
		}
	}

	/**
	 * 同步快照
	 *
	 * @param models
	 * @param vendor
	 * @param userId
	 * @param volumeMap
	 * @param region
	 * @throws Exception
	 */
	private void syncSnapshot(List<SnapshotModel> models, CloudVendor vendor, Long userId, Map<String, Long> volumeMap,
			String region) throws Exception {
		if (ListTool.isEmpty(models)) {
			snapshotRepository.removeByVid(vendor.getId(), region, userId);
			return;
		}
		List<Snapshot> snapshots = snapshotRepository.listByVid(vendor.getId(), region);
		Map<String, Snapshot> snapshotMap = Maps.newHashMap();
		for (Snapshot snapshot : snapshots) {
			snapshotMap.put(snapshot.getSnapshotUuid(), snapshot);
		}
		for (SnapshotModel model : models) {
			if (snapshotMap.containsKey(model.getSnapshotUuid())) {
				Snapshot snapshot = snapshotMap.get(model.getSnapshotUuid());
				BeanUtils.copyProperties(model, snapshot);
				snapshot.setMenderId(userId);
				snapshot.setRegionId(region);
				snapshot.setVolumeId(volumeMap.get(model.getVolumeUuid()));
				snapshotRepository.update(snapshot);
				snapshotMap.remove(model.getSnapshotUuid());
				continue;
			}
			Snapshot snapshot = JSONObject.parseObject(JSONObject.toJSONString(model), Snapshot.class);
			snapshot.setVolumeId(volumeMap.get(model.getVolumeUuid()));
			snapshot.setRegionId(region);
			snapshot.preSave(userId, userId, vendor.getId(), null, 0L, 0L);
			snapshotRepository.save(snapshot);
		}
		for (Entry<String, Snapshot> entry : snapshotMap.entrySet()) {
			snapshotRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步安全组
	 *
	 * @param models
	 * @param vendor
	 * @param userId
	 * @throws Exception
	 */
	private void syncSecurityGroup(List<SecurityGroupModel> models, CloudVendor vendor, Long userId, String region)
			throws Exception {
		// 当安全组为空时,删除数据库残留数据
		if (ListTool.isEmpty(models)) {
			securityGroupRepository.removeByVid(vendor.getId(), region, userId);
			return;
		}
		List<SecurityGroup> groups = securityGroupRepository.listByVendorId(vendor.getId(), region, null);
		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.setMenderId(userId);
				group.setRegionId(region);
				securityGroupRepository.update(group);
				if (null != model.getModels() && model.getModels().size() > 0) {
					securityGroupRuleRepository.removeBySgId(group.getId(), userId);
					for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
						SecurityGroupRule securityGroupRule = new SecurityGroupRule();
						BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
						securityGroupRule.setCreatorId(userId);
						securityGroupRule.setVendorId(vendor.getId());
						securityGroupRule.setGroupId(group.getId());
						securityGroupRule.setGroupUuid(group.getGroupUuid());
						securityGroupRuleRepository.save(securityGroupRule);
					}
				}
				groupMap.remove(model.getGroupUuid());
				continue;
			}
			group = JSONObject.parseObject(JSONObject.toJSONString(model), SecurityGroup.class);
			BeanUtils.copyProperties(model, group);
			group.preSave(userId, userId, vendor.getId(), 0L, 0L);
			group.setRegionId(region);
			securityGroupRepository.save(group);
			if (null != model.getModels() && model.getModels().size() > 0) {
				securityGroupRuleRepository.removeBySgId(group.getId(), userId);
				for (SecurityGroupRuleModel securityGroupRuleModel : model.getModels()) {
					SecurityGroupRule securityGroupRule = new SecurityGroupRule();
					BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
					securityGroupRule.setCreatorId(userId);
					securityGroupRule.setVendorId(vendor.getId());
					securityGroupRule.setGroupId(group.getId());
					securityGroupRule.setGroupUuid(group.getGroupUuid());
					securityGroupRuleRepository.save(securityGroupRule);
				}
			}
		}
		// 删除不存在的安全组
		for (Entry<String, SecurityGroup> entry : groupMap.entrySet()) {
			securityGroupRepository.remove(entry.getValue().getId(), userId);
		}
	}

	/**
	 * 同步虚拟机
	 *
	 * @param models
	 * @param vendor
	 * @param userId
	 * @param groupMap
	 * @throws Exception
	 */
	private void syncServer(List<ServerModel> models, CloudVendor vendor, Long userId, Map<String, Long> groupMap,
			Region region, Map<String, Long> keyPairMap, Map<String, Image> imageMap) throws Exception {
		if (null != groupMap && groupMap.keySet().size() > 0) {
			for (String key : groupMap.keySet()) {
				serverSgroupRepository.removeBySgid(groupMap.get(key));
			}
		}
		// 删除 虚拟机 秘钥关联关系
		List<CloudServer> servers = cloudServerRepository.listByVid(vendor.getId(), region.getRegionId());
		for (CloudServer cloudServer : servers) {
			serverKeyPairRepository.removeBySid(cloudServer.getId());
		}
		if (ListTool.isEmpty(models)) {
			cloudServerRepository.removeByVid(vendor.getId(), region.getRegionId(), userId);
			// 删除资源表
			resourceRepository.removeByVidReg(vendor.getId(), region.getRegionId(), userId);
			return;
		}
		Map<String, CloudServer> serverMap = Maps.newHashMap();
		for (CloudServer server : servers) {
			serverMap.put(server.getInstanceId(), server);
		}
		for (ServerModel model : models) {
			CloudServer server = new CloudServer();
			List<CmdbRelation> relations = Lists.newArrayList();
			relations.add(new CmdbRelation(ModuleCode.REGION.name(), 1L, ListUtils.getList(region.getGuid())));
			if (serverMap.containsKey(model.getInstanceId())) {
				server = serverMap.get(model.getInstanceId());
				model.setPassword(server.getPassword());
				BeanUtils.copyProperties(model, server);
				server.setGmtModify(new Date());
				server.setGmtVmCreate(model.getGmtVmCreate());
				server.setRegionId(region.getRegionId());
				server.setVendorType(vendor.getType());
				server.setIsTemplate(false);
				Image image = imageMap.get(model.getImageUuid());
				if (null != image) {
					server.setOsCategory(image.getOsCategory());
					server.setOsName(image.getOsName());
					server.setOsVersion(image.getOsVersion());
					String account = server.getAccount();
					if (StringUtils.isEmpty(account)) {
						server.setAccount(image.getDefaultUser());
					}
				}
				server.setSecurityGroupId(model.getGroups());
				cloudServerRepository.update(server);
				this.updateSGroup(server.getId(), model.getGroups(), groupMap);
				this.updateServerKeyPair(server, region.getRegionId());
				// 更新资源表
				updateResource(server, vendor, region.getRegionId(), userId);
				// 更新虚拟机绑定的安全组
				serverMap.remove(model.getInstanceId());
				continue;
			}
			BeanUtils.copyProperties(model, server);
			server.setCreatorId(0L);
			server.setGmtCreate(new Date());
			server.setVendorId(vendor.getId());
			server.setVendorType(vendor.getType());
			server.setTenantId(0L);
			server.setMenderId(0L);
			server.setOwnerId(0L);
			server.setProjectId(0L);
			server.setRegionId(region.getRegionId());
			server.setIsTemplate(false);
			server.setRecycle(false);
			Image image = imageMap.get(model.getImageUuid());
			if (null != image) {
				server.setOsCategory(image.getOsCategory());
				server.setOsName(image.getOsName());
				server.setOsVersion(image.getOsVersion());
				String account = server.getAccount();
				if (StringUtils.isEmpty(account)) {
					server.setAccount(image.getDefaultUser());
				}
			}
			server.setSecurityGroupId(model.getGroups());
			cloudServerRepository.save(server);
			this.updateSGroup(server.getId(), model.getGroups(), groupMap);
			this.updateServerKeyPair(server, region.getRegionId());
			// 更新资源表
			updateResource(server, vendor, region.getRegionId(), userId);
			// 更新虚拟机绑定的安全组
			serverMap.remove(model.getInstanceId());
		}
		for (Entry<String, CloudServer> entry : serverMap.entrySet()) {
			CloudServer server = entry.getValue();
			cloudServerRepository.remove(server.getId(), userId);
			// 删除资源表
			resourceRepository.remove(server.getId(), ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
					userId);
			serverSgroupRepository.removeBySid(server.getId());
			serverKeyPairRepository.removeBySid(server.getId());
		}
	}

	/**
	 * 更新虚拟机安全组
	 *
	 * @param serverId
	 * @param groups
	 * @param groupMap
	 * @throws Exception
	 */
	private void updateSGroup(Long serverId, String groups, Map<String, Long> groupMap) throws Exception {
		ServerSgroup serverSgroup = new ServerSgroup(serverId, groupMap.get(groups));
		serverSgroupRepository.save(serverSgroup);
	}

	private void updateServerKeyPair(CloudServer server, String region) throws Exception {
		String keypairName = server.getKeypairName();
		if (null != keypairName && !"".equals(keypairName)) {
			List<String> keyPairList = JSON.parseArray(server.getKeypairName(), String.class);
			ServerKeypair serverKeypair = null;
			for (String keyId : keyPairList) {
				Keypair byFingerprint = keypairRepository.getByFingerprint(keyId, server.getVendorId());
				if (null != byFingerprint) {
					serverKeypair = new ServerKeypair();
					serverKeypair.setKeypairId(byFingerprint.getId());
					serverKeypair.setServerId(server.getId());
					serverKeyPairRepository.save(serverKeypair);
				}
			}
		}
	}

	/**
	 * 更新资源表相关信息
	 *
	 * @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.isEmpty(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);
		}
	}

	public ImageRepository getImageRepository() {
		return imageRepository;
	}

	public void setImageRepository(ImageRepository imageRepository) {
		this.imageRepository = imageRepository;
	}

	public FlavorRepository getFlavorRepository() {
		return flavorRepository;
	}

	public void setFlavorRepository(FlavorRepository flavorRepository) {
		this.flavorRepository = flavorRepository;
	}

	public VolumeRepository getVolumeRepository() {
		return volumeRepository;
	}

	public void setVolumeRepository(VolumeRepository volumeRepository) {
		this.volumeRepository = volumeRepository;
	}

	public SnapshotRepository getSnapshotRepository() {
		return snapshotRepository;
	}

	public void setSnapshotRepository(SnapshotRepository snapshotRepository) {
		this.snapshotRepository = snapshotRepository;
	}

	public SecurityGroupRepository getSecurityGroupRepository() {
		return securityGroupRepository;
	}

	public void setSecurityGroupRepository(SecurityGroupRepository securityGroupRepository) {
		this.securityGroupRepository = securityGroupRepository;
	}

	public SecurityGroupRuleRepository getSecurityGroupRuleRepository() {
		return securityGroupRuleRepository;
	}

	public void setSecurityGroupRuleRepository(SecurityGroupRuleRepository securityGroupRuleRepository) {
		this.securityGroupRuleRepository = securityGroupRuleRepository;
	}

	public ServerSgroupRepository getServerSgroupRepository() {
		return serverSgroupRepository;
	}

	public void setServerSgroupRepository(ServerSgroupRepository serverSgroupRepository) {
		this.serverSgroupRepository = serverSgroupRepository;
	}

	public CloudServerRepository getCloudServerRepository() {
		return cloudServerRepository;
	}

	public void setCloudServerRepository(CloudServerRepository cloudServerRepository) {
		this.cloudServerRepository = cloudServerRepository;
	}

	public RegionRepository getRegionRepository() {
		return regionRepository;
	}

	public void setRegionRepository(RegionRepository regionRepository) {
		this.regionRepository = regionRepository;
	}

	public ZoneRepository getZoneRepository() {
		return zoneRepository;
	}

	public void setZoneRepository(ZoneRepository zoneRepository) {
		this.zoneRepository = zoneRepository;
	}

	public ResourceRepository getResourceRepository() {
		return resourceRepository;
	}

	public void setResourceRepository(ResourceRepository resourceRepository) {
		this.resourceRepository = resourceRepository;
	}

	public VpcRepository getVpcRepository() {
		return vpcRepository;
	}

	public void setVpcRepository(VpcRepository vpcRepository) {
		this.vpcRepository = vpcRepository;
	}

	public QcloudTransportor(ImageRepository imageRepository, FlavorRepository flavorRepository,
			VolumeRepository volumeRepository, SnapshotRepository snapshotRepository,
			SecurityGroupRepository securityGroupRepository, SecurityGroupRuleRepository securityGroupRuleRepository,
			ServerSgroupRepository serverSgroupRepository, CloudServerRepository cloudServerRepository,
			RegionRepository regionRepository, ZoneRepository zoneRepository, ResourceRepository resourceRepository,
			VpcRepository vpcRepository, KeypairRepository keypairRepository, FloatingIpRepository floatingIpRepository,
			SubnetRepository subnetRepository, ServerKeypairRepository serverKeyPairRepository,
			ObjectRelationRepository objectRelationRepository, NetworkCardRepository networkCardRepository) {
		super();
		this.imageRepository = imageRepository;
		this.flavorRepository = flavorRepository;
		this.volumeRepository = volumeRepository;
		this.snapshotRepository = snapshotRepository;
		this.securityGroupRepository = securityGroupRepository;
		this.securityGroupRuleRepository = securityGroupRuleRepository;
		this.serverSgroupRepository = serverSgroupRepository;
		this.cloudServerRepository = cloudServerRepository;
		this.regionRepository = regionRepository;
		this.zoneRepository = zoneRepository;
		this.resourceRepository = resourceRepository;
		this.vpcRepository = vpcRepository;
		this.keypairRepository = keypairRepository;
		this.floatingIpRepository = floatingIpRepository;
		this.subnetRepository = subnetRepository;
		this.serverKeyPairRepository = serverKeyPairRepository;
		this.objectRelationRepository = objectRelationRepository;
	}

	public QcloudTransportor() {
		super();
	}

	public KeypairRepository getKeypairRepository() {
		return keypairRepository;
	}

	public void setKeypairRepository(KeypairRepository keypairRepository) {
		this.keypairRepository = keypairRepository;
	}

	public FloatingIpRepository getFloatingIpRepository() {
		return floatingIpRepository;
	}

	public void setFloatingIpRepository(FloatingIpRepository floatingIpRepository) {
		this.floatingIpRepository = floatingIpRepository;
	}

	public SubnetRepository getSubnetRepository() {
		return subnetRepository;
	}

	public void setSubnetRepository(SubnetRepository subnetRepository) {
		this.subnetRepository = subnetRepository;
	}

	public ServerKeypairRepository getServerKeyPairRepository() {
		return serverKeyPairRepository;
	}

	public void setServerKeyPairRepository(ServerKeypairRepository serverKeyPairRepository) {
		this.serverKeyPairRepository = serverKeyPairRepository;
	}

	public ObjectRelationRepository getObjectRelationRepository() {
		return objectRelationRepository;
	}

	public void setObjectRelationRepository(ObjectRelationRepository objectRelationRepository) {
		this.objectRelationRepository = objectRelationRepository;
	}

}
