package com.bocloud.ims.service.resource;

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

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 com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.loadbalance.LbDriver;
import com.bocloud.cmp.model.HealthMonitorModel;
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.SimpleBean;
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.HealthMonitor;
import com.bocloud.ims.interfaces.resource.HealthMonitorService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.HealthMonitorRepository;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;

/**
 * 负载均衡器健康检查service实现
 *
 * @author wangyu
 * @version 1.0
 * @since 2017年9月4日
 */
@Service("healthMonitorService")
public class HealthMonitorServiceImpl implements HealthMonitorService {

	private static Logger logger = LoggerFactory.getLogger(HealthMonitorServiceImpl.class);
	@Autowired
	private HealthMonitorRepository healthMonitorRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private LbDriver lbDriver;
	@Autowired
	private LockFactory lockFactory;

	@Override
	public BocloudResult list(Pager pager, RequestContext context) {
		GridBean gridBean = null;
		List<SimpleBean> beans = 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);
			int total = healthMonitorRepository.count(params);
			if (simple) {
				beans = healthMonitorRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<HealthMonitor> list = healthMonitorRepository.list(page, rows, params, sorter);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BocloudResult<>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list lb member failure:", e);
			return new BocloudResult<>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<HealthMonitor> create(HealthMonitor healthMonitor, RequestContext context, Long vendorId) {
		try {
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			if (null == vendor) {
				return new BocloudResult<>(false, "云平台不存在");
			}
			HealthMonitorModel hmModel = new HealthMonitorModel();
			BeanUtils.copyProperties(healthMonitor, hmModel);
			BocloudResult bocloudResult = lbDriver.createHealMonitor(vendor.getUuid(), null, hmModel);
			if (bocloudResult.isFailed()) {
				return new BocloudResult<>(false, bocloudResult.getMessage());
			}
			hmModel = JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()),
					HealthMonitorModel.class);
			BeanUtils.copyProperties(hmModel, healthMonitor);
			healthMonitor.setOwnerId(1L);
			healthMonitor.setCreatorId(context.getTarget());
			healthMonitor.setTenantId(context.getTenant());
			healthMonitor.setProjectId(context.getProject());
			healthMonitorRepository.save(healthMonitor);
			return new BocloudResult<HealthMonitor>(true, "创建成功");
		} catch (Exception e) {
			logger.error("create health monitor fail:", e);
			return new BocloudResult<HealthMonitor>(false, "创建失败");
		}
	}

	@Override
	public BocloudResult<HealthMonitor> modify(HealthMonitor healthMonitor, Long userId, Long vendorId) {
		String path = HealthMonitor.class.getSimpleName() + "_" + healthMonitor.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			if (null == vendor) {
				return new BocloudResult<HealthMonitor>(false, "云平台不存在");
			}
			HealthMonitor monitor = healthMonitorRepository.query(healthMonitor.getId());
			if (null == monitor) {
				return new BocloudResult<HealthMonitor>(false, "数据不存在");
			}
			HealthMonitorModel hmModel = new HealthMonitorModel();
			BeanUtils.copyProperties(healthMonitor, hmModel);
			BocloudResult bocloudResult = lbDriver.updateHealMonitor(vendor.getUuid(), null, hmModel);
			if (bocloudResult.isFailed()) {
				return new BocloudResult<HealthMonitor>(false, bocloudResult.getMessage());
			}
			hmModel = JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()),
					HealthMonitorModel.class);
			BeanUtils.copyProperties(hmModel, healthMonitor);
			healthMonitor.setMenderId(userId);
			healthMonitorRepository.update(healthMonitor);
			return new BocloudResult<HealthMonitor>(true, healthMonitor, "修改成功");
		} catch (Exception e) {
			logger.error("update health monitor fail:", e);
			return new BocloudResult<HealthMonitor>(false, "修改失败");
		}
	}

	@Override
	public BocloudResult<HealthMonitor> detail(Long id) {
		try {
			HealthMonitor healthMonitor = healthMonitorRepository.query(id);
			return new BocloudResult<HealthMonitor>(true, healthMonitor, "查询成功");
		} catch (Exception e) {
			logger.error("query health monitor fail:", e);
			return new BocloudResult<HealthMonitor>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult remove(Long id, Long userId) {
		String path = HealthMonitor.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			HealthMonitor monitor = healthMonitorRepository.query(id);
			if (null == monitor) {
				return new BocloudResult<>(false, "数据不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(monitor.getVendorId());
			if (null == vendor) {
				return new BocloudResult<>(false, "云平台不存在");
			}
			BocloudResult bocloudResult = lbDriver.removeHealMonitor(vendor.getUuid(), null, monitor.getHealthUuid());
			if (bocloudResult.isFailed()) {
				return new BocloudResult<>(false, bocloudResult.getMessage());
			}
			// 删除本地成员记录
			healthMonitorRepository.remove(id, userId);
			return new BocloudResult<>(true, "删除成功");
		} catch (Exception e) {
			logger.error("remove health monitor fail:", e);
			return new BocloudResult<>(false, "删除失败");
		}
	}

}
