package com.bocloud.ims.repository.resource;

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

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

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: NetworkInterfaceRepositoryImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2019/9/27 15:02
 */
@Repository("networkInterfaceRepository")
public class NetworkInterfaceRepository extends BasicGenericDao<NetworkInterface, Long> {

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

	public List<NetworkInterface> list(Long vendorId) throws Exception {
		String sql = "select * from network_interface where vendor_id = :vendorId and is_deleted = 0";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public List<NetworkInterface> listByVendorId(Long vendorId, String regionId) throws Exception {
		String sql = "select * from network_interface where vendor_id = :vendorId and is_deleted = 0 and region_id = :regionId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put(Common.REGIONID, regionId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public NetworkInterface query(Long id){
		String sql = "SELECT e.public_ip public_ip_address , n.* , s.name security_group_name,z.name zone_name,r.name region_name,c.name server_name,v.name vpc_name,cv.name vendor_name ,v.vpc_id vpc_uuid ,c.instance_id server_uuid,sb.subnet_uuid subnet_uuid FROM network_interface n "
				+ " LEFT JOIN security_group s ON n.security_group_id = s.id "
				+ " LEFT JOIN cloud_server c ON n.server_id = c.id " + " LEFT JOIN vpc v ON n.vpc_id = v.id "
				+ " left join region r on r.vendor_id = n.vendor_id and r.region_id = n.region_id "
				+ " left join zone z on z.vendor_id = n.vendor_id and z.zone_id= n.zone "
				+ " LEFT JOIN subnet sb ON n.subnet_id = sb.id " + " LEFT JOIN cloud_vendor cv ON n.vendor_id = cv.id "
				+ " LEFT JOIN elastic_ip e on e.vendor_id = n.vendor_id and e.network_interface_id= n.network_interface_uuid and e.is_deleted = 0 "
				+ " WHERE n.id = :id AND n.is_deleted = 0  ";
		Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
		List<NetworkInterface> list = this.list(NetworkInterface.class, sql, params);
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	public NetworkInterface query(String nicsUuid, Long vendorId) throws Exception {
		String sql = "SELECT n.* , s.name security_group_name,c.name server_name,v.name vpc_name,cv.name vendor_name FROM network_interface n "
				+ " LEFT JOIN security_group s ON n.security_group_id = s.id "
				+ " LEFT JOIN cloud_server c ON n.server_id = c.id " + " LEFT JOIN vpc v ON n.vpc_id = v.id "
				+ " LEFT JOIN cloud_vendor cv ON n.vendor_id = cv.id "
				+ " WHERE n.network_interface_uuid = :nicsUuid AND n.vendor_id = :vendorId AND n.is_deleted = 0 ";
		Map<String, Object> params = MapTools.simpleMap("nicsUuid", nicsUuid);
		params.put("vendorId", vendorId);
		List<NetworkInterface> list = this.list(NetworkInterface.class, sql, params);
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	public boolean delete(Long id, Long userId) throws Exception {
		String sql = "update network_interface set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where id = :id";
		Map<String, Object> params = MapTools.simpleMap("id", id);
		params.put("gmtModify", new Date());
		params.put("menderId", userId);
		return this.execute(sql, params) > 0;
	}

	public boolean deleteByVid(Long vendorId, Long userId) throws Exception {
		String sql = "update network_interface set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("gmtModify", new Date());
		params.put("menderId", userId);
		return this.execute(sql, params) > 0;
	}

	public List<NetworkInterface> list(int page, int rows, List<Param> params, Map<String, String> sorter)
			throws Exception {
		String sql = "SELECT cs.name server_name ,z.name zone_name,r.name region_name , cs.instance_id server_uuid,c.name vendor_name,v.name vpc_name , "
				+ "v.vpc_id vpc_uuid,s.name subnet_name,s.subnet_uuid subnet_uuid ,n.* ,t.name tenant_name "
				+ "FROM network_interface n "
				+ "LEFT JOIN cloud_vendor c ON n.vendor_id = c.id "
				+ "LEFT JOIN vpc v ON n.vpc_id = v.id "
				+ "LEFT JOIN subnet s ON n.subnet_id = s.id "
				+ " left join region r on r.vendor_id = n.vendor_id and r.region_id = n.region_id "
				+ " left join zone z on z.vendor_id = n.vendor_id and z.zone_id= n.zone "
				+ "LEFT JOIN tenant t ON n.tenant_id = t.id "
				+ "LEFT JOIN cloud_server cs ON n.server_id = cs.id "
				+ "WHERE n.is_deleted = 0";
		sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "n");
		return this.list(NetworkInterface.class, sql);
	}

	public int count(List<Param> params) throws Exception {
		String sql = "SELECT count(1) " + "FROM network_interface n "
				+ "LEFT JOIN cloud_vendor c ON n.vendor_id = c.id " + "LEFT JOIN vpc v ON n.vpc_id = v.id "
				+ "LEFT JOIN subnet s ON n.subnet_id = s.id " + "LEFT JOIN tenant t ON n.tenant_id = t.id "
				+ "LEFT JOIN cloud_server cs ON n.server_id = cs.id " + "WHERE n.is_deleted = 0";
		sql = QueryBuilder.buildRaw(sql, params, null, "n");
		Map<String, Object> param = QueryBuilder.getParam(params);
		return this.countQuery(sql, param).intValue();
	}

	public boolean removeByVid(Long vendorId, Long userId, String regionId) throws Exception {
		String sql = "update network_interface set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId and region_id = :regionId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put(Common.REGIONID, regionId);
		params.put("gmtModify", new Date());
		params.put("menderId", userId);
		return this.execute(sql, params) > 0;
	}

	public List<NetworkInterface> list(List<Param> params) throws Exception {
		String sql = "SELECT n.* " + "FROM network_interface n " + "LEFT JOIN cloud_vendor c ON n.vendor_id = c.id "
				+ "LEFT JOIN vpc v ON n.vpc_id = v.id " + "LEFT JOIN subnet s ON n.subnet_id = s.id "
				+ "LEFT JOIN cloud_server cs ON n.server_id = cs.id " + "WHERE n.is_deleted = 0";
		sql = QueryBuilder.buildRaw(sql, params, null, "n");
		Map<String, Object> param = QueryBuilder.getParam(params);
		List<NetworkInterface> list = this.list(NetworkInterface.class, sql, param);
		return list;
	}

	public List<NetworkInterface> listBySgId(Long vendorId, Long sgId) throws Exception {
		String sql = "select * from network_interface where vendor_id = :vendorId and is_deleted = 0 and security_group_id = :sgId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("sgId", sgId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public int count(List<Param> params, Long tenantId, List<Long> projectIds) {
		String sql = " select count(a.id) from network_interface a where a.is_deleted = 0 ";
		Map<String, Object> paramMap = QueryBuilder.getParam(params);
		if (null != tenantId && 0L != tenantId) {
			sql += " and a.tenant_id = :tenantId";
			paramMap.put("tenantId", tenantId);
		}
		if (!ListTool.isEmpty(projectIds)) {
			sql += " and a.project_id in (:projectIds) ";
			paramMap.put("projectIds", projectIds);
		}
		sql = QueryBuilder.buildRaw(sql, params, null, "a");
		return this.countQuery(sql, paramMap).intValue();
	}

	public List<NetworkInterface> list(int page, int rows, List<Param> params, Map<String, String> sorter,
			Long tenantId, List<Long> projectIds) {
		String sql = "select a.*,v.name vendor_name,v.type vendor_type, r.name region_name,t.name tenant_name,ob.expired_time from network_interface a left join object_relation ob on a.id = ob.res_id and ob.category = 'networkInterface'"
				+ " left join region r on a.vendor_id = r.vendor_id and a.region_id = r.region_id "
				+ " left join tenant t on a.tenant_id = t.id left join cloud_vendor v on a.vendor_id = v.id"
				+ " left join project project on a.project_id = project.id " + " where a.is_deleted = 0 ";
		Map<String, Object> paramMap = QueryBuilder.getParam(params);
		if (null != tenantId && 0L != tenantId) {
			sql += " and a.tenant_id = :tenantId";
			paramMap.put("tenantId", tenantId);
		}
		if (!ListTool.isEmpty(projectIds)) {
			sql += " and a.project_id in (:projectIds) ";
			paramMap.put("projectIds", projectIds);
		}
		sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
		return this.list(NetworkInterface.class, sql, paramMap);
	}

	public List<NetworkInterface> listByServerId(Long vendorId, Long serverId) throws Exception {
		String sql = "select * from network_interface where vendor_id = :vendorId and is_deleted = 0 and server_id = :serverId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("serverId", serverId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public boolean removeByGroupId(Long vendorId, Long userId, Long resourceGroupId) throws BoCloudDBException {
		String sql = "update network_interface set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId and resource_group_id = :resourceGroupId";
		Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
		params.put("resourceGroupId", resourceGroupId);
		params.put("gmtModify", new Date());
		params.put(Common.MENDER_ID, userId);
		return this.execute(sql, params) > 0;
	}

	public NetworkInterface getByNetworkInterfaceId(String networkInterfaceId, Long vendorId) {
		String sql = "select a.* from network_interface a "
				+ "where a.is_deleted = 0 and a.network_interface_uuid = :networkInterfaceId";
		Map<String, Object> params = MapTools.simpleMap("networkInterfaceId", networkInterfaceId);
		if (vendorId != null) {
			sql += " and a.vendor_id = :vendorId ";
			params.put(Common.VENDORID, vendorId);
		}
		List<NetworkInterface> list = this.list(NetworkInterface.class, sql, params);
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	public List<NetworkInterface> listForNatGatewayRule(Long vendorId, String regionId, Long vpcId) {
		String sql = " select a.id,if(a.interface_type='Primary',b.name,a.name) as name,a.primary_private_ip_address,"
				+ "a.private_ip_address,a.interface_type from network_interface a LEFT JOIN cloud_server b on a.server_id = b.id and b.is_deleted = 0 "
				+ " where a.vendor_id = :vendorId and a.is_deleted = 0  and a.region_id = :regionId and a.vpc_id = :vpcId ";
		Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
		params.put("regionId", regionId);
		params.put("vpcId", vpcId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public List<NetworkInterface> listByVpcId(Long vpcId) throws Exception {
		String sql = "select * from network_interface where is_deleted = 0 and vpc_id = :vpcId";
		Map<String, Object> params = MapTools.simpleMap("vpcId", vpcId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public List<NetworkInterface> listBysubnetId(Long vendorId, Long subnetId) throws Exception {
		String sql = "select a.* from network_interface a where a.is_deleted = 0 and a.vendor_id = :vendorId and a.subnet_id = :subnetId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("subnetId", subnetId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public List<NetworkInterface> listAvailableNics(Long vendorId, String regionId) {
		String sql = "select a.* from network_interface a LEFT JOIN elastic_ip b on a.network_interface_uuid=b.instance_id "
				+ " where a.is_deleted=0 and a.vendor_id = :vendorId and a.region_id = :regionId and b.instance_id is null and a.interface_type != 'Primary' ";
		Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
		params.put("regionId", regionId);
		return this.list(NetworkInterface.class, sql, params);
	}

	public List<NetworkInterface> list(Long vendorId, String regionId, Long vpcId, String interfaceType) {
		String sql = " select a.*  from network_interface a " +
				" where a.is_deleted=0 and a.vendor_id = :vendorId and a.region_id = :regionId " +
				" and a.vpc_id = :vpcId and a.interface_type = :interfaceType  ";
		Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
		params.put("regionId", regionId);
		params.put("vpcId",vpcId);
		params.put("interfaceType",interfaceType);
		return this.list(NetworkInterface.class, sql, params);
	}

	public boolean removeByNatUuid(String natUuid, Long vendorId, Long userId) {
		String sql = "update network_interface set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId and nat_gateway_uuid = :natUuid ";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("natUuid", natUuid);
		params.put("gmtModify", new Date());
		params.put("menderId", userId);
		return this.execute(sql, params) > 0;
	}

}
