package com.persagy.server.services.task

import cn.sagacloud.server.scanbuilding.User
import com.alibaba.fastjson.JSONObject
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.persagy.base.extensions.toJson
import com.persagy.database.SFilter
import com.persagy.database.SPageQueryInfo
import com.persagy.mybatis.SMybatisDao
import com.persagy.server.datacenter.models.entities.assistant.TaskPic
import com.persagy.server.datacenter.models.entities.dict.EquipCategory
import com.persagy.server.datacenter.models.entities.objects.Equipment
import com.persagy.server.datacenter.models.entities.task.*
import com.persagy.server.datacenter.models.requests.ModelScanSQueryRequest
import com.persagy.server.mappers.StatisticsCountMapper
import com.persagy.server.scanbuilding.UserLog
import com.persagy.server.services.EquipmentService
import com.persagy.server.services.base.RService
import com.persagy.server.util.IdUtils
import com.persagy.service.SBaseService
import com.persagy.service.SObjectService
import com.persagy.service.SPageContext
import com.persagy.service.models.enums.SResponseType
import com.persagy.service.models.requests.SCreateRequest
import com.persagy.service.models.requests.SQueryRequest
import com.persagy.service.models.responses.SQueryResponse
import com.persagy.service.utils.SSpringContextUtil
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.RequestBody
import java.util.*
import kotlin.collections.ArrayList


/**
 * 模型任务
 *
 * @author  邓婷婷
 */
object ModelScanTaskService : RService<ModelScanTask>(SMybatisDao(ModelScanTask::class.java))  {

    // 日志
    private val logger = LoggerFactory.getLogger(ModelScanTaskService::class.java)


    val modelScanTaskService = SBaseService(SMybatisDao(ModelScanTask::class.java))
    /** 设备类型 */
    val equipCategoryService = SObjectService(SMybatisDao(EquipCategory::class.java))
    /** 扫楼日志 */
    var userLogService = SObjectService(SMybatisDao(UserLog::class.java))
    /** 用户 */
    var userService = SObjectService(SMybatisDao(User::class.java))


    /** 实例化 mapper 对象 */
    val mapper by lazy {
        SSpringContextUtil.getBean(StatisticsCountMapper::class.java) as StatisticsCountMapper
    }


    /**
     * 插入之前先过滤已经存在未验证任务的对象，返回新列表
     */
    fun createBefore(@RequestBody request: SCreateRequest<ModelScanTask>): SCreateRequest<ModelScanTask> {
        val modelList = request.content;
        var newList = arrayListOf<ModelScanTask>()
        for(model in modelList){
            val modelTask = ModelScanTaskService.select("equipId" to model.equipId!!,"taskState" to 1).entity()
            if(modelTask==null){//表示当前设备不存在未验证的任务
                newList.add(model)
            }
        }

        request.content = newList
        println(newList.size)
        return request
    } // Fun createBefore

    /**
     * 创建之前操作
     */
    override fun onCreateBefore(modelScanTask: ModelScanTask): Boolean  {
        try {
                val gson = Gson()
                var flag = false
                if (modelScanTask.taskState == -1) {//前台传数据过来状态为-1 表示当前任务是未找到状态 重新生成任务，将之前的设备任务状态和部件任务改为已完成
                    flag = true
                    resetTaskStatus(modelScanTask)
                }
                val projectId = SPageContext.getHeader("ProjectId")
//                if (modelScanTask.id.isNullOrEmpty()) {
                    modelScanTask.id = UUID.randomUUID().toString()
//                }
                if (!projectId.isNullOrEmpty()) {
                    modelScanTask.projectId = projectId
                }
                modelScanTask.taskSource = 1//数据源为模型
                modelScanTask.taskState = 1//任务状态为待验证
                modelScanTask.taskType = "1"

                if (!modelScanTask.equipId.isNullOrEmpty()) {//当设备id不为空时，去设备表查询对应的详细信息
                    val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
                    val equipment = equipmentService.select("id" to modelScanTask.equipId!!).entity()

                    if (modelScanTask.schemeId.isNullOrEmpty()){
                        modelScanTask.schemeId = SchemeUtils.setScheme(equipment!!.category!!)
                    }

//                equipment.ledgerParam.PhotoDoc.Pic
                    if(equipment!!.ledgerParam != null){//设备图片信息
                        val photoDoc = equipment!!.ledgerParam!!.get("PhotoDoc")
                        if( photoDoc != null){
                            val obj = JSONObject.parseObject(photoDoc!!.toJson())
                            val pic = obj.getString("Pic")

                            val type = object : TypeToken<ArrayList<TaskPic>>() {
                            }.type
                            val siInSpList = gson.fromJson<ArrayList<TaskPic>>(pic, type)
                            modelScanTask.taskPicList = siInSpList
                        }

                        val siteinstall =  equipment!!.ledgerParam!!.get("Siteinstall")//安装位置
                        if(siteinstall != null){
                            val obj = JSONObject.parseObject(siteinstall!!.toJson())
                            val installLocation = obj.getString("InstallLocation")

                            modelScanTask.installLocation = installLocation
                        }
                    }

                    try {
                        if (!equipment.ledgerParam.isNullOrEmpty()){
                            val containsKey = equipment.ledgerParam!!.containsKey("EquipManufactor")
                            if (containsKey){
                                val jsonObject = JSONObject.parseObject(equipment.ledgerParam!!["EquipManufactor"]!!.toJson())
                                var date = jsonObject.get("Manufacturer")
                                if (date != null && !date.toString().isNullOrEmpty()) {
                                    modelScanTask.manufacturer = date.toString()
                                }
                                var specification = jsonObject.get("Specification")
                                if (specification != null && !specification.toString().isNullOrEmpty()) {
                                    modelScanTask.specification = specification.toString()
                                }
                            }

                            val containsKeys = equipment.ledgerParam!!.containsKey("SupplyPurchase")
                            if (containsKeys){
                                val jsonObject = JSONObject.parseObject(equipment.ledgerParam!!["SupplyPurchase"]!!.toJson())
                                var date = jsonObject.get("Supplier")
                                if (date != null && !date.toString().isNullOrEmpty()) {
                                    modelScanTask.supplier = date.toString()
                                }
                            }

                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }

                    if (flag) {
                        modelScanTask.equipName = equipment!!.name
                        modelScanTask.localId = equipment!!.localId
                        modelScanTask.localName = equipment!!.localName
                        modelScanTask.bimId = equipment!!.bimId
                        modelScanTask.category = equipment!!.category
                        modelScanTask.buildingId = equipment!!.buildingId
                        modelScanTask.floorId = equipment!!.floorId
                        modelScanTask.cadId = equipment!!.cadId
                        modelScanTask.bimLocation = equipment.bimLocation

                        if (equipment.codeType!=null){
                            modelScanTask.taskType = equipment.codeType.toString()
                        }else{
                            modelScanTask.taskType = "1"
                        }
                    } else {

                        if (modelScanTask.equipName.isNullOrEmpty()) {
                            modelScanTask.equipName = equipment!!.name
                        }
                        if (modelScanTask.localId.isNullOrEmpty()) {
                            modelScanTask.localId = equipment!!.localId
                        }
                        if (modelScanTask.localName.isNullOrEmpty()) {
                            modelScanTask.localName = equipment!!.localName
                        }
                        if (modelScanTask.bimId.isNullOrEmpty()) {
                            modelScanTask.bimId = equipment!!.bimId
                        }
                        if (modelScanTask.category.isNullOrEmpty()) {
                            modelScanTask.category = equipment!!.category
                        }
                        if (modelScanTask.buildingId.isNullOrEmpty()) {
                            modelScanTask.buildingId = equipment!!.buildingId
                        }
                        if (modelScanTask.floorId.isNullOrEmpty()) {
                            modelScanTask.floorId = equipment!!.floorId
                        }
                        if (modelScanTask.cadId.isNullOrEmpty()) {
                            modelScanTask.cadId = equipment!!.cadId
                        }

                        if (modelScanTask.bimLocation.isNullOrEmpty()){
                            modelScanTask.bimLocation = equipment.bimLocation
                        }

                        if (modelScanTask.taskType.isNullOrEmpty()){
                            if (equipment.codeType!=null){
                                modelScanTask.taskType = equipment.codeType.toString()
                            }else{
                                modelScanTask.taskType = "1"
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                    e.printStackTrace()
            }
      return true
    } // Function onCreateBefore()

    /**
     * 创建设备台账任务成功之后，设备级联部件，所有部件也增加任务
     */
    override fun onCreateSuccess(modelScanTaskList: ArrayList<ModelScanTask>) {
        val projectId = SPageContext.getHeader("ProjectId")

        for(task in modelScanTaskList){
            val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
            val componentList = equipmentService.select("parentId" to task.equipId!!).exec()

            for(equipment in componentList){
                val modelScanTask = ModelScanTask()
                modelScanTask.id = IdUtils.uuidCreate()
                if(!task.projectId.isNullOrEmpty()){
                    modelScanTask.projectId = task.projectId
                }else{
                    modelScanTask.projectId = projectId
                }
                modelScanTask.taskSource = 4//数据源为模型任务
                modelScanTask.taskState = 1//任务状态为待验证
                modelScanTask.parentId = task.equipId
                modelScanTask.equipId = equipment!!.id
                modelScanTask.equipName = equipment!!.name
                modelScanTask.localId = equipment!!.localId
                modelScanTask.localName = equipment!!.localName
                modelScanTask.bimId = equipment!!.bimId
                modelScanTask.category = equipment!!.category
                modelScanTask.buildingId = equipment!!.buildingId
                modelScanTask.floorId = equipment!!.floorId
                modelScanTask.cadId = equipment!!.cadId
                modelScanTask.bimLocation = equipment.bimLocation
                modelScanTask.taskParentId = task.id
                if (equipment.codeType!=null){
                    modelScanTask.taskType = equipment.codeType.toString()
                }else{
                    modelScanTask.taskType = "1"
                }
                ModelScanTaskService.insert(modelScanTask)
            }
            resetObjStatus(task)
        }
    } // Fun onCreateSuccess



    /**
     * 状态修改完成之后，若修改为  已完成状态  则级联部件任务状态全部修改为  已完成
     */
    override fun onUpdateSuccess(list: ArrayList<ModelScanTask>) {

        val projectId = SPageContext.getHeader("ProjectId")
        val comming = SPageContext.getHeader("Coming")
        val account = SPageContext.getHeader("Account")

        for (task in list) {
            val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
            if(task.equipId == null ){
                val modelScanTaskScanTask = ModelScanTaskService.select("id" to task.id!!).entity()
                task.equipId = modelScanTaskScanTask!!.equipId
            }

            if (!task.confirmingPersonId.isNullOrEmpty()&&task.taskState == 0){
                task.taskState = -1
                //更改部件对象状态
                updateComponetObjStatus(task)
                //更改部件任务状态
                updateComponetTaskStatus(task)
            }else if(task.confirmingPersonId.isNullOrEmpty()&&task.taskState == 0) {
                task.taskState = 0
                //更改部件对象状态
                updateComponetObjStatus(task)
                //更改部件任务状态
                updateComponetTaskStatus(task)
            }
            //更改设备对象的状态
            val equipmentOld = equipmentService.select("id" to task.equipId!!).entity()
            if(equipmentOld!!.taskState != -1){//未找到
                val equip = Equipment()
                equip.id = task.equipId!!
                equip.taskState = task.taskState
                equipmentService.update(equip)
            }
            try {
                if (!comming.isNullOrEmpty()){
                    if (comming == "app"){
                        val entity = userService.select(SFilter.eq("projectId", projectId!!), SFilter.eq("phone", account!!)).entity()
                        val userLog = UserLog()
                        userLog.comming = "app"
                        userLog.action = "修改任务"
                        userLog.id = IdUtils.uuidCreate()
                        userLog.note = "项目ID: "+projectId+" 用户ID："+entity!!.id+" 手机号："+ account+" 请求来源："+comming+ " "+task.toJson()
                        userLog.phone = account
                        userLog.projectId = projectId
                        userLog.userId = entity!!.id
                        userLog.name = entity.name
                        userLog.objectId = task.equipId
                        userLogService.insert(userLog)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    } // Fun onUpdateSuccess

    /**
     * 更新设备对象状态时，对应更改部件对象状态，当为未找到状态时，特殊处理
     */
    fun updateComponetObjStatus(task: ModelScanTask){
        val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
        val componentList = equipmentService.select("parentId" to task!!.equipId!!).exec()

        if(task.taskState == 1 || task.taskState == -1){ // 待验证和未找到
            for(component in componentList){
                component.taskState = task.taskState
                equipmentService.update(component)
            }
        }else if(task.taskState == 0){ // 已完成
            for(component in componentList){
                if(component.taskState != -1){//如果部件状态为未找到，则不改变状态
                    component.taskState = task.taskState
                    equipmentService.update(component)
                }
            }
        }
    }

    /**
     * 更新设备任务状态时，对应更改部件任务状态
     */
    fun updateComponetTaskStatus(task: ModelScanTask){
        val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
        val modelScanTaskService = SBaseService(SMybatisDao(ModelScanTask::class.java))

        val componentTaskList = modelScanTaskService.select("parentId" to task!!.equipId!!).exec()

        for(childTask in componentTaskList){
            childTask.taskState = task.taskState
            ModelScanTaskService.update(childTask)
        }
    } // Fun updateStatus

    /**
     * 更新设备对象状态时，对应更改部件对象状态
     */
    fun resetComponetObjStatus(task: ModelScanTask){
        val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
        val componentList = equipmentService.select("parentId" to task!!.equipId!!).exec()
        for(component in componentList){
            component.taskState = task.taskState
            equipmentService.update(component)
        }
    }

    /**
     * 重新生成任务时，将任务状态改为已完成
     */
    fun resetTaskStatus(task: ModelScanTask) {
        val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))
        val modelScanTaskService = SBaseService(SMybatisDao(ModelScanTask::class.java))
        val resetTask = modelScanTaskService.select("equipId" to task.equipId!!, "taskState" to -1).entity()
        if (resetTask != null) {
            resetTask.taskState = 0
            modelScanTaskService.update(resetTask)//更改设备任务状态
            updateComponetTaskStatus(resetTask)//更改部件任务状态
        }
    }
    /**
     * 重新生成任务时，将设备和部件状态改变为待验证
     */
    fun resetObjStatus(task: ModelScanTask){
        val equipmentService = SBaseService(SMybatisDao(Equipment::class.java))

        //更改设备对象状态
        val equip = Equipment()
        equip.id = task.equipId!!
        equip.taskState = task.taskState
        equipmentService.update(equip)
        //更改部件对象状态
        resetComponetObjStatus(task)
    }


    /**
     * 查询所有模型文件夹和文件
     */
    fun modelFileQuery(): SQueryResponse<ModelFolder> {
        val pageQuery: SPageQueryInfo<ModelFolder>
        val gson = Gson()
        return try {
            val projectId = SPageContext.getHeader("ProjectId")
            var request = SQueryRequest()
            val modelFolderService = SBaseService(SMybatisDao(ModelFolder::class.java))
            val modelFolderQueryBuilder = modelFolderService.select(request.filters)
            modelFolderQueryBuilder.tableName = "scantask.f_get_modelfile('$projectId')"
            pageQuery = modelFolderQueryBuilder.pageQuery(1, 1000)

            for(folder in pageQuery.content!!){
                if(folder.fileListStr != null){
                    val listStr = folder.fileListStr!!.replace("/\\","")
                    val newStr = "["+listStr.substring(1,listStr.length-1)+"]"
                    val type = object : TypeToken<ArrayList<ModelFile>>() {
                    }.type
                    val siInSpList = gson.fromJson<ArrayList<ModelFile>>(newStr, type)
                    folder.fileList = siInSpList
                    folder.fileListStr = null
                }
            }
            SQueryResponse(pageQuery)
        } catch (e: Exception) {
            e.printStackTrace()
            SQueryResponse(SResponseType.failure, e.message!!)
        }
    } //  Fun modelFileQuery

    /**
     * 根据元空间id查询设备
     */
    fun  equipQuery(request: ModelScanSQueryRequest): SQueryResponse<EquipmentTaskTwo>{
        return  try{
            val projectId = SPageContext.getHeader("ProjectId")
            val modelScanTaskService = SBaseService(SMybatisDao(EquipmentTaskTwo::class.java))
            if (!request.modelId.isNullOrEmpty()&&!request.idList.isNullOrEmpty()&&request.idList!!.size>0){
                val list = ArrayList<EquipmentTaskTwo>()
                for ( bimId in request.idList!!){
                    if (request.category.isNullOrEmpty()){
                        val equipInISpaceList = mapper.equipInISpace(projectId!!, request.modelId!!, bimId)
                        if (equipInISpaceList.size>0){
                            list.addAll(equipInISpaceList)
                        }
                    }else{
                        val equipInISpaceList = mapper.equipInISpaceTwo(projectId!!, request.modelId!!, bimId,request.category!!)
                        if (equipInISpaceList.size>0){
                            list.addAll(equipInISpaceList)
                        }
                    }
                }
                if (list.size>0){
                    val pageNumber = request.pageNumber
                    val pageSize = request.pageSize
                    /** 开始条数 */
                    var fromIndex = pageSize* (pageNumber-1)
                    var toIndex = fromIndex + pageSize
                    if (toIndex>=list.size){
                        toIndex = list.size
                    }

                    val sQueryResponse = SQueryResponse<EquipmentTaskTwo>(SResponseType.success)
                    sQueryResponse.total = list.size.toLong()
                    val subList = list.subList(fromIndex, toIndex)
                    if (subList.size>0){
                        for (equip in subList){
                            try {
                                val entity = equipCategoryService.select(SFilter.eq("equipCode", equip.category!!)).entity()
                                if (entity!=null){
                                    equip.equipCategory = entity
                                }
                                val exec = modelScanTaskService.select(SFilter.eq("parentId", equip.id!!)).exec()
                                if (exec.size>0){
                                    equip.component = exec
                                }
                                val entity1 = EquipmentService.select(SFilter.eq("id", equip.id!!)).entity()
                                equip.bimId = entity1!!.bimId
                                equip.localId = entity1.localId
                                equip.localName = entity1.localName
                            } catch (e: Exception) {
                                e.printStackTrace()
                            }
                        }
                    }
                    sQueryResponse.content = subList
                    sQueryResponse.pageSize = pageSize
                    sQueryResponse.pageNumber = pageNumber
                    sQueryResponse
                }else{
                    val sQueryResponse = SQueryResponse<EquipmentTaskTwo>(SResponseType.success)
                    sQueryResponse.content = ArrayList<EquipmentTaskTwo>()
                    sQueryResponse.pageNumber = request.pageNumber
                    sQueryResponse.pageSize = request.pageSize
                    sQueryResponse
                }
            }else{
                val sQueryResponse = SQueryResponse<EquipmentTaskTwo>(SResponseType.failure)
                sQueryResponse.message = "入参错误"
                sQueryResponse
            }

//            if (!request.idList.isNullOrEmpty()){
//                return EquipmentService.pageQuery(request, arrayListOf(SFilter.inList(SEndWithChar("bimId",":"),request.idList!!) ,
//                        SFilter.eq("projectId",projectId!!)))
//            }else{
//                return EquipmentService.pageQuery(request, arrayListOf(
//                        SFilter.eq("projectId",projectId!!)))
//            }

//           return EquipmentService.pageQuery(request, arrayListOf(SFilter.inList(SEndWithChar("bimId",":"),listId) ,
//                   SFilter.eq("projectId",projectId!!)))

    } catch (e: Exception) {
        e.printStackTrace()
        SQueryResponse(SResponseType.failure, e.message!!)
    }
    }

//    private fun getDatas(list: ArrayList<Equipment>,firstIndex: Int, lastIndex: Int): List<Equipment> {
//        val resList = ArrayList<Equipment>()
//        for (i in firstIndex until lastIndex) {
//            if (i < list.size) {
//                resList.add(list[i])
//            }
//        }
//        return resList
//    }




    override fun onDeleteBefore(entity: ModelScanTask): Boolean {

        try {
            val entity2 = EquipScanTaskService.select(SFilter.eq("id", entity.id!!)).entity()
            val entity1 = EquipmentService.select(SFilter.eq("id", entity2!!.equipId!!)).entity()
            if (entity1!=null){
                if (entity1.taskState == 1){
                    entity1.taskState = null
                    EquipmentService.update(entity1, arrayListOf("TaskState"))
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return super.onDeleteBefore(entity)
    }

    /**
     * 统计设备下部件的类型以及数量
     */
    fun categoryCounts(equipScanTask: ModelScanTask): SQueryResponse<CategoryStatistics>{
        try {
            if (!equipScanTask.id.isNullOrEmpty()&&!equipScanTask.equipId.isNullOrEmpty()){
                val categoryStatistics = mapper.categoryStatisticsModel(equipScanTask.id!!, equipScanTask.equipId!!)
                val sQueryResponse = SQueryResponse<CategoryStatistics>()
                sQueryResponse.total = categoryStatistics.size.toLong()
                sQueryResponse.content = categoryStatistics
                sQueryResponse.result = SResponseType.success
                return sQueryResponse
            }else{
                val sQueryResponse = SQueryResponse<CategoryStatistics>(SResponseType.failure)
                sQueryResponse.message = "入参错误"
                return sQueryResponse
            }
        } catch (e: Exception) {
            e.printStackTrace()
            return SQueryResponse(SResponseType.failure,e.message.toString())
        }
    } // Fun

} // Class ModelScanTaskService