package com.bocloud.ims.service.builder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.network.NetworkInterfaceDriver;
import com.bocloud.cmp.driver.network.PublicIPAddressDriver;
import com.bocloud.cmp.driver.network.SecurityGroupDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.NetworkInterfaceModel;
import com.bocloud.cmp.model.SecurityGroupModel;
import com.bocloud.cmp.model.SecurityGroupRuleModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.azure.PublicIPAddressModel;
import com.bocloud.cmp.model.azure.network.NicIpConfigurationModel;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.common.enums.AzureIpRelationType;
import com.bocloud.ims.common.enums.AzureTaskStatus;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.azure.AvailabilitySet;
import com.bocloud.ims.entity.resource.azure.network.NicIpConfiguration;
import com.bocloud.ims.entity.resource.azure.network.PublicIPAddress;
import com.bocloud.ims.entity.resource.azure.network.ResourcePublicIPAddressRelation;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.repository.resource.azure.AvailabilitySetRepository;
import com.bocloud.ims.repository.resource.azure.network.NicIpConfigurationRepository;
import com.bocloud.ims.repository.resource.azure.network.PublicIPAddressRepository;
import com.bocloud.ims.repository.resource.azure.network.ResourcePublicIPAddressRelationRepository;
import com.bocloud.ims.service.utils.PwdRandom;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: AzureServerBuilder
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2019/9/18 17:55
 */
@Slf4j
public class AzureServerBuilder implements ServerBuilder {

    private CloudServerRepository cloudServerRepository;
    private FlavorRepository flavorRepository;
    private ImageRepository imageRepository;
    private VolumeRepository volumeRepository;
    private SecurityGroupRepository securityGroupRepository;
    private VpcRepository vpcRepository;
    private SubnetRepository subnetRepository;
    private KeypairRepository keypairRepository;
    private ServerKeypairRepository serverKeypairRepository;
    private ServerSgroupRepository serverSgroupRepository;
    private ServerLabelRepository serverLabelRepository;
    private ResourceRepository resourceRepository;
    private ResourceEventRepository resourceEventRepository;
    private ServerDriver serverDriver;
    private VolumeDriver volumeDriver;
    private CloudVendor vendor;
    private ServerModel model;
    private RequestContext context;
    //--
    private NetworkInterfaceRepository interfaceRepository;
    private NetworkInterfaceDriver interfaceDriver;
    private SecurityGroupDriver securityGroupDriver;
    private SecurityGroupRuleRepository securityGroupRuleRepository;
    private AvailabilitySetRepository availabilitySetRepository;
    private PublicIPAddressRepository publicIPAddressRepository;
    private ResourcePublicIPAddressRelationRepository resourcePublicIPAddressRelationRepository;
    private ResourceGroupRepository resourceGroupRepository;
    private PublicIPAddressDriver publicIPAddressDriver;
    private NicIpConfigurationRepository nicIpConfigurationRepository;

    public AzureServerBuilder() {
        super();
    }

    public AzureServerBuilder(CloudServerRepository cloudServerRepository, FlavorRepository flavorRepository,
                              ImageRepository imageRepository, VolumeRepository volumeRepository, SecurityGroupRepository securityGroupRepository,
                              VpcRepository vpcRepository, SubnetRepository subnetRepository, KeypairRepository keypairRepository,
                              ServerKeypairRepository serverKeypairRepository, ServerSgroupRepository serverSgroupRepository, ServerLabelRepository serverLabelRepository,
                              ResourceRepository resourceRepository, ResourceEventRepository resourceEventRepository, ServerDriver serverDriver,
                              NetworkInterfaceRepository interfaceRepository, NetworkInterfaceDriver interfaceDriver, SecurityGroupDriver securityGroupDriver, SecurityGroupRuleRepository securityGroupRuleRepository,
                              AvailabilitySetRepository availabilitySetRepository,
                              VolumeDriver volumeDriver, CloudVendor vendor, RequestContext context, PublicIPAddressRepository publicIPAddressRepository,
                              ResourcePublicIPAddressRelationRepository resourcePublicIPAddressRelationRepository, ResourceGroupRepository resourceGroupRepository,
                              PublicIPAddressDriver publicIPAddressDriver, NicIpConfigurationRepository nicIpConfigurationRepository) {
        this.cloudServerRepository = cloudServerRepository;
        this.flavorRepository = flavorRepository;
        this.imageRepository = imageRepository;
        this.volumeRepository = volumeRepository;
        this.securityGroupRepository = securityGroupRepository;
        this.vpcRepository = vpcRepository;
        this.subnetRepository = subnetRepository;
        this.keypairRepository = keypairRepository;
        this.serverKeypairRepository = serverKeypairRepository;
        this.serverSgroupRepository = serverSgroupRepository;
        this.serverLabelRepository = serverLabelRepository;
        this.resourceRepository = resourceRepository;
        this.resourceEventRepository = resourceEventRepository;
        this.serverDriver = serverDriver;
        this.volumeDriver = volumeDriver;
        this.vendor = vendor;
        this.context = context;
        this.interfaceRepository = interfaceRepository;
        this.interfaceDriver = interfaceDriver;
        this.securityGroupDriver = securityGroupDriver;
        this.securityGroupRuleRepository = securityGroupRuleRepository;
        this.availabilitySetRepository = availabilitySetRepository;
        this.publicIPAddressRepository = publicIPAddressRepository;
        this.resourcePublicIPAddressRelationRepository = resourcePublicIPAddressRelationRepository;
        this.resourceGroupRepository = resourceGroupRepository;
        this.publicIPAddressDriver = publicIPAddressDriver;
        this.nicIpConfigurationRepository = nicIpConfigurationRepository;
    }

    @Override
    public BocloudResult<ServerModel> prepare(JSONObject object) throws Exception {
        /*必要参数*/
        String name = object.getString(Common.NAME);// 虚拟机名
        String remark = object.getString("remark");// 描述
        model = new ServerModel(name, remark);
        //设置地域
        String regionId = object.getString("regionId");
        if (null != regionId && !"".equals(regionId)) {
            model.setRegionId(regionId);
        }
        //设置资源组
        Long resourceGroupId = object.getLong("resourceGroupId");
        ResourceGroup resourceGroup = resourceGroupRepository.query(resourceGroupId);
        if (ObjectUtils.isEmpty(resourceGroup)) {
            return new BocloudResult<>(false, "资源组不存在");
        }
        model.setResourceGroupName(resourceGroup.getName());
        model.setRgId(resourceGroup.getId());

        //设置镜像
        Image image = imageRepository.query(object.getLong("imageId"));
        if (null != image) {
            model.setImageUuid(image.getImageUuid());
            model.setOsCategory(image.getOsCategory());
            model.setImageType(image.getImageType());
            model.setOffer(image.getOffer());
            model.setPublisher(image.getPublisher());
            model.setSku(image.getSku());
        } else {
            //区分linux镜像和windows镜像
            String popularLinuxImage = object.getString("popularLinuxImage");
            if (null != popularLinuxImage && !"".equals(popularLinuxImage)) {
                model.setPopularLinuxImage(popularLinuxImage);
                model.setImageType("PUBLIC");
                model.setOsCategory("LINUX");
            }
            String popularWindowsImage = object.getString("PopularWindowsImage");
            if (null != popularWindowsImage && !"".equals(popularWindowsImage)) {
                model.setPopularWindowsImage(popularWindowsImage);
                model.setImageType("PUBLIC");
                model.setOsCategory("WINDOWS");
            }
        }

        //设置系统盘
        String systemDiskName = object.getString("systemDiskName");
        String systemDiskCaching = object.getString("systemDiskCaching");
        Integer systemDiskSize = object.getInteger("systemDiskSize");
        String systemDiskCategory = object.getString("systemDiskCategory");
        model.setSystemDiskName(systemDiskName);
        model.setSystemDiskCaching(systemDiskCaching);
        model.setSystemDiskSize(systemDiskSize);
        model.setSystemDiskCategory(systemDiskCategory);

        //设置规格
        Long flavorId = object.getLong("flavorId");
        Flavor flavor = flavorRepository.query(flavorId);
        if (null == flavor) {
            return new BocloudResult<>(false, "规格不存在");
        }
        model.setFlavorUuid(flavor.getFlavorUuid());
        model.setCpu(flavor.getCpu());
        model.setMemory(flavor.getMemory());

        //设置用户
        String account = object.getString("account");
        model.setAccount(account);
        //设置密码
        String password = object.getString("password");
        if (StringUtils.isEmpty(password)) {
            password = randomStr(12);
        }
        model.setPassword(password);
        //设置密钥
        Long keypairId = object.getLong("keypairId");
        if (null != keypairId) {
            Keypair keypair = keypairRepository.query(keypairId);
            model.setKeypairName(keypair.getName());
            model.setSshKey(keypair.getPublicKey());
        }
        //设置vpc 子网
        Long vpcId = object.getLong("vpcId");
        Long subnetId = object.getLong("subnetId");
        Vpc vpc = vpcRepository.query(vpcId);
        Subnet subnet = subnetRepository.query(subnetId);
        if (null == vpc) {
            return new BocloudResult<>(false, "网络不存在");
        }
        if (null == subnet) {
            return new BocloudResult<>(false, "子网不存在");
        }
        model.setVpcUuid(vpc.getVpcId());
        model.setSubnetName(subnet.getName());
        model.setSubnetUuid(subnet.getSubnetUuid());

        //设置可用性集
        Long availabilitySetId = object.getLong("availabilitySetId");
        if (null != availabilitySetId) {
            Optional.ofNullable(availabilitySetRepository.query(availabilitySetId)).map(availabilitySet -> availabilitySet.getUuid()).ifPresent(model::setAvailabilitySetUuid);
        }

        //设置公共ip地址
        model.setIsUsePublicIp(object.getBoolean("isUsePublicIp"));
        Long publicIpAddressId = object.getLong("publicIpAddressId");
        if (null != publicIpAddressId) {
            Optional.ofNullable(publicIPAddressRepository.query(publicIpAddressId)).map(publicIPAddress -> publicIPAddress.getUuid()).ifPresent(model::setPublicIpAddressUuid);
        }

        //设置混合权益
        String licenseType = object.getString("licenseType");
        model.setLicenseType(licenseType);

        //设置可用性区域
        String availabilityZoneIds = object.getString("availabilityZoneIds");
        model.setAvailabilityZoneIds(availabilityZoneIds);

        // 虚拟机标签
        if (!StringUtils.isEmpty(object.getString("labelIds"))) {
            List<Long> labelIds = JSONArray.parseArray(object.getString("labelIds"), Long.class);
            model.setLabelIds(labelIds);
        }
        return new BocloudResult<>(true, model, "success");
    }

    @Override
    public BocloudResult<CloudServer> builder(CloudServer oldServer) throws Exception {
        // 创建虚拟机
        BocloudResult result = serverDriver.create(vendor.getUuid(), oldServer.getRegionId(), model);
        // 操作记录
        Long userId = context.getTarget();
        String handler = "虚拟机创建";
        ResourceEvent event = null;
        if (result.isSuccess()) {
            event = new ResourceEvent(oldServer.getId(), handler, "成功", userId, new Date(), "VM", vendor.getId(), context.getCatalog());
            String content = JSONObject.toJSONString(result.getData());
            CloudServer newServer = JSONObject.parseObject(content, CloudServer.class);
            oldServer.setName(newServer.getName());
            oldServer.setRegionId(newServer.getRegionId());
            oldServer.setZone(newServer.getRegionId());
            oldServer.setInstanceId(newServer.getInstanceId());
            oldServer.setStatus(newServer.getStatus());
            oldServer.setPublicIps(newServer.getPublicIps());
            oldServer.setPrivateIps(newServer.getPrivateIps());
            oldServer.setVpcUuid(newServer.getVpcUuid());
            oldServer.setOsName(newServer.getOsName());
            oldServer.setOsCategory(model.getOsCategory());
            oldServer.setOsVersion(newServer.getOsVersion());
            oldServer.setSystemDiskCategory(newServer.getSystemDiskCategory());
            oldServer.setSystemDiskSize(newServer.getSystemDiskSize());
            oldServer.setAccount(model.getAccount());
            oldServer.setPswd(model.getPassword());
            oldServer.setSecurityGroupId(JSON.toJSONString(newServer.getSecurityGroups()));
            oldServer.setSubnetUuid(model.getSubnetUuid());
            oldServer.setFlavorUuid(model.getFlavorUuid());
            oldServer.setCpu(model.getCpu());
            oldServer.setMemory(model.getMemory());
            oldServer.setImageUuid(model.getImageUuid());
            oldServer.setDisk(newServer.getDisk());
            oldServer.setProps(newServer.getProps());
            oldServer.setResourceGroupId(model.getRgId());
            oldServer.setLicenseType(newServer.getLicenseType());
            oldServer.setAvailabilityZoneIds(newServer.getAvailabilityZoneIds());
            // 新创建的虚拟机 秘钥 同步不回来 所以直接采用model中的秘钥数据
            String keypairName = model.getKeypairName();
            if (null != keypairName && !"".equals(keypairName)) {
                List<String> keyPairList = new ArrayList<>();
                keyPairList.add(keypairName);
                oldServer.setKeypairName(JSON.toJSONString(keyPairList));
            }

            if (StringUtils.isEmpty(model.getAvailabilitySetUuid())) {
                AvailabilitySet availabilitySet = availabilitySetRepository.queryUuid(model.getAvailabilitySetUuid(), oldServer.getVendorId());
                Optional.ofNullable(availabilitySet).ifPresent(aSet -> oldServer.setAvailabilitySetId(aSet.getId()));
            }

            // 保存标签信息
            List<Long> labelIds = model.getLabelIds();
            if (!ListTool.isEmpty(labelIds)) {
                List<ServerLabel> serverLabels = Lists.newArrayList();
                for (Long labelId : labelIds) {
                    serverLabels.add(new ServerLabel(oldServer.getId(), labelId, "VM", vendor.getId()));
                }
                if (!ListTool.isEmpty(serverLabels)) {
                    serverLabelRepository.batchSave(serverLabels);
                }
            }
            oldServer.setRecycle(false);
            cloudServerRepository.update(oldServer);

            // 保存 秘钥
            this.updateServerKeyPair(oldServer, vendor.getId());

            //网络接口
            this.saveNetworkInterface(oldServer, newServer, userId, model.getRgId());

            //新加一个存储系统盘于数据库中
            if (null != newServer.getSystemDiskUuid()) {
                BocloudResult volumeDetailResult = volumeDriver.detail(newServer.getSystemDiskUuid(), vendor.getUuid(), newServer.getRegionId());
                if (volumeDetailResult.isSuccess()) {
                    String volumeContent = JSONObject.toJSONString(volumeDetailResult.getData());
                    Volume volume = JSONObject.parseObject(volumeContent, Volume.class);
                    volume.setCreatorId(userId);
                    volume.setVendorId(vendor.getId());
                    volume.setVendorType(vendor.getType());
                    volume.setInstanceId(newServer.getInstanceId());
                    volume.setTenantId(oldServer.getTenantId() == null ? 0L : oldServer.getTenantId());
                    Long projectId = oldServer.getProjectId();
                    if (null != projectId && projectId > 0) {
                        volume.setProjectId(projectId);
                    }
                    volume.setBootVolume(true);//系统盘
                    volume.setRegionId(newServer.getRegionId());
                    volume.setName(volume.getName());
                    volume.setServerId(oldServer.getId());
                    volumeRepository.save(volume);
                }
            }
            List<Volume> volumeModels = newServer.getDiskDevices();
            if (!ListTool.isEmpty(volumeModels)) {
                for (Volume volume : volumeModels) {
                    volume.setCreatorId(userId);
                    volume.setGmtCreate(new Date());
                    volume.setVendorId(vendor.getId());
                    volume.setVendorType(vendor.getType());
                    volume.setTenantId(oldServer.getTenantId() == null ? 0L : oldServer.getTenantId());
                    Long projectId = oldServer.getProjectId();
                    if (null != projectId && projectId > 0) {
                        volume.setProjectId(projectId);
                    }
                    volume.setRegionId(newServer.getRegionId());
                    volume.setServerId(oldServer.getId());
                    volume.setName(volume.getVolumeUuid());
                    volume.setServerId(oldServer.getId());
                    volumeRepository.save(volume);
                }
            }
            List<Volume> listByServerId = volumeRepository.listByServerId(oldServer.getId());
            if (null != listByServerId && listByServerId.size() > 0) {
                oldServer.setDiskDevices(listByServerId);
            }
            // 保存资源
            List<String> ips = Lists.newArrayList();
            if (!StringUtils.isEmpty(newServer.getPrivateIps())) {
                List<String> objects = JSONObject.parseArray(newServer.getPrivateIps(), String.class);
                for (String ip : objects) {
                    ips.add(ip);
                }
            }
            Resource resource = resourceRepository.query(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                    oldServer.getId());
            if (null == resource) {
                resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
                        oldServer.getId(), JSONObject.toJSONString(ips), oldServer.getOsCategory(), vendor.getId());
                resource.setRegionId(oldServer.getRegionId());
                resource.preSave(oldServer.getName(), oldServer.getStatus(), userId, context.getTenant(),
                        context.getProject());
                resource.setInventory(JSONObject.toJSONString(oldServer));
                resourceRepository.save(resource);
            } else {
                resource.setInventory(JSONObject.toJSONString(oldServer));
                resource.setStatus(oldServer.getStatus());
                resource.setMenderId(userId);
                resource.setCreatorId(userId);
                resource.setGmtModify(new Date());
                resource.setGmtCreate(new Date());
                resource.setPrivateIps(JSONObject.toJSONString(ips));
                resource.setRegionId(oldServer.getRegionId());
                resourceRepository.update(resource);
            }
        } else {
            //todo  在这删除关联的网卡
            if (model.getIsUsePublicIp()) {
                String publicIpAddressUuid = model.getPublicIpAddressUuid();
                if (!StringUtils.isEmpty(publicIpAddressUuid)) {
                    log.info("虚拟机创建失败，存在已有IP信息，执行解绑操作......");
                    BocloudResult pResult = publicIPAddressDriver.detail(vendor.getUuid(), oldServer.getRegionId(), publicIpAddressUuid);
                    if (pResult.isSuccess()) {
                        PublicIPAddressModel publicIPAddressModel = JSONObject.parseObject(JSONObject.toJSONString(pResult.getData()), PublicIPAddressModel.class);
                        NicIpConfigurationModel nicIpConfigurationModel = publicIPAddressModel.getNicIpConfigurationModel();
                        if (null != nicIpConfigurationModel) {
                            BocloudResult ncResult = interfaceDriver.nicIpConfigurationdetachPublicIpAddress(vendor.getUuid(), oldServer.getRegionId(), nicIpConfigurationModel);
                            if (ncResult.isSuccess()) {
                                log.info("网卡配置解绑成功！");
                                //删除网卡
                                BocloudResult nwResult = interfaceDriver.remove(vendor.getUuid(), oldServer.getRegionId(), nicIpConfigurationModel.getNetworkInterfaceUuid());
                                if (nwResult.isSuccess()) {
                                    log.info("网络接口删除成功！");
                                } else {
                                    log.info("虚拟机创建失败，网络接口删除失败:{},执行结束", nwResult.getMessage());
                                }
                            } else {
                                log.info("虚拟机创建失败，网卡配置解绑失败:{},执行结束", ncResult.getMessage());
                            }
                        } else {
                            log.info("虚拟机创建失败，无网卡信息配置,执行结束");
                        }

                    } else {
                        log.info("虚拟机创建失败，存在已有IP信息，已有IP查询失败：{},执行结束", pResult.getMessage());
                    }
                } else {
                    //自生成的公共ip以后在处理，{虚拟机创建失败，自生成的ip获取不到，但是自动同步会有数据，可以执行删除，后续在优化}
                }
            }

            event = new ResourceEvent(oldServer.getId(), handler, "失败", userId, new Date(), "VM", vendor.getId(), context.getCatalog());
            cloudServerRepository.remove(oldServer.getId(), context.getTarget());
        }
        resourceEventRepository.save(event);
        return result.isSuccess() ? new BocloudResult<>(true, oldServer, "success")
                : new BocloudResult<>(false, oldServer, result.getMessage());
    }

    //网络接口绑定关系
    private void saveNetworkInterface(CloudServer oldServer, CloudServer newServer, Long userId, Long resourceGroupId) throws Exception {


        // 更改网络接口绑定关系
        List<NetworkInterfaceModel> nics = newServer.getNetworkInterfaces();
        for (NetworkInterfaceModel interfaceModel : nics) {
            NetworkInterface networkInterface = interfaceRepository.query(interfaceModel.getNetworkInterfaceUuid(),
                    vendor.getId());
            if (ObjectUtils.isEmpty(networkInterface)) {
                // 查询不到说明网络接口是原生端自动生成的
                networkInterface = new NetworkInterface();
                BocloudResult nicsResult = interfaceDriver.detail(vendor.getUuid(), newServer.getRegionId(),
                        interfaceModel.getNetworkInterfaceUuid());
                if (nicsResult.isSuccess()) {
                    NetworkInterfaceModel networkInterfaceModel = JSONObject.parseObject(JSONObject.toJSONString(nicsResult.getData()), NetworkInterfaceModel.class);
                    BeanUtils.copyProperties(networkInterfaceModel, networkInterface);
                    //关系绑定  vpc 子网
                    Subnet subnet = subnetRepository.query(model.getSubnetUuid(), vendor.getId());
                    if (!ObjectUtils.isEmpty(subnet)) {
                        networkInterface.setSubnetId(subnet.getId());
                        networkInterface.setSubnetName(subnet.getName());
                        networkInterface.setVpcId(subnet.getVpcId());
                    }
                    //关系绑定 安全组
                    if (!StringUtils.isEmpty(networkInterfaceModel.getSecurityGroupUuid())) {
                        SecurityGroup group = securityGroupRepository.getByGroupId(networkInterfaceModel.getSecurityGroupUuid());
                        if (ObjectUtils.isEmpty(group)) {
                            //安全组为空
                            BocloudResult sgResult = securityGroupDriver.detail(networkInterfaceModel.getSecurityGroupUuid(), vendor.getUuid(), newServer.getRegionId());
                            if (sgResult.isSuccess()) {
                                SecurityGroupModel securityGroupModel = JSONObject.parseObject(JSONObject.toJSONString(sgResult.getData()), SecurityGroupModel.class);
                                SecurityGroup securityGroup = new SecurityGroup();
                                BeanUtils.copyProperties(securityGroupModel, securityGroup);
                                securityGroup.preSave(userId, userId, vendor.getId(), context.getTenant(), context.getProject());
                                securityGroup.setRegionId(newServer.getRegionId());
                                securityGroupRepository.save(securityGroup);
                                securityGroupRuleRepository.removeBySgId(securityGroup.getId(), userId);
                                for (SecurityGroupRuleModel securityGroupRuleModel : securityGroupModel.getModels()) {
                                    SecurityGroupRule securityGroupRule = new SecurityGroupRule();
                                    BeanUtils.copyProperties(securityGroupRuleModel, securityGroupRule);
                                    securityGroupRule.setCreatorId(userId);
                                    securityGroupRule.setVendorId(vendor.getId());
                                    securityGroupRule.setGroupId(securityGroup.getId());
                                    securityGroupRule.setGroupUuid(securityGroup.getGroupUuid());
                                    securityGroupRuleRepository.save(securityGroupRule);
                                }
                                networkInterface.setSecurityGroupId(securityGroup.getId());
                                //加入虚拟机和安全组绑定关系
                                ServerSgroup serverSgroup = new ServerSgroup(oldServer.getId(), securityGroup.getId());
                                serverSgroupRepository.save(serverSgroup);

                            }
                        } else {
                            //安全组不为空
                            networkInterface.setSecurityGroupId(group.getId());
                            ServerSgroup serverSgroup = new ServerSgroup(oldServer.getId(), group.getId());
                            serverSgroupRepository.save(serverSgroup);

                        }
                    }
                    networkInterface.setServerId(oldServer.getId());
                    networkInterface.setCreatorId(userId);
                    networkInterface.setVendorId(vendor.getId());
                    networkInterface.setRegionId(oldServer.getRegionId());
                    networkInterface.setZone(oldServer.getZone());
                    networkInterface.setTenantId(oldServer.getTenantId() == null ? 0L : oldServer.getTenantId());
                    Long projectId = oldServer.getProjectId();
                    if (null != projectId && projectId > 0) {
                        networkInterface.setProjectId(projectId);
                    } else {
                        networkInterface.setProjectId(0L);
                    }
                    if (context.getCatalog() == RequestContext.Catalog.User) {
                        networkInterface.setUserId(context.getTarget());
                    }
                    networkInterface.setResourceGroupId(resourceGroupId);
                    interfaceRepository.save(networkInterface);
                    //获取公共IP地址
                    Map<String, PublicIPAddress> publicIPAddressMap = Optional
                            .ofNullable(publicIPAddressRepository.list(vendor.getId(), oldServer.getRegionId()))
                            .map(entitys -> entitys.stream()
                                    .collect(Collectors.toMap(entity -> entity.getUuid().toLowerCase(), entity -> entity)))
                            .orElse(Maps.newHashMap());

                    List<NicIpConfigurationModel> nicIpConfigurationModels = networkInterfaceModel.getNicIpConfigurationModels();
                    for (NicIpConfigurationModel nicIpConfigurationModel : nicIpConfigurationModels) {
                        NicIpConfiguration nicIpConfiguration = new NicIpConfiguration();
                        BeanUtils.copyProperties(nicIpConfigurationModel, nicIpConfiguration);
                        nicIpConfiguration.setNetworkInterfaceId(networkInterface.getId());
                        nicIpConfiguration.setVpcId(networkInterface.getVpcId());
                        nicIpConfiguration.setSubnetId(networkInterface.getSubnetId());
                        nicIpConfigurationRepository.save(nicIpConfiguration);
                        //公共ip绑定关系
                        this.savePublicRelation(nicIpConfigurationModel, nicIpConfiguration, publicIPAddressMap, oldServer, userId, projectId);
                    }
                }
            }
        }
    }


    //公共IP绑定关系
    private void savePublicRelation(NicIpConfigurationModel nicIpConfigurationModel, NicIpConfiguration nicIpConfiguration, Map<String, PublicIPAddress> publicIPAddressMap, CloudServer cloudServer, Long userId, Long projectId) {
        String publicIpAddressUuid = nicIpConfigurationModel.getPublicIpAddressUuid();
        if (null != publicIpAddressUuid) {
            PublicIPAddress publicIPAddress = publicIPAddressMap.get(publicIpAddressUuid.toLowerCase());
            if (!ObjectUtils.isEmpty(publicIPAddress)) {
                //插入绑定关系
                ResourcePublicIPAddressRelation relation = new ResourcePublicIPAddressRelation();
                relation.setIpId(publicIPAddress.getId());
                relation.setResourceId(nicIpConfiguration.getId());
                relation.setResourceType(AzureIpRelationType.NICIPCONFIGURATION.name());
                resourcePublicIPAddressRelationRepository.save(relation);
                //重置状态
                publicIPAddress.setStatus(AzureTaskStatus.IN_USE.name());
                publicIPAddressRepository.update(publicIPAddress);
                //重置ip配置
                nicIpConfiguration.setPublicIpAddressId(publicIPAddress.getId());
                nicIpConfigurationRepository.update(nicIpConfiguration);
            } else {//说明公共ip地址是自动创建的
                BocloudResult publicIPAddressResult = publicIPAddressDriver.detail(vendor.getUuid(), cloudServer.getRegionId(),
                        publicIpAddressUuid);
                if (publicIPAddressResult.isSuccess()) {
                    PublicIPAddress pia = new PublicIPAddress();
                    PublicIPAddressModel publicIPAddressModel = JSONObject.parseObject(JSONObject.toJSONString(publicIPAddressResult.getData()), PublicIPAddressModel.class);
                    BeanUtils.copyProperties(publicIPAddressModel, pia);
                    pia.setCreatorId(userId);
                    pia.setVendorId(vendor.getId());
                    pia.setResourceGroupId(cloudServer.getResourceGroupId());
                    pia.setTenantId(cloudServer.getTenantId() == null ? 0L : cloudServer.getTenantId());
                    if (null != cloudServer.getProjectId() && cloudServer.getProjectId() > 0) {
                        pia.setProjectId(projectId);
                    } else {
                        pia.setProjectId(0L);
                    }
                    if (context.getCatalog() == RequestContext.Catalog.User) {
                        pia.setUserId(context.getTarget());
                    }
                    pia.setRegionId(cloudServer.getRegionId());
                    publicIPAddressRepository.save(pia);
                    //绑定关系
                    ResourcePublicIPAddressRelation relation = new ResourcePublicIPAddressRelation();
                    relation.setIpId(pia.getId());
                    relation.setResourceId(nicIpConfiguration.getId());
                    relation.setResourceType(AzureIpRelationType.NICIPCONFIGURATION.name());
                    resourcePublicIPAddressRelationRepository.save(relation);
                    //重置状态
                    pia.setStatus(AzureTaskStatus.IN_USE.name());
                    publicIPAddressRepository.update(pia);
                    //重置ip配置
                    nicIpConfiguration.setPublicIpAddressId(pia.getId());
                    nicIpConfigurationRepository.update(nicIpConfiguration);
                }
            }
        }
    }


    private void updateServerKeyPair(CloudServer server, Long vendorId) throws Exception {
        String keypairName = server.getKeypairName();
        if (null != keypairName && !"".equals(keypairName) && !"null".equalsIgnoreCase(keypairName)) {
            List<String> keyPairList = JSON.parseArray(keypairName, String.class);
            ServerKeypair serverKeypair = null;
            for (String keyName : keyPairList) {
                if (null != keyName && !"".equals(keyName) && !"null".equalsIgnoreCase(keyName)) {
                    serverKeypair = new ServerKeypair();
                    Keypair keypair = keypairRepository.getByName(keyName, vendorId, server.getRegionId());
                    serverKeypair.setKeypairId(keypair.getId());
                    serverKeypair.setServerId(server.getId());
                    serverKeypairRepository.save(serverKeypair);
                }
            }
        }
    }


    /**
     * 返回随机字符串，同时包含数字、大小写字母
     *
     * @param len 字符串长度，不能小于3
     * @return String 随机字符串
     */
    public static String randomStr(int len) {
        if (len < 3) {
            throw new IllegalArgumentException("字符串长度不能小于3");
        }
        // 数组，用于存放随机字符
        char[] chArr = new char[len];
        // 为了保证必须包含数字、大小写字母
        chArr[0] = (char) ('0' + PwdRandom.uniform(0, 10));
        chArr[1] = (char) ('A' + PwdRandom.uniform(0, 26));
        chArr[2] = (char) ('a' + PwdRandom.uniform(0, 26));

        char[] codes = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
                'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
                'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
                'z'};
        // charArr[3..len-1]随机生成codes中的字符
        for (int i = 3; i < len; i++) {
            chArr[i] = codes[PwdRandom.uniform(0, codes.length)];
        }

        // 将数组chArr随机排序
        for (int i = 0; i < len; i++) {
            int r = i + PwdRandom.uniform(len - i);
            char temp = chArr[i];
            chArr[i] = chArr[r];
            chArr[r] = temp;
        }

        return new String(chArr);
    }

}
