package com.bocloud.ims.service.builder;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.hmc.HmcPartitionDriver;
import com.bocloud.cmp.driver.hmc.HmcProfileDriver;
import com.bocloud.cmp.driver.hmc.HmcServerDriver;
import com.bocloud.cmp.entity.enums.AlarmLevel;
import com.bocloud.cmp.model.hmc.HmcPartitionModel;
import com.bocloud.cmp.model.hmc.sdk.module.LogicalPartition;
import com.bocloud.cmp.model.hmc.sdk.module.LogicalPartitionEntry;
import com.bocloud.cmp.model.hmc.sdk.module.LogicalPartitionProfileEntry;
import com.bocloud.cmp.model.hmc.sdk.module.LogicalPartitionProfileResponse;
import com.bocloud.cmp.model.hmc.sdk.module.ManagedSystem;
import com.bocloud.cmp.model.hmc.sdk.module.ManagedSystemEntry;
import com.bocloud.cmp.model.hmc.sdk.module.VirtualIOServer;
import com.bocloud.cmp.model.hmc.sdk.module.VirtualIOServerEntry;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.ServerAction;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ResourceAlarm;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.hmc.HmcPartition;
import com.bocloud.ims.entity.resource.hmc.HmcServer;
import com.bocloud.ims.entity.resource.hmc.HmcSystemSharedProcessorPool;
import com.bocloud.ims.interfaces.resource.hmc.HmcPartitionService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ResourceAlarmRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.hmc.HmcServerRepository;
import com.bocloud.ims.repository.resource.hmc.HmcSystemSharedProcessorPoolRepository;
import com.bocloud.ims.service.resource.hmc.HmcDatabaseHelper;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service("hmcServerBuilder")
public class HmcServerBuilder {

	private static Logger logger = LoggerFactory.getLogger(HmcServerBuilder.class);
	private static OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;

	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private HmcServerRepository hmcServerRepository;
	@Autowired
	private ResourceAlarmRepository alarmRepository;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;
	@Autowired
	private HmcDatabaseHelper hmcDatabaseHelper;
	@Autowired
	private HmcPartitionService hmcPartitionService;
	@Autowired
	private ResourceEventRepository resourceEventRepository;
	@Autowired
	private HmcPartitionDriver hmcPartitionDriver;
	@Autowired
	private HmcProfileDriver hmcProfileDriver;
	@Autowired
	private HmcServerDriver serverDriver;
	@Autowired
	private HmcSystemSharedProcessorPoolRepository sharedProcessorPoolRepository;

	public BocloudResult<HmcPartition> prepare(HmcPartition par, CloudVendor vendor, RequestContext context) {
		try {

			// 设置这个概要文件是默认概要文件
			if (null != par.getHmcLparProfile()) {
				par.getHmcLparProfile().setIsDefaultProfile(true);
			}

			// 保存分区信息到DB
			par.setStatus("PARTITION_CREATING");
			par.setTenantId(context.getTenant());
			// 查询分区使用的共享存储池hmc端的id
			if (par.getHmcLparProfile().getSharedProPoolId() != null) {
				// 如果是使用系统所有资源创建，则共享处理器池的id是空的，所以需要增加上面的非空判断
				HmcSystemSharedProcessorPool sharedProcessorPool = sharedProcessorPoolRepository
						.getById(par.getHmcLparProfile().getSharedProPoolId());
				par.getHmcLparProfile().setSharedProPoolId(Long.valueOf(sharedProcessorPool.getHmcPoolId()));
			}
			hmcDatabaseHelper.savePartition(par, context.getTarget());
			return new BocloudResult<HmcPartition>(true, par, "");
		} catch (Exception e) {
			logger.error("create server error:", e);
			return new BocloudResult<>(false, "创建失败!");
		}
	}

	public void builder(Long vendorId, HmcPartition lpar, RequestContext context) {
		String operate = "hmc.partition";
		String content = "分区[" + lpar.getName() + "]创建失败";
		try {
			ResourceEvent event = null;
			Boolean isVios = false;
			if ("Virtual IO Server".equals(lpar.getPartitionType())) {
				isVios = true;
			}
			BocloudResult result = create(vendorId, lpar, isVios);
			if (result.isSuccess()) {
				// update database for the new partition
				LogicalPartition logicalPartition = null;
				VirtualIOServer virtualIOServer = null;
				String parUuid = null;
				if (isVios) {
					VirtualIOServerEntry entry = (VirtualIOServerEntry) result.getData();
					parUuid = entry.getId();
					virtualIOServer = entry.getContent().getVirtualIOServer();
				} else {
					LogicalPartitionEntry entry = (LogicalPartitionEntry) result.getData();
					parUuid = entry.getId();
					logicalPartition = entry.getContent().getLogicalPartition();
				}
				// 获取分区概要文件
				LogicalPartitionProfileEntry profileEntry = null;
				BocloudResult profileResult = getPartitionProfile(vendorId, parUuid, isVios);
				if (profileResult.isSuccess()) {
					LogicalPartitionProfileResponse response = (LogicalPartitionProfileResponse) profileResult
							.getData();
					profileEntry = response.getEntries().get(0);
				}
				if (isVios) {
					hmcDatabaseHelper.updatePartition(lpar, virtualIOServer, profileEntry, false, context.getTarget());
					hmcPartitionService.updateVirtualScsiAdapterForVios(lpar, virtualIOServer.getVirtualSCSIMappings());
				} else {
					hmcDatabaseHelper.updatePartition(lpar, logicalPartition, profileEntry, false, context.getTarget());
					hmcPartitionService.updateVirtualScsiAdapterForLpar(lpar, vendorId);
				}
				// 如果服务器是待机状态，在添加了新的分区后，它的状态会更新为正在运行
				HmcServer server = hmcServerRepository.getServerById(lpar.getServerId());
				if ("standby".equals(server.getStatus())) {
					CloudVendor vendor = cloudVendorRepository.query(vendorId);
					String vendorUuid = vendor.getUuid();

					BocloudResult serverResult = serverDriver.queryManagedSystemAttribute(vendorUuid, server.getUuid());
					ManagedSystemEntry entry = (ManagedSystemEntry) serverResult.getData();
					ManagedSystem managedSystem = entry.getContent().getManagedSystem();
					server.setStatus(managedSystem.getState());
					server.setReferenceCode(managedSystem.getMergedReferenceCode().getValue());
					hmcServerRepository.update(server);
				}
				// 同步更新CloudServer表
				hmcPartitionService.updateCloudServerByHmcPartition(lpar.getId(), context.getTarget());
				content = "分区[" + lpar.getName() + "]创建成功，\n详情：[" + result.getMessage() + "]";
			} else {
				hmcDatabaseHelper.removePartition(lpar.getId(), context.getTarget());
				content = "分区[" + lpar.getName() + "]创建失败，\n详情：[" + result.getMessage() + "]";
				saveAlarm(lpar.getId(), lpar.getName());
			}

			if (result.isSuccess()) {
				event = new ResourceEvent(lpar.getId(), ServerAction.CREATE.name(), "成功", context.getTarget(),
						new Date(), "HMC", vendorId, context.getCatalog());
			} else {
				event = new ResourceEvent(lpar.getId(), ServerAction.CREATE.name(), "失败", context.getTarget(),
						new Date(), "HMC", vendorId, context.getCatalog());
			}
			resourceEventRepository.save(event);
			resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
					MapTools.simpleMap("vendorId", vendorId), operateCategory, context));
		} catch (Exception e) {
			logger.error("Get Message Exception:", e);
			resourceEventPublisher.send(new OperateResult(false, content, operate,
					MapTools.simpleMap("vendorId", vendorId), operateCategory, context));
		}
	}

	/**
	 * 保存告警
	 *
	 * @param name
	 * @throws Exception
	 */
	private void saveAlarm(Long id, String name) throws Exception {
		// 创建告警
		ResourceAlarm alarm = new ResourceAlarm(AlarmLevel.WARN.name(), "VM", id, null, new Date(), true, false,
				"虚拟机模板不存在");
		alarm.setCreatorId(1L);
		alarm.setGmtCreate(new Date());
		alarm.setStatus("UNCONFIRMED");
		alarm.setDeleted(false);
		alarm.setName("分区[" + name + "]创建失败");
		alarm.setTargetName(name);
		alarmRepository.save(alarm);
	}

	private BocloudResult create(Long vendorId, HmcPartition par, Boolean isVios) throws Exception {
		CloudVendor vendor = cloudVendorRepository.query(vendorId);
		String vendorUuid = vendor.getUuid();

		String managedSystemUuid = par.getServerUuid();
		if (isVios) {
			return hmcPartitionDriver.createVirtualIOServer(vendorUuid, managedSystemUuid,
					JSONObject.parseObject(JSONObject.toJSONString(par), HmcPartitionModel.class));
		} else {
			return hmcPartitionDriver.createLogicalPartition(vendorUuid, managedSystemUuid,
					JSONObject.parseObject(JSONObject.toJSONString(par), HmcPartitionModel.class));
		}
	}

	private BocloudResult getPartitionProfile(Long vendorId, String parUuid, Boolean isVios) throws Exception {
		CloudVendor vendor = cloudVendorRepository.query(vendorId);
		BocloudResult result = hmcProfileDriver.getProfile(vendor.getUuid(), isVios, parUuid);
		return result;
	}
}
