/*
 * *********************************************************************************************************************
 *
 *          !!
 *        .F88X
 *        X8888Y
 *      .}888888N;
 *        i888888N;        .:!              .I$WI:
 *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
 *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
 *            +888888N;  .8888888Y                                  "&&8Y.}8,
 *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
 *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
 *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
 *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
 *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
 *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
 *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
 *      .:R888888I
 *      .&888888I                                          Copyright (c) 2016-2020.  博锐尚格科技股份有限公司
 *        ~8888'
 *        .!88~                                                                     All rights reserved.
 *
 * *********************************************************************************************************************
 */

import { SGraphDeleteListCommand, SGraphEditScene, SGraphEdit } from "@persagy-web/edit"
import { SMouseEvent } from "@persagy-web/base/lib";
import { SArrowStyleType, SPoint, SRect } from '@persagy-web/draw';
import { SItemStatus, SRectSelectItem } from '@persagy-web/big/lib';
import { SGraphItem, SGraphSelectContainer, SOrderSetType } from "@persagy-web/graph/lib/";
import { SBaseArrow, SBaseExpainEdit, SBasePipe } from "./"
import { SBaseArrowPolyEdit } from './items/SBaseArrowPolyEdit';
import { SGraphAddListCommand } from '@persagy-web/edit/lib/';

/**
 * big-edit 场景
 *
 * @author 韩耀龙 <han_yao_long@163.com>
 */
export class SBaseEditScene extends SGraphEditScene {
    /** 图例节点 */
    Nodes: any = [];  // 图例节点，所有与工程信息化相关的图例（图标类型与区域）
    /** 图例节点 */  // 与工程信息无关的标识对象（增加文本注释，图上的图片说明）
    Markers: any = [];
    /** 管线对象 */
    Relations: any = [];
    /** 复制的对象 */
    copyString: any[] = [];
    /** 选中的对象 */
    grabItem: null | SGraphEdit | SGraphItem = null;

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

    /**
     * 新增基础类注释
     *
     * @param event   鼠标事件参数
     */
    addExplainItem(event: SMouseEvent): void {
        const data = {
            /** 名称 */
            name: '基础注释文本',
            /** 图标 */
            type: "Text",
            /** 位置 */
            pos: { x: event.x, y: event.y },
            /** 由应用自己定义 */
            properties: {
                type: "BaseExplain",
            },
            style: {
                default: {
                    text: '请在右侧属性栏输入文字！',
                    color: "#646c73",
                    font: 14,
                    backgroundcolor: "#f7f9facc",
                }
            }
        };

        const item = new SBaseExpainEdit(null, data);
        item.moveTo(event.x, event.y);
        item.selectable = true;
        item.moveable = true;
        this.addItem(item);
        this.grabItem = null;
        item.connect("onContextMenu", this, this.getItem);
        this.finishCreated(item);
    }

    /**
     * 新增基础箭头（折线）
     *
     * @param event 鼠标事件
     */
    addPolyLineArrow(event: SMouseEvent): void {
        const data = {
            name: '基础箭头',
            type: "Arrow",
            pos: { x: 0, y: 0 },
            properties: {
                type: "BaseArrow",
            },
            style: {
                outLine: [{ x: event.x, y: event.y }],
                begin: SArrowStyleType.None,  //开端箭头样式
                end: SArrowStyleType.None,    //结尾箭头样式
                isMove: true,                 //是否可以移动
                default: {}
            }
        };

        const item = new SBaseArrow(null, data);
        item.status = SItemStatus.Create;
        item.selectable = true;
        this.addItem(item);
        this.grabItem = item;
        item.connect("finishCreated", this, this.finishCreated);
        item.connect("onContextMenu", this, this.getItem);
        if (this.view) {
            this.view.update();
        }
    }

    /**
     * 新增基础箭头（多边形）
     *
     * @param event 鼠标事件
     */
    addPolygonArrow(event: SMouseEvent): void {
        const data = {
            /** 名称 */
            name: '多边形箭头',
            /** 图标（Image），线类型(Line) */
            type: "ArrowPolygon",
            /** 缩放比例（Image），线类型(Line) */
            scale: { x: 1, y: 1, z: 1 },
            /** 缩放比例（Image），线类型(Line) */
            rolate: { x: 0, y: 0, z: 0 },
            /** 位置 */
            pos: { x: 0, y: 0 },
            /** 由应用自己定义 */
            properties: {
                type: "BaseArrowPolygon"           // 自定义类型用于区分mark与node
            },
            style: {
                line: [{ x: event.x, y: event.y }],
                default: {
                }
            }
        };
        const item = new SBaseArrowPolyEdit(null, data);
        item.status = SItemStatus.Create;
        item.selectable = true;
        this.addItem(item);
        this.grabItem = item;
        item.connect("finishCreated", this, this.finishCreated);
        item.connect("onContextMenu", this, this.getItem);
        if (this.view) {
            this.view.update();
        }
    }

    // /**
    //  * 添加基本设备 item
    //  *
    //  * @param event     鼠标事件
    //  * @param legendObj 图例样式
    //  */
    // addEuqipment(event: SMouseEvent, legendObj: any): void {
    //     const data = {
    //         nodeId: uuid(),
    //         /** 名称 */
    //         name: '基础设备',
    //         /** 返回物理世界对象 ID 列表 */
    //         attachObjectIds: [],
    //         size: { width: 50, height: 50 },
    //         /** 图标 (Image)，线类型 (Line) */
    //         type: "Image",
    //         /** 位置 */
    //         pos: { x: event.x, y: event.y },
    //         /** 由应用自己定义 */
    //         properties: {
    //             type: "BaseEquipment",
    //             infoMsgList: [{

    //             }]
    //         },
    //         style: {
    //             default: {
    //                 strokecolor: "#c0ccda",
    //                 url: require('./../../../assets/images/equip/' + legendObj.url),
    //             }
    //         }
    //     }
    //     const item = new SBaseEquipment(null, data);
    //     item.status = SItemStatus.Create;
    //     this.addItem(item);
    //     item.selectable = true;
    //     item.moveable = true;
    //     this.grabItem = item;
    //     this.finishCreated(item)
    //     item.connect("onContextMenu", this, this.getItem);
    //     if (this.view) {
    //         this.view.update();
    //     }
    // }

    /**
     * 新增管道
     *
     * @param event 鼠标事件
     */
    addBasePipe(event: SMouseEvent, legendObj: any) {
        const anc = this.clickIsAnchor(event);
        if (anc) {
            const p = anc.mapToScene(0, 0)
            anc.isConnected = true;
            event.x = p.x;
            event.y = p.y;
        };
        const data = {
            name: legendObj.name,
            graphElementId: legendObj.id,
            lineType: '',
            node1Id: '',
            node2Id: '',
            anchor1Id: '',
            anchor2Id: '',
            pointList: [{ x: event.x, y: event.y }],
            properties: {
                type: "BasePipe",
            },
            style: {
                default: {
                    strokeColor: legendObj.color,
                    lineWidth: 4
                }
            }
        };
        const item = new SBasePipe(null, data);
        item.status = SItemStatus.Create;
        item.selectable = true;
        this.addItem(item);
        this.grabItem = item;
        // 起始锚点
        item.startAnchor = anc;
        if (anc) {
            anc.parent?.connect('changePos', item, item.changePos)
            item.anchor1Id = anc.id;
            item.node1Id = anc.parent ? anc.parent.nodeId : '';
        }

        console.log('anc', anc)
        item.connect("finishCreated", this, this.finishCreated);
        item.connect("onContextMenu", this, this.getItem);
        if (this.view) {
            this.view.update();
        }
    }

    /**
     * 重做
     */
    redo(): void {
        if (this.grabItem && this.grabItem instanceof SGraphEdit) {
            this.grabItem.redo()
        } else {
            this.undoStack.redo();
        }
    }

    /**
     * 撤销
     */
    undo(): void {
        if (this.grabItem && this.grabItem instanceof SGraphEdit) {
            this.grabItem.undo()
        } else {
            this.undoStack.undo();
        }
    }

    /**
     * 删除
     *
     * @return 删除的图例
     */
    deleteItem(itemArr: SGraphItem[] = []): any {
        let itemList = null;
        if (itemArr && itemArr.length && itemArr[0]) {
            itemList = [...itemArr]
        } else {
            if (this.selectContainer.count == 0) {
                return []
            }
            itemList = this.selectContainer.itemList;
            this.undoStack.push(new SGraphDeleteListCommand(this, [...itemList]))
        }
        // 推入 undo/redo 栈
        itemList.forEach((element: any) => {
            this.removeItem(element)
        });
        if (this.view) {
            this.view.update()
        }
        return itemList
    }

    /**
     * 框选
     */
    addRectSelect(event: SMouseEvent): void {
        let point = new SPoint(event.x, event.y);
        let rect = new SRectSelectItem(null, point);
        this.addItem(rect);
        this.grabItem = rect;
    }

    /**
     * 计算框选交集
     *
     * @param ctrl  是否点击ctrl
     */
    groupSelect(ctrl: boolean) {
        if (this.grabItem instanceof SRectSelectItem) {
            const rect = this.grabItem.boundingRect();
            this.arrToSelect(this.root.children, rect)
        }
    }

    /**
     * 选中item:框选
     *
     * @param arr       实例数组
     * @param rect      框选矩形区域
     */
    private arrToSelect(arr: SGraphItem[], rect: SRect) {
        if (Array.isArray(arr) && arr.length) {
            arr.forEach(t => {
                if (!(t instanceof SGraphSelectContainer) && t.parent) {
                    let temp = t.boundingRect();
                    let lefttop = t.mapToScene(temp.left, temp.top)
                    let rightbottom = t.mapToScene(temp.right, temp.bottom)
                    let r = new SRect(lefttop, rightbottom)
                    if (rect.isIn(r)) {
                        this.selectContainer.toggleItem(t)
                    }
                }
            })
        }
    }

    /////////////////////////////////////////////////////////////////////
    // 鼠标事件
    /**
     * 鼠标左键按下
     *
     * @param event   鼠标事件参数
     */
    onMouseDown(event: SMouseEvent): any {
        if (!super.onMouseDown(event) && 1 == event.buttons) {
            this.addRectSelect(event);
        }
    }

    /**
     * 鼠标抬起
     *
     * @param event   鼠标事件参数
     */
    onMouseUp(event: SMouseEvent): boolean {
        if (this.grabItem) {
            // 鼠标抬起时，如果grabItem为框选则删除框选item
            if (this.grabItem instanceof SRectSelectItem) {
                this.removeItem(this.grabItem);
                this.groupSelect(false);
                this.grabItem = null;

                if (this.view) {
                    this.view.update()
                }
                return true;
            }

            return this.grabItem.onMouseUp(event);
        }

        return super.onMouseUp(event)
    }

    /**
     * 复制
     */
    copy(): void {
        const itemList = this.save(false);
        if (itemList) {
            // 删除对应得id
            itemList.markers.map((item: any) => {
                delete item.id;
                delete item.graphId;
                delete item.markerId;
                return item
            });

            itemList.nodes.map((item: any) => {
                delete item.id;
                delete item.graphId;
                delete item.markerId;
                return item
            });

            itemList.relations.map((item: any) => {
                delete item.id;
                delete item.graphId;
                delete item.markerId;
                return item
            });

            this.copyString = itemList
            // 获取input dom
            const input = document.createElement('input');
            input.setAttribute('id', 'COPYINPUT')
            input.value = JSON.stringify(this.copyString)
            sessionStorage.setItem("copyString", input.value);
            document.body.appendChild(input);
            input.select()
            document.execCommand('copy');
            input.style.display = 'none';
            console.log(input.value, Date.now());
            document.body.removeChild(input)
        }
    }



    /**
     * 添加多个item命令
     *
     *  @param itemList    鼠标事件对象
     */
    addListCommand(itemList: SGraphEdit[]): void {
        this.undoStack.push(new SGraphAddListCommand(this, itemList));
    }

    /**
     * 图例置顶、置底
     *
     * @parm type   设置类型
     */
    setOrder(type: string) {
        this.selectContainer.setOrder(SOrderSetType[type])
    }

    /**
   * 设置管线结束锚点
   */
    setTipeEndanchor(event: SMouseEvent): void {
        if (this.grabItem instanceof SBasePipe) {
            const anc = this.clickIsAnchor(event);
            if (anc) {
                const p = anc.mapToScene(0, 0)
                anc.isConnected = true;
                event.x = p.x;
                event.y = p.y;
                if (this.grabItem.status == SItemStatus.Create) {
                    if (this.grabItem.pointList.length) {
                        this.grabItem.endAnchor = anc;
                        anc.parent?.connect('changePos', this.grabItem, this.grabItem.changePos)
                    }

                    this.grabItem.anchor2Id = anc.id
                    this.grabItem.node2Id = anc.parent.nodeId
                    this.grabItem.onMouseDown(event)
                    this.grabItem.status = SItemStatus.Normal;
                    this.finishCreated(this.grabItem)
                    return
                }
            }

            this.grabItem.onMouseDown(event)
        }
    }

    /**
     * 获取item (常用与场景外的调用F)
     *
     * @params isAll    是否为全部item数据
     * @return obj      返回保存的数据接口
     */
    save(isAll: boolean = true): any {
    }
}