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

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.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.bocloud.cmp.driver.storage.StoragePoolDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.model.DataStoreModel;
import com.bocloud.cmp.model.h3c.H3cStoragePoolModel;
import com.bocloud.cmp.model.h3c.H3cVolumeModel;
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.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.DataStore;
import com.bocloud.ims.entity.resource.DataStoreFile;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.StoreHost;
import com.bocloud.ims.interfaces.h3c.H3cDataStoreService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.DataStoreFileRepository;
import com.bocloud.ims.repository.resource.DataStoreRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.repository.resource.StoreHostRepository;
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("h3cStorageService")
public class H3cDataStoreServiceImpl implements H3cDataStoreService {

	private static final Logger logger = LoggerFactory.getLogger(H3cDataStoreServiceImpl.class);

	@Autowired
	DataStoreRepository dataStoreRepository;

	@Autowired
	StoreHostRepository storeHostRepository;

	@Autowired
	DataStoreFileRepository dataStoreFileRepository;

	@Autowired
	CloudVendorRepository cloudVendorRepository;

	@Autowired
	StoragePoolDriver storagePoolDriver;

	@Autowired
	private VolumeDriver volumeDriver;

	@Autowired
	private ResourceEventPublisher resourceEventPublisher;

	@Autowired
	private ServerRepository serverRepository;
	@Autowired
	private LockFactory lockFactory;

	@Override
	public BocloudResult<List<DataStore>> listStores(Long hostId) {
		List<DataStore> dataStores = null;
		try {
			dataStores = dataStoreRepository.listByHost(hostId);
			return new BocloudResult<List<DataStore>>(true, dataStores, "查询成功");
		} catch (Exception e) {
			logger.error("查询失败", e);
			return new BocloudResult<List<DataStore>>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<List<DataStoreFile>> listStoreFiles(Long storeId) {
		List<DataStoreFile> storeFiles = null;
		try {
			storeFiles = dataStoreFileRepository.listByDataStore(storeId);
			return new BocloudResult<List<DataStoreFile>>(true, storeFiles, "查询成功");
		} catch (Exception e) {
			logger.error("查询失败", e);
			return new BocloudResult<List<DataStoreFile>>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<String> create(DataStore model, RequestContext context) {
		try {
			CloudVendor vendor = cloudVendorRepository.query(model.getVendorId());
			if (null == vendor) {
				return new BocloudResult(false, "获取云供应商失败");
			}

			Server host = serverRepository.query(model.getHostId());
			if (host == null) {
				return new BocloudResult(false, "该宿主机不存在");
			}
			boolean flag = dataStoreRepository.exists(model.getName(), model.getVendorId());
			if (flag) {
				return new BocloudResult(false, "该存储池已经存在");
			}
			new Thread(() -> {
				String operate = vendor.getType().toLowerCase() + ".datastore";
				String msgContent = "存储池创建失败";
				DataStoreModel dataStoreModel = new DataStoreModel();
				dataStoreModel.setName(model.getName());
				dataStoreModel.setHostId(Long.valueOf(host.getUuid()));
				BocloudResult result = storagePoolDriver.create(vendor.getUuid(), dataStoreModel);
				try {
					if (result.isSuccess()) {
						msgContent = "存储池创建成功";
						// 同步集群
						BocloudResult detailResult = storagePoolDriver.detail(vendor.getUuid(), dataStoreModel);
						H3cStoragePoolModel h3cStoragePoolModel = (H3cStoragePoolModel) detailResult.getData();
						model.setPath(h3cStoragePoolModel.getPath());
						model.setCapacity(h3cStoragePoolModel.getTotalSize());
						model.setFreeSpace(h3cStoragePoolModel.getFreeSize());
						dataStoreRepository.save(model);
						StoreHost storeHost = new StoreHost();
						storeHost.setStoreId(model.getId());
						storeHost.setVhostId(host.getId());
						storeHost.setCategory("PM");
						storeHost.setVendorId(model.getVendorId());
						storeHostRepository.save(storeHost);
						resourceEventPublisher.send(new OperateResult(true, msgContent, operate,
								MapTools.simpleMap("vendorId", vendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
					} else {
						msgContent = "存储池创建失败";
						resourceEventPublisher.send(new OperateResult(false, msgContent, operate,
								MapTools.simpleMap("vendorId", vendor.getId()),
								OperateResult.OperateCategory.ResourceEvent, context));
					}
				} catch (Exception e) {
					logger.error("Get error message:", e);
					resourceEventPublisher.send(new OperateResult(false, msgContent, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), OperateResult.OperateCategory.ResourceEvent,
							context));
				}
			}).start();
			return new BocloudResult<String>(true, "存储池创建任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("create cluster error", e);
			return new BocloudResult<String>(false, "创建存储池失败");
		}
	}

	@Override
	public BocloudResult<GridBean<DataStore>> listStores(Pager pager, RequestContext context) {
		GridBean<DataStore> 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);
			int total = this.dataStoreRepository.countByHost(params);
			if (simple) {
				List<DataStore> beans = this.dataStoreRepository.listByHost(params);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<DataStore> list = this.dataStoreRepository.listByHost(params, sorter, page, rows);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BocloudResult<GridBean<DataStore>>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query server list fail:", e);
			return new BocloudResult<GridBean<DataStore>>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<GridBean<DataStoreFile>> listStoreFiles(Pager pager, RequestContext context) {
		GridBean<DataStoreFile> 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);
			int total = this.dataStoreFileRepository.count(params);
			if (simple) {
				List<SimpleBean> beans = this.dataStoreFileRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<DataStoreFile> list = this.dataStoreFileRepository.list(page, rows, params, sorter);
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BocloudResult<GridBean<DataStoreFile>>(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query server list fail:", e);
			return new BocloudResult<GridBean<DataStoreFile>>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult<String> removeStoreFile(Long id, RequestContext context) {
		String path = DataStoreFile.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			DataStoreFile dataStoreFile = dataStoreFileRepository.query(id);
			if (null == dataStoreFile) {
				logger.warn("dataStoreFile does not exist!");
				return new BocloudResult<String>(false, "存储卷不存在!");
			}
			CloudVendor cloudVendor = cloudVendorRepository.query(dataStoreFile.getVendorId());
			if (null == cloudVendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult<String>(false, "平台验证失败");
			}
			DataStore dataStore = dataStoreRepository.query(dataStoreFile.getStoreId());
			if (null == dataStore) {
				return new BocloudResult<String>(false, "存储池不存在！");
			}
			Server server = serverRepository.query(dataStoreFile.getHostId());
			if (null == server) {
				return new BocloudResult<String>(false, "存储卷所在主机异常！");
			}
			H3cVolumeModel volumeModel = new H3cVolumeModel();
			volumeModel.setVolName(dataStoreFile.getName());
			volumeModel.setHostId(Long.parseLong(server.getUuid()));
			volumeModel.setSpName(dataStore.getName());
			@SuppressWarnings("unchecked")
			BocloudResult<String> bocloudResult = volumeDriver.remove(volumeModel, cloudVendor.getUuid());
			if (bocloudResult.isFailed()) {
				return bocloudResult;
			}
			dataStoreFileRepository.remove(id, context.getTarget());
			return new BocloudResult<String>(true, "存储卷删除【" + dataStoreFile.getName() + "】成功");
		} catch (Exception e) {
			logger.error("remove dataStoreFile fail:", e);
			return new BocloudResult(false, "存储卷删除失败:" + e.getMessage());
		}

	}

}
