import Point from '../Geometry/Point.js'
import Line from '../Geometry/Line.js'
import ElementEvents from '../enum/ElementEvents.js'
import { listenLayer } from '../ListenLayer'
import Constant from '../Constant'
import { floorplanService } from './FloorplanService'
import { mathUtil } from '../MathUtil.js'
import { wallService } from './WallService.js'

export class ElementService {
    constructor() {
        this.startAddWall = null
        this.newWall = null
        this.checkLines = {
            X: null,
            Y: null,
        }

        this.vCheckLines = {
            X: null,
            Y: null,
        }

        this.init()
    }

    init() {
        this.startAddWall = new Point(0, 0)
        this.startAddWall.name = ElementEvents.StartAddWall

        this.newWall = new Line({ x: 0, y: 0 }, { x: 1, y: 1 })
        this.newWall.name = ElementEvents.NewWall

        this.checkLines.X = new Line({ x: 0, y: 0 }, { x: 1, y: 1 })
        this.checkLines.X.name = ElementEvents.CheckLinesX

        this.checkLines.Y = new Line({ x: 0, y: 0 }, { x: 1, y: 1 })
        this.checkLines.Y.name = ElementEvents.CheckLinesY

        this.vCheckLines.X = new Line({ x: 0, y: 0 }, { x: 1, y: 1 })
        this.vCheckLines.X.name = ElementEvents.VCheckLinesX

        this.vCheckLines.Y = new Line({ x: 0, y: 0 }, { x: 1, y: 1 })
        this.vCheckLines.Y.name = ElementEvents.VCheckLinesY
    }

    showStartAddWall() {
        this.startAddWall.display = true
    }

    hideStartAddWall() {
        this.startAddWall.display = false
    }

    setStartAddWall(position) {
        this.startAddWall.setPosition(position)
    }

    showNewWall() {
        this.newWall.display = true
    }

    hideNewWall() {
        this.newWall.display = false
    }

    setNewWall(point1, point2) {
        this.newWall.setPositions(point1, point2)
    }

    setNewWallStartPosition(startPosition) {
        this.newWall.start.x = startPosition.x
        this.newWall.start.y = startPosition.y
    }

    setNewWallEndPosition(endPosition) {
        this.newWall.end.x = endPosition.x
        this.newWall.end.y = endPosition.y
    }

    setNewWallState(state) {
        this.newWall.state = state
    }

    showCheckLinesX() {
        this.checkLines.X.display = true
    }

    hideCheckLinesX() {
        this.checkLines.X.display = false
    }

    setCheckLinesX(point1, point2) {
        this.checkLines.X.setPositions(point1, point2)
    }

    showCheckLinesY() {
        this.checkLines.Y.display = true
    }

    hideCheckLinesY() {
        this.checkLines.Y.display = false
    }

    setCheckLinesY(point1, point2) {
        this.checkLines.Y.setPositions(point1, point2)
    }

    showVCheckLinesX() {
        this.vCheckLines.X.display = true
    }

    hideVCheckLinesX() {
        this.vCheckLines.X.display = false
    }

    setVCheckLinesX(point1, point2) {
        this.vCheckLines.X.setPositions(point1, point2)
    }

    showVCheckLinesY() {
        this.vCheckLines.Y.display = true
    }

    hideVCheckLinesY() {
        this.vCheckLines.Y.display = false
    }

    setVCheckLinesY(point1, point2) {
        this.vCheckLines.Y.setPositions(point1, point2)
    }

    hideAll() {
        this.hideCheckLinesX()
        this.hideCheckLinesY()
        this.hideStartAddWall()
        this.hideNewWall()
        this.hideVCheckLinesX()
        this.hideVCheckLinesY()
    }

    execute(startPosition, position) {
        this.hideVCheckLinesX()
        this.hideVCheckLinesY()
        this.hideCheckLinesX()
        this.hideCheckLinesY()

        if (listenLayer.modifyPoint) {
            if (listenLayer.modifyPoint.linkedPointIdX) {
                const linkedPointX = floorplanService.getPoint(listenLayer.modifyPoint.linkedPointIdX)
                this.setCheckLinesX(linkedPointX, position)
                this.showCheckLinesX()
            }

            if (listenLayer.modifyPoint.linkedPointIdY) {
                const linkedPointY = floorplanService.getPoint(listenLayer.modifyPoint.linkedPointIdY)
                this.setCheckLinesY(linkedPointY, position)
                this.showCheckLinesY()
            }
        }
        //垂直校验
        if (startPosition) {
            if (Math.abs(position.x - startPosition.x) < Constant.minAdsorb) {
                position.x = startPosition.x
                this.setVCheckLinesX(startPosition, position)
                this.showVCheckLinesX()
            }

            if (Math.abs(position.y - startPosition.y) < Constant.minAdsorb) {
                position.y = startPosition.y
                this.setVCheckLinesY(startPosition, position)
                this.showVCheckLinesY()
            }

            if (mathUtil.equalPoint(position, startPosition)) {
                this.hideVCheckLinesX()
                this.hideVCheckLinesY()
            }
        }
    }

    //pointId是角度的顶点
    //exceptPointId表示position对应的pointId(如果有的话)
    checkAngle(position, pointId, exceptPointId) {
        //type:1表示90°，2表示180°
        function ajust(position, point1, point2, type) {
            let line = mathUtil.createLine1(point1, point2)
            let join = null
            if (type == 1) {
                let vLine = mathUtil.getVerticalLine(line, point1)
                join = mathUtil.getJoinLinePoint(position, vLine)
            } else if (type == 2) {
                join = mathUtil.getJoinLinePoint(position, line)
            }
            return join
        }

        let points = wallService.getNeighPoints(pointId, exceptPointId)
        let point = floorplanService.getPoint(pointId)
        let newPosition = null
        for (let i = 0; i < points.length; ++i) {
            let angle = mathUtil.Angle(point, position, points[i])
            if (Math.abs((angle / Math.PI) * 180 - 90) < Constant.minAngle/2) {
                newPosition = ajust(position, point, points[i], 1)
            } else if (Math.abs((angle / Math.PI) * 180) < Constant.minAngle/2 || Math.abs((angle / Math.PI) * 180 - 180) < Constant.minAngle/2) {
                newPosition = ajust(position, point, points[i], 2)
            }
            if (newPosition != null) {
                return newPosition
            }
        }
        return newPosition
    }
}

const elementService = new ElementService()
export { elementService }
