package com.bocloud.ims.repository.resource;

import com.bocloud.common.utils.MapTools;
import com.bocloud.database.utils.PageHelper;
import com.bocloud.ims.entity.resource.StorageHost;
import com.bocloud.ims.entity.resource.StorageHostVolume;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.repository.resource.common.EnhancedBaseRepository;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Repository("storageHostVolumeRepository")
public class StorageHostVolumeRepository extends EnhancedBaseRepository<StorageHostVolume, Long> {

	public void removeByHost(long hostId) {
		String sql = "delete from storage_host_volume where host_id = :hostId";
		Map<String, Object> params = MapTools.simpleMap("hostId", hostId);
		this.update(sql, params);
	}

	public void removeByVolume(long volumeId) {
		String sql = "delete from storage_host_volume where volume_id = :volumeId";
		Map<String, Object> params = MapTools.simpleMap("volumeId", volumeId);
		this.update(sql, params);
	}

	public List<StorageHostVolume> listByHost(long hostId) {
		String sql = "select a.* from storage_host_volume a where a.host_id = :hostId";
		Map<String, Object> params = MapTools.simpleMap("hostId", hostId);
		return this.list(StorageHostVolume.class, sql, params);
	}

	public List<StorageHostVolume> listByVolume(long volumeId) {
		String sql = "select a.* from storage_host_volume a where a.volume_id = :volumeId";
		Map<String, Object> params = MapTools.simpleMap("volumeId", volumeId);
		return this.list(StorageHostVolume.class, sql, params);
	}

	public StorageHostVolume getByHostAndVolume(long hostId, long volumeId) {
		String sql = "select a.* from storage_host_volume a where a.volume_id = :volumeId and a.host_id = :hostId";
		Map<String, Object> params = MapTools.simpleMap("volumeId", volumeId);
		params.put("hostId", hostId);
		List<StorageHostVolume> list = this.list(StorageHostVolume.class, sql, params);
		return list == null || list.size() == 0 ? null : list.get(0);
	}

	public void remove(long id) {
		String sql = "delete from storage_host_volume where id = :id";
		Map<String, Object> params = MapTools.simpleMap("id", id);
		this.update(sql, params);
	}

	public List<Volume> listVolumeForHostAttach(int page, int rows, long hostId, Map<String, Object> params){
		String sql = " select a.*, c.name as pool_name from volume a left join volume_pool c on a.pool_id = c.id where a.is_deleted = 0 "
				+ " and a.id not in (select b.volume_id from storage_host_volume b where b.host_id = :hostId) "
				+ " and a.storage_id = (select d.storage_id from storage_host d where d.id = :hostId) ";
		Map<String, Object> sqlParams = MapTools.simpleMap("hostId", hostId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		if (params.containsKey("poolId")) {
			sql += " and a.pool_id = :poolId";
			sqlParams.put("poolId", params.get("poolId"));
		}
		sql += PageHelper.buildPageSql(page, rows);
		List<Object> objects = this.queryForList(sql, sqlParams, Volume.class);
		List<Volume> volumes = new ArrayList<>();
		for (Object object : objects) {
			volumes.add((Volume) object);
		}
		return volumes;
	}

	public int countVolumeForHostAttach(long hostId, Map<String, Object> params) {
		String sql = " select count(1) from volume a where a.is_deleted = 0 "
				+ " and a.id not in (select b.volume_id from storage_host_volume b where b.host_id = :hostId) "
				+ " and a.storage_id = (select d.storage_id from storage_host d where d.id = :hostId) ";
		Map<String, Object> sqlParams = MapTools.simpleMap("hostId", hostId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		if (params.containsKey("poolId")) {
			sql += " and a.pool_id = :poolId";
			sqlParams.put("poolId", params.get("poolId"));
		}
		return this.countQuery(sql, params).intValue();
	}

	public List<StorageHost> listHostForVolumeAttach(int page, int rows, long volumeId, Map<String, Object> params)
			throws Exception {
		String sql = " select a.* from storage_host a where a.is_deleted = 0 "
				+ " and a.id not in (select b.host_id from storage_host_volume b where b.volume_id = :volumeId) "
				+ " and a.storage_id = (select d.storage_id from volume d where d.id = :volumeId)";
		Map<String, Object> sqlParams = MapTools.simpleMap("volumeId", volumeId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		sql += PageHelper.buildPageSql(page, rows);
		List<Object> objects = this.queryForList(sql, sqlParams, StorageHost.class);
		List<StorageHost> hosts = new ArrayList<>();
		for (Object object : objects) {
			hosts.add((StorageHost) object);
		}
		return hosts;
	}

	public int countHostForVolumeAttach(long volumeId, Map<String, Object> params) {
		String sql = " select count(1) from storage_host a where a.is_deleted = 0 "
				+ " and a.id not in (select b.host_id from storage_host_volume b where b.volume_id = :volumeId) "
				+ " and a.storage_id = (select d.storage_id from volume d where d.id = :volumeId)";
		Map<String, Object> sqlParams = MapTools.simpleMap("volumeId", volumeId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		return this.countQuery(sql, params).intValue();
	}

	public List<Volume> listVolumeOfHostAttached(int page, int rows, long hostId, Map<String, Object> params)
			throws Exception {
		String sql = "select a.*, c.name as pool_name from volume a left join volume_pool c on a.pool_id = c.id where a.is_deleted = 0 "
				+ "and a.id in (select b.volume_id from storage_host_volume b where b.host_id = :hostId)";
		Map<String, Object> sqlParams = MapTools.simpleMap("hostId", hostId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		if (params.containsKey("poolId")) {
			sql += " and a.pool_id = :poolId";
			sqlParams.put("poolId", params.get("poolId"));
		}
		sql += PageHelper.buildPageSql(page, rows);
		List<Object> objects = this.queryForList(sql, sqlParams, Volume.class);
		List<Volume> volumes = new ArrayList<>();
		for (Object object : objects) {
			volumes.add((Volume) object);
		}
		return volumes;
	}

	public int countVolumeOfHostAttached(long hostId, Map<String, Object> params) {
		String sql = "select count(1) from volume a where a.is_deleted = 0 "
				+ "and a.id in (select b.volume_id from storage_host_volume b where b.host_id = :hostId)";
		Map<String, Object> sqlParams = MapTools.simpleMap("hostId", hostId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		if (params.containsKey("poolId")) {
			sql += " and a.pool_id = :poolId";
			sqlParams.put("poolId", params.get("poolId"));
		}
		return this.countQuery(sql, params).intValue();
	}

	public List<StorageHost> listHostOfVolumeAttached(int page, int rows, long volumeId, Map<String, Object> params)
			throws Exception {
		String sql = "select a.* from storage_host a where a.is_deleted = 0 "
				+ "and a.id in (select b.host_id from storage_host_volume b where b.volume_id = :volumeId)";
		Map<String, Object> sqlParams = MapTools.simpleMap("volumeId", volumeId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		sql += PageHelper.buildPageSql(page, rows);
		List<Object> objects = this.queryForList(sql, sqlParams, StorageHost.class);
		List<StorageHost> hosts = new ArrayList<>();
		for (Object object : objects) {
			hosts.add((StorageHost) object);
		}
		return hosts;
	}

	public int countHostOfVolumeAttached(long volumeId, Map<String, Object> params) {
		String sql = "select count(1) from storage_host a where a.is_deleted = 0 "
				+ "and a.id in (select b.host_id from storage_host_volume b where b.volume_id = :volumeId)";
		Map<String, Object> sqlParams = MapTools.simpleMap("volumeId", volumeId);
		if (params.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + params.get("name") + "%");
		}
		return this.countQuery(sql, params).intValue();
	}
}
