package com.bocloud.ims.repository.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.RackDevice;
import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.IDFactory;
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.PageHelper;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.Rack;
import com.bocloud.ims.entity.resource.Room;
import com.bocloud.ims.entity.resource.Server;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.apache.commons.lang3.StringUtils;

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

/**
 * 物理服务器数据访问
 *
 * @author wangyu
 * @version 1.0
 * @since 2020年5月15日
 */
@Repository("serverRepository")
public class ServerRepository extends BasicGenericDao<Server, Long> {

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

    @Override
    public void save(Server server) {
        server.setGuid(IDFactory.instance().uuid());
        super.save(server);
    }

    public Server query(Long id) {
        String sql = "select a.*,b.id rack_id,b.name rackname,c.id as room_id,c.name roomname,d.id dc_id,d.name dcname,e.name cluster_name,f.name vdc_name,j.name vendor_name from server a "
                + "left join rack b on a.rack_id = b.id " + "left join room c on a.room_id = c.id "
                + "left join cluster e on a.cluster_id = e.id " + "left join vdc f on a.vdc_id = f.id "
                + "left join cloud_vendor j on a.vendor_id = j.id " + "left join data_center d on d.id = a.dc_id "
                + "where a.is_deleted = 0 and a.id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        List<Server> list = this.list(Server.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public Server basic(Long id) {
        String sql = "select a.name,b.name cluster_name,c.name vdc_name from server a left join cluster b on b.id = a.cluster_id left join vdc c on c.id = a.vdc_id where a.id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        List<Server> list = this.list(Server.class, sql, params);
        return ListTool.isEmpty(list) ? null : list.get(0);
    }

    public List<Server> list(int page, int rows, List<Param> params, Map<String, String> sorter, List<Long> labelIds, String vendorType,String clusterName,String vdcName)
            throws Exception {
        String sql = "select a.*,b.name rackname,c.name roomname,d.name cluster_name,e.name vdc_name, "
                + "f.name vendor_name, f.type as vendor_type,dc.name dcname from server a "
                + "left join rack b on a.rack_id = b.id " + "left join room c on a.room_id = c.id "
                + "left join cluster d on a.cluster_id = d.id " + "left join vdc e on a.vdc_id = e.id "
                + "left join cloud_vendor f on a.vendor_id = f.id " + "left join data_center dc on dc.id = a.dc_id "
                + "where a.is_deleted = 0";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and a.id in (select target from server_label where type = 'PM' and id in (:labelIds))";
            paramMap.put("labelIds", labelIds);
        }
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and f.type = :vendorType ";
            paramMap.put("vendorType", vendorType);
        }
        if (!com.mysql.cj.util.StringUtils.isNullOrEmpty(clusterName)) {
            sql += " and d.name like '%" + clusterName + "%' ";
        }
        if (!com.mysql.cj.util.StringUtils.isNullOrEmpty(vdcName)) {
            sql += " and e.name like '%" + vdcName + "%' ";
        }
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        return this.list(Server.class, sql, paramMap);
    }
    
    public List<Server> list(int page, int rows, List<Param> params, Map<String, String> sorter, List<Long> labelIds)
            throws Exception {
        String sql = "select a.*,b.name rackname,c.name roomname,d.name cluster_name,e.name vdc_name, "
                + "f.name vendor_name, f.type as vendor_type,dc.name dcname from server a "
                + "left join rack b on a.rack_id = b.id " + "left join room c on a.room_id = c.id "
                + "left join cluster d on a.cluster_id = d.id " + "left join vdc e on a.vdc_id = e.id "
                + "left join cloud_vendor f on a.vendor_id = f.id " + "left join data_center dc on dc.id = a.dc_id "
                + "where a.is_deleted = 0";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and a.id in (select target from server_label where type = 'PM' and id in (:labelIds))";
            paramMap.put("labelIds", labelIds);
        }
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        return this.list(Server.class, sql, paramMap);
    }

    public List<SimpleBean> list(List<Param> params, Map<String, String> sorter, List<Long> labelIds) {
        String sql = "select a.id,a.name from server a where a.is_deleted = 0";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and a.id in (select target from server_label where type = 'PM' and id in (:labelIds))";
            paramMap.put("labelIds", labelIds);
        }
        sql = QueryBuilder.build(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a");
        List<Server> servers = this.list(Server.class, sql, paramMap);
        List<SimpleBean> beans = new ArrayList<SimpleBean>();
        for (Server server : servers) {
            beans.add(new SimpleBean(server.getId(), server.getName()));
        }
        return beans;
    }

    public boolean release(Long id, Long userId) {
        String sql = "update server set rack_id = null,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("menderId", userId);
        params.put("gmtModify", new Date());
        return this.execute(sql, params) > 0;
    }

    public boolean belong(RackDevice rackDevice, Long userId) {
        String sql = "update server set slot_start = :slotStart,slot_num = :slotNum,rack_id = :rackId,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", rackDevice.getDeviceId());
        params.put("rackId", rackDevice.getDeviceId());
        params.put("slotStart", rackDevice.getSlotStart());
        params.put("slotNum", rackDevice.getSlotNum());
        params.put("menderId", userId);
        params.put("gmtModify", new Date());
        return this.execute(sql, params) > 0;
    }

    public List<Server> listFree() {
        String sql = "select * from server where is_deleted = 0 and rack_id is null";
        return this.list(Server.class, sql);
    }

    public List<Server> queryAll() {
        String sql = "select * from server where is_deleted = 0";
        return this.list(Server.class, sql);
    }

    public List<Server> listByCondition(Long vdcId, Long clusterId, String serverName, List<Long> vendorIds) {
        String sql = "select a.*,b.`name` as vendor_name,c.`name` as dc_name,d.`name` as cluster_name from server a LEFT JOIN cloud_vendor b ON a.vendor_id = b.id LEFT JOIN data_center c ON b.dc_id = c.id LEFT JOIN cluster d ON a.cluster_id = d.id  where a.is_deleted = 0 ";
        Map<String, Object> params = new HashMap<>(8);
        if (!ListTool.isEmpty(vendorIds)) {
            sql += " and a.vendor_id in (:vendorIds)";
            params.put("vendorIds", vendorIds);
        }
        if (null != vdcId && 0L != vdcId) {
            sql += " and a.vdc_id = :vdcId";
            params.put("vdcId", vdcId);
        }
        if (null != clusterId && 0L != clusterId) {
            sql += " and a.cluster_id = :clusterId";
            params.put("clusterId", clusterId);
        }
        if (null != serverName) {
            sql += " and a.name like :serverName ";
            params.put("serverName", "%" + serverName + "%");
        }
        return this.list(Server.class, sql, params);
    }
    
	public List<Server> listByIds(List<Long> resourceIds, String type) {
		String sql = "select a.* from server a where a.is_deleted = 0 ";
		Map<String, Object> params = new HashMap<>(8);
		if (!ListTool.isEmpty(resourceIds) && "vdc".equalsIgnoreCase(type)) {
			sql += " and a.vdc_id in (:resourceIds)";
			params.put("resourceIds", resourceIds);
		}
		if (!ListTool.isEmpty(resourceIds) && "cluster".equalsIgnoreCase(type)) {
			sql += " and a.cluster_id in (:resourceIds)";
			params.put("resourceIds", resourceIds);
		}
		if (!ListTool.isEmpty(resourceIds) && "host".equalsIgnoreCase(type)) {
			sql += " and a.id in (:resourceIds)";
			params.put("resourceIds", resourceIds);
		}
		return this.list(Server.class, sql, params);
	}

    public int count(List<Param> params, List<Long> labelIds, String vendorType) {
        String sql = "select count(1) from server a left join cloud_vendor c on a.vendor_id = c.id  where a.is_deleted = 0";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and a.id in (select target from server_label where type = 'PM' and id in (:labelIds))";
            paramMap.put("labelIds", labelIds);
        }
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and c.type = :vendorType ";
            paramMap.put("vendorType", vendorType);
        }
        sql = QueryBuilder.buildRaw(sql, params, null, "a");
        return this.countQuery(sql, paramMap).intValue();
    }

    public int counts(List<Param> params, List<Long> labelIds, String vendorType,String clusterName,String vdcName) {
        String sql = "select count(1) from server a left join cloud_vendor c on a.vendor_id = c.id  " +
                "left join cluster d on a.cluster_id = d.id " + "left join vdc e on a.vdc_id = e.id " +
                "where a.is_deleted = 0";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and a.id in (select target from server_label where type = 'PM' and id in (:labelIds))";
            paramMap.put("labelIds", labelIds);
        }
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and c.type = :vendorType ";
            paramMap.put("vendorType", vendorType);
        }
        if (!StringUtils.isEmpty(clusterName)) {
            sql += " and d.name like '%" + clusterName + "%' ";
        }
        if (!StringUtils.isEmpty(vdcName)) {
            sql += " and e.name like '%" + vdcName + "%' ";
        }
        sql = QueryBuilder.buildRaw(sql, params, null, "a");
        return this.countQuery(sql, paramMap).intValue();
    }
    
	public int count(List<Param> params, List<Long> labelIds) {
		String sql = "select count(1) from server a left join cloud_vendor c on a.vendor_id = c.id  where a.is_deleted = 0";
		Map<String, Object> paramMap = QueryBuilder.getParam(params);
		if (!ListTool.isEmpty(labelIds)) {
			sql += " and a.id in (select target from server_label where type = 'PM' and id in (:labelIds))";
			paramMap.put("labelIds", labelIds);
		}
		sql = QueryBuilder.buildRaw(sql, params, null, "a");
		return this.countQuery(sql, paramMap).intValue();
	}

    public int countByRack(Long rackId) {
        String sql = "select count(id) from server a where a.is_deleted = 0 and a.rack_id = :rackId";
        Map<String, Object> paramMap = MapTools.simpleMap("rackId", rackId);
        return this.countQuery(sql, paramMap).intValue();
    }

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

    public boolean isolate(Long id, Long userId) {
        String sql = "update server set status = :status,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("menderId", userId);
        params.put("gmtModify", new Date());
        params.put("status", "ISOLATE");
        return this.execute(sql, params) > 0;
    }

    public boolean recover(Long id, Long userId) {
        String sql = "update server set status = :status,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("menderId", userId);
        params.put("gmtModify", new Date());
        params.put("status", "RUNNING");
        return this.execute(sql, params) > 0;
    }

    public boolean exists(String ip) {
        String sql = "select * from server a where a.is_deleted = 0 and a.manage_ip = :ip";
        Map<String, Object> params = MapTools.simpleMap("ip", ip);
        List<Server> list = this.list(Server.class, sql, params);
        return !list.isEmpty();
    }

    public List<Server> listFreeNode(Long id, Class<?> clazz) {
        String sql = "";
        if (clazz == Rack.class) {
            sql = "select * from server a where not exists(select * from cluster_node b where b.type = 'PM' and a.id = b.node_id) "
                    + "and not exists(select * from resource c where c.type = 'PM' and a.id = c.res_id) and a.is_deleted = 0 and a.rack_id = :id";
        } else if (clazz == Room.class) {
            sql = "select * from server a where not exists(select * from cluster_node b where b.type = 'PM' and a.id = b.node_id) "
                    + "and not exists(select * from resource c where c.type = 'PM' and a.id = c.res_id) and "
                    + "exists(select * from room d,rack r where a.rack_id = r.id and r.room_id = d.id and d.id = :id) and a.is_deleted = 0";
        } else {
            sql = "select * from server a where not exists(select * from cluster_node b where b.type = 'PM' and a.id = b.node_id) "
                    + "and not exists(select * from resource c where c.type = 'PM' and a.id = c.res_id) and "
                    + "exists(select * from data_center f,room d,rack r where a.rack_id = r.id and r.room_id = d.id and d.dc_id = f.id and f.id = :id ) and a.is_deleted = 0";
        }

        Map<String, Object> params = MapTools.simpleMap("id", id);
        return this.list(Server.class, sql, params);
    }

    public List<Server> listFreeManager(Long id, Class<?> clazz) {
        String sql = "";
        if (clazz == Rack.class) {
            sql = "select * from server a where not exists(select * from cluster_manager b where b.type = 'PM' and a.id = b.manager_id) "
                    + "and not exists(select * from resource c where c.type = 'PM' and a.id = c.res_id) and a.is_deleted = 0 and a.rack_id = :id";
        } else if (clazz == Room.class) {
            sql = "select * from server a where not exists(select * from cluster_manager b where b.type = 'PM' and a.id = b.manager_id) "
                    + "and not exists(select * from resource c where c.type = 'PM' and a.id = c.res_id) and "
                    + "exists(select * from room d,rack r where a.rack_id = r.id and r.room_id = d.id and d.id = :id) and a.is_deleted = 0";
        } else {
            sql = "select * from server a where not exists(select * from cluster_manager b where b.type = 'PM' and a.id = b.manager_id) "
                    + "and not exists(select * from resource c where c.type = 'PM' and a.id = c.res_id) and "
                    + "exists(select * from data_center f,room d,rack r where a.rack_id = r.id and r.room_id = d.id and d.dc_id = f.id and f.id = :id ) and a.is_deleted = 0";
        }

        Map<String, Object> params = MapTools.simpleMap("id", id);
        return this.list(Server.class, sql, params);
    }

    public Server get(String ip) {
        String sql = "select * from server a where a.is_deleted = 0 and a.manage_ip = :ip";
        Map<String, Object> params = MapTools.simpleMap("ip", ip);
        List<Server> list = this.list(Server.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public List<String> ips() {
        String sql = "select manage_ip from server  where is_deleted = 0";
        List<Server> list = this.list(Server.class, sql);
        List<String> result = new ArrayList<String>();
        for (Server server : list) {
            result.add(server.getManageIp());
        }
        return result;
    }

    public List<String> rackIps(Long rackId) {
        String sql = "select DISTINCT(a.manage_ip) from server a,rack b where a.is_deleted = 0 and a.rack_id = b.id and b.id = :rackId";
        Map<String, Object> params = MapTools.simpleMap("rackId", rackId);
        List<Server> list = this.list(Server.class, sql, params);
        List<String> result = new ArrayList<String>();
        for (Server server : list) {
            result.add(server.getManageIp());
        }
        return result;
    }

    public List<String> roomIps(Long roomId) {
        String sql = "select DISTINCT(a.manage_ip) from server a,rack b,room c where a.is_deleted = 0 and a.rack_id = b.id and b.room_id = c.id and c.id = :roomId";
        Map<String, Object> params = MapTools.simpleMap("roomId", roomId);
        List<Server> list = this.list(Server.class, sql, params);
        List<String> result = new ArrayList<String>();
        for (Server server : list) {
            result.add(server.getManageIp());
        }
        return result;
    }

    public List<String> dcIps(Long dcId) {
        String sql = "SELECT DISTINCT(a.manage_ip) FROM server a,rack b,room c,data_center d WHERE a.is_deleted = 0 AND a.rack_id = b.id AND b.room_id = c.id AND c.dc_id = d.id AND d.id = :dcId ";
        Map<String, Object> params = MapTools.simpleMap("dcId", dcId);
        List<Server> list = this.list(Server.class, sql, params);
        List<String> result = new ArrayList<String>();
        for (Server server : list) {
            result.add(server.getManageIp());
        }
        return result;
    }

    public List<String> nodeIps(Long clusterId) {
        String sql = "select a.manage_ip from server a,cluster_node b,cluster c where a.is_deleted = 0 and a.id = b.node_id and b.cluster_id = c.id and c.id = :clusterId";
        Map<String, Object> params = MapTools.simpleMap("clusterId", clusterId);
        List<Server> list = this.list(Server.class, sql, params);
        List<String> resutl = new ArrayList<String>();
        for (Server server : list) {
            resutl.add(server.getManageIp());
        }
        return resutl;
    }

    public List<String> managerIps(Long clusterId) {
        String sql = "select a.manage_ip from server a,cluster_manager b,cluster c where a.is_deleted = 0 and a.id = b.manager_id and b.cluster_id = c.id and c.id = :clusterId";
        Map<String, Object> params = MapTools.simpleMap("clusterId", clusterId);
        List<Server> list = this.list(Server.class, sql, params);
        List<String> resutl = new ArrayList<String>();
        for (Server server : list) {
            resutl.add(server.getManageIp());
        }
        return resutl;
    }

    public List<RackDevice> positions(Long rackId, String sorter) {
        String sql = "select a.id,a.slot_start,a.slot_num from server a where a.is_deleted = 0 and a.rack_id = :rackId";
        if (sorter.equals(Common.ZERO)) {
            sql += " order by a.slot_start asc";
        } else {
            sql += " order by a.slot_start desc";
        }
        Map<String, Object> paramMap = MapTools.simpleMap("rackId", rackId);
        List<Map<String, Object>> devices = this.list(sql, paramMap);
        List<RackDevice> list = new ArrayList<RackDevice>();
        for (Map<String, Object> map : devices) {
            RackDevice device = new RackDevice();
            device.setDeviceId(Long.parseLong(map.get(Common.ID.toUpperCase()).toString()));
            device.setRackId(rackId);
            device.setSlotNum(Integer.parseInt(map.get("slot_start").toString()));
            device.setSlotStart(Integer.parseInt(map.get("slot_num").toString()));
            list.add(device);
        }
        return list;
    }

    public List<Map<String, String>> getAll4Snmp() {
        String sql = "select uuid,manage_ip from server where is_deleted = 0";
        List<Server> servers = this.list(Server.class, sql);

        List<Map<String, String>> result = new ArrayList<>();
        Map<String, String> map;
        String ip;

        for (Server server : servers) {
            ip = server.getManageIp();
            if (StringUtils.isEmpty(ip)) {
                continue;
            }

            map = new HashMap<>(8);
            map.put("uuid", server.getUuid());
            map.put("ip", ip);
            result.add(map);
        }

        return result;
    }

    public List<Server> listByDataCenter(Long dcId) {
        String sql = "select a.* from server a left join rack b on a.rack_id = b.id left join room c on b.room_id = c.id where a.is_deleted = 0 and c.dc_id = '"
                + dcId + "'";
        return this.list(Server.class, sql);
    }

    public List<Server> listByRoom(Long roomId) {
        String sql = "select a.* from server a left join rack b on a.rack_id = b.id where a.is_deleted = 0 and b.room_id = '"
                + roomId + "'";
        return this.list(Server.class, sql);
    }

    public List<Server> listByRack(Long rackId) {
        String sql = "select a.* from server a where a.is_deleted = 0 and a.rack_id = '" + rackId + "'";
        return this.list(Server.class, sql);
    }

    public Server getByName(String name, Long vendorId) {
        String sql = "select * from server where is_deleted = 0 and name = :name and vendor_id = :vendorId";
        Map<String, Object> param = MapTools.simpleMap("name", name);
        param.put(Common.VENDORID, vendorId);
        List<Server> list = this.list(Server.class, sql, param);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public Server getByHostName(String hostName, Long vendorId) {
        String sql = "select * from server where is_deleted = 0 and hostname = :hostname and vendor_id = :vendorId";
        Map<String, Object> param = MapTools.simpleMap("hostname", hostName);
        param.put(Common.VENDORID, vendorId);
        List<Server> list = this.list(Server.class, sql, param);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

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

    public List<Server> listByVdc(Long vdcId) {
        String sql = "select a.* from server a where a.is_deleted = 0 and a.vdc_id = :vdcId";
        Map<String, Object> params = MapTools.simpleMap("vdcId", vdcId);
        return this.list(Server.class, sql, params);
    }

    public List<Server> listByCluster(Long clusterId) {
        String sql = "select a.* from server a where a.is_deleted = 0 and a.cluster_id = :clusterId";
        Map<String, Object> params = MapTools.simpleMap("clusterId", clusterId);
        return this.list(Server.class, sql, params);
    }

    public List<Server> listByCluster(Long clusterId, Long vendorId) {
        String sql = "select a.* from server a where a.is_deleted = 0 and a.cluster_id = :clusterId and a.vendor_id = :vendorId ";
        Map<String, Object> params = MapTools.simpleMap("clusterId", clusterId);
        params.put("vendorId", vendorId);
        return this.list(Server.class, sql, params);
    }
    
	public List<Server> listByClusters(List<Long> clusterIds, Long vendorId) {
		String sql = "select a.* from server a where a.is_deleted = 0 and a.vendor_id = :vendorId ";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		if (!ListTool.isEmpty(clusterIds)) {
			sql += " and a.cluster_id in (:clusterIds) ";
			params.put("clusterIds", clusterIds);
		}
		return this.list(Server.class, sql, params);
	}

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

    public List<Server> list(int page, int rows, List<Param> params, Map<String, String> sorter, String type)
            throws Exception {
        String sql = "select a.*,b.name cluster_name,c.name vdc_name,d.name vendor_name from server a left join cluster b on a.cluster_id = b.id left join vdc c on a.vdc_id = c.id,cloud_vendor d where a.is_deleted = 0 and a.vendor_id = d.id";
        if (!StringUtils.isEmpty(type)) {
            sql += " and d.type = '" + type + "'";
        }
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        return this.list(Server.class, sql, paramMap);
    }

    public int count(List<Param> params, String type) {
        String sql = "select count(1) from server a,cloud_vendor b where a.is_deleted = 0 and a.vendor_id = b.id";
        if (!StringUtils.isEmpty(type)) {
            sql += " and b.type = '" + type + "'";
        }
        sql = QueryBuilder.buildRaw(sql, params, null, "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        return this.countQuery(sql, paramMap).intValue();
    }

    public List<Server> list(Long vendorId, String type) {
        String sql = "select a.*,b.name vendor_name from server a,cloud_vendor b where a.is_deleted = 0 and a.vendor_id = b.id";
        if (!StringUtils.isEmpty(type)) {
            sql += " and b.type = '" + type + "'";
        }
        Map<String, Object> params = new HashMap<>(8);
        if (null != vendorId) {
            sql += " and a.vendor_id = :vendorId";
            params.put(Common.VENDORID, vendorId);
        }
        return this.list(Server.class, sql, params);
    }

    public List<Server> listAll() {
        String sql = "select a.*,b.name cluster_name,c.name vdc_name,d.name vendor_name from server a left join cluster b on a.cluster_id = b.id left join vdc c on a.vdc_id = c.id,cloud_vendor d where a.is_deleted = 0 and a.vendor_id = d.id";
        return this.list(Server.class, sql);
    }

    public boolean deleteByCluster(Long clusterId, Long userId) {
        String sql = "update server set is_deleted = true , gmt_modify = :gmtModify ,mender_id = :menderId where is_deleted = 0 and cluster_id = :clusterId";
        Map<String, Object> params = MapTools.simpleMap("clusterId", clusterId);
        params.put("menderId", userId);
        params.put("gmtModify", new Date());
        return this.execute(sql, params) > 0;
    }

    public List<Server> listByStore(Long storeId) {
        String sql = "select a.* from server a,store_host b where a.is_deleted = 0 and a.id = b.vhost_id and b.category = 'PM' and b.store_id = :storeId";
        Map<String, Object> params = MapTools.simpleMap("storeId", storeId);
        return this.list(Server.class, sql, params);
    }

    public List<Server> listByIds(List<Long> ids) {
        String sql = "select  a.* from server a where a.id in (:ids) and a.is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("ids", ids);
        return this.list(Server.class, sql, params);
    }

    public int count(String category, Long targetId, List<Param> params) {
        String sql = null;
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (category.equals(ResourceCategory.Storage.name())) {
            sql = "select DISTINCT count(a.id) from server a,store_host b where a.is_deleted = 0 and a.id = b.vhost_id and b.category = 'PM' and b.store_id = :targetId";
            paramMap.put("targetId", targetId);
        } else if (category.equals(ResourceCategory.Network.name())) {
            sql = "select DISTINCT count(a.id) from server a,network_host b where a.is_deleted = 0 and a.id = b.vhost_id and b.category = 'PM' and b.network_id = :targetId";
            paramMap.put("targetId", targetId);
        } else {
            sql = "select DISTINCT count(a.id) from server a where a.is_deleted = 0";
        }
        sql = QueryBuilder.buildRaw(sql, params, null, "a");
        return this.countQuery(sql, paramMap).intValue();
    }

    public List<Server> listServers(int page, int rows, List<Param> params, Map<String, String> sorter, Long targetId,
                                    String category) {
        String sql = null;
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (category.equals(ResourceCategory.Storage.name())) {
            sql = "select DISTINCT a.* from server a,store_host b where a.is_deleted = 0 and a.id = b.vhost_id and b.category = 'PM' and b.store_id = :targetId";
            paramMap.put("targetId", targetId);
        } else if (category.equals(ResourceCategory.Network.name())) {
            sql = "select DISTINCT a.* from server a,network_host b where a.is_deleted = 0 and a.id = b.vhost_id and b.category = 'PM' and b.network_id = :targetId";
            paramMap.put("targetId", targetId);
        } else {
            sql = "select DISTINCT a.*,b.name vendor_name from server a left join cloud_vendor b on a.vendor_id = b.id where a.is_deleted = 0";
        }
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        return this.list(Server.class, sql, paramMap);
    }

    public Long queryIdByUuid(String uuid) {
        String sql = "select id from server a where a.is_deleted = 0 and a.uuid = :uuid";
        Map<String, Object> params = MapTools.simpleMap("uuid", uuid);
        List<Server> list = this.list(Server.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0).getId();
    }

    public Server getByUuid(String uuid) {
        String sql = "select * from server a where a.is_deleted = 0 and a.uuid = :uuid";
        Map<String, Object> params = MapTools.simpleMap("uuid", uuid);
        List<Server> list = this.list(Server.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public List<Server> getByAssetCategory(String assetCategory) {
        String sql = "select * from server a where a.is_deleted = 0 and a.asset_category = :assetCategory";
        Map<String, Object> params = MapTools.simpleMap("assetCategory", assetCategory);
        return this.list(Server.class, sql, params);
    }

    public Server getByNodeId(String rackhdNodeId) {
        String sql = "select * from server a where a.is_deleted = 0 ";
        Map<String, Object> params = new HashMap<>(8);
        if (rackhdNodeId != null) {
            params.put("rackhdNodeId", rackhdNodeId);
            sql += " and a.rackhd_node_id = :rackhdNodeId";
        }
        List<Server> list = this.list(Server.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public Server getByResourceId(String resourceId) {
        String sql = "select * from server a where a.is_deleted = 0 ";
        Map<String, Object> params = new HashMap<>(8);
        if (resourceId != null) {
            params.put("resource_id", resourceId);
            sql += " and a.resource_id = :resource_id";
        }
        List<Server> list = this.list(Server.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public Server queryByIp(String ip) {
        String sql = "select * from server a where is_deleted = 0 and manage_ip = :ip ";
        Map<String, Object> params = MapTools.simpleMap("ip", ip);
        List<Server> list = this.list(Server.class, sql, params);
        if (!ListTool.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    public List<Server> listServerOutAccessPath(Integer page, Integer rows, Long accessPathId,
                                                Map<String, Object> paramMap, Map<String, String> sorter) {
        String sql = "select a.* from server a where a.is_deleted = 0 and "
                + "a.id not in (select host_id from storage_access_path_gateway where access_path_id = :accessPathId) "
                + "and a.vendor_Id in (select vendor_id from storage_access_path_gateway where access_path_id = :accessPathId)";
        Map<String, Object> sqlParams = new HashMap<>(8);
        sqlParams.put("accessPathId", accessPathId);
        if (paramMap.containsKey("name")) {
            sql += " and a.name like :name";
            sqlParams.put("name", "%" + paramMap.get("name") + "%");
        }
        sql += PageHelper.buildPageSql(page, rows);
        return this.list(Server.class, sql, sqlParams);
    }

    public int countListServerOutAccessPath(Long accessPathId, Map<String, Object> paramMap) {
        String sql = "select count(1) from server a where a.is_deleted = 0 and "
                + "a.id not in (select host_id from storage_access_path_gateway where access_path_id = :accessPathId) "
                + "and a.vendor_Id in (select vendor_id from storage_access_path_gateway where access_path_id = :accessPathId)";
        Map<String, Object> sqlParams = new HashMap<>(8);
        sqlParams.put("accessPathId", accessPathId);
        if (paramMap.containsKey("name")) {
            sql += " and a.name like :name";
            sqlParams.put("name", "%" + paramMap.get("name") + "%");
        }
        return this.countQuery(sql, sqlParams).intValue();
    }

    public List<Server> listServerInAccessPath(Integer page, Integer rows, Long accessPathId,
                                               Map<String, Object> paramMap, Map<String, String> sorter) {
        String sql = "select a.*, b.iqn as iqn from server a "
                + "left join storage_access_path_gateway b on a.id = b.host_id and b.is_deleted = 0 and b.access_path_id=:accessPathId "
                + "where a.is_deleted = 0 and "
                + "a.id in (select host_id from storage_access_path_gateway where access_path_id = :accessPathId and is_deleted = 0)";
        Map<String, Object> sqlParams = new HashMap<>(8);
        sqlParams.put("accessPathId", accessPathId);
        if (paramMap.containsKey("name")) {
            sql += " and a.name like :name";
            sqlParams.put("name", "%" + paramMap.get("name") + "%");
        }
        sql += PageHelper.buildPageSql(page, rows);
        return this.list(Server.class, sql, sqlParams);
    }

    public int countListServerInAccessPath(Long accessPathId, Map<String, Object> paramMap) {
        String sql = "select count(1) from server a "
                + "left join storage_access_path_gateway b on a.id = b.host_id and b.is_deleted = 0 and b.access_path_id=:accessPathId "
                + "where a.is_deleted = 0 and "
                + "a.id in (select host_id from storage_access_path_gateway where access_path_id = :accessPathId and is_deleted=0 )";
        Map<String, Object> sqlParams = new HashMap<>(8);
        sqlParams.put("accessPathId", accessPathId);
        if (paramMap.containsKey("name")) {
            sql += " and a.name like :name";
            sqlParams.put("name", "%" + paramMap.get("name") + "%");
        }
        return this.countQuery(sql, sqlParams).intValue();
    }

    public Integer licenseNodeCount() {
        String sql = "select count(a.id) from server a where a.is_deleted = 0 and a.asset_category in ('BARE_METAL','X86_SERVER','HYPERVISOR','POWER_SERVER')";
        Map<String, Object> paramMap = new HashMap<>(8);
        return this.countQuery(sql, paramMap).intValue();
    }

    public List<Server> listByLabelIds(List<Long> labelIds, Long vendorId) {
        String sql = "select a.* from server a left join server_label b on b.target = a.id and b.type = 'PM' where a.is_deleted = 0 and a.vendor_id = :vendorId and a.status = 'RUNNING'";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and b.label_id in (:labelIds)";
            params.put("labelIds", labelIds);
        }
        return this.list(Server.class, sql, params);
    }

    public List<Server> listByVendorIds(List<Long> vendorIds, JSONObject object) {
        String sql = "select a.*,b.`name` as vendor_name,c.`name` as vdc_name, d.`name` as cluster_name from server a LEFT JOIN cloud_vendor b ON a.vendor_id = b.id LEFT JOIN vdc c ON c.vendor_id = b.id LEFT JOIN cluster d ON a.cluster_id = d.id where a.is_deleted = 0 ";
        Map<String, Object> params = new HashMap<>(8);
        if (!ListTool.isEmpty(vendorIds)) {
            sql += " and a.vendor_id in (:vendorIds)";
            params.put("vendorIds", vendorIds);
        }
        Long clusterId = object.getLong("clusterId");
        String name = object.getString("name");
        if (null != clusterId) {
            sql += " and a.cluster_id = :clusterId ";
            params.put("clusterId", clusterId);
        }
        if (null != name) {
            sql += " and a.name like :name ";
            params.put("name", "%" + name + "%");
        }
        return this.list(Server.class, sql, params);
    }

    public Server getServerBean(Long id) {
        String sql = "select a.*,b.name rackname,e.id room_id,e.name roomname,f.id dc_id,f.name dcname "
                + "from server a left join rack b on a.rack_id = b.id left join room e on b.room_id = e.id "
                + "left join data_center f on e.dc_id = f.id where a.is_deleted = 0 and a.id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        List<Server> list = this.list(Server.class, sql, params);
        return ListTool.isEmpty(list) ? null : list.get(0);
    }

    public List<Map<String, Object>> summary(List<Long> vendorIds, String orderBy) {
        String sql = "SELECT sum(b.cpu_used) / sum(b.cpu_hz) cpu_rate, sum(b.mem_used) / sum(b.memory_capacity) memory_rate, sum(b.disk_used) / sum(b.disk_capacity) disk_rate, c.`name` vendor_name FROM 	`server` a LEFT JOIN server_config b ON b.server_id = a.id LEFT JOIN cloud_vendor c ON c.id = a.vendor_id WHERE a.vendor_id in (:vendorIds) GROUP BY a.vendor_id ORDER BY "
                + orderBy + " DESC";
        return this.list(sql, MapTools.simpleMap("vendorIds", vendorIds));
    }

    public List<Map<String, Object>> serverAllocated(Long vendorId) {
        String sql = "select 'total' as type,count(*) as count from server where is_deleted = 0 and vendor_id = :vendorId union select 'allocated' as type,count(*) as count from server where id in (select host_id from cloud_server where is_deleted = 0 and vendor_id = :vendorId group by host_id)";
        return this.list(sql, MapTools.simpleMap("vendorId", vendorId));
    }
}
