/*
 * ********************************************************************************************************************
 *
 *                     :*$@@%$*:                         ;:                ;;    ;;
 *                   :@@%!  :!@@%:                       %!             ;%%@@%$ =@@@@@@@%;     @%@@@%%%%@@@@@
 *                  :@%;       :$=                       %%$$$%$$         ;$$  ;$@=   !@$
 *                  =@!                                  %!              @ $=;%   !@@@%:      !$$$$$$$$$$$$$$=
 *                  =@*                                  %!              @ $= % %@=   =%@!      %=
 *             *$%%! @@=        ;=$%%%$*:                %!              @ $= % =%%%%%%@$      *%:         =%
 *           %@@!:    !@@@%=$@@@@%!  :*@@$:              %!              @ $= % $*     ;@      @*          :%*
 *         ;@@!          ;!!!;:         ;@%:      =======@%========*     @ $$ % $%*****$@     :@$=*********=@$
 *         $@*   ;@@@%=!:                *@*
 *         =@$    ;;;!=%@@@@=!           =@!
 *          %@$:      =@%: :*@@@*       %@=                    Copyright (c) 2016-2019.  北京上格云技术有限公司
 *           ;%@@$=$@@%*       *@@@$=%@@%;
 *              ::;::             ::;::                                              All rights reserved.
 *
 * ********************************************************************************************************************
 */

package com.persagy.revit.services.json

import com.alibaba.fastjson.JSONObject
import com.alibaba.fastjson.util.ParameterizedTypeImpl
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.persagy.database.SFilter
import com.persagy.revit.models.entities.BaseComponent
import com.persagy.revit.models.entities.WindowDoorBase
import com.persagy.revit.models.jsonAnalyzer.AllComponents
import com.persagy.revit.models.jsonAnalyzer.BaseObj
import com.persagy.revit.models.modelFile.ModelFile
import com.persagy.revit.services.BaseDataService
import com.persagy.revit.services.CommonService
import com.persagy.revit.services.endpoint.UploadService
import com.persagy.service.SObjectService
import com.persagy.service.models.enums.SResponseType
import com.persagy.service.models.responses.SBaseResponse
import org.springframework.stereotype.Component
import java.io.InputStream
import java.lang.reflect.Type


/**
 * 解析revit-json服务
 *
 * @author jxing
 */
@Suppress("UNCHECKED_CAST")
@Component
open class JSONAnalyzerService {

//    private var doorService = SObjectService(SMybatisDao(Door::class.java))
//    private var windowService = SObjectService(SMybatisDao(Window::class.java))
//    private var columnService = SObjectService(SMybatisDao(Column::class.java))
//    private var wallService = SObjectService(SMybatisDao(Wall::class.java))
//    private var virtualWallService = SObjectService(SMybatisDao(VirtualWall::class.java))
//    private var spaceService = SObjectService(SMybatisDao(Space::class.java))
//    private var modelService = SObjectService(SMybatisDao(ModelFile::class.java))
//    private var boundarySegmentService = SObjectService(SMybatisDao(BoundarySegment::class.java))

    var dataService = BaseDataService

    /**
     * 组合泛型具体类型组合成大类型
     */
    fun buildType(vararg types: Type): Type? {
        var beforeType: ParameterizedTypeImpl? = null
        if (types.isNotEmpty()) {
            for (i in types.size - 1 downTo 1) {
                beforeType = ParameterizedTypeImpl(arrayOf<Type>(if (beforeType == null) types[i] else beforeType), null, types[i - 1])
            }
        }
        return beforeType
    }


    /**
     * 获取jsonz文件内的模型id
     */
    fun getModelIdInJSON(json: JSONObject): String? {
        val mapper = ObjectMapper()
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        val baseObj = mapper.readValue<BaseObj<AllComponents>>(json.toString(), mapper.typeFactory.constructParametricType(BaseObj::class.java, AllComponents::class.java))
        // 验证是否baseObj.modelId合法, 不合法不允许入库
        val modelFile = checkModelId(baseObj.modelId) ?: return null
        return modelFile.id
    }

    fun handleSingleJSON(json: JSONObject): BaseObj<AllComponents>? {
        val mapper = ObjectMapper()
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        val baseObj = mapper.readValue<BaseObj<AllComponents>>(json.toString(), mapper.typeFactory.constructParametricType(BaseObj::class.java, AllComponents::class.java))
        return baseObj
    }


    /**
     * 处理上传的json
     */
    fun handleSingleJSON(baseObj: BaseObj<AllComponents>, bimIdPrefix: String): String? {
//        val baseObj = json.toJavaObject<BaseObj<AllComponents>>(buildType(BaseObj::class.java, AllComponents::class.java)!!)
//        val mapper = ObjectMapper()
//        val baseObj = mapper.readValue<BaseObj<AllComponents>>(json.toString(), mapper.typeFactory.constructParametricType(BaseObj::class.java, AllComponents::class.java))
        // 验证是否baseObj.modelId合法, 不合法不允许入库
        val modelFile = checkModelId(baseObj.modelId) ?: return "ModelId ${baseObj.modelId} 不存在!"
        var result = true
        // 获取model, 更新字段
        result = result and ModelAnalyzer.analyze(dataService.modelFileService, modelFile, baseObj)
        if (!result) {
            return "获取model异常"
        }
        // 处理VirtualWall, 填充数据, replace插入表
        result = result and BaseBehavier.analyze(
                dataService.virtualWallService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.virtualWalls as ArrayList<BaseComponent>?
        )
        if (!result) {
            return "处理VirtualWall异常"
        }
        // 处理Wall, 填充数据, replace插入表
        result = result and BaseBehavier.analyze(
                dataService.wallService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.walls as ArrayList<BaseComponent>?
        )
        if (!result) {
            return "处理Wall异常"
        }
        // 处理door, 填充数据, 填充wallId, replace插入表
        result = result and DoorWindowAnalyzer.analyze(
                dataService.doorService as SObjectService<WindowDoorBase>,
                baseObj,
                baseObj.elements!!.doors as ArrayList<WindowDoorBase>?
        )   // 依赖 wall
        if (!result) {
            return "处理door异常"
        }
        // 处理Window, 填充数据, 填充wallId, replace插入表
        result = result and DoorWindowAnalyzer.analyze(
                dataService.windowService as SObjectService<WindowDoorBase>,
                baseObj,
                baseObj.elements!!.windows as ArrayList<WindowDoorBase>?
        )  // 依赖 wall
        if (!result) {
            return "处理Window异常"
        }
        // 处理column, 填充数据, replace插入表
        result = result and BaseBehavier.analyze(
                dataService.columnService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.columns as ArrayList<BaseComponent>?
        )
        if (!result) {
            return "处理column异常"
        }
        // 处理Space, 填充数据, replace插入表
        result = result and SpaceAnalyzer.analyze(dataService.spaceService, baseObj, baseObj.elements!!.spaces)
        if (!result) {
            return "处理Space异常"
        }

        //处理Room, 填充数据, replace插入表
        result = result and RoomAnalyzer.analyze(dataService.roomService, baseObj, baseObj.elements!!.rooms)
        if (!result) {
            return "处理Room异常"
        }


        // 处理BoundarySegment, 填充数据, replace方式插入表
        result = result and BoundarySegmentAnalyzer.analyze(
                dataService.boundarySegmentService,
                baseObj,
                baseObj.elements!!.boundarySegments
        )
        if (!result) {
            return "处理BoundarySegment异常"
        }
        // 处理Pipe
        val revitIdMap = HashMap<String, BaseComponent>() //     revit_id --> 对象
        result = result and RevitIdAnalyzer.analyzePipesDucts(
                dataService.pipeService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.pipes as ArrayList<BaseComponent>?,
                revitIdMap,
                "Pipe"
        )
        if (!result) {
            return "处理Pipe异常"
        }
        // 处理flexPipe
        result = result and RevitIdAnalyzer.analyzePipesDucts(
                dataService.pipeService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.flexPipes as ArrayList<BaseComponent>?,
                revitIdMap,
                "FlexPipe"
        )
        if (!result) {
            return "处理FlexPipe异常"
        }
        // 处理duct
        result = result and RevitIdAnalyzer.analyzePipesDucts(
                dataService.ductService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.ducts as ArrayList<BaseComponent>?,
                revitIdMap,
                "Duct"
        )
        if (!result) {
            return "处理Duct异常"
        }
        // 处理flexDuct
        result = result and RevitIdAnalyzer.analyzePipesDucts(
                dataService.ductService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.flexDucts as ArrayList<BaseComponent>?,
                revitIdMap,
                "FlexDuct"
        )
        if (!result) {
            return "处理FlexDuct异常"
        }
        // 处理other
        result = result and RevitIdAnalyzer.analyze(
                dataService.otherService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.others as ArrayList<BaseComponent>?,
                revitIdMap
        )
        if (!result) {
            return "处理other异常"
        }
        // 处理joinObject
        result = result and RevitIdAnalyzer.analyze(
                dataService.joinObjectService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.joinObjects as ArrayList<BaseComponent>?,
                revitIdMap
        )
        if (!result) {
            return "处理joinObject异常"
        }
        // 处理equipment
        result = result and EquipmentAnalyzer.analyze(
                dataService.equipmentService,
                baseObj,
                baseObj.elements!!.equipments,
                bimIdPrefix, revitIdMap,
                checkProject(baseObj.mbiName),
                dataService.dictCompService,
                dataService.infoPointCompService
        )
        if (!result) {
            return "处理equipment异常"
        }
        // 处理部件(component)
        result = result and EquipmentAnalyzer.analyzeComponent(
                dataService.componentService,
                baseObj,
                baseObj.elements!!.equipParts,
                bimIdPrefix,
                revitIdMap
        )
        if (!result) {
            return "处理component异常"
        }
        // 处理连接件
        result = result and RevitIdAnalyzer.analyzeConnector(
                dataService.connectorService,
                baseObj,
                baseObj.elements!!.connectors,
                revitIdMap
        )
        if (!result) {
            return "处理连接件异常"
        }
        // 处理level, 标高
        result = result and BaseBehavier.analyze(
                dataService.levelService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.levels as ArrayList<BaseComponent>?
        )
        if (!result) {
            return "处理level异常"
        }
        // 处理grid, 轴网
        result = result and BaseBehavier.analyze(
                dataService.gridService as SObjectService<BaseComponent>,
                baseObj,
                baseObj.elements!!.grids as ArrayList<BaseComponent>?
        )
        if (!result) {
            return "处理grid异常"
        }
        return null
    }

    /**
     * 检查模型文件id是否存在
     */
    private fun checkModelId(modelId: String?): ModelFile? {
        modelId ?: return null
        val modelFileList = dataService.modelFileService.select(SFilter.eq("id", modelId)).exec()
        if (modelFileList.isEmpty())
            return null
        return modelFileList[0]
    }

    /**
     * 导入模型数据到数据库
     */
    fun importModelData(jsonData: BaseObj<AllComponents>, bimIdPrefix: String): SBaseResponse {
        try {
            val ret = handleSingleJSON(jsonData, bimIdPrefix)
            if (ret == null)
                return SBaseResponse(SResponseType.success)
            else
                return SBaseResponse(SResponseType.failure, ret)
        } catch (e: Exception) {
            return SBaseResponse(SResponseType.failure, "error:${e.message}, ${CommonService.getStackTrace(e)}")
        }
    }

    /**
     * 解析json数据
     */
    fun analyzeJsonzFile(fileStream: InputStream?): BaseObj<AllComponents>? {
        try {
            val map = UploadService.getJSONObjectMap(fileStream!!)
            val iterator = map.iterator()
            if (iterator.hasNext()) {
                return handleSingleJSON(iterator.next().value)
            } else {
                throw Exception("jsonz文件出错")
            }
        } catch (e: Exception) {
            throw Exception("jsonz文件出错: ${CommonService.getStackTrace(e)}")
        }
    }

    /**
     * 判断需要转换的项目
     */

    fun checkProject(projectId: String?): Boolean {
        if (projectId.isNullOrEmpty()) {
            return false;
        }
        return dataService.projectService.select(SFilter.eq("id", projectId)).entity() != null;
    }
}