package com.bocloud.ims.service.apply;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.common.*;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.interfaces.apply.ResourceOperationService;
import com.bocloud.ims.interfaces.resource.*;
import com.bocloud.nms.enums.OrderItemStatus;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 资源申请处理服务实现类
 */
@Service("resourceOperationService")
public class ResourceOperationServiceImpl implements ResourceOperationService {
	private static Logger logger = LoggerFactory.getLogger(ResourceOperationServiceImpl.class);
	@Autowired
	private AmqpTemplate amqpTemplate;
	@Autowired
	private VpcService vpcService;
	@Autowired
	private VMApplyService vmApplyService;
	@Autowired
	private VolumeService volumeService;
	@Autowired
	private FloatingIpService floatingIpService;
	@Autowired
	private LoadBalancerService loadBalancerService;

	/**
	 * 通知order 修改对应订单状态
	 * 
	 * @param uuid
	 * @param operation
	 * @param message
	 * @param status
	 * @param context
	 * @param newSn
	 */
	private void syncOrderStatus(String uuid, OrderMessage.Operation operation, String message, OrderItemStatus status,
			RequestContext context, String newSn, List<QuotaBean> quotas, String category) {
		OrderMessage orderMessage = new OrderMessage(uuid, operation, status, null, message, null, null,
				new ArrayList<>(), category, context);
		orderMessage.setNewSn(newSn);
		orderMessage.setQuotas(quotas);
		amqpTemplate.convertAndSend("resource.result.queue", orderMessage);
	}

	@Override
	public Result process(ResourceCategory category, JSONObject param, OrderMessage.Operation operation) {
		RequestContext context = JSONObject.parseObject(param.getString(Common.CONTEXT), RequestContext.class);
		Result result = null;
		switch (operation) {
		case Application:
			result = application(category, param, context, operation);
			break;
		case Upgrade:
		case ScaleIn:
		case ScaleOut:
			result = alteration(category, param, context, operation);
			break;
		case Extension:
			result = extension(category, param, context, operation);
			break;
		case Cancelation:
			result = cancelation(category, param, context, operation);
			break;
		default:
			result = new Result(false, "暂不支持资源的其他类型操作");
			break;
		}
		return result;
	}

	/**
	 * 服务申请
	 * 
	 * @param category
	 * @param param
	 * @param context
	 * @param operation
	 * @return
	 */
	private Result application(ResourceCategory category, JSONObject param, RequestContext context,
			OrderMessage.Operation operation) {
		BocloudResult result = null;
		try {
			switch (category) {
			case Vpc:
				result = vpcService.apply(JSONObject.parseObject(param.toJSONString(), ApplicationParam.class));
				break;
			case Computer:
				result = vmApplyService.apply(JSONObject.parseObject(param.toJSONString(), ApplicationParam.class));
				break;
			case Storage:
				result = volumeService.apply(JSONObject.parseObject(param.toJSONString(), ApplicationParam.class));
				break;
			case FloatingIp:
				result = floatingIpService.apply(JSONObject.parseObject(param.toJSONString(), ApplicationParam.class));
				break;
			case LoadBalance:
				result = loadBalancerService.apply(JSONObject.parseObject(param.toJSONString(), ApplicationParam.class));
				break;
			default:
				result = new BocloudResult(false, "暂不支持该类型资源申请");
				break;
			}
			if (result.isFailed()) {
				ApplicationParam aplicaiton = JSONObject.parseObject(param.toJSONString(), ApplicationParam.class);
				if (!StringUtils.isEmpty(aplicaiton.getCallback())) {
					amqpTemplate.convertAndSend(aplicaiton.getCallback(), JSONObject.toJSON(result));
				}
				ServiceOrder order = aplicaiton.getOrder();
				List<OrderItem> items = order.getItems();
				List<QuotaBean> quotas = aplicaiton.getQuotas() == null ? new ArrayList<>() : aplicaiton.getQuotas();
				List<QuotaBean> beans = new ArrayList<>();
				for (QuotaBean bean : quotas) {
					beans.add(new QuotaBean(bean.getCode(), bean.getValue() / items.size()));
				}
				List<OrderItem> lastOrderItems = JSONObject.parseArray(JSONObject.toJSONString(result.getData()), OrderItem.class);
				if(!ListTool.isEmpty(lastOrderItems)) {
					items = lastOrderItems;
				}
				for (OrderItem item : items) {
					// 通知订单修改订单状态
					syncOrderStatus(item.getSn(), operation, result.getMessage(), OrderItemStatus.OpenedFailure,
							context, null, beans, category.name());
				}
				return result;
			}
			return new BocloudResult(true, "资源申请处理成功");
		} catch (Exception e) {
			logger.error("Get error message:", e);
			ApplicationParam aplicaiton = JSONObject.parseObject(param.toJSONString(), ApplicationParam.class);
			if (!StringUtils.isEmpty(aplicaiton.getCallback())) {
				amqpTemplate.convertAndSend(aplicaiton.getCallback(),
						JSONObject.toJSON(new BocloudResult(false, "资源申请处理失败：" + e.getMessage())));
			}
			return new BocloudResult(false, "资源申请处理失败！");
		}
	}

	/**
	 * 服务变更
	 * 
	 * @param category
	 * @param param
	 * @param context
	 * @param operation
	 * @return
	 */
	private Result alteration(ResourceCategory category, JSONObject param, RequestContext context,
			OrderMessage.Operation operation) {
		AlterationParam alteration = JSONObject.parseObject(param.toJSONString(), AlterationParam.class);
		BocloudResult result = null;
		try {
			switch (category) {
			case Computer:
				result = vmApplyService.alteration(alteration);
				break;
			case Storage:
				result = volumeService.alteration(alteration);
				break;
			default:
				result = new BocloudResult(false, "暂不支持该类型资源变更");
				break;
			}
			if (null != result && result.isFailed()) {
				// 通知订单修改订单状态
				syncOrderStatus(alteration.getInstance(), operation, result.getMessage(), OrderItemStatus.ChangeFailure,
						context, alteration.getNewInstance(), alteration.getQuotas(), category.name());
				return result;
			}
			return new BocloudResult(true, "资源变更成功处理成功");
		} catch (Exception e) {
			logger.error("Get error message:", e);
			return new BocloudResult(false, "资源变更处理失败！");
		}
	}

	/**
	 * 服务延期
	 * 
	 * @param category
	 * @param param
	 * @param context
	 * @param operation
	 * @return
	 */
	private Result extension(ResourceCategory category, JSONObject param, RequestContext context,
			OrderMessage.Operation operation) {
		BocloudResult result = null;
		ExtensionParam extension = JSONObject.parseObject(param.toJSONString(), ExtensionParam.class);
		try {
			switch (category) {
			case Vpc:
				result = vpcService.extension(JSONObject.parseObject(param.toJSONString(), ExtensionParam.class));
				break;
			case Computer:
				result = vmApplyService.extension(JSONObject.parseObject(param.toJSONString(), ExtensionParam.class));
				break;
			case Storage:
				result = volumeService.extension(JSONObject.parseObject(param.toJSONString(), ExtensionParam.class));
				break;
			case LoadBalance:
				result = loadBalancerService.extension(JSONObject.parseObject(param.toJSONString(), ExtensionParam.class));
				break;
			case FloatingIp:
				result = floatingIpService.extension(JSONObject.parseObject(param.toJSONString(), ExtensionParam.class));
				break;
			default:
				result = new BocloudResult(false, "暂不支持该类型资源延期");
			}
			if (null != result && result.isFailed()) {
				// 通知订单修改订单状态
				syncOrderStatus(extension.getInstance(), operation, result.getMessage(),
						OrderItemStatus.ExtensionFailure, context, null, null, category.name());
				// 通知订单修改订单状态
				return result;
			}
			return new BocloudResult(true, "资源变更成功处理成功");
		} catch (Exception e) {
			logger.error("Get error message:", e);
			return new BocloudResult(false, "资源变更处理失败！");
		}

	}

	/**
	 * 服务退订
	 * 
	 * @param category
	 * @param param
	 * @param context
	 * @param operation
	 * @return
	 */
	private Result cancelation(ResourceCategory category, JSONObject param, RequestContext context,
			OrderMessage.Operation operation) {
		BocloudResult result = null;
		CancelationParam cancelation = JSONObject.parseObject(param.toJSONString(), CancelationParam.class);
		try {
			switch (category) {
			case Vpc:
				result = vpcService.cancelation(cancelation);
				break;
			case Computer:
				result = vmApplyService.cancelation(cancelation);
				break;
			case Storage:
				result = volumeService.cancelation(cancelation);
				break;
			case FloatingIp:
				result = floatingIpService.cancelation(cancelation);
				break;
			case LoadBalance:
				result = loadBalancerService.cancelation(cancelation);
				break;
			default:
				result = new BocloudResult(false, "暂不支持该类型资源退订");
				break;
			}
			if (null != result && result.isFailed()) {
				// 通知订单修改订单状态
				syncOrderStatus(cancelation.getInstance(), operation, result.getMessage(), OrderItemStatus.UnsubscribeFailure,
						context, null, null, category.name());
				return result;
			}
			return new BocloudResult(true, "资源退订处理成功");
		} catch (Exception e) {
			logger.error("Get error message:", e);
			return new BocloudResult(false, "资源退订处理失败！");
		}
	}

}
