package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.GwQosDriver;
import com.bocloud.cmp.model.GwQosModel;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.OperateResult;
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.common.utils.JSONTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.QosPolicy;
import com.bocloud.ims.entity.resource.TenantProvider;
import com.bocloud.ims.interfaces.resource.QosPolicyService;
import com.bocloud.ims.interfaces.resource.VendorProjectService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.QosPolicyRepository;
import com.bocloud.ims.repository.resource.QosPolicyRulesRepository;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
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.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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * qos policy service impl
 * 
 * @author ymh
 * @时间 2019年11月13日
 */
@Service("qosPolicyService")
public class QosPolicyServiceImpl implements QosPolicyService {

	private static Logger logger = LoggerFactory.getLogger(QosPolicyServiceImpl.class);
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private QosPolicyRepository qosPolicyRepository;
	@Autowired
	private GwQosDriver gwQosDriver;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private QosPolicyRulesRepository qosPolicyRulesRepository;
	@Autowired
	private VendorProjectService vendorProjectService;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;

	@Override
	public BocloudResult<GridBean<QosPolicy>> list(Pager pager, RequestContext context) {
		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);
		List<QosPolicy> list = Lists.newArrayList();
		GridBean gridBean = null;
		String tenantUuid = null;
		try {
			for (Param param : params) {
				Map<String, Object> paramMap = param.getParam();
				if (paramMap.containsKey("tenantUuid")) {
					tenantUuid = paramMap.get("tenantUuid").toString();
					paramMap.remove("tenantUuid");
				}
			}
			int total = qosPolicyRepository.count(params, tenantUuid);
			if (simple) {
				List<SimpleBean> beans = qosPolicyRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				list = qosPolicyRepository.list(page, rows, params, sorter, tenantUuid);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BocloudResult<>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list qosPolicy failure:", e);
			return new BocloudResult<>(false, "查询失败", null, null);
		}

	}

	@Override
	public BocloudResult<String> create(QosPolicy qosPolicy, RequestContext context) {
		try {
			CloudVendor cloudVendor = cloudVendorRepository.query(qosPolicy.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "云平台不存在！");
			}
			String projectName = qosPolicy.getOsTenantName();
			TenantProvider provider = vendorProjectService.getAncestorProject(cloudVendor.getId(), context.getTenant());
			if (null != provider) {
				projectName = provider.getProjectName();
			}
			GwQosModel gwQosModel = new GwQosModel();
			BeanUtils.copyProperties(qosPolicy, gwQosModel);
			BocloudResult policyCreate = gwQosDriver.qosPolicyCreate(gwQosModel, projectName, cloudVendor.getUuid());
			if (policyCreate.isSuccess()) {
				GwQosModel model = (GwQosModel) policyCreate.getData();
				QosPolicy policy = new QosPolicy();
				BeanUtils.copyProperties(model, policy);
				policy.setCreatorId(context.getTarget());
				policy.setVendorId(cloudVendor.getId());
				qosPolicyRepository.save(policy);
				return new BocloudResult<>(true, "新建成功！");
			} else {
				return new BocloudResult<>(false, policyCreate.getMessage());
			}
		} catch (Exception e) {
			logger.error("新建失败：" + e.getMessage());
			return new BocloudResult<>(false, "新建失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult<String> modify(QosPolicy qosPolicy, Long userId) {
		String path = QosPolicy.class.getSimpleName() + "_" + qosPolicy.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			QosPolicy policy = qosPolicyRepository.query(qosPolicy.getId());
			if (null == policy) {
				return new BocloudResult<>(false, "QoS Policy不存在！");
			}
			CloudVendor cloudVendor = cloudVendorRepository.query(policy.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "云平台不存在！");
			}
			GwQosModel gwQosModel = new GwQosModel();
			BeanUtils.copyProperties(qosPolicy, gwQosModel);
			gwQosModel.setPolicyUuid(policy.getPolicyUuid());
			BocloudResult policyModify = gwQosDriver.qosPolicyModify(gwQosModel, cloudVendor.getUuid());
			if (policyModify.isSuccess()) {
				GwQosModel model = (GwQosModel) policyModify.getData();
				BeanUtils.copyProperties(model, policy);
				qosPolicyRepository.update(policy);
				return new BocloudResult<>(true, "编辑成功！");
			} else {
				return new BocloudResult<>(false, policyModify.getMessage());
			}
		} catch (Exception e) {
			logger.error("编辑失败：" + e.getMessage());
			return new BocloudResult<>(false, "编辑失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult<String> remove(Long id, RequestContext context) {
		try {
			QosPolicy qosPolicy = qosPolicyRepository.query(id);
			if (null == qosPolicy) {
				return new BocloudResult<>(false, "删除失败");
			}
			CloudVendor cloudVendor = cloudVendorRepository.query(qosPolicy.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "云平台不存在！");
			}
			GwQosModel gwQosModel = new GwQosModel();
			gwQosModel.setPolicyUuid(qosPolicy.getPolicyUuid());
			BocloudResult policyRemove = gwQosDriver.qosPolicyRemove(gwQosModel, cloudVendor.getUuid());
			if (policyRemove.isSuccess()) {
				qosPolicyRepository.remove(id, context.getTarget());
				qosPolicyRulesRepository.remove(qosPolicy.getPolicyUuid(), cloudVendor.getId(), context.getTarget());
				return new BocloudResult<>(true, "删除成功！");
			} else {
				return new BocloudResult<>(false, policyRemove.getMessage());
			}
		} catch (Exception e) {
			logger.error("删除失败：" + e.getMessage());
			return new BocloudResult<>(false, "删除失败：" + e.getMessage());
		}
	}

	/**
	 * 查询可用创建rule的policy
	 * 
	 * @return
	 */
	public BocloudResult<List<QosPolicy>> listPolicysByRule(String params, RequestContext context) {
		try {
			JSONObject jsonObject = JSONTools.isJSONObj(params);
			if (null == jsonObject) {
				return new BocloudResult<>(false, "参数异常");
			}
			Long vendorId = jsonObject.getLong(Common.VENDORID);// 云平台ID
			CloudVendor cloudVendor = cloudVendorRepository.query(vendorId);
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "平台信息错误！");
			}
			List<QosPolicy> qosPolicys = qosPolicyRepository.listPolicysByRule(vendorId);
			return new BocloudResult<>(true, qosPolicys, "查询成功！");
		} catch (Exception e) {
			logger.error("查询失败：" + e.getMessage());
			return new BocloudResult<>(false, "查询失败：" + e.getMessage());
		}
	}

	/**
	 * 查询可用创建rule的policy
	 * 
	 * @return
	 */
	public BocloudResult<List<QosPolicy>> listPolicysByVm(String params, RequestContext context) {
		try {
			JSONObject jsonObject = JSONTools.isJSONObj(params);
			if (null == jsonObject) {
				return new BocloudResult<>(false, "参数异常");
			}
			Long vendorId = jsonObject.getLong(Common.VENDORID);// 云平台ID
			String tenantUuid = jsonObject.getString("tenantUuid");
			CloudVendor cloudVendor = cloudVendorRepository.query(vendorId);
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "平台信息错误！");
			}
			List<QosPolicy> qosPolicys = qosPolicyRepository.listPolicysByVm(vendorId, tenantUuid);
			return new BocloudResult<>(true, qosPolicys, "查询成功！");
		} catch (Exception e) {
			logger.error("查询失败：" + e.getMessage());
			return new BocloudResult<>(false, "查询失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult<QosPolicy> detail(Long id) {
		try {
			QosPolicy qosPolicy = qosPolicyRepository.query(id);
			if (null == qosPolicy) {
				return new BocloudResult<>(false, "数据不存在！");
			}
			return new BocloudResult<>(true, qosPolicy, "success!");
		} catch (Exception e) {
			logger.error("查询失败：" + e.getMessage());
			return new BocloudResult<>(false, "查询失败：" + e.getMessage());
		}
	}

	@Override
	public BocloudResult<String> batchRemove(List<Long> idArray, RequestContext context) {
		try {
			if (ListTool.isEmpty(idArray)) {
				return new BocloudResult<>(false, "数据不存在！");
			}
			QosPolicy qosPolicy = qosPolicyRepository.query(idArray.get(0));
			CloudVendor cloudVendor = cloudVendorRepository.query(qosPolicy.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "平台数据错误！");
			}
			new Thread(new Runnable() {
				@Override
				public void run() {
					String operate = cloudVendor.getType().toLowerCase() + ".stack";
					String content = "批量删除任务失败";
					try {
						List<BocloudResult> success = new ArrayList<BocloudResult>();
						List<BocloudResult> fail = new ArrayList<BocloudResult>();
						for (Long id : idArray) {
							QosPolicy qosPolicy = qosPolicyRepository.query(id);
							if (null == qosPolicy) {
								continue;
							}
							BocloudResult bocloudResult = remove(id, context);
							if (bocloudResult.isSuccess()) {
								success.add(bocloudResult);
							} else {
								fail.add(bocloudResult);
							}
						}
						if (idArray.size() == success.size()) {
							content = "批量删除任务成功！";
						}
						if (fail.size() > 0) {
							content += " : ";
							for (BocloudResult result : fail) {
								content += result.getMessage() + "/n";
							}
						}
						resourceEventPublisher.send(new OperateResult(true, content, operate,
								MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
					} catch (Exception e) {
						logger.error("批量删除失败：" + e.getMessage());
						resourceEventPublisher.send(new OperateResult(false, "批量删除失败：" + e.getMessage(), operate,
								MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
					}
				}
			}).start();
		} catch (Exception e) {
			logger.error("batch action server fail:", e);
			return new BocloudResult<>(false, "批量任务下发失败");
		}
		return new BocloudResult<>(true, "批量删除任务已下发，正在执行...");
	}

	@Override
	public BocloudResult<List<QosPolicy>> condition(String condition, RequestContext context) {
		condition = Optional.ofNullable(condition).orElse("");
		JSONObject object = JSONObject.parseObject(condition);
		String action = object.getString("condition");
		if ("listPolicysByRule".equalsIgnoreCase(action)) {
			return listPolicysByRule(condition, context);
		}
		if ("listPolicysByVm".equalsIgnoreCase(action)) {
			return listPolicysByVm(condition, context);
		}
		return new BocloudResult<>(false, "参数格式错误");
	}

}
