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 java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
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.LbListenerModel;
import com.bocloud.cmp.model.LbModel;
import com.bocloud.cmp.model.NetworkCardModel;
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.TencentSyncModel;
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.model.Result;
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.LbListener;
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.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.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;

import lombok.extern.slf4j.Slf4j;

/**
 * 腾讯云同步调整
 * @author ymh
 * @date 2022/01/26
 */
@Slf4j
@Component
public class TencentTransporter extends AbstractTransporter {

    @Override
    public Result transport(CloudVendor vendor, Long operator) {
    	return this.syncCloudResource(vendor, operator);
    }
    
    @Override
	public BocloudResult process(CloudVendor vendor, Object data, Region region, Long operator, List<CmdbInfo> infos) {
        try {
            if (null != data) {
                if (cloudServerRepository.hasBuilding(vendor.getId())) {
                    return new BocloudResult(false, "该平台下有云主机正在创建，请稍后进行同步操作");
                }
                String content = JSONObject.toJSONString(data);
                TencentSyncModel model = JSONObject.parseObject(content, TencentSyncModel.class);
                // 同步域
                log.info("Starting sync region and zone......");
                this.syncRegion(model.getRegionModels(), vendor, region.getRegionId(), operator);
                log.info("End sync region and zone......");
                // 同步安全组
                log.info("sync data to datastore...start ");
                this.syncSecurityGroup(model.getSecurityGroupModels(), vendor, operator, region.getRegionId());
                log.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());
                }
                // 同步密钥
                log.info("Starting sync keyPairs.....");
                this.syncKeyPairs(model.getKeypairModels(), vendor.getId(), operator, region.getRegionId());
                log.info("End sync keyPairs......");
                // 获取秘钥数据
                List<Keypair> keyPairList = keypairRepository.listByVid(vendor.getId());
                Map<String, Long> keyPairMap = new HashMap<>();
                for (Keypair keypair : keyPairList) {
                    keyPairMap.put(keypair.getFingerprint(), keypair.getId());
                }
                // 同步镜像
                log.info("Starting sync image......");
                this.syncImage(model.getImageModels(), vendor, operator, region.getRegionId());
                log.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);
                }
                // 浮动IP
                log.info("statr sync floatingIP...");
                this.syncFloatingIp(model.getFloatModels(), vendor.getId(), operator, region.getRegionId());
                log.info("statr sync floatingIP... END");
                // 同步云主机
                log.info("Starting sync server......");
                this.syncServer(model.getServerModels(), vendor, operator, groupMap, region, keyPairMap, infos, imageMap);
                log.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());
                }
                // 同步云硬盘
                log.info("Starting sync volume......");
                this.syncVolume(model.getVolumeModels(), vendor, operator, serverMap, region.getRegionId());
                log.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());
                }
                // 同步云快照
                log.info("Starting sync snapshot......");
                this.syncSnapshot(model.getSnapshotModels(), vendor, operator, volumeMap, region.getRegionId());
                log.info("End sync snapshot......");
                // 同步云主机规格
                log.info("Starting sync instance type......");
                this.syncInstanceType(model.getFlavorModels(), vendor.getId(), region.getRegionId());
                log.info("End sync instance type......");
                // 同步vpc
                log.info("Starting sync vpc......");
                this.syncVpc(model.getVpcModels(), vendor.getId(), operator, region.getRegionId());
                log.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());
                }
                // 同步子网
                log.info("Starting sync subnet.....");
                this.syncSubnet(model.getSubnetModels(), vendor.getId(), operator, region.getRegionId(), vpcMap);
                log.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());
                }
                // 弹性网卡
                log.info("statr sync networkcard...");
                this.syncNetworkCard(model.getNetworkCardModels(), vendor.getId(), operator, region.getRegionId());
                log.info("statr sync networkcard... END");
                // 同步云负载
                log.info("start sync load Balance ... START");
                this.syncLoadBalance(model.getLbModels(), vendor.getId(), operator, region.getRegionId(), vpcMap,
                    subnetMap);
                log.info("start sync load Balance ... END");
            }
            return new BocloudResult(true, null, "云平台【 " + vendor.getName() + " 】数据同步成功");
        } catch (Exception e) {
            log.error("腾讯云同步数据失败 ： " + e);
            return new BocloudResult(false, e.getMessage(), "云平台【 " + vendor.getName() + " 】数据同步失败:" + e.getMessage());
        }
    
	}
    
    private void syncLoadBalance(List<LbModel> lbModels, Long vendorId, Long userId, String regionId,
            Map<String, Long> vpcMap, Map<String, Long> subnetMap) throws Exception {
            if (ListTool.isEmpty(lbModels)) {
                loadBalancerRepository.removeByVid(vendorId, regionId, userId);
                return;
            }
            List<LoadBalancer> loadBalancerList = loadBalancerRepository.listByVid(vendorId, regionId);
            Map<String, LoadBalancer> loadBalancerMap = Maps.newHashMap();
            for (LoadBalancer loadBalancer : loadBalancerList) {
                loadBalancerMap.put(loadBalancer.getLbUuid(), loadBalancer);
            }
            LoadBalancer loadBalancer = null;
            for (LbModel model : lbModels) {
                if (loadBalancerMap.containsKey(model.getLbUuid())) {
                    loadBalancer = loadBalancerMap.get(model.getLbUuid());
                    BeanUtils.copyProperties(model, loadBalancer);
                    loadBalancer.setMenderId(userId);
                    String vpcUuid = loadBalancer.getVpcUuid();
                    if (null != vpcUuid && !"".equals(vpcUuid)) {
                        loadBalancer.setVpcId(vpcMap.get(vpcUuid));
                    }
                    String subnetUuid = loadBalancer.getSubnetUuid();
                    if (null != subnetUuid && !"".equals(subnetUuid)) {
                        loadBalancer.setSubnetId(subnetMap.get(subnetUuid));
                    }
                    loadBalancer.setRegion(regionId);
                    loadBalancer.setGmtModify(new Date());
                    loadBalancer.setMenderId(userId);
                    loadBalancer.setVendorId(vendorId);
                    loadBalancerRepository.update(loadBalancer);
                    this.syncLoadBalancerListener(model.getModels(), vendorId, userId, loadBalancer);
                    loadBalancerMap.remove(model.getLbUuid());
                    continue;
                }
                loadBalancer = new LoadBalancer();
                BeanUtils.copyProperties(model, loadBalancer);
                loadBalancer.setMenderId(userId);
                loadBalancer.setCreatorId(userId);
                loadBalancer.setRegion(regionId);
                loadBalancer.setGmtModify(new Date());
                loadBalancer.setVendorId(vendorId);
                loadBalancer.setTenantId(0L);
                loadBalancer.setProjectId(0L);
                String vpcUuid = loadBalancer.getVpcUuid();
                if (null != vpcUuid && !"".equals(vpcUuid)) {
                    loadBalancer.setVpcId(vpcMap.get(vpcUuid));
                }
                String subnetUuid = loadBalancer.getSubnetUuid();
                if (null != subnetUuid && !"".equals(subnetUuid)) {
                    loadBalancer.setSubnetId(subnetMap.get(subnetUuid));
                }
                loadBalancerRepository.save(loadBalancer);
                this.syncLoadBalancerListener(model.getModels(), vendorId, userId, loadBalancer);
            }
            for (Map.Entry<String, LoadBalancer> entry : loadBalancerMap.entrySet()) {
                loadBalancerRepository.remove(entry.getValue().getId(), userId);
            }
        }

        private void syncLoadBalancerListener(List<LbListenerModel> lbListenerModel, Long vendorId, Long userId,
            LoadBalancer loadBalancer) throws Exception {
            lbListenerRepository.removeByLbId(loadBalancer.getId(), userId);
            if (null != lbListenerModel && lbListenerModel.size() > 0) {
                List<LbListener> listListener = new ArrayList<>();
                LbListener listener = null;
                for (LbListenerModel model : lbListenerModel) {
                    listener = new LbListener();
                    BeanUtils.copyProperties(model, listener);
                    listener.setLbId(loadBalancer.getId());
                    listener.setLbUuid(loadBalancer.getLbUuid());
                    listener.setVendorId(vendorId);
                    listener.setMenderId(userId);
                    listener.setCreatorId(userId);
                    listener.setTenantId(0L);
                    listener.setProjectId(0L);
                    listListener.add(listener);
                }
                if (listListener.size() > 0) {
                    lbListenerRepository.batchSave(listListener, listListener.size() + 1);
                }
            }
        }

        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);
                    networkCardRepository.update(networkCard);
                    networkCardMap.remove(model.getNetworkcardUuid());
                    continue;
                }
                networkCard = new NetworkCard();
                BeanUtils.copyProperties(model, networkCard);
                networkCard.setMenderId(userId);
                networkCard.setRegionId(regionId);
                networkCard.setCategory("VM");
                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 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());
                if (vpcMap.containsKey(subnetModel.getNetworkUuid())) {
                    subnet.setNetworkId(vpcMap.get(subnetModel.getNetworkUuid()));
                    subnet.setVpcId(vpcMap.get(subnetModel.getNetworkUuid()));
                }
                subnet.setVpcUuid(subnetModel.getNetworkUuid());
                subnet.setMenderId(userId);
                subnet.setGmtModify(new Date());
                subnet.setCreatorId(userId);
                subnet.setVendorId(id);
                subnet.setRegionId(region);
                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, userId);
                return;
            }
            List<Keypair> keypairs = keypairRepository.listByVid(vendorId);
            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.setGmtModify(new Date());
                    keypairRepository.update(keypair);
                    keypairMap.remove(keypair.getFingerprint());
                    continue;
                }
                BeanUtils.copyProperties(model, keypair);
                keypair.setCreatorId(userId);
                keypair.setGmtCreate(model.getGmtCreate());
                keypair.setVendorId(vendorId);
                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.setRegionId(region);
                    vpcRepository.update(vpc);
                    vpcMap.remove(model.getVpcId());
                    continue;
                }
                BeanUtils.copyProperties(model, vpc);
                vpc.setCreatorId(userId);
                vpc.setMenderId(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.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(0L);
                volume.setGmtCreate(new Date());
                volume.setVendorId(vendor.getId());
                volume.setRegionId(region);
                volume.setVendorType(vendor.getType());
                volume.setProjectId(0L);
                volume.setTenantId(0L);
                volume.setMenderId(0L);
                volume.setCreatorId(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, Long userId)
            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, userId);
            }
        }

        /**
         * 同步域下面的区
         *
         * @param models
         * @param vendorId
         * @throws Exception
         */
        private void syncZone(List<ZoneModel> models, String regionId, CloudVendor vendor, Long userId) throws Exception {
            zoneRepository.deleteByRegionId(regionId, vendor.getId());
            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(vendor.getId());
                    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);
            }
            List<Image> updateList = new ArrayList<Image>();
            List<Image> instertList = new ArrayList<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);
                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);
                    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);
                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
         * @param infos
         * @throws Exception
         */
        private void syncServer(List<ServerModel> models, CloudVendor vendor, Long userId, Map<String, Long> groupMap,
            Region region, Map<String, Long> keyPairMap, List<CmdbInfo> infos, 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)) {
                for (CloudServer server : servers) {
                    // cmdb：删除云主机
                    infos.add(CmdbInfoConvertor.getInfo(server, "delete", null));
                }
                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());
                    String account = server.getAccount();
                    if (StringUtils.isEmpty(account)) {
                        Image image = imageRepository.getByImageUuid(server.getImageUuid());
                        if (null != image) {
                            account = image.getDefaultUser();
                        }
                    }
                    model.setAccount(account);
                    model.setPassword(server.getPassword());
                    BeanUtils.copyProperties(model, server);
                    server.setGmtModify(new Date());
                    server.setGmtVmCreate(model.getGmtVmCreate());
                    Date gmtExpiredTime = model.getGmtExpiredTime();
                    if(null != gmtExpiredTime) {
                    	server.setExpiredTime(gmtExpiredTime);
                    }
                    server.setRegionId(region.getRegionId());
                    Integer diskSize = model.getSystemDiskSize();
                    server.setDisk(diskSize);
                    server.setVendorType(vendor.getType());
                    server.setIsTemplate(false);
                    List<String> securityGroups = model.getSecurityGroups();
                    Image image = imageMap.get(model.getImageUuid());
                    if (null != image) {
                        server.setOsCategory(image.getOsCategory());
                    }
                    List<String> publicIps = JSON.parseArray(server.getPublicIps(), String.class);
                    if (!ListTool.isEmpty(publicIps)) {
                        for (int i = publicIps.size() - 1; i >= 0; i--) {
                            String publicIp = publicIps.get(i);
                            FloatingIp floatingIp =
                                floatingIpRepository.getByFloatingIp(publicIp, server.getVendorId(), server.getRegionId());
                            if (null == floatingIp) {
                                publicIps.remove(publicIp);
                            }
                        }
                        server.setPublicIps(JSON.toJSONString(publicIps));
                    }
                    cloudServerRepository.update(server);
                    this.updateServerKeyPair(server, keyPairMap);
                    // 更新资源表
                    updateResource(server, vendor, region.getRegionId(), userId);
                    // 更新云主机绑定的安全组
                    serverSgroupRepository.removeBySid(server.getId());
                    if (null != securityGroups) {
                        updateSGroup(server.getId(), JSON.toJSONString(securityGroups), groupMap);
                    }
                    // CMDB更新集群数据
                    infos.add(CmdbInfoConvertor.getInfo(server, null, relations));
                    serverMap.remove(model.getInstanceId());
                    continue;
                }
                BeanUtils.copyProperties(model, server);
                List<String> securityGroups = model.getSecurityGroups();
                server.setCreatorId(0L);
                server.setOwnerId(0L);
                server.setGmtCreate(new Date());
                server.setVendorId(vendor.getId());
                server.setVendorType(vendor.getType());
                Integer diskSize = model.getSystemDiskSize();
                List<VolumeModel> diskDevices = model.getDiskDevices();
                if (null != diskDevices && diskDevices.size() > 0) {
                    for (VolumeModel volumeModel : diskDevices) {
                        diskSize += volumeModel.getSize();
                    }
                }
                server.setDisk(diskSize);
                server.setTenantId(0L);
                server.setProjectId(0L);
                server.setMenderId(0L);
                server.setRegionId(region.getRegionId());
                server.setIsTemplate(false);
                server.setRecycle(false);
                Image image = imageMap.get(model.getImageUuid());
                if (null != image) {
                    server.setOsCategory(image.getOsCategory());
                }
                List<String> publicIps = JSON.parseArray(server.getPublicIps(), String.class);
                if (!ListTool.isEmpty(publicIps)) {
                    for (int i = publicIps.size() - 1; i >= 0; i--) {
                        String publicIp = publicIps.get(i);
                        FloatingIp floatingIp =
                            floatingIpRepository.getByFloatingIp(publicIp, server.getVendorId(), server.getRegionId());
                        if (null == floatingIp) {
                            publicIps.remove(publicIp);
                        }
                    }
                    server.setPublicIps(JSON.toJSONString(publicIps));
                }
                Date gmtExpiredTime = model.getGmtExpiredTime();
                if(null != gmtExpiredTime) {
                	server.setExpiredTime(gmtExpiredTime);
                }
                cloudServerRepository.save(server);
                this.updateServerKeyPair(server, keyPairMap);
                // 更新资源表
                updateResource(server, vendor, region.getRegionId(), userId);
                // 更新云主机绑定的安全组
                serverSgroupRepository.removeBySid(server.getId());
                if (null != securityGroups) {
                    updateSGroup(server.getId(), JSON.toJSONString(securityGroups), groupMap);
                }
                // CMDB更新集群数据
                infos.add(CmdbInfoConvertor.getInfo(server, null, relations));
                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);
                // cmdb：删除云主机
                infos.add(CmdbInfoConvertor.getInfo(server, "delete", null));
                serverSgroupRepository.removeBySid(server.getId());
                serverKeypairRepository.removeBySid(server.getId());
            }
        }

        private void updateServerKeyPair(CloudServer server, Map<String, Long> keyPairMap) 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 keyName : keyPairList) {
                    Long keyPairId = keyPairMap.get(keyName);
                    serverKeypair = new ServerKeypair();
                    serverKeypair.setKeypairId(keyPairId);
                    serverKeypair.setServerId(server.getId());
                    serverKeypairRepository.save(serverKeypair);
                }
            }
        }

        /**
         * 更新云主机安全组
         *
         * @param serverId
         * @param groups
         * @param groupMap
         * @throws Exception
         */
        private void updateSGroup(Long serverId, String groups, Map<String, Long> groupMap) throws Exception {
            if (!StringUtils.isEmpty(groups)) {
                List<String> groupList = JSONArray.parseArray(groups, String.class);
                for (String group : groupList) {
                    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.isEmpty(server.getPrivateIps())) {
                ips.addAll(JSONObject.parseArray(server.getPrivateIps(), String.class));
            }
            if (!StringUtils.isEmpty(server.getPublicIps())) {
                ips.addAll(JSONObject.parseArray(server.getPublicIps(), String.class));
            }
            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);
            }
        }
    
	@Override
	public void register() {
		// TODO Auto-generated method stub
		 
	}

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

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

}
