<template>
    <div>
        <el-button @click="addCircle">Circle</el-button>
        <el-button @click="addRect">Rect</el-button>
        <el-button @click="deleteItem">Delete</el-button>
        <el-button @click="undo">Undo</el-button>
        <el-button @click="redo">Redo</el-button>
        <el-button @click="log">日志</el-button>
        <canvas id="undoFrame" width="800" height="400"/>
    </div>
</template>

<script lang="ts">
import { SMouseEvent, SUndoStack } from "@persagy-web/base";
import { SColor, SPainter, SRect } from "@persagy-web/draw";
import { SGraphAddCommand, SGraphItem, SGraphMoveCommand, SGraphScene, SGraphView } from "@persagy-web/graph";
import { SPoint } from "@persagy-web/draw/lib";

/**
 * Undo/Redo
 *
 * @author 郝洁 <haojie@persagy.com>
 */
class RectItem extends SGraphItem {
    /** 宽度 */
    width = 100;
    /** 高度 */
    height = 100;
    /** 图 Id */
    id = new Date().getTime() + '';

    /**
     * 构造函数
     *
     * @param parent     Item 图像引擎
     */
    constructor(parent: SGraphItem | null) {
        super(parent);
        this.moveable = true;
        this.selectable = true;
        this.selected = true;
        this.isTransform = true;
        this.rotate = 60;
    }

    /**
     * 矩形数据类型绘制
     *
     * @return 边界区域
     */
    boundingRect(): SRect {
        return new SRect(0, 0, this.width, this.height);
    }

    /**
     * Item 绘制操作
     * @param canvas    绘制对象
     */
    onDraw(canvas: SPainter): void {
        canvas.pen.color = SColor.Blue;
        canvas.pen.lineWidth = 5;
        canvas.brush.color = this.selected ? SColor.Red : SColor.Green;
        canvas.drawRect(0, 0, this.width, this.height)
    }
}



class CircleItem extends SGraphItem {
    /** 半径 */
    r = 50;
    /** 图 Id */
    id = new Date().getTime() + ""

    /**
     * 构造函数
     *
     * @param parent     Item 图像引擎
     */
    constructor(parent: SGraphItem | null) {
        super(parent);
        this.moveable = true;
        this.selectable = true;
        this.isTransform = false;
    }

    /**
     * 矩形数据类型绘制
     */
    boundingRect(): SRect {
        return new SRect(0, 0, this.r * 2, this.r * 2);
    }

    /**
     * Item 绘制操作
     * @param canvas    绘制对象
     */
    onDraw(canvas: SPainter): void {
        canvas.pen.color = SColor.Blue;
        canvas.pen.lineWidth = 5;
        canvas.brush.color = this.selected ? SColor.Red : SColor.Green;
        canvas.drawCircle(this.r, this.r, this.r);
    }
}

class SScene extends SGraphScene {
    /** 实例化 */
    undoStack = new SUndoStack();
    /** 定义命令 */
    cmd = 0;

    /**
     * 构造函数
     */
    constructor() {
        super();
    }

    /**
     * 鼠标抬起事件
     *
     * @param  event   事件参数
     * @return   是否处理
     */
    onMouseUp(event: SMouseEvent): boolean {
        switch (this.cmd) {
            case 1:
                this.addCircle(event.x, event.y);
                break;
            case 2:
                this.addRect(event.x, event.y);
                break;
            default:
                super.onMouseUp(event);
        }
        this.cmd = 0;
        return false
    }

    /**
     * 添加圆形
     * @param x     x轴
     * @param y     y轴
     */
    private addCircle(x: number, y: number): void {
        let item = new CircleItem(null);
        item.moveTo(x - 50, y - 50);
        this.addItem(item);
        this.undoStack.push(new SGraphAddCommand(this, item));
        item.connect("onMove", this, this.onItemMove.bind(this));
    }

    /**
     * 添加矩形
     * @param x     x轴
     * @param y     y轴
     */
    private addRect(x: number, y: number): void {
        let item = new RectItem(null);
        item.moveTo(x - 50, y - 50);
        this.addItem(item);
        this.undoStack.push(new SGraphAddCommand(this, item));
        item.connect("onMove", this, this.onItemMove.bind(this));
    }

    /**
     * 移动操作
     * @param item     图像引擎
     * @param arg      数组
     */
    onItemMove(item: SGraphItem, ...arg: any): void {
        this.undoStack.push(new SGraphMoveCommand(this, item, arg[0][0] as SPoint, arg[0][1] as SPoint));
    }
}

class TestView extends SGraphView {
    /**
     * 构造函数
     *
     * @param undoFrame     绘制引擎
     */
    constructor(undoFrame) {
        super(undoFrame);
    }
}

    export default {
        data() {
            return {
                /** 命令所属的场景类 */
                scene: new SScene(),
            }
        },
        /**
         * 页面挂载
         */
        mounted(): void {
            let view = new TestView('undoFrame');
            view.scene = this.scene;
        },
        methods: {
            /**
             * 定义圆形命令
             */
            addCircle() {
                this.scene.cmd = 1;
            },
            /**
             * 定义矩形命令
             */
            addRect() {
                this.scene.cmd = 2;
            },
            /**
             * 删除操作
             */
            deleteItem() {
            // do something ...
            },
            /**
             * 取消操作
             */
            undo() {
                this.scene.undoStack.undo();
            },
            /**
             * 重做操作
             */
            redo() {
                this.scene.undoStack.redo();
            },
            /**
             * 将命令堆栈转为日志(命令数组)
             */
            log() {
                let str = this.scene.undoStack.toLog();
                console.log(str)
            }
        }
    }
</script>

<style scoped>

</style>
