package cn.sagacloud.server.algorithm.services.datacenter


import cn.sagacloud.server.algorithm.backstage.model.datacenter.*
import cn.sagacloud.server.algorithm.models.request.BindFloorRequest
import com.alibaba.fastjson.JSONObject
import com.sybotan.service.models.enums.SResponseType
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.lang.StringBuilder
import java.util.HashSet
import kotlin.math.ceil

/**
 *
 *
 * @author jxing
 */
@Suppress("UNCHECKED_CAST")
@Component
class DataCenterService {
    // 获取数据时, 一次获取多少个数据
    val pageSize = 300
    // 提交数据时, 一次提交多少个数据
    val range = 300
    companion object{
        private val logger = LoggerFactory.getLogger(DataCenterService::class.java)
        /**
         * 生成查询语句
         */
        fun generateSelectStr(floorIds: ArrayList<String>, key : String): String {
            val sb = StringBuilder()
            sb.append("$key in [")
            for (floorId in floorIds) {
                sb.append("'${floorId}',")
            }
            if (sb.endsWith(","))
                sb.deleteCharAt(sb.length - 1)
            sb.append("]")
            return sb.toString()
        }
    }
    @Autowired
    lateinit var request : DataCenterRequest

    /**
     * 根据楼层id获取楼层
     */
    fun getFloor(floorIds : ArrayList<String>, projectId: String) : ArrayList<DCFloor>?{
        val body = QueryRequest()
        body.filters = generateSelectStr(floorIds, "floorId")
        val response = request.floorQuery(body, projectId)
        if(response != null && response.result == "success")
            return response.content
        return null
    }

    fun getFloorWithModelId(floorId : String, projectId: String) : ArrayList<DCFloor>?{
        val body = QueryRequest()
        body.filters = generateSelectStr(arrayListOf(floorId), "modelId")
        val response = request.floorQuery(body, projectId)
        if(response != null && response.result == "success")
            return response.content
        return null
    }

    /**
     * 根据楼层id获取楼层
     */
    fun getFloor(revitFloorId : String, projectId: String) : ArrayList<DCFloor>?{
        val body = QueryRequest()
        body.filters = generateSelectStr(arrayListOf(revitFloorId), "modelId")
        val response = request.floorQuery(body, projectId)
        if(response != null && response.result == "success")
            return response.content
        return null
    }

    /**
     * 根据id获取建筑
     */
    fun getBuilding(buildingIds : ArrayList<String>, projectId: String) : ArrayList<DCBuilding>?{
        val body = QueryRequest()
        body.filters = generateSelectStr(buildingIds, "id")
        val response = request.buildingQuery(body, projectId)
        if(response != null && response.result == "success")
            return response.content
        return null
    }

    /**
     * 根据资产id获取资产
     */
    fun getPropertyById(propertyIds : ArrayList<String>, projectId: String) : ArrayList<DCProperty>?{
        val body = QueryRequest()
        body.filters = generateSelectStr(propertyIds, "id")
        val response = request.propertyQuery(body, projectId)
        if(response != null && response.result == "success")
            return response.content
        return null
    }

    /**
     * 根据楼层id获取楼层下的设备
     */
    fun getEquipmentByFloorId(floorId: String, projectId: String): HashMap<String, DCEquipment>? {
        val body = QueryRequest()
        body.filters = "floorId in ['$floorId']"
        return getEquipmentWithCondition(body, projectId)
    }//"BIMID startWith '${prefix}'"

    /**
     * 根据BIMID前缀获取设备
     */
    fun getEquipmentByBIMIDPrefix(bimIdPrefix : String, projectId: String): HashMap<String, DCEquipment>? {
        val body = QueryRequest()
        body.filters = "bimId startWith '${bimIdPrefix}'"
        return getEquipmentWithCondition(body, projectId)
    }

    /**
     * 根据QueryRequest对象查询设备
     */
    private fun getEquipmentWithCondition(body: QueryRequest, projectId: String): HashMap<String, DCEquipment>? {
        val map = HashMap<String, DCEquipment>()
        body.pageNumber = 1
        body.pageSize = pageSize
        body.orders = "createTime, id"
        var totalPage = 1
        while (body.pageNumber <= totalPage) {
            val response = request.equipQuery(body, projectId)
            if (response != null && response.result == "success") {
                totalPage = ceil(response.total.toDouble() / response.pageSize).toInt()
                response.content!!.forEach {
                    if (it.id != null)
                        if (!map.containsKey(it.id!!))
                            map[it.id!!] = it//JSON.toJavaObject(it, DCEquipment::javaClass.javaClass)
                        else
                            println(it.id)
                }
                ++body.pageNumber
            } else
                return null
        }
        return map
    }

    /**
     * 根据查询条件获取设备/ 部件/ 元空间
     */
    private fun getObjectByBatch(body: QueryRequest, projectId: String, dcDataType: DCDataType): HashMap<String, DCDataBase>? {
        val map = HashMap<String, DCDataBase>()
        body.pageNumber = 1
        body.pageSize = pageSize
        body.orders = "createTime, id"
        var totalPage = 1
        while (body.pageNumber <= totalPage) {
            //var response : QueryResponse<DCDataBase>? = null
            val response = when(dcDataType){
                DCDataType.component -> {
                    request.componentQuery(body, projectId) as QueryResponse<DCDataBase>?
                }
                DCDataType.equip -> {
                    request.equipQuery(body, projectId) as QueryResponse<DCDataBase>?
                }
                DCDataType.iSpace -> {
                    request.iSpaceQuery(body, projectId) as QueryResponse<DCDataBase>?
                }
            }

            if (response != null && response.result == "success") {
                totalPage = ceil(response.total.toDouble() / response.pageSize).toInt()
                response.content!!.forEach {
                    if (it.bimId != null)
                        if (!map.containsKey(it.bimId!!))
                            map[it.bimId!!] = it
                }
                ++body.pageNumber
            } else
                return null
        }
        return map
    }

    /**
     * 绑定楼层
     */
    fun bindFloor(body: BindFloorRequest, projectId: String): Boolean{
        val result = request.bindFloor(body, projectId)
        if(result != null && "success".equals(result.result))
            return true
        return false
    }


    /**
     * 根据查询条件获取设备/ 部件/ 元空间
     */
    private fun getJSONObjectByBatch(body: QueryRequest, projectId: String, dcDataType: DCDataType): HashMap<String, JSONObject>? {
        val map = HashMap<String, JSONObject>()
        body.pageNumber = 1
        body.pageSize = pageSize
        body.orders = "createTime, id"
        var totalPage = 1
        while (body.pageNumber <= totalPage) {
            val response = when(dcDataType){
                DCDataType.component -> {
                    request.componentQueryJSONObject(body, projectId)
                }
                DCDataType.equip -> {
                    request.equipQueryJSONObject(body, projectId)
                }
                DCDataType.iSpace -> {
                    request.iSpaceQueryJSONObject(body, projectId)
                }
            }

            if (response != null && response.result == "success") {
                totalPage = ceil(response.total.toDouble() / response.pageSize).toInt()
                response.content!!.forEach {
                    if (it.getString("bimId") != null)
                        if (!map.containsKey(it.getString("bimId")!!))
                            map[it.getString("bimId")!!] = it
                }
                ++body.pageNumber
            } else
                return null
        }
        return map
    }

    /**
     * 根据楼层id获取楼层下部件
     */
    fun getComponentByFloorId(floorId: String, projectId: String): HashMap<String, DCComponent>? {
        val body = QueryRequest()
        body.filters = "floorId in ['$floorId']"
        return getComponent(body, projectId)
    }

    /**
     * 根据BINID前缀获取部件
     */
    fun getComponentByBIMIDPrefix(bimIdPrefix: String, projectId: String): HashMap<String, DCComponent>? {
        val body = QueryRequest()
        body.filters = "bimId startWith '${bimIdPrefix}'"
        return getComponent(body, projectId)
    }


    /**
     * 根据QueryRequest对象获取部件
     */
    private fun getComponent(body: QueryRequest, projectId: String): HashMap<String, DCComponent>? {
        val map = HashMap<String, DCComponent>()
        body.pageNumber = 1
        body.pageSize = pageSize
        body.orders = "createTime, id"
        var totalPage = 1
        while (body.pageNumber <= totalPage) {
            val response = request.componentQuery(body, projectId)
            if (response != null && response.result == "success") {
                totalPage = ceil(response.total.toDouble() / response.pageSize).toInt()
                response.content!!.forEach {
                    if (it.id != null)
                        if (!map.containsKey(it.id!!))
                            map[it.id!!] = it
                        else
                            println(it.id)
                }
                ++body.pageNumber
            } else
                return null
        }
        return map
    }

    /**
     * 根据楼层id获取楼层下的元空间
     */
    fun getISpaceByFloorId(floorId: String, projectId: String): HashMap<String, DCISpace>? {
        val body = QueryRequest()
        body.filters = "floorId in ['$floorId']"
        return getISpace(body, projectId)
    }

    /**
     * 根据BIMID前缀获取元空间
     */
    fun getISpaceByBIMIDPrefix(bimIdPrefix: String, projectId: String): HashMap<String, DCISpace>? {
        val body = QueryRequest()
        body.filters = "bimId startWith '${bimIdPrefix}'"
        return getISpace(body, projectId)
    }

    /**
     * 根据QueryRequest对象获取元空间
     */
    fun getISpace(body: QueryRequest, projectId: String): HashMap<String, DCISpace>? {
        val map = HashMap<String, DCISpace>()
        body.pageNumber = 1
        body.orders = "createTime, id"
        body.pageSize = pageSize
        var totalPage = 1
        while(body.pageNumber <= totalPage) {
            val response = request.iSpaceQuery(body, projectId)
            if (response != null && response.result == "success") {
                totalPage = ceil(response.total.toDouble() / response.pageSize).toInt()
                response.content!!.forEach {
                    if(it.id != null)
                        map[it.id!!] = it
                }
                ++body.pageNumber
            } else
                return null
        }
        return map
    }

    /**
     * 创建设备
     */
    fun equipCreate(createList: ArrayList<DCEquipment>, projectId: String?, out: ArrayList<DCEquipment>) : Boolean{
        val createRequest = CreateRequest<DCEquipment>()
        createRequest.content = createList
        val result = request.equipCreate(createRequest, projectId!!)
        if(result != null &&"success" == result.result){
            if(result.entityList != null)
                out.addAll(result.entityList!!)
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 创建模型构件到数据中心
     */
    fun modelComponentCreate(createList: ArrayList<Any>, projectId: String?, operator : DataCenterOperator) : Boolean{
        return true
//        val createRequest = CreateRequest<Any>()
//        createRequest.content = createList
//        val result = request.modelComponentCreate(createRequest, projectId!!, operator)
//        if(result != null && result.result == SResponseType.success){
//            return true
//        }
//        logger.error(result.toString())
//        return false
    }

    /**
     * 删除设备
     */
    fun equipDelete(deleteList: ArrayList<DCEquipment>, projectId: String?) : Boolean {
        val result = request.equipDelete(deleteList, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 更新设备
     */
    fun equipUpdate(updateList: ArrayList<DCEquipment>, projectId: String?) : Boolean {
        val updateRequest = UpdateRequest<DCEquipment>()
        updateRequest.content = updateList
        val result = request.equipUpdate(updateRequest, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 创建设备
     */
    fun componentCreate(createList: ArrayList<DCComponent>, projectId: String?, out: ArrayList<DCComponent>) : Boolean{
        val createRequest = CreateRequest<DCComponent>()
        createRequest.content = createList
        val result = request.componentCreate(createRequest, projectId!!)
        if(result != null && "success" == result.result){
            if(result.entityList != null)
                out.addAll(result.entityList!!)
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 删除部件
     */
    fun componentDelete(deleteList: ArrayList<DCComponent>, projectId: String?) : Boolean {
        val result = request.componentDelete(deleteList, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 更新部件
     */
    fun componentUpdate(updateList: ArrayList<DCComponent>, projectId: String?) : Boolean {
        val updateRequest = UpdateRequest<DCComponent>()
        updateRequest.content = updateList
        val result = request.componentUpdate(updateRequest, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 更新资产
     */
    fun propertyUpdate(updateList: ArrayList<DCProperty>, projectId: String?) : Boolean {
        val updateRequest = UpdateRequest<DCProperty>()
        updateRequest.content = updateList
        val result = request.propertyUpdate(updateRequest, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 元空间更新
     */
    fun iSpaceCreate(createList: ArrayList<DCISpace>, projectId: String?) : Boolean{
        val createRequest = CreateRequest<DCISpace>()
        createRequest.content = createList
        val result = request.iSpaceCreate(createRequest, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 删除元空间
     */
    fun iSpaceDelete(deleteList: ArrayList<DCISpace>, projectId: String?) : Boolean {
        val result = request.iSpaceDelete(deleteList, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 更新元空间
     */
    fun iSpaceUpdate(updateList: ArrayList<DCISpace>, projectId: String?) : Boolean {
        val updateRequest = UpdateRequest<DCISpace>()
        updateRequest.content = updateList
        val result = request.iSpaceUpdate(updateRequest, projectId!!)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 根据BIMID set获取对应的设备
     */
    fun getEquipmentByBimIdSet(parentBimId: HashSet<String>, projectId: String): HashMap<String, DCEquipment>? {
        val queryRequest = QueryRequest()
        val sb = StringBuilder()
        sb.append("bimId in [")
        parentBimId.forEach {
            sb.append("'").append(it).append("',")
        }
        if(sb.endsWith(","))
            sb.deleteCharAt(sb.length - 1)
        sb.append("]")
        queryRequest.filters = sb.toString()
        return getObjectByBatch(queryRequest, projectId, DCDataType.equip) as HashMap<String, DCEquipment>?
    }

    /**
     * 获取对象的JSONObject
     */
    fun getDCDataByBimIdPrefix(prefix : String, projectId: String, dcDataType: DCDataType): HashMap<String, JSONObject>? {
        val queryRequest = QueryRequest()
        val sb = StringBuilder()
        sb.append("bimId startWith '${prefix}'")
        queryRequest.filters = sb.toString()
        return getJSONObjectByBatch(queryRequest, projectId, dcDataType)
    }

    /**
     * 楼层更新
     */
    fun floorUpdate(dcFloor: DCFloor, projectId: String) : Boolean{
        val updateRequest = UpdateRequest<DCFloor>()
        updateRequest.content = arrayListOf(dcFloor)
        val result = request.floorUpdate(updateRequest, projectId)
        if(result != null && "success" == result.result){
            return true
        }
        logger.error(result.toString())
        return false
    }

    /**
     * 同步对象
     */
    fun sync(arr: ArrayList<Any>, out: ArrayList<Any>?, projectId: String?, operator: DataCenterOperator){
        var index = 0
        val tmp = ArrayList<Any>()
        while(index < arr.size) {
            if(index + range <= arr.size)
                tmp.addAll(arr.subList(index, index + range))
            else
                tmp.addAll(arr.subList(index, arr.size))
            when(operator){
                DataCenterOperator.componentCreate ->{
                    if (!componentCreate(tmp as ArrayList<DCComponent>, projectId, out as ArrayList<DCComponent>))
                        throw Exception("创建部件失败")
                }
                DataCenterOperator.componentDelete ->{
                    if (!componentDelete(tmp as ArrayList<DCComponent>, projectId))
                        throw Exception("删除部件失败")
                }
                DataCenterOperator.componentUpdate ->{
                    if (!componentUpdate(tmp as ArrayList<DCComponent>, projectId))
                        throw Exception("更新部件失败")
                }
                DataCenterOperator.equipCreate ->{
                    if (!equipCreate(tmp as ArrayList<DCEquipment>, projectId, out as ArrayList<DCEquipment>))
                        throw Exception("创建设备失败")
                }
                DataCenterOperator.equipDelete ->{
                    if (!equipDelete(tmp as ArrayList<DCEquipment>, projectId))
                        throw Exception("删除设备失败")
                }
                DataCenterOperator.equipUpdate ->{
                    if (!equipUpdate(tmp as ArrayList<DCEquipment>, projectId))
                        throw Exception("更新设备失败")
                }
                DataCenterOperator.iSpaceCreate ->{
                    if (!iSpaceCreate(tmp as ArrayList<DCISpace>, projectId))
                        throw Exception("创建元空间失败")
                }
                DataCenterOperator.iSpaceDelete ->{
                    if (!iSpaceDelete(tmp as ArrayList<DCISpace>, projectId))
                        throw Exception("删除元空间失败")
                }
                DataCenterOperator.iSpaceUpdate ->{
                    if (!iSpaceUpdate(tmp as ArrayList<DCISpace>, projectId))
                        throw Exception("更新元空间失败")
                }
                DataCenterOperator.windowCreate ->{
                    if(!modelComponentCreate(tmp, projectId, operator))
                        throw Exception("添加构件-窗户失败")
                }
                DataCenterOperator.doorCreate ->{
                    if(!modelComponentCreate(tmp, projectId, operator))
                        throw Exception("添加构件-门失败")
                }
                DataCenterOperator.virtualWallCreate ->{
                    if(!modelComponentCreate(tmp, projectId, operator))
                        throw Exception("添加构件-虚拟墙失败")
                }
            }
            tmp.clear()
            index += range
        }
    }

    /**
     * 获取项目下所有CADID不为null且BIMID为null的设备
     */
    fun getEquipmentByCADID(projectId: String): java.util.HashMap<String, DCEquipment>? {
        val body = QueryRequest()
        body.filters = "bimId isnull ; not cadId isnull"
        return getEquipmentWithCondition(body, projectId)
    }

    fun getComponentByCADID(projectId: String): HashMap<String, DCComponent>? {
        val body = QueryRequest()
        body.filters = "bimId isnull ; not cadId isnull"
        return getComponent(body, projectId)
    }

    /**
     * 枚举数据中心操作
     */
    enum class DataCenterOperator{
        equipCreate, equipDelete, equipUpdate, componentCreate, componentDelete, componentUpdate, iSpaceCreate,
        iSpaceDelete, iSpaceUpdate, windowCreate, virtualWallCreate, doorCreate
    }

    /**
     * 枚举数据中心对象类型
     */
    enum class DCDataType{
        equip, iSpace, component
    }
}