import { floorplanService } from '../Service/FloorplanService'
import { elementService } from '../Service/ElementService'
import { wallService } from '../Service/WallService'
import { historyUtil } from './HistoryUtil'
import { change } from './Change'
import { stateService } from '../Service/StateService'
import HistoryEvents from '../enum/HistoryEvents'
import { historyService } from '../Service/HistoryService'
import { tagService } from '../Service/TagService'
import { coordinate } from '../Coordinate'
import { signService } from '../Service/SignService'
import { tableService } from '../Service/TableService'
import { rectangleService } from '../Service/RectangleService'
import { circleService } from '../Service/CircleService'
import { arrowService } from '../Service/ArrowService'
import { iconService } from '../Service/IconService'
import mitt from 'mitt'

export default class History {
    constructor() {
        this.bus = mitt()
    }

    init() {
        change.saveCurrentInfo()
        this.bus.emit('redoAvailable', false)
        this.bus.emit('undoAvailable', false)
    }

    save() {
        const flag = change.operate()
        if (!flag) {
            return
        }
        historyService.addHistoryRecord(change.elements)
        change.saveCurrentInfo()
        this.setState()
        const historyState = historyService.getHistoryState()
        if (historyState.pre) {
            this.bus.emit('undoAvailable', true)
        }
        return change.elements
    }

    setState() {
        const state = {
            pre: 0,
            next: 0,
        }

        const currentRecordIndex = historyService.getCurrentRecordIndex()
        const records = historyService.getHistoryRecords()

        if (currentRecordIndex > -1) {
            state.pre = 1
        }

        if (currentRecordIndex < records.length - 1) {
            state.next = 1
        }
        const lastState = historyService.getHistoryState()
        if (lastState.pre != state.pre || lastState.next != state.next) {
            historyService.setHistoryState(state.pre, state.next)
        }
    }

    // 是否可以撤销
    canUndo() {
        const state = this.setState()
        if (state.pre == 0) {
            return false
        } else {
            return true
        }
    }

    // 是否可以恢复
    canRedo() {
        const state = this.setState()
        if (state.next == 0) {
            return false
        } else {
            return true
        }
    }

    // 撤销
    handleUndo() {
        this.goPreState()
        this.layer.renderer.autoRedraw()
        const historyState = historyService.getHistoryState()
        if (historyState.pre) {
            //可以继续撤销
            this.bus.emit('undoAvailable', true)
        }
        else{
            //不能继续撤销
            this.bus.emit('undoAvailable', false)
        }
        this.bus.emit('redoAvailable', true)
        this.layer.uiControl.clearUI();
    }

    // 恢复
    handleRedo() {
        this.goNextState()
        this.layer.renderer.autoRedraw()
        const historyState = historyService.getHistoryState()
        if (historyState.next) {
            //可以继续恢复
            this.bus.emit('redoAvailable', true)
        }
        else{
            //不能继续恢复
            this.bus.emit('redoAvailable', false)
        }
        this.bus.emit('undoAvailable', true)
        this.layer.uiControl.clearUI();
    }
   
    // 撤销
    goPreState() {
        const item = historyService.getHistoryRecord()
        if (item) {
            stateService.clearItems()
            this.layer.uiControl.clearUI()

            item.type = 'pre'
        
            this.goPreForPoints(item.points)
            this.goPreForWalls(item.walls)
            this.goPreForTags(item.tags)
            this.goPreForCells(item.cells)
            this.goPreForTables(item.tables)
            this.goPreForRectangles(item.rectangles)
            this.goPreForCircles(item.circles)
            this.goPreForArrows(item.arrows)
            this.goPreForIcons(item.icons)
            this.goPreForSigns(item.signs)

            this.goPreForTitle(item.title)
            this.goPreForImage (item.image)
            this.goPreForCompass(item.compass)

            historyService.undoHistoryRecord()
            change.saveCurrentInfo()
            this.setState()

            // const points = floorplanService.getPoints()
            // if (Object.keys(points).length > 0) {
            //     this.layer.$xui.toolbar.clear = true
            //     this.layer.$xui.toolbar.download = true
            // } else {
            //     this.layer.$xui.toolbar.clear = false
            //     this.layer.$xui.toolbar.download = false
            // }
        } else {
            console.error('goPreState超出范围！')
        }
    }

    goPreForPoints(itemForPoints) {
        for (let i = 0; i < itemForPoints.length; ++i) {
            const item = itemForPoints[i]
            if (item.handle == HistoryEvents.AddPoint) {
                historyUtil.deletePoint(item.point.id)
            } else if (item.handle == HistoryEvents.DeletePoint) {
                let point = wallService.createPoint(item.point.x, item.point.y, item.point.id)
                point.parent = JSON.parse(JSON.stringify(item.point.parent))
            } else if (item.handle == HistoryEvents.ModifyPoint) {
                const prePoint = item.prePoint
                let currentPoint = floorplanService.getPoint(item.curPoint.id)
                historyUtil.assignPointFromPoint(currentPoint, prePoint)
            }
        }
    }

    goPreForWalls(itemForWalls) {
        for (let i = 0; i < itemForWalls.length; ++i) {
            const item = itemForWalls[i]
            if (item.handle == HistoryEvents.AddWall) {
                floorplanService.deleteWall(item.wall.id)
            } else if (item.handle == HistoryEvents.DeleteWall) {
                const preWall = item.wall
                let newWall = wallService.createWall(preWall.start, preWall.end, preWall.id)
                historyUtil.assignWallFromWall(newWall, preWall)
            } else if (item.handle == HistoryEvents.ModifyWall) {
                const preWall = item.preWall
                let currentWall = floorplanService.getWall(item.curWall.id)
                historyUtil.assignWallFromWall(currentWall, preWall)
            }
        }
    }

    goPreForSigns(itemForSigns) {
        for (let i = 0; i < itemForSigns.length; ++i) {
            const item = itemForSigns[i]
            if (item.handle == HistoryEvents.AddSign) {
                floorplanService.deleteSign(item.sign.id)
            } else if (item.handle == HistoryEvents.DeleteSign) {
                let vSign = signService.createSign(item.sign.center, item.sign.type, item.sign.id)
                historyUtil.assignSignFromSign(vSign, item.sign)
            } else if (item.handle == HistoryEvents.ModifySign) {
                const preSign = item.preSign
                let currentSign = floorplanService.getSign(item.curSign.id)
                historyUtil.assignSignFromSign(currentSign, preSign)
            }
        }
    }

    goPreForTags(itemForTags) {
        for (let i = 0; i < itemForTags.length; ++i) {
            const item = itemForTags[i]
            if (item.handle == HistoryEvents.AddTag) {
                tagService.deleteTag(item.tag.id)
            } else if (item.handle == HistoryEvents.DeleteTag) {
                let newTag = tagService.createTag(item.tag.center, item.tag.id)
                historyUtil.assignTagFromTag(newTag, item.tag)
            } else if (item.handle == HistoryEvents.ModifyTag) {
                const preTag = item.preTag
                let currentTag = floorplanService.getTag(item.curTag.id)
                historyUtil.assignTagFromTag(currentTag, preTag)
            }
        }
    }

    goPreForCells(itemForCells) {
        for (let i = 0; i < itemForCells.length; ++i) {
            const item = itemForCells[i]
            if (item.handle == HistoryEvents.AddCell) {    
                tableService.deleteCell(item.cell.id)
            } else if (item.handle == HistoryEvents.DeleteCell) {
                let newCell = tableService.createCell(item.cell.parent,item.cell.id)
                historyUtil.assignCellFromCell(newCell, item.cell)
            } else if (item.handle == HistoryEvents.ModifyCell) {
                const preCell = item.preCell
                let curCell = floorplanService.getCell(item.curCell.id)
                historyUtil.assignCellFromCell(curCell, preCell)
            }
        }
    }

    goPreForTables(itemForTables) {
        for (let i = 0; i < itemForTables.length; ++i) {
            const item = itemForTables[i]
            if (item.handle == HistoryEvents.AddTable) {
                tableService.deleteTable(item.table.id)
            } else if (item.handle == HistoryEvents.DeleteTable) {
                let newTable = tableService.createTable(item.table.center, item.table.id)
                historyUtil.assignTableFromTable(newTable, item.table)
            } else if (item.handle == HistoryEvents.ModifyTable) {
                const preTable = item.preTable
                let curTable = floorplanService.getTable(item.curTable.id)
                historyUtil.assignTableFromTable(curTable, preTable)
            }
        }
    }

    goPreForRectangles(itemForRectangles) {
        for (let i = 0; i < itemForRectangles.length; ++i) {
            const item = itemForRectangles[i]
            if (item.handle == HistoryEvents.AddRectangle) {    
                rectangleService.deleteRectangle(item.rectangle.id)
            } else if (item.handle == HistoryEvents.DeleteRectangle) {
                let newRectangle = rectangleService.createRectangle(item.rectangle.points[0],item.rectangle.points[2],item.rectangle.id)
                historyUtil.assignRectangleFromRectangle(newRectangle, item.rectangle)
            } else if (item.handle == HistoryEvents.ModifyRectangle) {
                const preRectangle = item.preRectangle
                let curRectangle = floorplanService.getRectangle(item.curRectangle.id)
                historyUtil.assignRectangleFromRectangle(curRectangle, preRectangle)
            }
        }
    }

    goPreForCircles(itemForCircles) {
        for (let i = 0; i < itemForCircles.length; ++i) {
            const item = itemForCircles[i]
            if (item.handle == HistoryEvents.AddCircle) {    
                circleService.deleteCircle(item.circle.id)
            } else if (item.handle == HistoryEvents.DeleteCircle) {
                let newCircle = circleService.createCircle(item.circle.points[0],item.circle.points[2],item.circle.id)
                historyUtil.assignCircleFromCircle(newCircle, item.circle)
            } else if (item.handle == HistoryEvents.ModifyCircle) {
                const preCircle = item.preCircle
                let curCircle = floorplanService.getCircle(item.curCircle.id)
                historyUtil.assignCircleFromCircle(curCircle, preCircle)
            }
        }
    }

    goPreForArrows(itemForArrows) {
        for (let i = 0; i < itemForArrows.length; ++i) {
            const item = itemForArrows[i]
            if (item.handle == HistoryEvents.AddArrow) {    
                arrowService.deleteArrow(item.arrow.id)
            } else if (item.handle == HistoryEvents.DeleteArrow) {
                let newArrow = arrowService.createArrow(item.arrow.startPoint,item.arrow.endPoint,item.arrow.id)
                historyUtil.assignArrowFromArrow(newArrow, item.arrow)
            } else if (item.handle == HistoryEvents.ModifyArrow) {
                const preArrow = item.preArrow
                let curArrow = floorplanService.getArrow(item.curArrow.id)
                historyUtil.assignArrowFromArrow(curArrow, preArrow)
            }
        }
    }

    goPreForIcons(itemForIcons) {
        for (let i = 0; i < itemForIcons.length; ++i) {
            const item = itemForIcons[i]
            if (item.handle == HistoryEvents.AddIcon) {  
                iconService.deleteIcon(item.icon.id)
            } else if (item.handle == HistoryEvents.DeleteIcon) {
                let newIcon = iconService.createIcon(item.icon.points[0],item.icon.points[2],item.icon.value,item.icon.id)
                historyUtil.assignIconFromIcon(newIcon, item.icon)
            } else if (item.handle == HistoryEvents.ModifyIcon) {
                const preIcon = item.preIcon
                let curIcon = floorplanService.getIcon(item.curIcon.id)
                historyUtil.assignIconFromIcon(curIcon, preIcon)
            }
        }
    }

    goPreForTitle(itemForTitle) {
        if (itemForTitle != null && itemForTitle.handle == HistoryEvents.ModifyTitle) {
            const preTitle = itemForTitle.preTitle
            let curTitle = floorplanService.getTitle()
            historyUtil.assignTitleFromTitle(curTitle, preTitle)
        }
    }

    goPreForImage(itemForImage) {
        if (itemForImage != null && itemForImage.handle == HistoryEvents.ModifyImage) {
            const preImage = itemForImage.preImage
            let curImage = floorplanService.getBgImage()
            historyUtil.assignImageFromImage(curImage, preImage,this.layer)
        }
    }

    goPreForCompass(itemForCompass) {
        if (itemForCompass != null && itemForCompass.handle == HistoryEvents.ModifyCompass) {
            const preCompass = itemForCompass.preCompass
            let curCompass = floorplanService.getCompass()
            historyUtil.assignCompassFromCompass(curCompass, preCompass)
        }
    }


    // goPreForAngle(itemForAngle) {
    //     if (itemForAngle.handle == HistoryEvents.ModifyAngle) {
    //         coordinate.reSet()
    //         coordinate._setRes(itemForAngle.preState.res)
    //         //旋转cad
    //         floorplanService.setAngle(itemForAngle.preState.angle)
    //         coordinate.updateForRotate(itemForAngle.preState.angle - itemForAngle.curState.angle)
    //         //旋转三维模型
    //         let info = coordinate.getScreenInfoForCAD()
    //         info.floorPlanAngle = itemForAngle.preState.angle
    //         this.layer.app.core.get('CameraControls').emit('syncCadAnd3DForRotate', info)
    //         this.layer.app.store.getValue('metadata').floorPlanAngle = itemForAngle.preState.angle
    //         this.layer.initPanos(floorplanService.getCurrentFloor())
    //         return true
    //     } else {
    //         return false
    //     }
    // }

    goNextForPoints(itemForPoints) {
        for (let i = 0; i < itemForPoints.length; ++i) {
            const item = itemForPoints[i]
            if (item.handle == HistoryEvents.AddPoint) {
                let newPoint = wallService.createPoint(item.point.x, item.point.y, item.point.id)
                historyUtil.assignPointFromPoint(newPoint, item.point)
            } else if (item.handle == HistoryEvents.DeletePoint) {
                historyUtil.deletePoint(item.point.id)
            } else if (item.handle == HistoryEvents.ModifyPoint) {
                const currentPoint = item.curPoint
                let prePoint = floorplanService.getPoint(item.curPoint.id)
                historyUtil.assignPointFromPoint(prePoint, currentPoint)
            }
        }
    }

    goNextForWalls(itemForWalls) {
        for (let i = 0; i < itemForWalls.length; ++i) {
            const item = itemForWalls[i]
            if (item.handle == HistoryEvents.AddWall) {
                const preWall = item.wall
                let newWall = wallService.createWall(preWall.start, preWall.end, preWall.id)
                historyUtil.assignWallFromWall(newWall, preWall)
            } else if (item.handle == HistoryEvents.DeleteWall) {
                floorplanService.deleteWall(item.wall.id)
            } else if (item.handle == HistoryEvents.ModifyWall) {
                const currentWall = item.curWall
                let preWall = floorplanService.getWall(item.preWall.id)
                historyUtil.assignWallFromWall(preWall, currentWall)
            }
        }
    }

    goNextForTags(itemForTags) {
        for (let i = 0; i < itemForTags.length; ++i) {
            const item = itemForTags[i]
            if (item.handle == HistoryEvents.AddTag) {
                let vTag = tagService.createTag(item.tag.center, item.tag.id)
                historyUtil.assignTagFromTag(vTag, item.tag)
            } else if (item.handle == HistoryEvents.DeleteTag) {
                floorplanService.deleteTag(item.tag.id)
            } else if (item.handle == HistoryEvents.ModifyTag) {
                const currentTag = item.curTag
                let preTag = floorplanService.getTag(item.curTag.id)
                historyUtil.assignTagFromTag(preTag, currentTag)
            }
        }
    }

    goNextForCells(itemForCells) {
        for (let i = 0; i < itemForCells.length; ++i) {
            const item = itemForCells[i]
            if (item.handle == HistoryEvents.AddCell) {    
                let vCell = tableService.createCell(item.cell.parent, item.cell.id)
                historyUtil.assignCellFromCell(vCell, item.cell)
            } else if (item.handle == HistoryEvents.DeleteCell) {
                tableService.deleteCell(item.cell.id)
            } else if (item.handle == HistoryEvents.ModifyCell) {
                const curCell = item.curCell
                let preCell = floorplanService.getCell(item.curCell.id)
                historyUtil.assignCellFromCell(preCell, curCell)
            }
        }
    }

    goNextForTables(itemForTables) {
        for (let i = 0; i < itemForTables.length; ++i) {
            const item = itemForTables[i]
            if (item.handle == HistoryEvents.AddTable) {
                let vTable = tableService.createTable(item.table.center, item.table.id)
                historyUtil.assignTableFromTable(vTable, item.table)
            } else if (item.handle == HistoryEvents.DeleteTable) {
                tableService.deleteTable(item.table.id)
            } else if (item.handle == HistoryEvents.ModifyTable) {
                const curTable = item.curTable
                let preTable = floorplanService.getTable(item.curTable.id)
                historyUtil.assignTableFromTable(preTable, curTable)
            }
        }
    }

    goNextForRectangles(itemForRectangles) {
        for (let i = 0; i < itemForRectangles.length; ++i) {
            const item = itemForRectangles[i]
            if (item.handle == HistoryEvents.AddRectangle) {
                let vRectangle = rectangleService.createRectangle(item.rectangle.points[0],item.rectangle.points[2],item.rectangle.id)
                historyUtil.assignRectangleFromRectangle(vRectangle, item.rectangle)
            } else if (item.handle == HistoryEvents.DeleteRectangle) {
                rectangleService.deleteRectangle(item.rectangle.id)
            } else if (item.handle == HistoryEvents.ModifyRectangle) {
                const currentRectangle = item.curRectangle
                let preRectangle = floorplanService.getRectangle(item.curRectangle.id)
                historyUtil.assignRectangleFromRectangle(preRectangle, currentRectangle)
            }
        }
    }

    goNextForCircles(itemForCircles) {
        for (let i = 0; i < itemForCircles.length; ++i) {
            const item = itemForCircles[i]
            if (item.handle == HistoryEvents.AddCircle) {
                let vCircle = circleService.createCircle(item.circle.points[0],item.circle.points[2],item.circle.id)
                historyUtil.assignCircleFromCircle(vCircle, item.circle)
            } else if (item.handle == HistoryEvents.DeleteCircle) {
                floorplanService.deleteCircle(item.circle.id)
            } else if (item.handle == HistoryEvents.ModifyCircle) {
                const currentCircle = item.curCircle
                let preCircle = floorplanService.getCircle(item.curCircle.id)
                historyUtil.assignCircleFromCircle(preCircle, currentCircle)
            }
        }
    }

    goNextForArrows(itemForArrows) {
        for (let i = 0; i < itemForArrows.length; ++i) {
            const item = itemForArrows[i]
            if (item.handle == HistoryEvents.AddArrow) {
                let vArrow = arrowService.createArrow(item.arrow.startPoint,item.arrow.endPoint,item.arrow.id)
                historyUtil.assignArrowFromArrow(vArrow, item.arrow)
            } else if (item.handle == HistoryEvents.DeleteArrow) {
                arrowService.deleteArrow(item.arrow.id)
            } else if (item.handle == HistoryEvents.ModifyArrow) {
                const currentArrow = item.curArrow
                let preArrow = floorplanService.getArrow(item.curArrow.id)
                historyUtil.assignArrowFromArrow(preArrow, currentArrow)
            }
        }
    }

    goNextForIcons(itemForIcons) {
        for (let i = 0; i < itemForIcons.length; ++i) {
            const item = itemForIcons[i]
            if (item.handle == HistoryEvents.AddIcon) {
                let vIcon = iconService.createIcon(item.icon.points[0],item.icon.points[2],item.icon.value,item.icon.id)
                historyUtil.assignIconFromIcon(vIcon, item.icon)
            } else if (item.handle == HistoryEvents.DeleteIcon) {
                iconService.deleteIcon(item.icon.id)
            } else if (item.handle == HistoryEvents.ModifyIcon) {
                const currentIcon = item.curIcon
                let preIcon = floorplanService.getIcon(item.curIcon.id)
                historyUtil.assignIconFromIcon(preIcon, currentIcon)
            }
        }
    }

    goNextForSigns(itemForSigns) {
        for (let i = 0; i < itemForSigns.length; ++i) {
            const item = itemForSigns[i]
            if (item.handle == HistoryEvents.AddSign) {
                let vSign = signService.createSign(item.sign.center, item.sign.type, item.sign.id)
                historyUtil.assignSignFromSign(vSign, item.sign)
            } else if (item.handle == HistoryEvents.DeleteSign) {
                floorplanService.deleteSign(item.sign.id)
            } else if (item.handle == HistoryEvents.ModifySign) {
                const currentSign = item.curSign
                let preSign = floorplanService.getSign(item.curSign.id)
                historyUtil.assignSignFromSign(preSign, currentSign)
            }
        }
    }

    goNextForTitle(itemForTitle) {
        if (itemForTitle != null && itemForTitle.handle == HistoryEvents.ModifyTitle) {
            const currentTitle = itemForTitle.curTitle
            let preTitle = floorplanService.getTitle()
            historyUtil.assignTitleFromTitle(preTitle, currentTitle)
        }
    }

    goNextForImage(itemForImage) {
        if (itemForImage != null && itemForImage.handle == HistoryEvents.ModifyImage) {
            const currentImage = itemForImage.curImage
            let preImage = floorplanService.getBgImage()
            historyUtil.assignImageFromImage(preImage, currentImage,this.layer)
        }
    }

    goNextForCompass(itemForCompass) {
        if (itemForCompass != null && itemForCompass.handle == HistoryEvents.ModifyCompass) {
            const currentCompass = itemForCompass.curCompass
            let preCompass = floorplanService.getCompass()
            historyUtil.assignCompassFromCompass(preCompass, currentCompass)
        }
    }

    // goNextForAngle(itemForAngle) {
    //     if (itemForAngle.handle == HistoryEvents.ModifyAngle) {
    //         coordinate.reSet()
    //         coordinate._setRes(itemForAngle.curState.res)
    //         //旋转cad
    //         floorplanService.setAngle(itemForAngle.curState.angle)
    //         coordinate.updateForRotate(itemForAngle.curState.angle - itemForAngle.preState.angle)
    //         //旋转三维模型
    //         let info = coordinate.getScreenInfoForCAD()
    //         info.floorPlanAngle = itemForAngle.curState.angle
    //         this.layer.app.core.get('CameraControls').emit('syncCadAnd3DForRotate', info)
    //         this.layer.app.store.getValue('metadata').floorPlanAngle = itemForAngle.curState.angle
    //         this.layer.initPanos(floorplanService.getCurrentFloor())
    //         return true
    //     } else {
    //         return false
    //     }
    // }

    // 恢复
    goNextState() {
        historyService.redoHistoryRecord()
        const item = historyService.getHistoryRecord()
        if (item) {
            stateService.clearFocusItem()
            //this.layer.$xui.hideProps()
            this.layer.uiControl.selectUI = null
            let flag = false
            if (item.rotate == null) {
                flag = false
            } else {
                flag = this.goNextForAngle(item.rotate)
            }
            if (!flag) {
                this.goNextForPoints(item.points)
                this.goNextForWalls(item.walls)
                this.goNextForTags(item.tags)
                this.goNextForCells(item.cells)
                this.goNextForTables(item.tables)
                this.goNextForRectangles(item.rectangles)
                this.goNextForCircles(item.circles)
                this.goNextForArrows(item.arrows)
                this.goNextForIcons(item.icons)
                this.goNextForSigns(item.signs)

                this.goNextForTitle(item.title)
                this.goNextForImage (item.image)
                this.goNextForCompass(item.compass)
            }
            change.saveCurrentInfo()
            this.setState()

            // const points = floorplanService.getPoints()
            // if (Object.keys(points).length > 0) {
            //     this.layer.$xui.toolbar.clear = true
            //     this.layer.$xui.toolbar.download = true
            // } else {
            //     this.layer.$xui.toolbar.clear = false
            //     this.layer.$xui.toolbar.download = false
            // }
        } else {
            historyService.undoHistoryRecord()
            console.error('goNextState超出范围！')
        }
    }
}

const history = new History()
export { history }
