import { listenLayer } from '../ListenLayer'
import Constant from '../Constant'
import { mathUtil } from '../MathUtil'
import { floorplanService } from '../Service/FloorplanService'
import { elementService } from '../Service/ElementService'
import { wallService } from '../Service/WallService'
import { coordinate } from '../Coordinate'

export default class AddWall {
    constructor() {
        this.startInfo = {}
        this.endInfo = {}
        this.canAdd = false
    }

    setPointInfo(dir, pointInfo) {
        if (dir == 'start') {
            this.startInfo = {
                position: {
                    x: pointInfo.x,
                    y: pointInfo.y,
                },
                linkedPointId: pointInfo.linkedPointId,
                linkedWallId: pointInfo.linkedWallId,
            }
        } else if (dir == 'end') {
            this.endInfo = {
                position: {
                    x: pointInfo.x,
                    y: pointInfo.y,
                },
                linkedPointId: pointInfo.linkedPointId,
                linkedWallId: pointInfo.linkedWallId,
            }
        }
    }

    buildWall() {
        console.log('添加新墙！')

        let joinInfos = this.getJoinsForWalls()
        let splitPointIds = this.splitAllJoins(joinInfos)
        this.creatNewWalls(splitPointIds)
        this.canAdd = false
        this.updateStart(this.endInfo.position, splitPointIds[splitPointIds.length - 1])
        listenLayer.clear()
    }

    //开始新建墙，可能是多个
    creatNewWalls(splitPointIds) {
        for (let i = 0; i < splitPointIds.length - 1; ++i) {
            let pointId1 = splitPointIds[i]
            let pointId2 = splitPointIds[i + 1]
            let wallId = wallService.getWallId(pointId1, pointId2)
            if (!wallId) {
                wallService.createWall(pointId1, pointId2)
            }
        }
    }

    canAddWallForEnd(endPt) {
        if (listenLayer.modifyPoint) {
            if (mathUtil.getDistance(this.startInfo.position, listenLayer.modifyPoint) < Constant.minAdsorb) {
                return false
            }
        } else {
            if (mathUtil.getDistance(this.startInfo.position, endPt) < Constant.minAdsorb) {
                return false
            }
        }
        return true
    }

    getJoinsForWalls() {
        let result = []

        const walls = floorplanService.getWalls()
        let hasComputerPointIds = []
        let hasExitPointIds = []

        if (this.startInfo.linkedPointId) {
            hasComputerPointIds.push(this.startInfo.linkedPointId)
            hasExitPointIds.push(this.startInfo.linkedPointId)
            result.push({ join: { x: this.startInfo.position.x, y: this.startInfo.position.y }, pointId: this.startInfo.linkedPointId })
        } else if (this.startInfo.linkedWallId) {
            result.push({ join: { x: this.startInfo.position.x, y: this.startInfo.position.y }, wallId: this.startInfo.linkedWallId })
        } else {
            result.push({ join: { x: this.startInfo.position.x, y: this.startInfo.position.y } })
        }

        if (this.endInfo.linkedPointId) {
            hasComputerPointIds.push(this.endInfo.linkedPointId)
            hasExitPointIds.push(this.endInfo.linkedPointId)
            result.push({ join: { x: this.endInfo.position.x, y: this.endInfo.position.y }, pointId: this.endInfo.linkedPointId })
        } else if (this.endInfo.linkedWallId) {
            result.push({ join: { x: this.endInfo.position.x, y: this.endInfo.position.y }, wallId: this.endInfo.linkedWallId })
        } else {
            result.push({ join: { x: this.endInfo.position.x, y: this.endInfo.position.y } })
        }

        const line = mathUtil.createLine1(this.startInfo.position, this.endInfo.position)
        for (let key in walls) {
            if (this.startInfo.linkedWallId && this.startInfo.linkedWallId == key) {
                continue
            } else if (this.endInfo.linkedWallId && this.endInfo.linkedWallId == key) {
                continue
            }

            let wall = walls[key]
            if (hasExitPointIds.indexOf(wall.start) > -1 || hasExitPointIds.indexOf(wall.end) > -1) {
                continue
            }

            let startPoint = floorplanService.getPoint(wall.start)
            let endPoint = floorplanService.getPoint(wall.end)
            let flag = false

            if (hasComputerPointIds.indexOf(wall.start) < 0) {
                hasComputerPointIds.push(wall.start)
                const startJoin = mathUtil.getJoinLinePoint(startPoint, line)
                if (mathUtil.PointInSegment(startJoin, this.startInfo.position, this.endInfo.position, Constant.minAdsorb) && mathUtil.getDistance(startPoint, startJoin) < Constant.minAdsorb) {
                    result.push({ join: { x: startJoin.x, y: startJoin.y }, pointId: wall.start })
                    flag = true

                    hasExitPointIds.push(wall.start)
                }
            }

            if (hasComputerPointIds.indexOf(wall.end) < 0) {
                hasComputerPointIds.push(wall.end)
                const endJoin = mathUtil.getJoinLinePoint(endPoint, line)
                if (mathUtil.PointInSegment(endJoin, this.startInfo.position, this.endInfo.position, Constant.minAdsorb) && mathUtil.getDistance(endPoint, endJoin) < Constant.minAdsorb) {
                    result.push({ join: { x: endJoin.x, y: endJoin.y }, pointId: wall.end })
                    flag = true

                    hasExitPointIds.push(wall.end)
                }
            }

            if (!flag) {
                //不与墙key的端点相交
                if (hasExitPointIds.indexOf(wall.start) < 0 && hasExitPointIds.indexOf(wall.end) < 0) {
                    let join = mathUtil.getIntersectionPoint3(startPoint, endPoint, this.startInfo.position, this.endInfo.position)
                    if (join) {
                        result.push({ join: { x: join.x, y: join.y }, wallId: key })
                    }
                }
            }
        }
        return result
    }

    splitAllJoins(joinInfos) {
        // 对joinInfos要进行排序
        joinInfos = joinInfos.sort(sortNumber.bind(this))
        function sortNumber(a, b) {
            return mathUtil.getDistance(this.startInfo.position, a.join) - mathUtil.getDistance(this.startInfo.position, b.join)
        }

        const splitPointIds = []
        for (let i = 0; i < joinInfos.length; ++i) {
            const info = joinInfos[i]
            const join = info.join
            const wallId = info.wallId
            const pointId = info.pointId

            if (pointId) {
                splitPointIds.push(pointId)
            } else if (wallId) {
                // 拆分wallId
                const splitPoint = wallService.createPoint(join.x, join.y)
                const splitPointId = splitPoint.vectorId

                //可能joinInfos的两个点都在wallId上
                let newWallId = null
                if (joinInfos[i + 1] && joinInfos[i].wallId == joinInfos[i + 1].wallId) {
                    let wall = floorplanService.getWall(wallId)
                    let startPoint = floorplanService.getPoint(wall.start)
                    if (mathUtil.getDistance(startPoint, joinInfos[i].join) < mathUtil.getDistance(startPoint, joinInfos[i + 1].join)) {
                        newWallId = wallService.splitWall(wallId, splitPointId, 'end')
                    } else {
                        newWallId = wallService.splitWall(wallId, splitPointId, 'start')
                    }
                } else {
                    newWallId = wallService.splitWall(wallId, splitPointId, 'start')
                }

                if (newWallId == null) {
                    floorplanService.deletePoint(splitPointId)
                    continue
                }
                splitPointIds.push(splitPointId)
            }
            //首尾没有吸附的情况
            else {
                const splitPoint = wallService.createPoint(join.x, join.y)
                splitPointIds.push(splitPoint.vectorId)
            }
        }

        return splitPointIds
    }

    updateStart(position, linkedPointId) {
        mathUtil.clonePoint(this.startInfo.position, position)
        this.startInfo.linkedPointId = linkedPointId
        elementService.setNewWallStartPosition(this.startInfo.position)
    }

    setNewWallPoint(dir, position) {
        if (dir == 'start') {
            if (listenLayer.modifyPoint) {
                this.setPointInfo(dir, listenLayer.modifyPoint)
            } else {
                this.setPointInfo(dir, coordinate.getXYFromScreen(position))
            }
            return true
        } else if (dir == 'end') {
            if (listenLayer.modifyPoint) {
                this.setPointInfo(dir, listenLayer.modifyPoint)
            } else {
                this.setPointInfo(dir, coordinate.getXYFromScreen(position))
            }
            return true
        }
        return false
    }

    clear() {
        this.startInfo = {}
        this.endInfo = {}
        this.canAdd = false
        elementService.hideNewWall()
        elementService.hideStartAddWall()
    }
}

const addWall = new AddWall()
export { addWall }
