package com.bocloud.ims.service.builder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.common.enums.ResourceCatalog;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Flavor;
import com.bocloud.ims.entity.resource.Image;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.FlavorRepository;
import com.bocloud.ims.repository.resource.ImageRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import com.bocloud.ims.repository.resource.SecurityGroupRepository;
import com.bocloud.ims.repository.resource.ServerSgroupRepository;
import com.bocloud.ims.repository.resource.VolumeRepository;
import org.apache.commons.lang.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * 京东云虚拟机创建
 *
 * @author wangyu
 * @version 1.0
 * @since 2018年1月25日
 */
public class JcloudServerBuilder implements ServerBuilder {

	private CloudServerRepository cloudServerRepository;
	private ResourceRepository resourceRepository;
	private ResourceEventRepository resourceEventRepository;
	private ImageRepository imageRepository;
	private FlavorRepository flavorRepository;
	private ServerDriver serverDriver;
	private RequestContext context;
	private CloudVendor vendor;
	private ServerModel model;
	private VolumeRepository volumeRepository;

	/**
	 * @param cloudServerRepository
	 * @param resourceRepository
	 * @param resourceEventRepository
	 * @param imageRepository
	 * @param flavorRepository
	 * @param serverDriver
	 * @param context
	 * @param vendor
	 */
	public JcloudServerBuilder(CloudServerRepository cloudServerRepository, ResourceRepository resourceRepository,
			ResourceEventRepository resourceEventRepository, ImageRepository imageRepository,
			FlavorRepository flavorRepository, ServerDriver serverDriver, RequestContext context, CloudVendor vendor,
			SecurityGroupRepository securityGroupRepository, ServerSgroupRepository serverSgroupRepository,
			VolumeRepository volumeRepository) {
		super();
		this.cloudServerRepository = cloudServerRepository;
		this.resourceRepository = resourceRepository;
		this.resourceEventRepository = resourceEventRepository;
		this.imageRepository = imageRepository;
		this.flavorRepository = flavorRepository;
		this.serverDriver = serverDriver;
		this.context = context;
		this.vendor = vendor;
		this.volumeRepository = volumeRepository;
	}

	@Override
	public BocloudResult<ServerModel> prepare(JSONObject object) throws Exception {
		model = new ServerModel();
		// 虚拟机实例类型
		String instanceType = object.getString("instanceType");
		// 镜像
		Long imageId = object.getLong("imageId");
		// 虚拟机名称
		String name = object.getString("name");
		// 子网ID
		String subnetId = object.getString("subnetId");
		String zone = object.getString("zone");
		// 数据盘
		String dataDisks = object.getString("diskDevices");
		if (!StringUtils.isEmpty(dataDisks)) {
			List<VolumeModel> volumeModels = JSONArray.parseArray(dataDisks, VolumeModel.class);
			if (ListTool.isEmpty(volumeModels)) {
				return new BocloudResult<>(false, "参数格式不正确");
			}
			model.setDiskDevices(volumeModels);
		}
		if (StringUtils.isEmpty(instanceType) || null == imageId || 0L == imageId || StringUtils.isEmpty(name)
				|| StringUtils.isEmpty(subnetId)) {
			return new BocloudResult<>(false, "参数格式不正确");
		}
		Image image = imageRepository.query(imageId);
		if (null == image) {
			return new BocloudResult<>(false, "镜像不存在");
		}
		if (null == zone || "".equals(zone)) {
			zone = object.getString("zoneId");
		}
		model.setZone(zone);
		model.setName(name);
		model.setImageUuid(image.getImageUuid());
		model.setSubnetUuid(subnetId);
		Flavor flavor = flavorRepository.getByName(instanceType);
		if (null == flavor) {
			return new BocloudResult<>(false, "虚拟机实例类型不存在");
		}
		model.setInstanceType(instanceType);
		model.setCpu(flavor.getCpu());
		model.setMemory(flavor.getMemory());
		return new BocloudResult<>(true, model, "success");
	}

	@Override
	public BocloudResult<CloudServer> builder(CloudServer server) throws Exception {
		// 创建虚拟机
		BocloudResult result = serverDriver.create(vendor.getUuid(), null, model);
		// 操作记录
		Long userId = context.getTarget();
		String handler = "虚拟机创建";
		ResourceEvent event = null;
		if (result.isSuccess()) {
			event = new ResourceEvent(server.getId(), handler, "成功", userId, new Date(), "VM", vendor.getId(),
					context.getCatalog());
			String content = JSONObject.toJSONString(result.getData());
			ServerModel serverModel = JSONObject.parseObject(content, ServerModel.class);
			server.setInstanceId(serverModel.getInstanceId());
			server.setDisk(serverModel.getDisk());
			server.setManagerIp(serverModel.getManagerIp());
			server.setPublicIps(serverModel.getPublicIps());
			server.setPrivateIps(serverModel.getPrivateIps());
			server.setImageUuid(serverModel.getImageUuid());
			server.setPublicIps(serverModel.getPublicIps());
			server.setFlavorUuid(serverModel.getFlavorUuid());
			server.setZone(serverModel.getZone());
			server.setRemark(serverModel.getRemark());
			server.setKeypairName(serverModel.getKeypairName());
			server.setSubnetUuid(serverModel.getSubnetUuid());
			server.setSystemDiskCategory(serverModel.getSystemDiskCategory());
			server.setSystemDiskSize(serverModel.getSystemDiskSize());
			server.setRegionId(serverModel.getRegionId());
			String state = serverModel.getStatus();
			if ("running".equalsIgnoreCase(state)) {
				server.setStatus(BocloudStatus.Server.RUNNING.name());
			} else if ("stopped".equalsIgnoreCase(state)) {
				server.setStatus(BocloudStatus.Server.STOPPED.name());
			}
			Image image = imageRepository.getByImageUuid(server.getImageUuid());
			if (null != image) {
				server.setOsCategory(image.getOsCategory());
				server.setOsName(image.getOsName());
				server.setOsVersion(image.getOsVersion());
			}
			server.setRecycle(false);
			cloudServerRepository.update(server);

			List<VolumeModel> volumeList = JSON.parseArray(JSON.toJSONString(serverModel.getDiskDevices()),
					VolumeModel.class);
			if (!ListTool.isEmpty(volumeList)) {
				Volume volume = null;
				for (VolumeModel volumeModel : volumeList) {
					volume = new Volume();
					org.springframework.beans.BeanUtils.copyProperties(volumeModel, volume);
					volume.setCreatorId(userId);
					volume.setGmtCreate(new Date());
					volume.setStatus("IN_USE"); // /dev/sda
					volume.setVendorId(vendor.getId());
					volume.setDevice("/dev/" + volumeModel.getDeviceName());
					volume.setVendorType(vendor.getType());
					volume.setTenantId(server.getTenantId() == null ? 0L : server.getTenantId());
					Long projectId = server.getProjectId();
					if (null != projectId && projectId > 0) {
						volume.setProjectId(projectId);
					}
					volume.setRegionId(server.getRegionId());
					volume.setServerId(server.getId());
					volumeRepository.save(volume);
				}
			}
			List<Volume> listByServerId = volumeRepository.listByServerId(server.getId());
			if (null != listByServerId && listByServerId.size() > 0) {
				server.setDiskDevices(listByServerId);
			}

			// 保存资源
			Resource resource = resourceRepository.query(ResourceCategory.Computer.name(),
					ResourceCatalog.LOGICAL.name(), server.getId());
			if (null == resource) {
				resource = new Resource(ResourceCategory.Computer.name(), ResourceCatalog.LOGICAL.name(),
						server.getId(), server.getPrivateIps(), server.getOsCategory(), vendor.getId());
				resource.preSave(server.getName(), server.getStatus(), userId, context.getTenant(),
						context.getProject());
				resource.setInventory(JSONObject.toJSONString(server));
				resource.setAccurated(false);
				resource.setAuthed(false);
				resourceRepository.save(resource);
			} else {
				resource.setInventory(JSONObject.toJSONString(server));
				resource.setStatus(server.getStatus());
				resource.setMenderId(userId);
				resource.setCreatorId(userId);
				resource.setGmtModify(new Date());
				resource.setGmtCreate(new Date());
				resource.setPrivateIps(server.getPrivateIps());
				resource.setAccurated(false);
				resource.setAuthed(false);
				resourceRepository.update(resource);
			}
		} else {
			event = new ResourceEvent(server.getId(), handler, "失败", userId, new Date(), "VM", vendor.getId(),
					context.getCatalog());
			cloudServerRepository.remove(server.getId(), userId);
		}
		resourceEventRepository.save(event);
		return result.isSuccess() ? new BocloudResult<>(true, server, "success")
				: new BocloudResult<>(false, server, result.getMessage());
	}

}
