import { Point } from "@devexpress/utils/lib/geometry/point";

import { ConnectorRenderPointsContext } from "../../Model/Connectors/Routing/ConnectorRenderPointsContext";
import { ItemKey } from "../../Model/DiagramItem";
import { ModelManipulator } from "../../Model/ModelManipulator";
import { HistoryItem } from "../HistoryItem";

export class MoveConnectorPointHistoryItem extends HistoryItem {
    private oldPoint: Point;
    private renderContext: ConnectorRenderPointsContext | undefined;
    constructor(
        private connectorKey: ItemKey,
        private pointIndex: number,
        private newPoint: Point) {
        super();
    }
    redo(manipulator: ModelManipulator): void {
        const connector = manipulator.model.findConnector(this.connectorKey);
        this.oldPoint = connector.points[this.pointIndex].clone();
        this.renderContext = connector.tryCreateRenderPointsContext();
        manipulator.moveConnectorPoint(
            connector,
            this.pointIndex,
            connector => {
                connector.movePoint(this.pointIndex, this.newPoint);
                connector.onMovePoint(this.pointIndex, this.newPoint);
            });
    }
    undo(manipulator: ModelManipulator): void {
        const connector = manipulator.model.findConnector(this.connectorKey);
        manipulator.moveConnectorPoint(
            connector,
            this.pointIndex,
            connector => {
                connector.movePoint(this.pointIndex, this.oldPoint);
                connector.replaceRenderPoints(this.renderContext);
            });
    }
}

export class MoveConnectorRightAnglePointsHistoryItem extends HistoryItem {
    oldPoints: Point[] = [];
    renderContext: ConnectorRenderPointsContext | undefined;
    constructor(
        private connectorKey: ItemKey,
        private beginPointIndex: number,
        private lastPointIndex: number,
        private newX?: number,
        private newY?: number) {
        super();
    }
    redo(manipulator: ModelManipulator): void {
        const connector = manipulator.model.findConnector(this.connectorKey);
        this.renderContext = connector.tryCreateRenderPointsContext();
        this.oldPoints = connector.points.slice(this.beginPointIndex, this.lastPointIndex + 1).map(p => p.clone());
        const points: Point[] = [];
        manipulator.changeConnectorPoints(
            connector,
            connector => {
                for(let i = this.beginPointIndex; i <= this.lastPointIndex; i++) {
                    const newPoint = new Point(this.newX === undefined ? connector.points[i].x : this.newX, this.newY === undefined ? connector.points[i].y : this.newY);
                    points.push(newPoint);
                    connector.movePoint(i, newPoint);
                }
                connector.onMovePoints(this.beginPointIndex, this.lastPointIndex, points);
            });
    }
    undo(manipulator: ModelManipulator): void {
        const connector = manipulator.model.findConnector(this.connectorKey);
        manipulator.changeConnectorPoints(
            connector,
            connector => {
                for(let i = this.beginPointIndex; i <= this.lastPointIndex; i++)
                    connector.movePoint(i, this.oldPoints[i - this.beginPointIndex]);
                connector.replaceRenderPoints(this.renderContext);
            });
    }
}
