package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.InternetGatewayDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.InternetGatewayModel;
import com.bocloud.cmp.model.InternetGatewayParam;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.InternetGateway;
import com.bocloud.ims.interfaces.resource.InternetGatewayService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.InternetGatewayRepository;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service("internetGatewayService")
public class InternetGatewayServiceImpl implements InternetGatewayService {
	private static Logger logger = LoggerFactory.getLogger(InternetGatewayServiceImpl.class);
	@Autowired
	private InternetGatewayRepository internetGatewayRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private InternetGatewayDriver internetGatewayDriver;
	@Autowired
	private LockFactory lockFactory;

	@Override
	public BocloudResult<GridBean<InternetGateway>> 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);
			int total = internetGatewayRepository.count(params);
			List<InternetGateway> list = internetGatewayRepository.list(page, rows, params, sorter);
			GridBean<InternetGateway> gridBean = GridHelper.getBean(page, rows, total, list);
			return new BocloudResult<GridBean<InternetGateway>>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list InternetGateway failure:", e);
			return new BocloudResult<GridBean<InternetGateway>>(false, "查询失败", null, null);
		}
	}

	@Override
	public BocloudResult<InternetGateway> create(InternetGateway internetGateway, RequestContext context) {
		try {
			CloudVendor vendor = cloudVendorRepository.query(internetGateway.getVendorId());
			Assert.notNull(vendor, "云平台不存在");
			CloudProvider provider = CloudProvider.valueOf(vendor.getType());
			BocloudResult result = null;
			InternetGateway gateway = internetGateway;
			switch (provider) {
			case AWS:
				result = internetGatewayDriver.create(vendor.getUuid(), internetGateway.getName(),
						internetGateway.getRegionId());
				if (result.isFailed()) {
					return new BocloudResult<InternetGateway>(false, "创建失败:" + result.getMessage(), null, null);
				}
				gateway = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), InternetGateway.class);
				gateway.setName(internetGateway.getName());
				gateway.setRegionId(internetGateway.getRegionId());
				gateway.setVendorId(vendor.getId());
				gateway.setOwnerId(context.getTarget());
				gateway.setMenderId(context.getTarget());
				gateway.setCreatorId(context.getTarget());
				internetGatewayRepository.save(gateway);
				break;
			default:
				break;
			}

			return new BocloudResult<InternetGateway>(true, gateway, "创建成功");
		} catch (Exception e) {
			logger.error("create gateway failure:", e);
			return new BocloudResult<InternetGateway>(false, "创建失败:" + e.getMessage());
		}
	}

	@Override
	public BocloudResult remove(Long id, RequestContext context) {
		try {
			InternetGateway gateway = internetGatewayRepository.query(id);
			Assert.notNull(gateway,"互联网网关不存在");
			CloudVendor vendor = cloudVendorRepository.query(gateway.getVendorId());
			Assert.notNull(vendor,"云平台不存在");
			BocloudResult result = internetGatewayDriver.remove(vendor.getUuid(), gateway.getInternetGatewayUuid(),
					gateway.getRegionId());
			if (result.isFailed()) {
				return new BocloudResult<>(false, "删除失败:" + result.getMessage(), null, null);
			}
			internetGatewayRepository.remove(gateway.getId(), context.getTarget());
			return new BocloudResult<>(true, "删除成功", null, null);
		} catch (Exception e) {
			logger.error("remove gateway failure:", e);
			return new BocloudResult<>(false, "删除失败", null, null);
		}
	}

	@Override
	public BocloudResult attach(InternetGatewayParam internetGatewayParam, RequestContext context) {
		try {
			InternetGateway gateway = internetGatewayRepository.query(internetGatewayParam.getId());
			if (gateway == null) {
				return new BocloudResult<>(false, "互联网网关不存在", null, null);
			}
			CloudVendor vendor = cloudVendorRepository.query(gateway.getVendorId());
			if (null == vendor) {
				return new BocloudResult<>(false, "指定的地域下云平台不存在");
			}
			BocloudResult result = internetGatewayDriver.attach(vendor.getUuid(), gateway.getInternetGatewayUuid(),
					internetGatewayParam.getVpcId(), gateway.getRegionId());
			if (result.isFailed()) {
				return new BocloudResult<>(false, "附加失败:" + result.getMessage(), null, null);
			}
			gateway.setVpcId(internetGatewayParam.getVpcId());
			gateway.setMenderId(context.getTarget());
			gateway.setGmtModify(new Date());
			internetGatewayRepository.update(gateway);
			return new BocloudResult<>(true, "附加成功");
		} catch (Exception e) {
			logger.error("attach vpc failure:", e);
			return new BocloudResult<>(false, "附加失败", null, null);
		}
	}

	@Override
	public BocloudResult detach(InternetGatewayParam internetGatewayParam, RequestContext context) {
		try {
			InternetGateway gateway = internetGatewayRepository.query(internetGatewayParam.getId());
			if (gateway == null) {
				return new BocloudResult<>(false, "互联网网关不存在", null, null);
			}
			CloudVendor vendor = cloudVendorRepository.query(gateway.getVendorId());
			if (null == vendor) {
				return new BocloudResult<>(false, "指定的地域下云平台不存在");
			}
			BocloudResult result = internetGatewayDriver.detach(vendor.getUuid(), gateway.getInternetGatewayUuid(),
					internetGatewayParam.getVpcId(), gateway.getRegionId());
			if (result.isFailed()) {
				return new BocloudResult<>(false, "分离失败:" + result.getMessage(), null, null);
			}
			gateway.setVpcId(null);
			gateway.setMenderId(context.getTarget());
			gateway.setGmtModify(new Date());
			internetGatewayRepository.update(gateway);
			return new BocloudResult<>(true, "分离成功");
		} catch (Exception e) {
			logger.error("detach vpc failure:", e);
			return new BocloudResult<>(false, "分离失败", null, null);
		}
	}

	@Override
	public BocloudResult<InternetGateway> modify(InternetGateway gateway, RequestContext context) {
		String path = InternetGateway.class.getSimpleName() + "_" + gateway.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			InternetGateway oldgateway = internetGatewayRepository.query(gateway.getId());
			Assert.notNull(oldgateway, "InternetGateway不存在!");
			CloudVendor cloudVendor = cloudVendorRepository.query(oldgateway.getVendorId());
			Assert.notNull(cloudVendor, "云平台不存在!");
			InternetGatewayModel model = JSONObject.parseObject(JSONObject.toJSONString(gateway),
					InternetGatewayModel.class);
			BocloudResult bocloudResult = internetGatewayDriver.update(cloudVendor.getUuid(), model,
					gateway.getRegionId());
			if (bocloudResult.isFailed()) {
				return bocloudResult;
			}
			BeanUtils.copyProperties(model, oldgateway);
			oldgateway.setMenderId(context.getTarget());
			internetGatewayRepository.update(oldgateway);
			return new BocloudResult<InternetGateway>(true, "修改成功");
		} catch (Exception e) {
			logger.error("Modify InternetGateway fail:", e);
			return new BocloudResult<InternetGateway>(false, "修改失败", null, null);
		}
	}
}
