package cn.sagacloud.server.algorithm.backstage.state

import cn.sagacloud.server.algorithm.common.utils.SpaceAffectUtil
import cn.sagacloud.server.algorithm.dao.mapper.FloorMapper
import cn.sagacloud.server.algorithm.models.modelFile.ModelFile
import cn.sagacloud.server.algorithm.models.modelFile.StatusInfo
import cn.sagacloud.server.algorithm.services.BaseDataService
import cn.sagacloud.server.algorithm.services.datacenter.DataCenterService
import cn.sagacloud.server.algorithm.services.message.MessageService
import com.sybotan.database.SFilter
import com.sybotan.database.enums.SDirection
import com.sybotan.service.models.requests.SUpdateRequest
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.util.*

/**
 *
 *
 * @author jxing
 */
@Component
class FinishState_4 : ModelState {

    companion object{
        private val logger = LoggerFactory.getLogger(FinishState_4::class.java)
    }

    @Autowired
    lateinit var messageService: MessageService

    var modelList: ArrayList<ModelFile>? = null

    val dataService = BaseDataService

    @Autowired
    lateinit var dataCenterService: DataCenterService

    @Autowired
    lateinit var floorMapper : FloorMapper

    @Autowired
    lateinit var spaceAffectUtil: SpaceAffectUtil

    /**
     * 获取所有状态是4的模型
     */
    override fun prepareModel() {
        modelList = dataService.modelFileService.select(SFilter.and(SFilter.eq("status", 4),
                SFilter.eq("removed", false))).exec()
    }

    /**
     * 发送成功消息给JMS
     */
    override fun handle() {
        if (modelList.isNullOrEmpty()) {
            return
        }
        // 先给模型文件版本号和接收时间
        addVersionChangeName(modelList!!)
        modelList!!.forEach {
            try {
                // 获取模型的statusInfo的affectedSpace是否是true
                // 如果不是true
                if (it.statusInfo == null || it.statusInfo!!.affectedSpace != true) {
                    if (it.floorModelId == null) {
                        return@forEach
                    }
                    val floorModel = dataService.floorModelService.select(SFilter.and(SFilter.eq("currentModelId", it.id!!), SFilter.eq("id", it.floorModelId!!))).entity()
                            ?: return@forEach
                    // 判断数据中心是否有楼层绑定了该模型
                    val floors = dataCenterService.getFloorWithModelId(it.floorModelId!!, it.projectId!!)
                    // 如果有绑定, 则执行受影响的业务空间函数
                    if (!floors.isNullOrEmpty()) {
                        val calcAffected = spaceAffectUtil.affectedSpace(it.projectId!!, it.floorModelId!!)
//                                floorMapper.calcAffected(it.floorModelId!!)
                        // 如果返回true, 更新模型的statusInfo信息点
                        if (calcAffected == true) {
                            it.statusInfo = StatusInfo()
                            it.statusInfo!!.affectedSpace = true
                            dataService.modelFileService.update(it, arrayListOf("statusInfo"))
                        }
                    }
                }
            }catch (ex : Exception){
                ex.printStackTrace()
                logger.error("###########计算空间影响状态报错:"+it.id+ex.message)
            }
        }
    }
    private val projection = arrayListOf("version", "acceptTime")
    private fun addVersionChangeName(modelList: java.util.ArrayList<ModelFile>) {
        modelList.forEach {
            // 检验数据合法性
            if(it.floorModelId == null || it.floorModelId!!.isEmpty())
                return@forEach
            if(it.version != null)  // 已经改过的忽略掉
                return@forEach
            val largestVersion = dataService.modelFileService.select(SFilter.and(SFilter.eq("floorModelId", it.floorModelId!!), SFilter.not(SFilter.isNull("version")), SFilter.eq("removed", false))).order("version", SDirection.DESC).limit(1).entity()
            if(largestVersion == null){
                it.version = 1
            }else {
                it.version = largestVersion.version!! + 1
            }
            it.acceptTime = Date()
            val request = SUpdateRequest<ModelFile>()
            request.content = arrayListOf(it)
            request.projection = projection
            dataService.modelFileService.updateList(request)
        }
    }
}