package com.bocloud.ims.service.resource.h3c;

import com.alibaba.fastjson.JSONArray;
import com.bocloud.common.model.*;
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.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.Ip.IpStatus;
import com.bocloud.ims.interfaces.h3c.H3cNetworkService;
import com.bocloud.ims.repository.h3c.H3cNetworkRepository;
import com.bocloud.ims.repository.resource.IpPoolRepository;
import com.bocloud.ims.repository.resource.IpRepository;
import com.bocloud.ims.repository.resource.NetworkCardRepository;
import com.bocloud.ims.repository.resource.SwitcherRepository;
import com.bocloud.ims.service.utils.IPAddress;
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.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service("h3cNetworkService")
public class H3CNetworkServiceImpl implements H3cNetworkService {

	private static final Logger logger = LoggerFactory.getLogger(H3CNetworkServiceImpl.class);
	@Autowired
	private NetworkCardRepository networkCardRepository;
	@Autowired
	private H3cNetworkRepository h3cNetworkRepository;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private IpPoolRepository ipPoolRepository;
	@Autowired
	private IpRepository ipRepository;
	@Autowired
	private SwitcherRepository switcherRepository;

	@Override
	public BocloudResult<List<Map<String, Object>>> switchers(Long id) {
		try {
			List<Map<String, Object>> switchers = h3cNetworkRepository.listH3cSwitcherByHost(id);
			return new BocloudResult<List<Map<String, Object>>>(true, switchers, "查询成功");
		} catch (Exception e) {
			logger.error("查询失败", e);
			return new BocloudResult<List<Map<String, Object>>>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<List<NetworkCard>> netcards(Long hostId) {
		try {
			List<NetworkCard> cards = networkCardRepository.listByHost(hostId, "PM");
			return new BocloudResult<List<NetworkCard>>(true, cards, "查询成功");
		} catch (Exception e) {
			logger.error("查询失败", e);
			return new BocloudResult<List<NetworkCard>>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<Subnet> getSubnetBySwitcher(Long vSwitchId) {
		try {
			Subnet subnet = h3cNetworkRepository.getSubnetBySwitcher(vSwitchId);
			return new BocloudResult<>(true, subnet, "查询成功");
		} catch (Exception e) {
			logger.error(ExceptionUtils.getFullStackTrace(e));
			return new BocloudResult<>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<List<Ip>> getIp(Long vendorId, Long count) {
		String path = Ip.class.getSimpleName() + "_" + vendorId;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			List<IpPool> pools = ipPoolRepository.listByIpVersion(null);
			if (ListTool.isEmpty(pools)) {
				logger.warn("This vendor does not exist ip!");
				return new BocloudResult<>(false, "此平台下无IP可分配!");
			}
			List<Ip> ips = ipRepository.listByVendor(vendorId);
			Map<String, Ip> map = Maps.newHashMap();
			for (Ip ip : ips) {
				map.put(ip.getIp(), ip);
			}
			List<Ip> list = new ArrayList<>();
			int index = 0;
			for (IpPool pool : pools) {
				List<String> poolList = JSONArray.parseArray(pool.getPools(), String.class);
				String dns = JSONArray.parseArray(pool.getDnsNames(), String.class).get(0);
				for (String ipPools : poolList) {
					String[] startEndIp = ipPools.split("-");
					IPAddress address = IPAddress.getIPAddress(startEndIp[0]);
					BigInteger ipstart = address.ipToInteger(startEndIp[0]);// 获取起始IP的开始位置
					BigInteger ipend = address.ipToInteger(startEndIp[1]);// 获取终止IP的结束位置
					while (ipend.compareTo(ipstart) >= 0) {
						String ipKey = address.integerToIp(ipstart);
						if (!map.containsKey(ipKey)) {
							Ip ip = new Ip(ipKey, address.getMask(pool.getCidr()), pool.getGateway(), dns, vendorId,
									IDFactory.instance().uuid(), pool.getId(), IpStatus.used);
							ip.setCatalog("VM");
							ipRepository.save(ip);
							list.add(ip);
							index++;
						}
						if (index >= count) {
							break;
						}
						ipstart = ipstart.add(new BigInteger("1"));
					}
					if (index >= count) {
						break;
					}
				}
				if (index >= count) {
					break;
				}
			}
			if (list.isEmpty()) {
				return new BocloudResult<>(false, "此平台下无IP可分配!");
			}
			return new BocloudResult<>(true, list, "success");
		} catch (Exception e) {
			logger.error(ExceptionUtils.getFullStackTrace(e));
			return new BocloudResult<>(false, "此平台下无IP可分配!");
		}
	}

	@Override
	public BocloudResult<GridBean<Switcher>> list(Pager pager, RequestContext context) {
		List<Switcher> list = Lists.newArrayList();
		int total = 0;
		GridBean<Switcher> gridBean = null;
		try {
			List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
			Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
			Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
			sorter.put("gmtCreate", Common.ONE);
			Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
			Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
			total = switcherRepository.count(params);
			if (simple) {
				List<SimpleBean> beans = switcherRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				list = switcherRepository.list(page, rows, params, sorter);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BocloudResult<GridBean<Switcher>>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list switcher failure:", e);
			return new BocloudResult<GridBean<Switcher>>(false, "查询失败", null, null);
		}
	}

}
