package com.persagy.revit.services.modelCheck

import com.persagy.mybatis.SMybatisDao
import com.persagy.revit.models.dataCheck.GridCheckResult
import com.persagy.revit.models.dataCheck.LevelCheckResult
import com.persagy.revit.models.excel.IsPassedEnum
import com.persagy.revit.models.excel.report.BlockingTotalReport
import com.persagy.revit.models.excel.report.ModelGridReport
import com.persagy.revit.models.excel.report.ModelLevelReport
import com.persagy.revit.models.modelFile.ModelFile
import com.persagy.revit.models.scheduler.SagaCheckResult
import com.persagy.revit.models.scheduler.UnitCheckResult
import com.persagy.revit.services.comparator.FloorComparator
import com.persagy.revit.services.excel.ExcelService
import com.persagy.revit.services.message.MessageService
import com.persagy.service.SBaseService
import com.persagy.service.utils.SSpringContextUtil
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

@Component
class ModelCheckService {

    @Autowired
    lateinit var messageService: MessageService

    @Autowired
    lateinit var floorComparator: FloorComparator
    /**
     * 检查轴网
     */
    fun checkGrid(projectId : String, folderId : String, modelId : String): ArrayList<GridCheckResult> {
        var gridCheckService = SBaseService(SMybatisDao(GridCheckResult::class.java))
        var queryBuilder = gridCheckService.selectAll()
        queryBuilder.tableName = "revit_calc.check_grid_valid('${projectId}', '${folderId}', '${modelId}')"
        return queryBuilder.exec()
    }

    /**
     * 检查标高
     */
    fun checkLevel(projectId : String, folderId : String, modelId : String): ArrayList<LevelCheckResult> {
        var levelCheckService = SBaseService(SMybatisDao(LevelCheckResult::class.java))
        var queryBuilder = levelCheckService.selectAll()
        queryBuilder.tableName = "revit_calc.check_level_valid('${projectId}', '${folderId}', '${modelId}')"
        return queryBuilder.exec()
    }

    /**
     * 写检查轴网, 检查标高的报告
     * @return 检查结果是否出错, false表示失败, true表示检查都正常
     */
    fun writeStatus3CheckReport(excelService: ExcelService, projectId: String, folderId: String, model: ModelFile, floorName: String?, results : ArrayList<Boolean>) : Boolean{
        val levelCheckResult = checkLevel(projectId, folderId, model.id!!)
        levelCheckResult.sortWith(floorComparator)
        val gridCheckResult = checkGrid(projectId, folderId, model.id!!)
        gridCheckResult.sortWith(floorComparator)
        val involvedFloor = HashSet<String>()
        val isLevelError = writeLevelReport(levelCheckResult, excelService, involvedFloor)
        val isGridError = writeGridReport(gridCheckResult, excelService, model.id!!)
        results.add(isLevelError)
        results.add(isGridError)
        if(!isLevelError && !isGridError){
            return true
        }
        writeTotalReport(excelService, isLevelError, isGridError, floorName, involvedFloor)
        //保存excel报告到文件服务器
        excelService.saveToFileServer(model.id!!)
        return false
    }

    /**
     * 写阻塞性总体报告excel
     */
    private fun writeTotalReport(excelService: ExcelService, levelError: Boolean, gridError: Boolean, floorName: String?, involvedFloor: HashSet<String>) {
        var totalReport = SSpringContextUtil.getBean(BlockingTotalReport::class.java) as BlockingTotalReport
//        totalReport.writeToRow(SagaCheckResult.sheetCheckName, IsPassedEnum.getIsPassedEnum(true))
        totalReport.writeToRow(SagaCheckResult.sheetCheckName, IsPassedEnum.Pass)
        totalReport.writeToRow(UnitCheckResult.sheetCheckName, IsPassedEnum.Pass)
        if(levelError)
            totalReport.writeToRow("楼层标高与楼层顺序号检查", IsPassedEnum.Unpass)
        else
            totalReport.writeToRow("楼层标高与楼层顺序号检查", IsPassedEnum.Pass)
        if(gridError)
            totalReport.writeToRow("轴网检查", IsPassedEnum.Unpass)
        else
            totalReport.writeToRow("轴网检查", IsPassedEnum.Pass)
        totalReport.addCellValue(0, 1, floorName?:"")
        val sb = StringBuilder()
        for (singleFloorName in involvedFloor){
            sb.append(singleFloorName).append(", ")
        }
        if(sb.length > 1)
            sb.removeSuffix(", ")
        totalReport.addCellValue(2, 1, sb.toString())
        excelService.insertReport(totalReport)
        excelService.randomWrite(0, totalReport.cellValues)
    }

    /**
     * 写标高报告, 返回是否有错误
     */
    private fun writeLevelReport(levelCheckResult: ArrayList<LevelCheckResult>, excelService: ExcelService, involvedFloor : HashSet<String>): Boolean{
        var levelReport = SSpringContextUtil.getBean(ModelLevelReport::class.java) as ModelLevelReport
        var hasError = false
        for(levelCheck in levelCheckResult){
            var row = ModelLevelReport.Data()
            row.floorName = levelCheck.floorName?: ""
            if(row.floorName.isNotEmpty() && !involvedFloor.contains(row.floorName)){
                involvedFloor.add(row.floorName)
            }
            row.planName = levelCheck.planName?: ""
            row.levelHeight = (levelCheck.elevation?.div(1000))?.toString()?:""
            if(levelCheck.hasError == false)
                row.isPassed = IsPassedEnum.Pass
            else
                row.isPassed = IsPassedEnum.Unpass
            row.note = levelCheck.errorMsg?:""
            if(levelCheck.hasError == true)
                hasError = true
            levelReport.rowValue.add(row)
        }
        excelService.insertReport(levelReport)
        return hasError
    }

    /**
     * 写轴网报告, 返回是否有错误
     */
    fun writeGridReport(gridCheckResult: ArrayList<GridCheckResult>, excelService: ExcelService, modelId: String): Boolean{
        var gridReport = SSpringContextUtil.getBean(ModelGridReport::class.java) as ModelGridReport
        var hasError = hasMultiGroups(gridCheckResult)
        for(gridCheck in gridCheckResult){
            var row = ModelGridReport.Data()
            row.floorName = gridCheck.floorName?: ""
            row.gridGroup = gridCheck.groupId?.toString()?:""
            if(gridCheck.currentModelId == modelId && hasError) {
                row.isPassed = IsPassedEnum.Unpass
                row.note = "轴网不一致"
            }else{
                row.isPassed = IsPassedEnum.Pass
                row.note = ""
            }
            gridReport.rowValue.add(row)
        }
        excelService.insertReport(gridReport)
        return hasError
    }

    /**
     * 检查轴网是否有多个分组
     */
    private fun hasMultiGroups(gridCheckResult: ArrayList<GridCheckResult>) : Boolean{
        val groupSet = HashSet<Int>()
        for(gridCheck in gridCheckResult) {
            if(gridCheck.groupId != null && !groupSet.contains(gridCheck.groupId!!)){
                if(groupSet.size != 0){
                    return true
                }
                groupSet.add(gridCheck.groupId!!)
            }
        }
        return false
    }
}