package com.bocloud.ims.repository.topology;

import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.ims.entity.topology.InstanceRelation;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

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

/**
 * InstanceRelation Dao层
 *
 * @author lyy
 * @Version 1.0
 * @since 2017年9月15日
 */
@Repository("instanceRelationRepository")
public class InstanceRelationRepository extends BasicGenericDao<InstanceRelation, Long> {

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

    public InstanceRelation query(Long id) throws Exception {
        String sql = "select * from ci_instance_relation where id = :id";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, params);
        if (instanceRelations.isEmpty()) {
            return null;
        }
        return instanceRelations.get(0);

    }

    public boolean delete(Long id) throws Exception {
        String sql = "update ci_instance_relation set is_deleted=1 where id = :id";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        return this.execute(sql, params) > 0;
    }

    public List<InstanceRelation> queryByInstanceIdAndCategoryId(Long id, Long categoryId) throws Exception {
        String sql = "select * from ci_instance_relation a where a.category_id=:categoryId and (a.source_id = :id or a.target_id = :id) "
                + "and is_deleted = 0 and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module_relation c where a.module_relation_id=c.id  and c.is_deleted=0)";
        Map<String, Object> paramMap = MapTools.simpleMap("id", id);
        paramMap.put("categoryId", categoryId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, paramMap);
        return instanceRelations;
    }

    public Map<String, List<InstanceRelation>> queryAll4Cache() throws Exception {
        String sql = "select * from ci_instance_relation a where  is_deleted = 0  "
                + "and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module_relation c where a.module_relation_id=c.id  and c.is_deleted=0)";
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, null);
        Map<String, List<InstanceRelation>> result = Maps.newHashMap();
        for (InstanceRelation instanceRelation : instanceRelations) {
            if (!result.containsKey(instanceRelation.getSourceId() + "$$" + instanceRelation.getCategoryId())) {
                result.put(instanceRelation.getSourceId() + "$$" + instanceRelation.getCategoryId(),
                        Lists.newArrayList());
                result.get(instanceRelation.getSourceId() + "$$" + instanceRelation.getCategoryId())
                        .add(instanceRelation);
            } else {
                result.get(instanceRelation.getSourceId() + "$$" + instanceRelation.getCategoryId())
                        .add(instanceRelation);
            }
            if (!result.containsKey(instanceRelation.getTargetId() + "$$" + instanceRelation.getCategoryId())) {
                result.put(instanceRelation.getTargetId() + "$$" + instanceRelation.getCategoryId(),
                        Lists.newArrayList());
                result.get(instanceRelation.getTargetId() + "$$" + instanceRelation.getCategoryId())
                        .add(instanceRelation);
            } else {
                result.get(instanceRelation.getTargetId() + "$$" + instanceRelation.getCategoryId())
                        .add(instanceRelation);
            }
        }
        return result;
    }

    public int countQueryByInstanceIdAndCategoryId(Long id, Long categoryId) throws Exception {
        String sql = "select count(1) from ci_instance_relation a where a.category_id=:categoryId and (a.source_id = :id or a.target_id = :id) "
                + "and is_deleted = 0 and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module_relation c where a.module_relation_id=c.id  and c.is_deleted=0)";
        Map<String, Object> paramMap = MapTools.simpleMap("id", id);
        paramMap.put("categoryId", categoryId);
        return this.countQuery(sql, paramMap).intValue();
    }

    public List<InstanceRelation> queryByInstanceIdAndModuleRelationId(Long instanceId, Long relationId)
            throws Exception {
        String sql = "select * from ci_instance_relation a where (a.source_id = :instanceId or a.target_id = :instanceId)"
                + " and a.module_relation_id=:relationId and is_deleted = 0 "
                + "and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0)";
        Map<String, Object> paramMap = MapTools.simpleMap("instanceId", instanceId);
        paramMap.put("relationId", relationId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, paramMap);
        return instanceRelations;
    }

    public InstanceRelation queryBySourceIdAndTargetId(Long sourceId, Long targetId, Long relationId) throws Exception {
        String sql = "select * from ci_instance_relation a where (a.source_id = :sourceId and a.target_id = :targetId)"
                + " and a.module_relation_id=:relationId and is_deleted = 0 "
                + "and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0)";
        Map<String, Object> paramMap = MapTools.simpleMap("sourceId", sourceId);
        paramMap.put("targetId", targetId);
        paramMap.put("relationId", relationId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, paramMap);
        if (instanceRelations.isEmpty()) {
            return null;
        }
        return instanceRelations.get(0);
    }

    public List<InstanceRelation> queryByInstanceId(Long sourceId, Long targetId, Long categoryId) throws Exception {
        String sql = "select * from ci_instance_relation a where a.category_id=:categoryId and (a.source_id = :sourceId or a.target_id = :targetId) "
                + "and is_deleted = 0 and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0)";
        Map<String, Object> paramMap = MapTools.simpleMap("sourceId", sourceId);
        paramMap.put("targetId", targetId);
        paramMap.put("categoryId", categoryId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, paramMap);
        return instanceRelations;
    }

    public int countUsedByRelation(Long relationId) throws Exception {
        String sql = "select count(1) from ci_instance_relation a where  a.module_relation_id=:relationId and is_deleted = 0 "
                + "and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) and "
                + "exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0)";
        Map<String, Object> params = MapTools.simpleMap("relationId", relationId);
        return this.countQuery(sql, params).intValue();
    }

    public boolean deleteByRelationId(Long relationId) throws Exception {
        String sql = "update ci_instance_relation set is_deleted=1 where module_relation_id=:relationId and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("relationId", relationId);
        return this.execute(sql, params) > 0;
    }

    public List<InstanceRelation> queryByModuleRelationId(Long moduleRelationId) throws Exception {
        String sql = "select * from ci_instance_relation where module_relation_id = :moduleRelationId and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("moduleRelationId", moduleRelationId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, params);
        return instanceRelations;
    }

    public boolean deleteByModuleId(Long moduleId) throws Exception {
        String sql = "update ci_instance_relation set is_deleted=1 where "
                + "(source_module_id = :moduleId or target_module_id = :moduleId) and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("moduleId", moduleId);
        return this.execute(sql, params) > 0;
    }

    public boolean deleteByInstanceId(Long id) throws Exception {
        String sql = "update ci_instance_relation set is_deleted=1 "
                + "where (source_id = :id or target_id = :id) and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        return this.execute(sql, params) > 0;
    }

    public boolean deleteByInstanceIdOnlyAuto(Long id) throws Exception {
        String sql = "update ci_instance_relation set is_deleted=1 "
                + "where (source_id = :id or target_id = :id) and is_deleted = 0 and is_manual = 0";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        return this.execute(sql, params) > 0;
    }

    public List<InstanceRelation> queryByInstanceId(Long instanceId) throws Exception {
        String sql = "select * from ci_instance_relation a where  (a.source_id = :sourceId or a.target_id = :targetId) "
                + "and is_deleted = 0 and exists(select 1 from ci_module m where a.source_module_id=m.id and m.is_deleted=0 and m.is_disabled=0) "
                + "and exists(select 1 from ci_module m where a.target_module_id=m.id and m.is_deleted=0 and m.is_disabled=0)";
        Map<String, Object> paramMap = MapTools.simpleMap("sourceId", instanceId);
        paramMap.put("targetId", instanceId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, paramMap);
        return instanceRelations;
    }

    public boolean batchDelete(List<Long> ids) throws Exception {
        String sql = "update ci_instance_relation set is_deleted=1 where id in (:ids)";
        Map<String, Object> params = MapTools.simpleMap("ids", ids);
        return this.execute(sql, params) > 0;
    }

    public InstanceRelation queryByInstanceAndRelationId(Long instance, Long moduleRelationId, Boolean isSource)
            throws Exception {
        String sql = "SELECT * from ci_instance_relation WHERE module_relation_id = :moduleRelationId and is_deleted = 0 ";
        if (isSource) {
            sql += "and source_id = :instance ";
        } else {
            sql += "and target_id = :instance ";
        }
        Map<String, Object> paramMap = MapTools.simpleMap("instance", instance);
        paramMap.put("moduleRelationId", moduleRelationId);
        List<InstanceRelation> instanceRelations = this.list(InstanceRelation.class, sql, paramMap);
        if (instanceRelations.isEmpty()) {
            return null;
        }
        return instanceRelations.get(0);
    }

}
