package com.bocloud.ims.repository.resource;

import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.utils.Common;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.FlashCopy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Repository("flashCopyRepository")
public class FlashCopyRepository extends BasicGenericDao<FlashCopy, Long> {

	public FlashCopyRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate) {
		super(jdbcTemplate, npJdbcTemplate);
	}


	public List<FlashCopy> listSimple(int page, int rows, List<Param> params, Map<String, String> sorter, Long volumeId) {
		String sql = "select a.*, b.name as source_volume_name, c.name as target_volume_name, d.name as group_name, "
				+ "          e.name as source_pool_name, f.name as target_pool_name, "
				+ "          g.name as source_storage_name, h.name as target_storage_name "
				+ "from flash_copy a "
				+ "left join volume b on a.source_volume_id = b.id "
				+ "left join volume c on a.target_volume_id = c.id "
				+ "left join volume_pool e on b.pool_id = e.id "
				+ "left join volume_pool f on c.pool_id = f.id "
				+ "left join storage g on e.storage_id = g.id "
				+ "left join storage h on f.storage_id = h.id "
				+ "left join storage_synced_set d on a.group_id = d.id "
				+ "where a.is_deleted = 0 ";
		if (Objects.nonNull(volumeId)) {
			sql += " and (a.source_volume_id = :volumeId or a.target_volume_id = :volumeId) ";
		}
		sql = QueryBuilder.build(sql, new Pager(page, rows, params, sorter), "a");
		Map<String, Object> paramMap = QueryBuilder.getParam(params);
		for (Param param : params) {
			Map<String, Object> subMap = QueryBuilder.getParam(param.getSubParams());
			paramMap.putAll(subMap);
		}
		if (Objects.nonNull(volumeId)) {
			paramMap.put("volumeId", volumeId);
		}
		return this.list(FlashCopy.class, sql, paramMap);
	}

	public int countSimple(List<Param> params, Long volumeId) {
		String sql = "select count(1) from flash_copy a " + "left join volume b on a.source_volume_id = b.id "
				+ "left join volume c on a.target_volume_id = c.id "
				+ "left join storage_synced_set d on a.group_id = d.id "
				+ "where a.is_deleted = 0 ";
		if (Objects.nonNull(volumeId)) {
			sql += " and (a.source_volume_id = :volumeId or a.target_volume_id = :volumeId) ";
		}
		sql = QueryBuilder.build(sql, params, null, "a");
		Map<String, Object> paramMap = QueryBuilder.getParam(params);
		for (Param param : params) {
			Map<String, Object> subMap = QueryBuilder.getParam(param.getSubParams());
			paramMap.putAll(subMap);
		}
        if (Objects.nonNull(volumeId)) {
            paramMap.put("volumeId", volumeId);
        }
		return this.countQuery(sql, paramMap).intValue();
	}

	public List<FlashCopy> listGroup(int page, int rows, List<Param> params, Map<String, String> sorter)
			throws Exception {
		Map<String, String> sorterMap = new HashMap<>(8);
		sorterMap.put("group_id", "0");
		sorterMap.put("type", "1");
		String sql = "select * from ( " +

				"  select 'FlashCopy' as type, ifnull(a.group_id, 0) as group_id, ifnull(b.name, '不在组中') as group_name, "
				+ "         a.name, a.status, c.name as source_volume_name, d.name as target_volume_name, a.progress, a.start_time, "
				+ "         a.vendor_id " + "  from flash_copy a "
				+ "         left join storage_synced_set b on a.group_id = b.id "
				+ "         left join volume c on a.source_volume_id = c.id "
				+ "         left join volume d on a.target_volume_id = d.id " + "  where a.is_deleted = 0 " +

				"  union all " +

				"  select 'Group', a.id, a.name, null, a.status, null, null, null, null,b.vendor_id "
				+ "  from storage_synced_set a left join storage b  on a.storage_id = b.id "
				+ "  where a.is_deleted = 0 " +

				"  union all " +

				"  select 'Group', 0, '不在组中', null, 'Empty', null, null, null, null, a.id "
				+ "  from cloud_vendor a where a.is_deleted = 0 " +

				") t where 1 = 1 ";
		sql = QueryBuilder.build(sql, new Pager(page, rows, params, sorterMap), "t");
		Map<String, Object> paramMap = QueryBuilder.getParam(params);
		return this.list(FlashCopy.class, sql, paramMap);
	}

	public int countGroup(List<Param> params) {
		String sql = "select count(1) from ( "
				+ "select 'FlashCopy' as type, ifnull(a.group_id, 0) as group_id, ifnull(b.name, '不在组中') as group_name, "
				+ "       a.name, a.status, c.name as sourceVolumeName, d.name as targetVolumeName, a.progress, a.start_time, "
				+ "       a.vendor_id " + "from flash_copy a "
				+ "       left join storage_synced_set b on a.group_id = b.id "
				+ "       left join volume c on a.source_volume_id = c.id "
				+ "       left join volume d on a.target_volume_id = d.id " + "where a.is_deleted = 0 " +

				"union all " +

				"select 'Group', a.id, a.name, null, a.status, null, null, null, null, b.vendor_id "
				+ "from storage_synced_set a left join storage b  on a.storage_id = b.id " + "where a.is_deleted = 0 " +

				"union all " +

				"select 'Group', 0, '不在组中', null, 'Empty', null, null, null, null, a.id "
				+ "from cloud_vendor a where a.is_deleted = 0 " +

				") t where 1 = 1 ";
		sql = QueryBuilder.build(sql, params, null, "t");
		Map<String, Object> param = QueryBuilder.getParam(params);
		return this.countQuery(sql, param).intValue();
	}

	public void remove(long id) {
		String sql = "update flash_copy set is_deleted = 1 where id = :id ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("id", id);
		execute(sql, params);
	}

	public void removeByVendor(long vendorId) {
		String sql = "update flash_copy set is_deleted = 1 where vendor_id = :vendorId ";
		Map<String, Object> params = new HashMap<>(8);
		params.put(Common.VENDORID, vendorId);
		execute(sql, params);
	}

	public List<FlashCopy> listByVendor(long vendorId) {
		String sql = "select a.* from flash_copy a where is_deleted = 0 and vendor_id = :vendorId ";
		Map<String, Object> params = new HashMap<>(8);
		params.put(Common.VENDORID, vendorId);
		return this.list(FlashCopy.class, sql, params);
	}

	public List<FlashCopy> listByGroup(long groupId) {
		String sql = "select a.* from flash_copy a where is_deleted = 0 and group_id = :groupId ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("groupId", groupId);
		return this.list(FlashCopy.class, sql, params);
	}

	public List<FlashCopy> listByVolume(long volumeId) {
		String sql = "select a.* from flash_copy a where a.is_deleted = 0 and (a.source_volume_id = :volumeId or a.target_volume_id = :volumeId)";
		Map<String, Object> params = new HashMap<>(8);
		params.put("volumeId", volumeId);
		return this.list(FlashCopy.class, sql, params);
	}

	public List<FlashCopy> listBySourceVolume(long volumeId) {
		String sql = "select a.* from flash_copy a where a.is_deleted = 0 and a.source_volume_id = :volumeId";
		Map<String, Object> params = new HashMap<>(8);
		params.put("volumeId", volumeId);
		return this.list(FlashCopy.class, sql, params);
	}

	public List<FlashCopy> listByTargetVolume(long volumeId) {
		String sql = "select a.* from flash_copy a where a.is_deleted = 0 and a.target_volume_id = :volumeId";
		Map<String, Object> params = new HashMap<>(8);
		params.put("volumeId", volumeId);
		return this.list(FlashCopy.class, sql, params);
	}

	public FlashCopy get(long id) {
		String sql = "select a.* from flash_copy a where a.id = :id ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("id", id);
		List<FlashCopy> list = this.list(FlashCopy.class, sql, params);
		return list == null || list.size() == 0 ? null : list.get(0);
	}

	public FlashCopy getByNameAndVendorId(String name, long vendorId) {
		String sql = "select a.* from flash_copy a where a.is_deleted = 0 and a.name = :name and a.vendor_id = :vendorId ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("name", name);
		params.put(Common.VENDORID, vendorId);
		List<FlashCopy> list = this.list(FlashCopy.class, sql, params);
		return list == null || list.size() == 0 ? null : list.get(0);
	}

	public void updateStatus(long id, Integer progress, String status) {
		String sql = "update flash_copy set progress = :progress, status= :status where is_deleted = 0 and id = :id ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("id", id);
		params.put("status", status);
		params.put("progress", progress);
		execute(sql, params);
	}
}
