package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.PoolGroupTarget;
import com.bocloud.cmp.model.IpInfoModel;
import com.bocloud.cmp.provider.utils.IPAddress;
import com.bocloud.cmp.provider.utils.IPv4Address;
import com.bocloud.cmp.provider.utils.IPv6Address;
import com.bocloud.cmp.vm.model.IpScanParam;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.Result;
import com.bocloud.common.model.Sign;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.IDFactory;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.resource.Ip;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.entity.resource.IpPool;
import com.bocloud.ims.entity.resource.PoolGroup;
import com.bocloud.ims.entity.resource.PoolGroupRelation;
import com.bocloud.ims.entity.resource.PortGroupRelation;
import com.bocloud.ims.interfaces.resource.IpPoolService;
import com.bocloud.ims.interfaces.resource.IpService;
import com.bocloud.ims.repository.resource.IpPoolPortGroupRepository;
import com.bocloud.ims.repository.resource.IpPoolRepository;
import com.bocloud.ims.repository.resource.IpRepository;
import com.bocloud.ims.repository.resource.PoolGroupRelationRepository;
import com.bocloud.ims.repository.resource.PoolGroupRepository;
import com.bocloud.ims.repository.resource.PortGroupRelationRepository;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author wangyu
 * @version 5.1.0
 * @description IP池业务实现
 * @date: 2020-11-30
 */
@Service("ipPoolService")
public class IpPoolServiceImpl implements IpPoolService {

    private static Logger logger = LoggerFactory.getLogger(IpPoolServiceImpl.class);
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private IpPoolRepository ipPoolRepository;
    @Autowired
    private IpRepository ipRepository;
    @Autowired
    private PoolGroupRelationRepository poolGroupRelationRepository;
    @Autowired
    private PoolGroupRepository poolGroupRepository;
    @Autowired
    private IpService ipService;
    @Autowired
    private IpPoolPortGroupRepository ipPoolPortGroupRepository;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private PortGroupRelationRepository portGroupRelationRepository;

    @Override
    public BocloudResult<GridBean<IpPool>> list(Pager pager, RequestContext context) {
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            sorter.put("gmtCreate", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            Boolean countIp = false;
            for (Param param : params) {
                Map<String, Object> map = param.getParam();
                if (map.containsKey("countIp")) {
                    countIp = true;
                    map.remove("countIp");
                }
            }
            int total = ipPoolRepository.count(params);
            List<IpPool> list = this.ipPoolRepository.list(page, rows, params, sorter);
            // ip资源报表统计
            if (countIp) {
                for (IpPool ipPool : list) {
                    List<Param> paramsData = Lists.newArrayList();
                    paramsData.add(new Param(MapTools.simpleMap("poolId", ipPool.getId()), Sign.EQ));
                    List<String> pools = JSONArray.parseArray(ipPool.getPools(), String.class);
                    String[] split = pools.get(0).split("-");
                    BigInteger ipstart = new BigInteger(ipv6ToBytes(split[0]));// 获取起始IP的开始位置
                    BigInteger ipend = new BigInteger(ipv6ToBytes(split[1]));// 获取终止IP的结束位置
                    BigInteger ipCount = ipend.subtract(ipstart).add(new BigInteger("1"));
                    // 获取已使用ip数量
                    Pager ipPager = new Pager(1, Integer.MAX_VALUE, paramsData, sorter);
                    BocloudResult ipResult = ipService.list(ipPager);
                    Assert.notNull(ipResult.getData(), "获取已使用IP失败");
                    JSONObject ipUsedObject = JSONObject.parseObject(JSONObject.toJSONString(ipResult.getData()));
                    List<Ip> ips = JSONArray.parseArray(JSONObject.toJSONString(ipUsedObject.get("rows")),Ip.class);
                    ips = ips.stream().filter(ip -> null!=ip.getStatus() && !"free".equalsIgnoreCase(ip.getStatus().name())).collect(Collectors.toList());
                    Map<String, Ip> ipUsedMap = ips.stream().collect(Collectors.toMap(Ip::getIp, a -> a, (k1, k2) -> k1));
                    BigInteger ipUsed = BigInteger.valueOf(ipUsedMap.size());
                    ipPool.setIpTotal(ipCount);
                    ipPool.setIpUsed(ipUsed);
                    ipPool.setIpFree(ipCount.subtract(ipUsed));
                }
            }
            GridBean<IpPool> gridBean = GridHelper.getBean(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query ip pool list fail:{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * ipv4转为byte格式
     *
     * @param address
     * @return
     */
    private byte[] ipv4ToBytes(String address) {
        byte[] bytes = new byte[4];
        // 先找到IP地址字符串中.的位置
        int position1 = address.indexOf(".");
        int position2 = address.indexOf(".", position1 + 1);
        int position3 = address.indexOf(".", position2 + 1);
        // 将每个段转换为byte类型
        bytes[0] = (byte) Integer.parseInt(address.substring(0, position1));
        bytes[1] = (byte) Integer.parseInt(address.substring(position1 + 1, position2));
        bytes[2] = (byte) Integer.parseInt(address.substring(position2 + 1, position3));
        bytes[3] = (byte) Integer.parseInt(address.substring(position3 + 1));
        return bytes;
    }

    /**
     * ipv6转为byte格式
     *
     * @param address
     * @return
     */
    public byte[] ipv6ToBytes(String address) {
        byte[] bytes = new byte[17];
        bytes[0] = 0;
        int index = 16;
        boolean hasIpv4 = false;
        if (address.startsWith(":")) {
            address = address.substring(1);
        }
        String[] segments = address.split(":");
        for (int i = segments.length - 1; i > -1; i--) {
            if (segments[i].contains(".")) {// 当ipv6段最后是ipv4
                byte[] values = ipv4ToBytes(segments[i]);
                bytes[index--] = values[3];
                bytes[index--] = values[2];
                bytes[index--] = values[1];
                bytes[index--] = values[0];
                hasIpv4 = true;
            } else if ("".equals(segments[i])) { // ipv6段为空时，补全0
                int zeros = 8 - (segments.length - 1 + (hasIpv4 ? 1 : 0));
                while (zeros > 0) {
                    bytes[index--] = 0;
                    bytes[index--] = 0;
                    zeros--;
                }
            } else {
                int value = Integer.parseInt(segments[i], 16);
                bytes[index--] = (byte) value;
                bytes[index--] = (byte) (value >> 8);
            }
        }
        return bytes;
    }

    @Override
    public BocloudResult<IpPool> create(IpPool ipPoolParam, RequestContext context) {
        String ipPools = ipPoolParam.getPools();
        String cidr = ipPoolParam.getCidr();
        String gateway = ipPoolParam.getGateway();
        String dnsNames = ipPoolParam.getDnsNames();
        Integer vlanId = ipPoolParam.getVlanId();
        String version = ipPoolParam.getVersion();
        String name = ipPoolParam.getName();
        try {
            IpPool nameIpPool = ipPoolRepository.query(name);
            Assert.isNull(nameIpPool,"该ip池名称已经存在");
            Result checkResult = ipPoolCheck(cidr, gateway, ipPools, dnsNames, vlanId, version);
            if (checkResult.isFailed()) {
                return new BocloudResult<>(false, checkResult.getMessage());
            }
            List<String> newPools = JSONArray.parseArray(ipPools, String.class);
            // 和数据已有的ip地址池进行比较
            List<IpPool> oldLists = ipPoolRepository.listByIpVersion(version);
            List<String> oldPools = Lists.newArrayList();
            for (IpPool ipPool : oldLists) {
                oldPools.addAll(JSONArray.parseArray(ipPool.getPools(), String.class));
            }
            List<String> pools = compare(oldPools, newPools);
            if (pools.isEmpty()) {
                return new BocloudResult<>(false, "添加失败：该IP地址池已被包含在其他地址池中");
            }
            ipPoolParam.setCreatorId(context.getTarget());
            ipPoolParam.setMenderId(context.getTarget());
            ipPoolParam.setPools(JSONObject.toJSONString(pools));
            ipPoolParam.setGateway(gateway);
            ipPoolParam.setVersion(version);
            ipPoolRepository.save(ipPoolParam);
            IPAddress ipAddress = "V4".equalsIgnoreCase(version) ? new IPv4Address() : new IPv6Address();
            taskExecutor.execute(() -> {
                List<Ip> ips = ipRepository.listNotInPools();
                for (Ip ip : ips) {
                    if (null != ip.getPoolId() || !version.equalsIgnoreCase(IPAddress.getVersion(ip.getIp()))) {
                        continue;
                    }
                    boolean flag = ipAddress.isInPools(ip.getIp(), pools);
                    if (flag) {
                    	ip.setStatus(IpStatus.free);
                        ip.setPoolId(ipPoolParam.getId());
                        ip.setGateway(ipPoolParam.getGateway());
                        ip.setVendorId(ipPoolParam.getVendorId());
                        ipRepository.update(ip);
                    }
                }
                String dns = null;
                if (!StringUtils.isEmpty(ipPoolParam.getDnsNames())) {
                    List<String> dnss = JSONArray.parseArray(ipPoolParam.getDnsNames(), String.class);
                    if (!ListTool.isEmpty(dnss)) {
                        dns = dnss.get(0);
                    }
                }
                List<Ip> saveIps = getNewIps(ipPoolParam, ips, JSON.parseArray(ipPoolParam.getPools(), String.class), dns);
                logger.info("批量保存的ip数量：{}", JSONObject.toJSON(saveIps));
                if (!ListTool.isEmpty(saveIps)) {
                    ipRepository.batchCreate(saveIps);
                }
                // 扫描ip地址
                ipService.scan(IpScanParam.builder().poolId(ipPoolParam.getId()).build(), context);
            });
            return new BocloudResult<>(true, ipPoolParam, "创建成功!");
        } catch (Exception e) {
            logger.error("create ip pool failure:", e);
            return new BocloudResult<>(false, "创建失败," + e.getMessage());
        }
    }

	private List<Ip> getNewIps(IpPool ipPoolParam, List<Ip> ipList, List<String> newPools, String dns) {
		List<Ip> saveIps = new ArrayList<>();
		if (!ListTool.isEmpty(newPools)) {
			for (String newPool : newPools) {
				String start = newPool.split("-")[0];
				String end = newPool.split("-")[1];
				IPAddress address = IPAddress.getIPAddress(start);
				BigInteger ipstart = address.ipToInteger(start);// 获取起始IP的开始位置
				BigInteger ipend = address.ipToInteger(end);// 获取终止IP的结束位置
				while (ipend.compareTo(ipstart) >= 0) {
					String ipKey = address.integerToIp(ipstart);
					// Ip ip = ipRepository.checkExist(ipKey, null, null);
					Ip ip = ipList.stream().filter(ipInfo -> ipInfo.getIp().equals(ipKey)).findFirst().orElse(null);
					if (null == ip) {
						ip = new Ip(ipKey, address.getMask(ipPoolParam.getCidr()), ipPoolParam.getGateway(), dns,
								ipPoolParam.getVendorId(), IDFactory.instance().uuid(), ipPoolParam.getId(),
								IpStatus.free);
						saveIps.add(ip);
					} else {
						boolean flag = address.isInPools(ipKey, newPools);
						if (flag) {
							ip.setPoolId(ipPoolParam.getId());
							ip.setVendorId(ipPoolParam.getVendorId());
							ip.setDns(dns);
							ip.setMask(address.getMask(ipPoolParam.getCidr()));
							ip.setGateway(ipPoolParam.getGateway());
							ip.setStatus(IpStatus.free);
						}
					}
					ipstart = ipstart.add(new BigInteger("1"));
				}

			}
		}
		return saveIps;
	}

    private Result ipPoolCheck(String cidr, String gateway, String ipPools, String dnsNames, Integer vlanId, String version) {
        // 检查输入准确性
        if (StringUtils.isEmpty(cidr)) {
            return new Result(false, "子网掩码不能为空！");
        }
        int index = cidr.indexOf("/");
        if (index < 0) {
            return new Result(false, "网络地址格式不正确，参考 address/prefix");
        }
        Integer mask = Integer.valueOf(cidr.substring(index + 1));
        if (mask < 16) {
            return new Result(false, "只允许添加B类或者C类网络地址");
        }
        // 判断是ipv4还是ipv6
        IPAddress ipAddress = "V4".equalsIgnoreCase(version) ? new IPv4Address() : new IPv6Address();
        // 网关校验
        if (StringUtils.isEmpty(gateway)) {
            gateway = ipAddress.getDefaultGeteway(cidr);
        }
        if (StringUtils.isEmpty(ipPools)) {
            ipPools = ipAddress.getPools(gateway, cidr);
        } else {
            if (!ipAddress.isInRange(JSONObject.parseArray(ipPools, String.class), cidr)) {
                return new Result(false, "分配池超出范围，请检查");
            }
        }
        if (ipAddress.isInPools(gateway, JSONObject.parseArray(ipPools, String.class))) {
            return new Result(false, "网关不允许包含在分配池内，请检查");
        }
        if (!StringUtils.isEmpty(dnsNames)) {
            List<String> list = JSONObject.parseArray(dnsNames, String.class);
            if (!ListTool.isEmpty(list)) {
                for (String dns : list) {
                    if (!StringUtils.isEmpty(dns) && !ipAddress.validate(dns)) {
                        return new Result(false, "DNS不合法，请检查");
                    }
                }
            }
        }
        if (null != vlanId && vlanId > 4095) {
            return new Result(false, "所属vlanId超出划分范围");
        }
        return new Result(true, "校验通过");
    }

    /**
     * 新旧地址池比较，去除共同部分
     *
     * @param oldPools
     * @param newPools
     * @return
     */
    private List<String> compare(List<String> oldPools, List<String> newPools) {
        List<String> list = Lists.newArrayList();
        for (String newPool : newPools) {
            List<String> pools = Lists.newArrayList();
            pools.add(newPool);
            for (String oldPool : oldPools) {
                // 新地址池和旧地址池比较得到地址池list再和下一个旧的地址池比较，直到最后一个，去除全部共同部分
                pools = compare(pools, oldPool);
            }
            list.addAll(pools);
        }
        return list;
    }

    /**
     * 新旧地址池比较，去除共同部分
     *
     * @param pools
     * @param oldPool
     * @return
     */
    private List<String> compare(List<String> pools, String oldPool) {
        List<String> list = Lists.newArrayList();
        for (String pool : pools) {
            list.addAll(compare(pool, oldPool));
        }
        return list;
    }

    /**
     * 新旧地址池比较，去除共同部分
     *
     * @param newPool
     * @param oldPool
     * @return
     */
    private List<String> compare(String newPool, String oldPool) {
        String[] newIps = newPool.split("-");
        String[] oldIps = oldPool.split("-");
        IPAddress address = IPAddress.getIPAddress(newIps[0]);
        BigInteger newStartValue = address.ipToInteger(newIps[0]);
        BigInteger newEndValue = address.ipToInteger(newIps[1]);
        BigInteger oldStartValue = address.ipToInteger(oldIps[0]);
        BigInteger oldEndValue = address.ipToInteger(oldIps[1]);
        List<String> list = Lists.newArrayList();
        if (newEndValue.compareTo(oldStartValue) < 0 || newStartValue.compareTo(oldEndValue) > 0) {// 新池在旧池的两边
            list.add(newPool);
        } else if (newStartValue.compareTo(oldStartValue) < 0 && oldEndValue.compareTo(newEndValue) < 0) {// 新池包含旧池
            list.add(newIps[0] + "-" + address.integerToIp(oldStartValue.subtract(new BigInteger("1"))));
            list.add(address.integerToIp(oldEndValue.add(new BigInteger("1"))) + "-" + newIps[1]);
        } else if (newStartValue.compareTo(oldStartValue) < 0 && oldStartValue.compareTo(newEndValue) <= 0
                && newEndValue.compareTo(oldEndValue) <= 0) {// 新池在旧池左边，有共同部分
            list.add(newIps[0] + "-" + address.integerToIp(oldStartValue.subtract(new BigInteger("1"))));
        } else if (oldStartValue.compareTo(newStartValue) <= 0 && newStartValue.compareTo(oldEndValue) <= 0
                && oldEndValue.compareTo(newEndValue) < 0) {
            list.add(address.integerToIp(oldEndValue.add(new BigInteger("1"))) + "-" + newIps[1]);// 新池在旧池右边，有共同部分
        }
        return list;
    }

    @Override
    public BocloudResult<IpPool> modify(IpPool ipPool, RequestContext context) {
        Long id = ipPool.getId();
        String name = ipPool.getName();
        Integer vlanId = ipPool.getVlanId();
        String ipPools = ipPool.getPools();
        String cidr = ipPool.getCidr();
        String gateway = ipPool.getGateway();
        String dnsNames = ipPool.getDnsNames();
        Long portGroupId = ipPool.getPortGroupId();
        try {
            IpPool pool = ipPoolRepository.query(id);
            if (null == pool) {
                return new BocloudResult<>(false, "数据不存在");
            }
            if (!pool.getName().equals(name)){
                IpPool namePool = ipPoolRepository.query(name);
                Assert.isNull(namePool,"该ip池名称已经存在");
            }
            Result checkResult = ipPoolCheck(cidr, gateway, ipPools, dnsNames, vlanId, pool.getVersion());
            if (checkResult.isFailed()) {
                return new BocloudResult<>(false, checkResult.getMessage());
            }
            List<String> newPools = JSONArray.parseArray(ipPools, String.class);
            List<String> pools;
            // 和数据已有的ip其他地址池进行比较
            if (!pool.getPools().equals(ipPools)) {
                List<IpPool> oldLists = ipPoolRepository.listByIpVersion(pool.getVersion());
                List<String> oldPools = Lists.newArrayList();
                for (IpPool oldPool : oldLists) {
                    if (!oldPool.getId().equals(id)){
                    oldPools.addAll(JSONArray.parseArray(oldPool.getPools(), String.class));
                    }
                }
                pools = compare(oldPools, newPools);
                if (pools.isEmpty()) {
                    return new BocloudResult<>(false, "修改失败：该IP地址池已被包含在其他地址池中");
                }
            } else {
                pools = JSONArray.parseArray(ipPools, String.class);
            }
            pool.setPools(JSONObject.toJSONString(pools));
            pool.setName(name);
            pool.setMenderId(context.getTarget());
            pool.setPortGroupId(portGroupId);
            pool.setCidr(cidr);
            pool.setGateway(gateway);
            pool.setDnsNames(dnsNames);
            pool.setVlanId(vlanId);
            ipPoolRepository.update(pool);
            IPAddress ipAddress = "V4".equalsIgnoreCase(pool.getVersion()) ? new IPv4Address() : new IPv6Address();
            taskExecutor.execute(() -> {
                String dns = null;
                if (!StringUtils.isEmpty(pool.getDnsNames())) {
                    List<String> dnss = JSONArray.parseArray(pool.getDnsNames(), String.class);
                    if (!ListTool.isEmpty(dnss)) {
                        dns = dnss.get(0);
                    }
                }
                List<Ip> updateIpList = new ArrayList<>();
                List<Ip> ips = ipRepository.listNotInPools();
                ListIterator<Ip> ipListIterator = ips.listIterator();
                while (ipListIterator.hasNext()) {
                    Ip ip = ipListIterator.next();
                    if (pool.getId().equals(ip.getPoolId())) {
                        ipListIterator.remove();
                        continue;
                    }
                    if (null != ip.getPoolId() || !pool.getVersion().equalsIgnoreCase(IPAddress.getVersion(ip.getIp()))) {
                        continue;
                    }
                    boolean flag = ipAddress.isInPools(ip.getIp(), pools);
                    if (flag) {
                        ip.setPoolId(pool.getId());
                        ip.setGateway(pool.getGateway());
                        ip.setStatus(IpStatus.free);
                        ip.setVendorId(pool.getVendorId());
                        updateIpList.add(ip);
                    }

                }
                List<Ip> newIpList = getNewIps(pool, ips, JSONObject.parseArray(pool.getPools(), String.class), dns);
                List<String> newIps = newIpList.stream().map(Ip::getIp).collect(Collectors.toList());
                //logger.info("批量保存的ip数量：{}", JSONObject.toJSON(newIpList));
                List<Ip> oldIps = ipRepository.listByPool(pool.getId());
                //旧ip排除掉不包含的ip
                List<Ip> removeIp = oldIps.stream().filter(ip -> !newIps.contains(ip.getIp())).peek(ip -> ip.setPoolId(null)).collect(Collectors.toList());
                if (!removeIp.isEmpty()) {
                    updateIpList.addAll(removeIp);
                }
                //旧的ip包含在新ip里面的修改dns
                String finalDns = dns;
                List<Ip> oldUpdate = oldIps.stream().filter(ip -> newIps.contains(ip.getIp())).peek(ip -> ip.setDns(finalDns)).collect(Collectors.toList());
                if (!oldUpdate.isEmpty()) {
                    updateIpList.addAll(oldUpdate);
                }
                List<String> updateIps = updateIpList.stream().map(Ip::getIp).collect(Collectors.toList());
                // 旧的ip包含了的原有ip则从新增ip中移除
                newIpList.removeIf(ip -> updateIps.contains(ip.getIp()));
                if (!ListTool.isEmpty(newIpList)) {
                    ipRepository.batchCreate(newIpList);
                }
                if (!ListTool.isEmpty(updateIpList)) {
                	updateIpList.forEach(ip -> ip.setGateway(pool.getGateway()));
                    ipRepository.batchUpdate(updateIpList);
                }
                // 扫描ip地址
                ipService.scan(IpScanParam.builder().poolId(pool.getId()).build(), context);
            });
            return new BocloudResult<>(true, pool, "修改成功");
        } catch (Exception e) {
            logger.error("modify ip pool failure:", e);
            return new BocloudResult<>(false, "修改失败," + e.getMessage());
        }
    }

    @Override
    public BocloudResult remove(Long id, RequestContext context) {
        String path = IpPool.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            List<Ip> ips = ipRepository.listByPool(id, IpStatus.used);
            if (!ListTool.isEmpty(ips)) {
                return new BocloudResult<>(false, "删除失败:存在已使用的IP地址");
            }
            ipPoolRepository.remove(id, context.getTarget());
            ipRepository.deleteByPoolId(id);
            ipPoolPortGroupRepository.deleteByPoolId(id);
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove ip pool fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    @Override
    public BocloudResult<IpPool> detail(Long id) {
        try {
            IpPool pool = ipPoolRepository.query(id);
            List<String> pools = JSONArray.parseArray(pool.getPools(), String.class);
            List<Ip> ips = ipRepository.listByPool(id);
            String[] split = pools.get(0).split("-");
            BigInteger ipStart = new BigInteger(ipv6ToBytes(split[0]));// 获取起始IP的开始位置
            BigInteger ipEnd = new BigInteger(ipv6ToBytes(split[1]));// 获取终止IP的结束位置
            BigInteger ipCount = ListTool.isEmpty(ips) ? BigInteger.ZERO : BigInteger.valueOf(Long.valueOf(ips.size()));
            // 获取已使用ip数量
            BigInteger freeNum = BigInteger.ZERO;
            BigInteger lockNum = BigInteger.ZERO;
            BigInteger usedNum = BigInteger.ZERO;
            BigInteger preemptNum = BigInteger.ZERO;
            for (Ip ip : ips) {
                IpStatus status = ip.getStatus();
                switch (status) {
                    case lock:
                        lockNum = lockNum.add(BigInteger.ONE);
                        break;
                    case used:
                        usedNum = usedNum.add(BigInteger.ONE);
                        break;
                    case preempt:
                        preemptNum = preemptNum.add(BigInteger.ONE);
                        break;
                    default:
                        freeNum = freeNum.add(BigInteger.ONE);
                        break;
                }
            }
            pool.setIpTotal(ipCount);
            pool.setIpLock(lockNum);
            pool.setIpUsed(usedNum);
            pool.setIpPreempt(preemptNum);
            pool.setIpFree(freeNum);
            if ("V4".equalsIgnoreCase(pool.getVersion())) {
                ArrayList<IpPool.AddressSection> sections = new ArrayList<>();
                String startIp = split[0];
                String[] startIps = startIp.split("\\.");
                String endIp = split[1];
                String[] endIps = endIp.split("\\.");
                for (int i = 0; i < startIps.length; i++) {
                    String start = startIps[i];
                    String end = endIps[i];
                    IpPool.AddressSection section = new IpPool.AddressSection();
                    if (start.equals(end)) {
                        section.setValue(Integer.valueOf(start));
                        section.setMin(Integer.valueOf(start));
                        section.setMax(Integer.valueOf(start));
                    } else {
                        section.setValue(Integer.valueOf(start));
                        section.setMin(Integer.valueOf(start));
                        section.setMax(Integer.valueOf(end));
                    }
                    sections.add(section);
                }
                pool.setAddressSections(sections);
            }
            return new BocloudResult<>(true, pool, "查询成功!");
        } catch (Exception e) {
            logger.error("query pool detail failure:", e);
            return new BocloudResult<>(false, "查询详情失败!");
        }
    }

    @Override
    public BocloudResult<List<IpInfoModel>> ips(Long id, String cidr) {
        try {
            IpPool ipPool = ipPoolRepository.query(id);
            Assert.notNull(ipPool, "ip池不存在");
            cidr = Optional.ofNullable(cidr).orElse(ipPool.getCidr());
            String addressPrefix = cidr.substring(0, cidr.lastIndexOf(".") + 1);
            List<Ip> ips = ipRepository.listByPool(ipPool.getId());
            List<IpInfoModel> ipInfoModels = new ArrayList<>();
            for (Ip ip : ips) {
                if (ip.getIp().contains(addressPrefix)) {
                    IpInfoModel ipInfoModel = new IpInfoModel();
                    ipInfoModel.setCidr(ipPool.getCidr());
                    ipInfoModel.setDns(ip.getDns());
                    ipInfoModel.setName(ip.getIp());
                    ipInfoModel.setGateway(ip.getGateway());
                    ipInfoModel.setStatus(ip.getStatus().name());
                    String address = ip.getIp();
                    ipInfoModel.setSuffix(address.substring(address.lastIndexOf(".") + 1));
                    ipInfoModels.add(ipInfoModel);
                }
            }
            String version = ipPool.getVersion();
            if("V4".equalsIgnoreCase(version)) {
            	ipInfoModels.sort(Comparator.comparingInt(ipInfoModel->Integer.parseInt(ipInfoModel.getSuffix())));
            }
            return new BocloudResult<>(true, ipInfoModels, "查询成功");
        } catch (Exception e) {
            logger.error("query pool ips detail failure:", e);
            return new BocloudResult<>(false, "查询IP概览失败!");
        }
    }

    @Override
    public BocloudResult listIpPoolByPoolGroupId(Integer page, Integer rows, String params, RequestContext context) {
        try {
            JSONObject object = JSON.parseObject(params, JSONObject.class);
            if (null == object) {
                return new BocloudResult<>(false, "参数格式错误");
            }
            List<Param> param = Lists.newArrayList();
            Long poolGroupId = object.getLong("poolGroupId");
            PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
            if (null == poolGroup) {
                return new BocloudResult<>(false, "资源池不存在");
            }
            String category = object.getString("category");
            List<PoolGroupRelation> relationList = poolGroupRelationRepository.list(poolGroupId, category);
            param.add(new Param(MapTools.simpleMap("vendorId", poolGroup.getVendorId()), Sign.EQ));

            String pools = object.getString("pools");
            if (null != pools && !"".equals(pools)) {
                param.add(new Param(MapTools.simpleMap("pools", pools), Sign.LK));
            }
            String vlanId = object.getString("vlanId");
            if (null != vlanId && !"".equals(vlanId)) {
                param.add(new Param(MapTools.simpleMap("vlanId", vlanId), Sign.LK));
            }

            if (PoolGroupTarget.IpPool.name().equals(category)) {
                List<Long> ipPoolIds = new ArrayList<>();
                for (PoolGroupRelation poolGroupRelation : relationList) {
                    ipPoolIds.add(poolGroupRelation.getTarget());
                }
                param.add(new Param(MapTools.simpleMap("id", this.generateIpPoolIds(ipPoolIds)), Sign.IN));
            }
            Map<String, String> sorter = Maps.newHashMap();
            sorter.put("gmtCreate", Common.ONE);
            int total = this.ipPoolRepository.count(param);
            List<IpPool> ipPoolList = this.ipPoolRepository.list(page, rows, param, sorter);
            GridBean gridBean = GridHelper.getBean(page, rows, total, ipPoolList);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query ipPool list fail:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    private Object generateIpPoolIds(List<Long> ipPoolIds) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < ipPoolIds.size(); i++) {
            builder.append(ipPoolIds.get(i)).append(",");
        }
        builder.append(" -1 ");
        return builder.toString();
    }

    @Override
    public BocloudResult condition(String condition, RequestContext context) {
        condition = Optional.ofNullable(condition).orElse("");
        JSONObject object = JSONObject.parseObject(condition);
        if ("listIpPoolByPoolGroupId".equalsIgnoreCase(object.getString("condition"))) {
//			return this.listIpPoolByPoolGroupId(page, rows, condition, context);
        }
        if ("listNotBindPoolGroup".equalsIgnoreCase(object.getString("condition"))) {
			return this.listNotBindPoolGroup(condition, context);
        }
        return new BocloudResult<>(false, "参数格式错误");
    }

	private BocloudResult listNotBindPoolGroup(String condition, RequestContext context) {
		JSONObject object = JSON.parseObject(condition, JSONObject.class);
		if (null == object) {
			return new BocloudResult<>(false, "参数格式错误");
		}
		Long poolGroupId = object.getLong("poolGroupId");
		List<Long> portGroupIdsList = new ArrayList<>();
		List<PortGroupRelation> portGroupRelations = portGroupRelationRepository.listByGroupId(poolGroupId);
		if (!ListTool.isEmpty(portGroupRelations)) {
			portGroupIdsList = portGroupRelations.stream().map(PortGroupRelation::getIpPoolId)
					.collect(Collectors.toList());
		}
		List<IpPool> useIpPools = new ArrayList<>();
		List<IpPool> listAll = ipPoolRepository.listAll();
		if (!ListTool.isEmpty(listAll)) {
			for (IpPool ipPool : listAll) {
				if (null == ipPool.getPortGroupId() || portGroupIdsList.contains(ipPool.getId())) {
					useIpPools.add(ipPool);
				}
			}
		}
		return new BocloudResult<>(true, useIpPools, "查询成功");
	}

}
