package com.sybotan.android.demo.viewmodel

import android.app.Application
import android.graphics.PointF
import android.text.TextUtils
import androidx.lifecycle.viewModelScope
import cn.hutool.core.util.IdUtil
import cn.sagacloud.android.cadengine.items.SpaceItem
import cn.sagacloud.android.cadengine.items.TunableSpaceItem
import cn.sagacloud.android.cadengine.types.*
import com.framework.mvvm.model.db.entity.*
import com.framework.mvvm.model.db.entity.task.*
import com.framework.mvvm.model.repository.AdmRepository
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.rm.rmswitch.RMTristateSwitch
import com.sybotan.android.demo.activities.BaseActivity
import com.sybotan.android.demo.bean.request.*
import com.sybotan.android.demo.bean.result.*
import com.sybotan.android.demo.bean.result.Position
import com.sybotan.android.demo.bean.result.Z
import com.sybotan.android.demo.retrofit.BaseObserver
import com.sybotan.android.demo.retrofit.BaseViewModelInterface
import com.sybotan.android.demo.retrofit.RetrofitFactory
import com.sybotan.android.demo.tools.CommonUtils
import com.sybotan.android.demo.tools.ToastUtils
import com.sybotan.base.utils.SJsonUtil
import kotlinx.coroutines.launch
import org.kodein.di.DI
import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI
import org.kodein.di.instance
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import com.sybotan.android.demo.bean.*
import com.sybotan.android.demo.retrofit.Constant
import com.sybotan.android.demo.tools.Lasso
import com.sybotan.android.demo.tools.ObjectNameUtils
import com.sybotan.base.extensions.toInt
import java.io.File


/**
 * Created by lihao.
 * Date: 2021/6/9
 */
class GraphyVM(
    app: Application,
    b: BaseViewModelInterface?, activity: BaseActivity?, //建筑id
    private val buildingId: String, //楼层id
    private val floorId: String,
    private val projectId: String
) : BaseViewModel(app, b, activity), DIAware {
    private val gson = Gson()

    override val di: DI by closestDI()
    val repo: AdmRepository by instance()

    /**
     * 查询空间和任务
     */
    fun getSpaceJob(from: String, spaceList: ArrayList<SpaceItem>) {
        viewModelScope.launch {
            var spaceList: ArrayList<JobSpaceEntity> = ArrayList()
            if ("space".equals(from)) {
                val spaceByArchState1 = repo.getSpaceByArchStateFloorId(floorId, "1")
                val spaceByArchState2 = repo.getSpaceByArchStateFloorId(floorId, "2")
                spaceList.addAll(spaceByArchState1)
                spaceList.addAll(spaceByArchState2)
            } else {
                val spaceByEquipState1 = repo.getSpaceByEquipStateFloorId(floorId, "1")
                val spaceByEquipState2 = repo.getSpaceByEquipStateFloorId(floorId, "2")
                spaceList.addAll(spaceByEquipState1)
                spaceList.addAll(spaceByEquipState2)
            }
            var spaceJobList = ArrayList<SpaceJobModel>()
            for (spaceEntity in spaceList) {
                var spaceJobModel = SpaceJobModel()
                val objectEntity = repo.getObject(spaceEntity.spaceId)
                objectEntity?.let {
                    spaceJobModel.buildingId = buildingId
                    spaceJobModel.id = spaceEntity.spaceId
                    spaceJobModel.localName = objectEntity.localName + ObjectNameUtils.getEquipName(objectEntity)
                    spaceJobModel.name = objectEntity.name
                    spaceJobModel.projectId = projectId
                    val infos = gson.fromJson(objectEntity.infos, InfosForObj::class.java)
                    spaceJobModel.outline = infos.outline
                    spaceJobModel.objectEntity = objectEntity
                    if (from.equals("space")) {
                        val problems = repo.getProblemByAvalible(floorId)
                        var hasProblem = false
                        var list: ArrayList<PointF> = ArrayList()
                        for (line in spaceJobModel.outline[0]!!) {
                            if (line.size < 1) {
                                list.add(PointF(line[0].x, line[0].y))
                                continue
                            }
                            for (p in line) {
                                list.add(PointF(p.x, p.y))
                            }
                        }
                        for (problem in problems) {
                            val geomList = gson.fromJson<List<PointF>>(
                                problem.geom,
                                object : TypeToken<List<PointF?>?>() {}.type
                            )
                            for (gemo in geomList) {
                                val pointF: android.graphics.Point
                                if (geomList.size == 1) {
                                    pointF = android.graphics.Point(
                                        gemo.x.toInt(),
                                        -gemo.y.toInt()
                                    )
                                } else {
                                    pointF = android.graphics.Point(
                                        gemo.x.toInt(),
                                        gemo.y.toInt()
                                    )
                                }
                                if (Lasso.isPolygonContainsPoint(spaceJobModel.outline, pointF)) {
                                    hasProblem = true
                                    break
                                }
                            }
                        }
                        if (spaceEntity.archState == 1) {
                            if (hasProblem) {
                                spaceJobModel.job = "02"
                            } else {
                                spaceJobModel.job = "01"
                            }
                        } else {
                            spaceJobModel.job = "03"
                        }
                    } else {
                        if (spaceEntity.equipState == 1) {
                            spaceJobModel.job = "04"
                        } else {
                            spaceJobModel.job = "05"
                        }
                    }
                    spaceJobList.add(spaceJobModel)
                }
            }
            mEmitter.SendDirective(SPACE_JOB, spaceJobList)

        }
    }


    /**
     * 设置空间的任务状态(新建和修改)
     *
     * @param choseSpace 选中的空间
     * @param toString   数字化交付编码
     */
    fun setJob(choseSpace: TunableSpaceItem?, jobStatus: String) {
        viewModelScope.launch {
            if (jobStatus.equals("03")) {
                val qrcodes = repo.getQrcode(choseSpace!!.data.id!!)
                if (CommonUtils.IsNull(qrcodes)) {
                    ToastUtils.showMyToast("未安装空间二维码，不能完成空间核查")
                    return@launch
                }
            }
            var space = repo.getSpaceBySpaceId(choseSpace!!.data.id!!)
            if (jobStatus.equals("01")) {
                space.archState = 1
            } else if (jobStatus.equals("03")) {
                space.archState = 2
            } else if (jobStatus.equals("04")) {
                space.archState = 2
                space.equipState = 1
            } else if (jobStatus.equals("05")) {
                space.archState = 2
                space.equipState = 2
            }
            space.state()
            repo.insSpace(space)
            mEmitter.SendDirective(SET_JOB, null)
        }
    }

    /**
     * 查询空间下的设备(所在关系)
     *
     * @param choseSpace 选中的空间
     */
    fun getSpaceEq(choseSpace: TunableSpaceItem?) {
        viewModelScope.launch {
            val equips = repo.getEquipByFloorId(floorId)
            equips.filter { !TextUtils.isEmpty(it.containerId) }
            var models: ArrayList<SpaceEqModel> = ArrayList()
            for (equip in equips) {
                var hasParent = false
                for (model in models) {
                    if (model.type!!.equals(equip.classCode)) {
                        hasParent = true
                        val child = Children()
                        child.deviceId = equip.id
                        child.name = equip.name
                        val infos = gson.fromJson(equip.infos, InfosforEq::class.java)
                        child.digitalDeliveryID = infos.digitalDeliveryID
                        if (!equip.infos!!.asJsonObject.keySet().isEmpty() && infos.location != null) {
                            val eqProblems = repo.getEqProblem(equip.id)
                            //1-蓝 2-绿 3-红
                            if (eqProblems == null || TextUtils.isEmpty(eqProblems.id)) {
                                if (infos.equipCheck != null && (infos.equipCheck is Double || infos.equipCheck is Int)) {
                                    when {
                                        infos.equipCheck.toInt() == RMTristateSwitch.STATE_LEFT -> {
                                            child.type = 5
                                        }
                                        infos.equipCheck.toInt() == RMTristateSwitch.STATE_MIDDLE -> {
                                            child.type = 1
                                        }
                                        infos.equipCheck.toInt() == RMTristateSwitch.STATE_RIGHT -> {
                                            child.type = 2
                                        }
                                        infos.equipCheck.toInt() == 3 -> {
                                            child.type = 6
                                        }
                                    }
                                } else {
                                    child.type = 1
                                }
                            } else {
                                child.type = 3
                            }
                            val position = Position()
                            if (infos.location != null) {
                                position.x = infos.location.x().toString()
                                position.y = infos.location.y().toString()
                                val z = Z()
                                z.offset = infos.location.z().toString()
                                z.region = infos.zRegion
                                position.z = z
                                child.position = gson.toJson(position)
                            }
                            model.children.add(child)
                        }
                    }
                }
                if (!hasParent) {
                    val spaceModel = SpaceEqModel()
                    spaceModel.type = equip.classCode
                    var equipEntity = repo.getEquipByCode(equip.classCode!!)
                    spaceModel.typeName = equipEntity?.name
                    val child = Children()
                    child.deviceId = equip.id
                    child.name = equip.name
                    val infos = gson.fromJson(equip.infos, InfosforEq::class.java)
                    child.digitalDeliveryID = infos.digitalDeliveryID
                    if (!equip.infos!!.asJsonObject.keySet().isEmpty()) {
                        val eqProblems = repo.getEqProblem(equip.id)
                        if (eqProblems == null || TextUtils.isEmpty(eqProblems.id)) {
                            //type 1-蓝 2-绿 3-红 4-黄 5-紫
                            if (infos.equipCheck is Double || infos.equipCheck is Int) {
                                when {
                                    infos.equipCheck.toInt() == RMTristateSwitch.STATE_LEFT -> {
                                        child.type = 5
                                    }
                                    infos.equipCheck.toInt() == RMTristateSwitch.STATE_MIDDLE -> {
                                        child.type = 1
                                    }
                                    infos.equipCheck.toInt() == RMTristateSwitch.STATE_RIGHT -> {
                                        child.type = 2
                                    }
                                }
                            } else {
                                child.type = 1
                            }
                        } else {
                            child.type = 3
                        }
                        val position = Position()
                        if (infos.location != null) {
                            position.x = infos.location.x().toString()
                            position.y = infos.location.y().toString()
                            val z = Z()
                            z.offset = infos.location.z().toString()
                            z.region = infos.zRegion
                            position.z = z
                            child.position = gson.toJson(position)
                        }
                        spaceModel.children.add(child)
                        models.add(spaceModel)
                    }
                }
            }
            mEmitter.SendDirective(SPACE_EQ, models)
        }
    }

    /**
     * 获取管线类型
     */
    fun pipeList() {
        val bean = ReqPipeList()
        val observable = RetrofitFactory.getInstance().pipeList(getRequestBody(bean))
        sendRequest(observable, object : BaseObserver<ArrayList<PipeListModel>>(mActivity, this) {
            override fun onSuccess(models: ArrayList<PipeListModel>) {
                mEmitter.SendDirective(PIPE_LIST, models)
            }
        }, true)
    }

    /**
     * 添加管线
     * @param model         管线类型
     * @param pipeLineList  位置坐标
     * @param remark        描述
     * @param choseSpace    被选中的空间
     */
    fun addPipe(
//        model: PipeListModel,
//        pipeLineList: java.util.ArrayList<PointF>,
//        remark: String,
//        choseSpace: TunableSpaceItem?
    ) {
//        val bean = ReqAddPipe()
//        bean.spaceId = choseSpace!!.data.id
//        bean.sys = model.sysCode
//        bean.type = model.code
//        bean.position = pipeLineList
//        bean.remark = remark
//        bean.name = model.name
//        val observable = RetrofitFactory.getInstance().addPipe(getRequestBody(bean))
//        sendRequest(observable, object : BaseObserver<AddPipeModel>(mActivity, this) {
//            override fun onSuccess(models: AddPipeModel) {
//                mEmitter.SendDirective(ADD_PIPE, null)
//            }
//        }, true)
    }

    /**
     * 查询楼层下的管道数据
     */
    fun floorPipe() {
//        viewModelScope.launch {
//            val pipeModels = ArrayList<SpacePipeModel>()
//            val pipes = repo.getPipeByFloorId(floorId)
//            for (pipe in pipes) {
//                var hasParent = false
//                for (model in pipeModels) {
//                    if (model.type!!.equals(pipe.pipeType)) {
//                        val child = ChildrenZ()
//                        val objFrom = repo.getObject(pipe.objFrom!!)
//                        val objTo = repo.getObject(pipe.objTo!!)
//                        val infoFrom =
//                            gson.fromJson(objFrom!!.infos, InfosforEquip::class.java)
//                        child.position.add(PointF(infoFrom.location.x, infoFrom.location.y))
//
//                        val infoTo =
//                            gson.fromJson(objTo!!.infos, InfosforEquip::class.java)
//                        child.position.add(PointF(infoTo.location.x, infoTo.location.y))
//                        model.children.add(child)
//                        hasParent = true
//                    }
//                }
//                if (!hasParent) {
//                    val pipeModel = SpacePipeModel()
//                    pipeModel.typeName = pipe.pipeSubType + "--" + pipe.pipeType
//                    pipeModel.type = pipe.pipeType
//                    val child = ChildrenZ()
//                    val objFrom = repo.getObject(pipe.objFrom!!)
//                    val objTo = repo.getObject(pipe.objTo!!)
//                    val infoFrom =
//                        gson.fromJson(objFrom!!.infos, InfosforEquip::class.java)
//                    child.position.add(PointF(infoFrom.location.x, infoFrom.location.y))
//
//                    val infoTo = gson.fromJson(objTo!!.infos, InfosforEquip::class.java)
//                    child.position.add(PointF(infoTo.location.x, infoTo.location.y))
//                    pipeModel.children.add(child)
//                    pipeModels.add(pipeModel)
//                }
//
//            }
//            mEmitter.SendDirective(SPACE_PIPE, pipeModels)
//        }
    }


    fun getMap() {
        viewModelScope.launch {
            val floors = repo.getFloors()
            for (floor in floors) {
                if (floor.id.equals(floorId)) {
                    if (TextUtils.isEmpty(floor.floorMap)) {
                        ToastUtils.showMyToast("没有地图")
                        break
                    }
                    val mapFile = File("${floor.floorMap}")
                    val map = mapFile.bufferedReader().use { it.readText() }
                    val floorOfflineData = SJsonUtil.fromJson(map, FloorData::class.java)
                    mEmitter.SendDirective(MAP_LOAD, gson.toJson(floorOfflineData))
                    break
                }
            }

        }
    }


    /**
     * 增加设备问题
     */
    fun insProblemEquip(space: TunableSpaceItem, deviceId: String) {
        viewModelScope.launch {
            val equip = repo.getObject(deviceId)
            if (TextUtils.isEmpty(equip?.clientId)) {
                val proEntity = repo.getEqProblem(deviceId)
                if (proEntity == null) {
                    val entity = ProblemEquipEntity(
                        id = IdUtil.simpleUUID(),
                        floorId = floorId,
                        projectId = projectId,
                        buildingId = buildingId,
                        equipId = deviceId,
                        problemState = 1,
                        valid = 1,
                        state = 0
                    )
                    repo.insProblemEquipEntity(entity)
                }
            } else {
                equip?.valid = 0
                equip?.state()
                repo.insObject(equip!!)
            }
            getSpaceEq(space)
        }
    }

    /**
     * APP自动更新
     */
    fun queryAutoUpdate() {
        val bean = ApkVersionBean()
        val observable = RetrofitFactory.getInstance().autoUpdateApp(getRequestBody(bean))
        sendRequest(
            observable,
            object : BaseObserver<java.util.ArrayList<AutoUpDateBean.Content>>(mActivity, this) {
                override fun onSuccess(models: ArrayList<AutoUpDateBean.Content>) {
                    if (!CommonUtils.IsNull(models)) {
                        mEmitter.SendDirective(UPDATE_APP, models.get(0))
                    }
                }
            },
            true
        )
    }

    /**
     * 修改设备位置
     */
    fun insEquip(ob: ObjectEntity, position: Position) {
        viewModelScope.launch {
            var obj = repo.getObject(ob.id)
            val hashMap = gson.fromJson(obj!!.infos, HashMap::class.java) as HashMap<String, Any>
            val z = PointZ()
            z.x = position.x.toFloat()
            z.y = -position.y.toFloat()
            z.z = position.z.offset.toFloat()
            hashMap.put("location", z)
            hashMap.put("zRegion", position.z.region)
            obj.infos = gson.toJsonTree(hashMap)
            obj.state()
            repo.insObject(obj)
            mEmitter.SendDirective(UPDATE_LOCATION, null)
        }

    }

    /**
     * 获取设备服务区域
     */
    fun getServeArea(deviceId: String) {
        viewModelScope.launch {
            val entity = repo.getServeAreaByObjId(deviceId)
            if (entity == null) {
                mEmitter.SendDirective(SERVE_AREA, "无")
            } else {
                mEmitter.SendDirective(SERVE_AREA, "有")
            }
        }

    }

    /**
     * 获取无模型设备
     */
    fun getContainer(deviceId: String) {
        viewModelScope.launch {
            val objs = repo.getContainerObjs(deviceId)
            val equip = repo.getObject(deviceId)
            val configs = repo.getContainerConfig(equip!!.classCode!!)
            val hashMap = HashMap<String, Any>()
            hashMap.put("configs", configs)
            hashMap.put("objs", objs)
            mEmitter.SendDirective(CONTAINER_EQUIP, hashMap)
        }
    }

    fun getMajor() {
        viewModelScope.launch {
            val majors = repo.getMajors()
            mEmitter.SendDirective(MAJORS_LIST, majors)
        }
    }

    fun copyDetail(deviceId: String?) {
        viewModelScope.launch {
            val equip = repo.getObject(deviceId!!)
            val hashMap = gson.fromJson(equip!!.infos, HashMap::class.java) as HashMap<String, Any>
            hashMap.remove("localId")
            hashMap.remove("equipPhoto")
            hashMap.remove("equipCheck")
            hashMap.remove("equipContent")
            hashMap.remove("location")
            hashMap.remove("zRegion")
            Constant.infoMap = hashMap
            Constant.equipCode = equip.classCode
            ToastUtils.showMyToast("复制成功")
        }
    }

    companion object {

        //app版本更新
        const val UPDATE_APP = "UPDATE_APP"

        //地图加载
        const val MAP_LOAD = "MAP_LOAD"

        //查询空间和任务
        const val SPACE_JOB = "SPACE_JOB"

        //设置空间核查问题的信息和状态
        const val SET_PROBLEM = "SET_PROBLEM"

        //设置空间的任务状态(新建和修改)
        const val SET_JOB = "SET_JOB"

        //设置空间的任务状态(新建和修改)
        const val SPACE_EQ = "SPACE_EQ"

        //查询管道类型树
        const val PIPE_LIST = "PIPE_LIST"

        //添加管线
        const val ADD_PIPE = "ADD_PIPE"

        //查询空间下的管道Equip_INFOS
        const val SPACE_PIPE = "SPACE_PIPE"

        //管道二级列表
        const val PIPE = "PIPE"

        //编辑设备位置
        const val UPDATE_LOCATION = "UPDATE_LOCATION"

        //设备服务区域
        const val SERVE_AREA = "SERVE_AREA"

        //无模型设备
        const val CONTAINER_EQUIP = "CONTAINER_EQUIP"

        //专业列表
        const val MAJORS_LIST = "MAJORS_LIST"
    }

}