package com.bocloud.ims.service.resource.kubernetes;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

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 com.alibaba.fastjson.JSON;
import com.bocloud.cmp.driver.kubernetes.PersistentVolumeClaimDriver;
import com.bocloud.cmp.model.kubernetes.PersistentVolumeClaimModel;
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.Sign;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.kubernetes.KubeNamespace;
import com.bocloud.ims.entity.resource.kubernetes.KubePersistentVolume;
import com.bocloud.ims.entity.resource.kubernetes.KubePersistentVolumeClaim;
import com.bocloud.ims.interfaces.resource.kubernetes.KubePersistentVolumeClaimService;
import com.bocloud.ims.repository.kubernetes.KubeNamespaceRepository;
import com.bocloud.ims.repository.kubernetes.KubePersistentVolumeClaimRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
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;

@Service("kubePersistentVolumeClaimService")
public class KubePersistentVolumeClaimServiceImpl implements KubePersistentVolumeClaimService {

	private static final Logger logger = LoggerFactory.getLogger(KubePersistentVolumeClaimServiceImpl.class);
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private KubePersistentVolumeClaimRepository kubePersistentVolumeClaimRepository;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private PersistentVolumeClaimDriver persistentVolumeClaimDriver;
	@Autowired
	private KubeNamespaceRepository kubeNamespaceRepository;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;

	@Override
	public BocloudResult list(Pager pager, RequestContext context) {
		GridBean gridBean = null;
		try {
			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);

			Long tenantId = context.getTenant();
			if (null != tenantId && 0 != tenantId) {
				params.add(new Param(MapTools.simpleMap(Common.TENANTID, tenantId), Sign.EQ));
			}
			int total = this.kubePersistentVolumeClaimRepository.count(params);
			if (simple) {
				List<SimpleBean> beans = this.kubePersistentVolumeClaimRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<KubePersistentVolumeClaim> list = this.kubePersistentVolumeClaimRepository.list(page, rows, params,
						sorter);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BocloudResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query persistent volume list fail:", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult create(KubePersistentVolumeClaim volume, RequestContext context) {
		try {
			Long namespaceId = volume.getNamespaceId();
			KubeNamespace kubeNamespace = kubeNamespaceRepository.query(namespaceId);
			if (null == kubeNamespace) {
				return new BocloudResult(false, "应用管理数据异常！");
			}
			CloudVendor cloudVendor = cloudVendorRepository.query(kubeNamespace.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult(false, "集群信息异常！");
			}
			String labels = volume.getLabels();
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						PersistentVolumeClaimModel model = new PersistentVolumeClaimModel();
						BeanUtils.copyProperties(volume, model);
						model.setLabels(labels);
						model.setNamespace(kubeNamespace.getName());
						BocloudResult bocloudResult = persistentVolumeClaimDriver.create(cloudVendor.getUuid(), model);
						if (bocloudResult.isFailed()) {
							logger.error("创建PVC失败：" + bocloudResult.getMessage());
							resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(),
									"创建PVC失败：" + bocloudResult.getMessage(), "kubernetes.pvc",
									MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()),
									OperateResult.OperateCategory.ResourceEvent, context));

							return;
						}
						PersistentVolumeClaimModel persistentVolumeClaimModel = JSON.parseObject(
								JSON.toJSONString(bocloudResult.getData()), PersistentVolumeClaimModel.class);
						persistentVolumeClaimModel.setStorageClassName(volume.getStorageClassName());
						persistentVolumeClaimModel.setStorageClassType(volume.getStorageClassType());
						BeanUtils.copyProperties(persistentVolumeClaimModel, volume);
						volume.setCreatorId(context.getTarget());
						volume.setMenderId(context.getTarget());
						volume.setTenantId(context.getTenant());
						volume.setVendorId(cloudVendor.getId());
						volume.setAppId(kubeNamespace.getId());
						volume.setAppName(kubeNamespace.getName());
						kubePersistentVolumeClaimRepository.save(volume);
						resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), "创建成功！",
								"kubernetes.pvc", MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
					} catch (Exception e) {
						logger.error("创建PVC失败：" + e.getMessage());
						resourceEventPublisher.send(new OperateResult(false, "创建PVC失败：" + e.getMessage(),
								"kubernetes.pvc", MapTools.simpleMap(Common.VENDORID, cloudVendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
					}

				}
			}).start();
			return new BocloudResult(true, "任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("create persistent volume error", e);
			return new BocloudResult(false, "添加失败");
		}
	}

	@Override
	public BocloudResult modify(KubePersistentVolumeClaim volume, RequestContext context) {
		String path = KubePersistentVolume.class.getSimpleName() + "_" + volume.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			return new BocloudResult(true, "修改成功");
		} catch (Exception e) {
			logger.error("Modify persistent volume fail:", e);
			return new BocloudResult(false, "修改失败");
		}
	}

	@Override
	public BocloudResult remove(Long id, RequestContext context) {
		String path = KubePersistentVolumeClaim.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			KubePersistentVolumeClaim kubePersistentVolumeClaim = kubePersistentVolumeClaimRepository.query(id);
			if (null == kubePersistentVolumeClaim) {
				return new BocloudResult(false, "数据异常！");
			}
			CloudVendor cloudVendor = cloudVendorRepository.query(kubePersistentVolumeClaim.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult(false, "集群数据异常！");
			}
			PersistentVolumeClaimModel model = new PersistentVolumeClaimModel();
			model.setName(kubePersistentVolumeClaim.getName());
			model.setNamespace(kubePersistentVolumeClaim.getNamespace());
			BocloudResult bocloudResult = persistentVolumeClaimDriver.remove(model, cloudVendor.getUuid());
			if (bocloudResult.isFailed()) {
				return bocloudResult;
			}
			kubePersistentVolumeClaimRepository.remove(id, context.getTarget());
			return new BocloudResult(true, "删除成功");
		} catch (Exception e) {
			logger.error("Remove persistent volume error:", e);
			return new BocloudResult(false, "删除失败");
		}
	}

	@Override
	public BocloudResult detail(Long id) {
		try {
			return new BocloudResult(true, null, "查询详情成功");
		} catch (Exception e) {
			logger.error("Get persistent volume error：", e);
			return new BocloudResult(false, "查询详情失败");
		}
	}

}
