package com.bocloud.ims.service.scheduler.scheduler;


import com.bocloud.cmp.driver.common.HeatDriver;
import com.bocloud.cmp.model.HeatStackModel;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.ims.entity.resource.AutoScaling;
import com.bocloud.ims.entity.resource.CloudStack;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.OSTenant;
import com.bocloud.ims.interfaces.resource.CloudStackService;
import com.bocloud.ims.repository.resource.AutoScalingRepository;
import com.bocloud.ims.repository.resource.CloudStackRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.OSTenantRepository;
import com.bocloud.ims.service.resource.AutoScalingServiceImpl;
import com.bocloud.service.core.CurrentService;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * openstack 弹性伸缩 事件资源定时更新
 * 
 * @author ymh
 * @时间 2019年12月18日
 */
@Component
public class AutoScalingAlarmTaskScheduler {

	private static Logger logger = LoggerFactory.getLogger(AutoScalingAlarmTaskScheduler.class);
	@Autowired
	private CurrentService service;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private CloudStackRepository cloudStackRepository;
	@Autowired
	private HeatDriver heatDriver;
	@Autowired
	private CloudStackService cloudStackService;
	@Autowired
	private OSTenantRepository osTenantRepository;
	@Autowired
	private AutoScalingRepository autoScalingRepository;
	@Autowired
	private AutoScalingServiceImpl autoScalingService;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;

	@Scheduled(cron = "${autoscaling.event.schedule:0 0/5 * * * ?}")
	protected void syncStackEvent() throws Exception {
		if (!service.isLeader()) {
			return;
		}
		logger.info("start sync stack event scheduler ... ");
		String type = "OPENSTACK";
		List<CloudVendor> cloudVendors = cloudVendorRepository.listByType(type);
		if (null != cloudVendors && !cloudVendors.isEmpty()) {
			for (CloudVendor cloudVendor : cloudVendors) {
				this.syncStackEvent(cloudVendor);
			}
		}
		logger.info("end sync stack event scheduler ... ");
	}

	private void syncStackEvent(CloudVendor cloudVendor) {
		try {
			List<CloudStack> cloudStacks = cloudStackRepository.listByVendorId(cloudVendor.getId());
			if (null != cloudStacks && !cloudStacks.isEmpty()) {
				for (CloudStack cloudStack : cloudStacks) {
					HeatStackModel heatStackModel = new HeatStackModel();
					heatStackModel.setName(cloudStack.getName());
					heatStackModel.setStackUuid(cloudStack.getStackUuid());
					String projectName = null;
					OSTenant osTenant = osTenantRepository.getByTenantUuid(cloudStack.getTenantUuid(),
							cloudVendor.getId());
					if (null != osTenant) {
						projectName = osTenant.getName();
					}
					BocloudResult bocloudResult = heatDriver.detailStack(heatStackModel, projectName,
							cloudVendor.getUuid(), cloudStack.getRegionId());
					if (bocloudResult.isSuccess()) {
						HeatStackModel stackModel = (HeatStackModel) bocloudResult.getData();
						cloudStackService.syncStackEvent(stackModel, cloudVendor.getId(), cloudStack.getId());
					} else {
						logger.error(cloudStack.getName() + "栈事件同步异常 ： " + bocloudResult.getMessage());
					}
				}
			}
		} catch (Exception e) {
			logger.error("同步{}平台栈事件异常：" + e.getMessage(), cloudVendor.getName());
		}
	}

	@Scheduled(cron = "${autoscaling.resource.schedule:0 0 0/1 * * ?}")
	protected void syncStackServer() throws Exception {
		if (!service.isLeader()) {
			return;
		}
		logger.info("start sync stack server scheduler ... ");
		String type = "OPENSTACK";
		List<CloudVendor> cloudVendors = cloudVendorRepository.listByType(type);
		if (null != cloudVendors && !cloudVendors.isEmpty()) {
			for (CloudVendor cloudVendor : cloudVendors) {
				this.syncStackResource(cloudVendor);
			}
		}
		logger.info("end sync stack server scheduler ... ");
	}

	/**
	 * 定时同步栈资源
	 * 
	 * @param cloudVendor
	 */
	private void syncStackResource(CloudVendor cloudVendor) {
		try {
			List<AutoScaling> autoScalings = autoScalingRepository.listByVendorId(cloudVendor.getId());
			if (null != autoScalings && !autoScalings.isEmpty()) {
				for (AutoScaling autoScaling : autoScalings) {
					String path = AutoScaling.class.getSimpleName() + "_" + autoScaling.getId();
					CloudVendor vendor = cloudVendorRepository.query(autoScaling.getVendorId());
					if (null == vendor) {
						logger.error("定时同步栈资源异常：云平台信息异常！伸缩组名称：" + autoScaling.getName());
						continue;
					}
					CloudStack cloudStack = cloudStackRepository.query(autoScaling.getStackId());
					if (null == cloudStack) {
						logger.error("定时同步栈资源异常：栈信息不存在！伸缩组名称：" + autoScaling.getName());
						continue;
					}
					taskExecutor.submit(new Runnable() {
						@Override
						public void run() {
							try (BocloudACLock lock = lockFactory.getACLock(path)) {
								Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
								String projectName = null;
								OSTenant osTenant = osTenantRepository.getByTenantUuid(cloudStack.getTenantUuid(),
										vendor.getId());
								if (null != osTenant) {
									projectName = osTenant.getName();
								}
								HeatStackModel heatStackModel = new HeatStackModel();
								heatStackModel.setName(cloudStack.getName());
								heatStackModel.setStackUuid(cloudStack.getStackUuid());
								BocloudResult bocloudResult = heatDriver.detailStack(heatStackModel, projectName,
										vendor.getUuid(), null);
								if (bocloudResult.isSuccess()) {
									heatStackModel = (HeatStackModel) bocloudResult.getData();
									BeanUtils.copyProperties(heatStackModel, cloudStack);
									cloudStackRepository.update(cloudStack);
									RequestContext context = new RequestContext();
									context.setTarget(cloudStack.getCreatorId());
									autoScalingService.syncResources(cloudStack, vendor, context);
									if (autoScaling.getUseLb() == null ? false : autoScaling.getUseLb()) {
										autoScalingService.syncLoadBalancer(cloudStack, vendor, context, autoScaling);
									}
								} else {
									logger.error("定时同步栈资源失败：" + bocloudResult.getMessage());
								}
							} catch (Exception e) {
								logger.error("定时同步栈资源失败：" + e.getMessage());
							}
						}
					});
				}
			}
		} catch (Exception e) {
			logger.error("同步{}平台栈资源异常：" + e.getMessage(), cloudVendor.getName());
		}
	}
}
