/*
 * *********************************************************************************************************************
 *
 *          !!
 *        .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) 2009-2020.  博锐尚格科技股份有限公司
 *        ~8888'
 *        .!88~                                                                     All rights reserved.
 *
 * ****/

import { SBaseEditScene, SBasePipe, SBaseEquipment } from "@persagy-web/big-edit";
import { SGraphEdit } from "@persagy-web/edit";
import { SMouseEvent } from "@persagy-web/base/lib";
import { SGraphAddCommand, SGraphItem, SGraphMoveCommand, SGraphPropertyCommand, SGraphSelectContainer, SLineStyle } from "@persagy-web/graph";
import { rgbaNum } from "@persagy-web/big-edit/lib/until";
// 引入命令
import { SColor, SFont, SArrowStyleType, SPoint } from '@persagy-web/draw/lib';
import { PTopoParser, SBasePipeUninTool, SBaseEquation, SBaseInfoPoint, SBaseBtns } from "./"
import { ItemOrder, SItemStatus } from '@persagy-web/big/lib';

/**
 * 拓扑图场景类
 *
 *  @author  韩耀龙 <han_yao_long@163.com>
 */
export class PTopoScene extends SBaseEditScene {
    /** 图例数据 */
    legendObj: any = null;

    /** 是否打开吸附功能 */
    isAdsorb:boolean = false;

    // 静态服务器路径
    public imgServeUrl: string = '';
    // 联通方式
    public uninType: object = {
        wantou: '',
        santong: '',
        sitong: ''
    }
    constructor() {
        super()
        // 选择绑定选额item事件
        this.selectContainer.connect("listChange", this, this.listChange);
    }

    /**
     *  改变 view 背景色
     *
     * @param val 颜色值
     */
    changeBackgroundColor(val: any) {
        if (!this.view) return;
        if (val) {
            if (val.includes('#')) {
                this.view.backgroundColor = new SColor(val)
            } else {
                const colorlist: any = rgbaNum(val);
                if (!colorlist) return
                this.view.backgroundColor = new SColor(Number(colorlist[0]), Number(colorlist[1]), Number(colorlist[2]), colorlist[3] * 255)
            }
            this.view.update()

        }
    }

    /**
     * 选中返回的选中 item 回调方法
     *
     * @param event   鼠标事件参数
     */
    listChange(list: any): void {
        const itemList: any = []
        list.itemList.forEach((item: any) => {
            if ((item instanceof SGraphEdit) && !(item instanceof SGraphSelectContainer)) {
                itemList.push(item)
            }
        })

        this.emitChoice(itemList);
    }

    /**
     * 选中返回的选中 item 回调方法(用于场景的外部调用)
     *
     * @param list   选中的 item 数组
     */
    emitChoice(list: any) {
    }

    /**
     * 鼠标左键按下
     *
     * @param event   鼠标事件参数
     */
    onMouseDown(event: SMouseEvent): any {
        this.vueOnMouseDown(event) //外部调用
        if (this.grabItem) {
            if (this.grabItem instanceof SBasePipe && this.isAdsorb) {
                this.setTipeEndanchor(event)
                return true;
            }
            return this.grabItem.onMouseDown(event);
        }
        if (this.editCmd == "EditBaseLine") {
            const item = this.addPolyLineArrow(event);
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBasePolyLine") {
            this.addPolyLine(event);
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBasetext") {
            this.addTextItem(event);
            this.clearCmdStatus();
        } else if (this.editCmd == "BaseExplain") {
            this.addExplainItem(event);
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBaseImage") {
            this.addImageItem(event)
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBasePolygon") { //
            this.addPolygonItem(event);
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBaseRect") { // 设置层级与多边形一致
            const item = this.addRectItem(event)
            item.zOrder = ItemOrder.polygonOrder;
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBaseTriangle") {
            this.addTriangleItem(event)
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBaseCircle") { // 设置层级与多边形一致
            const item = this.addCircleItem(event)
            item.zOrder = ItemOrder.polygonOrder
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBaseArrows") { // 设置层级与多边形一致
            const item = this.addPolygonArrow(event)
            item.zOrder = ItemOrder.polygonOrder
            this.clearCmdStatus();
        } else if (this.editCmd == "wantou" || this.editCmd == "santong" || this.editCmd == "sitong") {
            this.addPipeUninTool(event, this.editCmd)
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBasePipe") {
            this.addBasePipe(event, this.legendObj);
            this.clearCmdStatus();
        } else if (this.editCmd == "equation") {
            // 添加公式
            this.addEquation(event, this.editCmd);
            this.clearCmdStatus();
        } else if (this.editCmd == "infoPoint") {
            // 添加信息点
            this.addInfoPoint(event, this.editCmd);
            this.clearCmdStatus();
        } else if (this.editCmd == "EditBaseBtn") {
            // 添加基础按钮
            this.SBaseBtn(event);
            this.clearCmdStatus();
        } else if (this.editCmd == "") {
            super.onMouseDown(event);
        }
    }

    /**
     * 鼠标双击事件
     *
     * @param	event         事件参数
     * @return	boolean
     */
    onDoubleClick(event: SMouseEvent): boolean {
        // 如果为复制状态则双击失效
        // if (this.isCopy == "true") {
        //     return true
        // }
        if (!this.isEditStatus) {
            return true
        } else {
            return super.onDoubleClick(event);
        }

    } // Function onDoubleClick()

    /**
     * 添加基本管道联通器
     *
     * @param event     鼠标事件
     * @param cmd       命令
     */
    addPipeUninTool(event: SMouseEvent, cmd: string): SBasePipeUninTool {
        const data = {
            /** 名称 */
            name: '基础管道接头',
            /** 图标 (Image)，线类型 (Line) */
            type: "Line",
            /** 位置 */
            pos: { x: event.x, y: event.y },
            /** 由应用自己定义 */
            properties: {
                type: "BasePipeUninTool",
            },
            style: {
                uninToolType: cmd,  //分别分二头连接器、三头连接器、四头连接器
                default: {
                    strokecolor: "#c0ccda",
                    width:64,
                    height:64,
                    zorder: ItemOrder.markOrder
                }
            }
        };

        const item = new SBasePipeUninTool(null, data);
        item.selectable = true;
        item.moveable = true;
        this.addItem(item);
        this.finishCreated(item)
        item.connect("onContextMenu", this, this.getItem);
        if (this.view) {
            this.view.update();
        }
        return item;
    }

    /**
     * 添加公式
     * @param event
     */
    addEquation(event: SMouseEvent, cmd: string): SBaseEquation {
        const data = {
            /** 名称 */
            name: '公式',
            /** 图标 */
            type: "Text",
            /** 位置 */
            pos: { x: event.x, y: event.y },
            size: { width: 0, height: 0 },
            /** 由应用自己定义 */
            properties: {
                type: "Equation"           // 自定义类型用于区分mark与node
            },
            style: {
                default: {
                    text: '请在右侧属性栏填写公式！',
                    color: "#646c73",
                    font: 14,
                    backgroundcolor: "#f7f9facc",
                }
            }
        };
        const item = new SBaseEquation(null, data);
        item.moveTo(event.x, event.y);
        item.moveable = true;
        this.addItem(item);
        this.grabItem = null;
        item.connect("onContextMenu", this, this.getItem);
        this.finishCreated(item);
        return item;
    }

    /**
     * 添加信息点
     * @param event
     */
    addInfoPoint(event: SMouseEvent, cmd: string): SBaseInfoPoint {
        const data = {
            /** 名称 */
            name: '信息点',
            /** 图标 */
            type: "Text",
            /** 位置 */
            pos: { x: event.x, y: event.y },
            size: { width: 0, height: 0 },
            /** 由应用自己定义 */
            properties: {
                type: "InfoPoint"           // 自定义类型用于区分mark与node
            },
            style: {
                default: {
                    text: '信息点',
                    color: "#646c73",
                    font: 14,
                    backgroundcolor: "#f7f9facc",
                }
            }
        };
        const item = new SBaseInfoPoint(null, data);
        item.moveTo(event.x, event.y);
        item.moveable = true;
        this.addItem(item);
        this.grabItem = null;
        item.connect("onContextMenu", this, this.getItem);
        this.finishCreated(item);
        return item;
    }

    /**
     * 添加按钮
     * @param event
     */
    SBaseBtn(event: SMouseEvent): SBaseBtns {
        const data = {
            /** 名称 */
            name: '按钮',
            /** 按钮 */
            type: "text",
            /** 位置 */
            pos: { x: event.x, y: event.y },
            size: { width: 60, height: 30 },
            /** 由应用自己定义 */
            properties: {
                type: "baseBtn",           // 自定义类型用于区分mark与node
                bindMsg: ''            //按钮绑定的信息
            },
            style: {
                default: {
                    text: '按钮',
                    color: "#646c73",
                    font: 14,
                    backgroundColor: "#427dd213",
                    lineWidth: 2,
                    strokeColor: '#000000'
                }
            }
        };
        const item = new SBaseBtns(null, data);
        item.moveTo(event.x, event.y);
        item.moveable = true;
        this.addItem(item);
        this.grabItem = null;
        item.connect("onContextMenu", this, this.getItem);
        this.finishCreated(item);
        return item;
    }


    /**
     * 鼠标右键事件
     *
     * @param   event   鼠标事件参数
     * @returns 是否点击右键
     */
    onContextMenu(event: SMouseEvent): boolean {
        if (!super.onContextMenu(event)) {
            this.getItem(null, [event])
        }

        return true
    }

    /**
     * 修改 item 样式，数据等方法
     *
     * @param styletype      string 修改样式类型
     * @param changeStyle    更改样式数据
     * @param itemList       ? SGraphEdit[] 如果不传入默认使用选择器中选中得item
     */
    updateStyle(styletype: string, changestyle: any, itemList?: SGraphEdit[]): void {
        // 如果未传入需要修改样式的item,默认取选择器中的item
        let List = null;
        if (itemList && itemList.length) {
            List = itemList;
        } else {
            List = this.selectContainer.itemList;
        };
        let styleValue: any
        if (styletype == "strokeColor" || styletype == "backgroundColor" || styletype == "fillColor" || styletype == "color") {
            const colorlist = rgbaNum(changestyle)
            styleValue = new SColor(Number(colorlist[0]), Number(colorlist[1]), Number(colorlist[2]), colorlist[3] * 255);
        } else if (styletype == "filterColor") {
            const color: any = rgbaNum(changestyle)
            styleValue = `'${color[0]} 0 0 0 0    0 ${color[1]} 0 0  0     0 0 ${color[2]} 0 0    0 0 0 ${color[3]} 0'`
        } else if (styletype == "lineStyle") {
            styleValue = SLineStyle[changestyle]
        } else if (styletype == "begin" || styletype == "end") {
            styleValue = SArrowStyleType[changestyle]
        } else if (styletype == "font") {
            styleValue = new SFont("sans-serif", changestyle)
        } else if (styletype == "url") {
            styleValue = this.imgServeUrl + changestyle;
            // 设置default url
            List.forEach((item: SGraphEdit) => {
                item.defaultUrl = changestyle
            })
        } else if (styletype == "rotate") { // 弯头设置旋转角度
            styleValue = changestyle;
        } else if (styletype == "radius") { // 圆角折线拐角半径
            styleValue = changestyle;
            console.log(changestyle, '===========');
        } else {
            styleValue = changestyle
        }

        List.forEach((item: SGraphEdit, index: number) => {
            if (item instanceof SGraphSelectContainer) {
                return
            }
            const oldMsg = item[styletype];
            const newMsg = styleValue;
            this.undoStack.push(new SGraphPropertyCommand(this, item, styletype, oldMsg, newMsg));
            item[styletype] = styleValue;
        })
    }

    /**
     * 修改指定设备得信息点
     *
     * @param obj Object    信息点
     */
    changeEquipMsgPoint(obj: any): void {
        const List = this.selectContainer.itemList.length ? this.selectContainer.itemList[0] : null;
        if (List && List instanceof SBaseEquipment) {
            List.setMsgPoint(obj);
        }
    }

    /**
     * item 创建完成后回调
     *
     * @param   event   鼠标事件参数
     */
    finishCreated(item: SGraphEdit): void {
        this.grabItem = null;
        item.status = SItemStatus.Normal;
        this.undoStack.push(new SGraphAddCommand(this, item));
        this.selectContainer.clear();
        this.selectContainer.toggleItem(item);
    }

    /**
     * 修改 cmdstatus 函数；常在在业务中调用
     */
    clearCmdStatus() {
        //do something
    }

    /**
     * 获取item (常用与场景外的调用F)
     * @param  event     SMouseEvent 鼠标事件
     * @param  item     SGraphEdit|null 返回item
     *
     */
    getItem(item: SGraphEdit | null, event: SMouseEvent[]): void {
        // do something
    }

    /**
     * 获取item (常用与场景外的调用F)
     * @param  event     SMouseEvent 鼠标事件
     * @param  item      SGraphEdit|null 返回item
     *
     */
    vueOnMouseDown(event: SMouseEvent) {
        // do something
    }

    /**
     * 设置 item 状态
     */
    setItemStatus() {
        const List = this.selectContainer.itemList[0];
        if (List && List instanceof SGraphEdit) {
            if (List.status == SItemStatus.Normal) {
                List.status = SItemStatus.Edit;
                this.grabItem = List;
            } else {
                List.status = SItemStatus.Normal;
                this.grabItem = null
            }

        }
    }

    /**
     * 获取item (常用与场景外的调用F)
     *
     * @params isAll    是否为全部item数据
     * @return obj      返回保存的数据接口
     */
    save(isAll: boolean = true) {
        if (!this.view) return;
        const Marktype: string[] = ['BasePolygon', 'BaseLine', 'BaseText', 'BaseExplain', 'BaseImage', 'BaseCircle', 'BaseArrow', 'BaseTriangle', 'BaseRect', 'BaseArrowPolygon', 'InfoPoint', 'BasePipeUninTool','baseBtn',"Equation"];
        const NodeType: string[] = ['BaseEquipment'];
        const RelationType: string[] = ["BasePipe"];
        const markers: any = [];   /**图例节点 */  // 与工程信息无关的标识对象（增加文本注释，图上的图片说明）
        const nodes: any = [];   /**图例节点 */  // 与工程信息无关的标识对象（增加文本注释，图上的图片说明）
        const relations: any = [];   /**图例节点 */  // 与工程信息无关的标识对象（增加文本注释，图上的图片说明）
        let nodeList;
        if (isAll) {
            nodeList = this.root.children;
        } else {
            nodeList = this.selectContainer.itemList;
        };

        nodeList.forEach(item => {
            if ((item instanceof SGraphEdit) && !(item instanceof SGraphSelectContainer)) {
                // 添加节点数据
                if (item.data && Marktype.includes(item.data.properties.type)) {
                    markers.push(item.toData())
                }

                if (item.legendData && NodeType.includes(item.legendData.properties.type)) {
                    nodes.push(item.toData())
                }

                if (item.relationData && RelationType.includes(item.relationData.properties.type)) {
                    relations.push(item.toData())
                }

            }

        });

        return {
            markers,
            nodes,
            relations
        }
    }

    /**
     * 粘贴
     */
    paste(): void {
        const copyList = JSON.parse(JSON.stringify(this.copyString));
        const parserData = new PTopoParser();
        const graphItemList: SGraphEdit[] = [];
        parserData.parseData(copyList);
        parserData.markers.forEach((item: SGraphEdit) => {
            item.selectable = true;
            item.moveable = true;
            if (this.view) {
                item.pos.x += 10 / this.view.scale
                item.pos.y += 10 / this.view.scale
            }
            this.addItem(item);
            graphItemList.push(item);
        });

        this.addListCommand(graphItemList);
        this.view ? this.view.update() : '';
    }

    /**
     * 覆盖底层添加 item 方法,增加绑定移动事件
    */
    addItem(item: SGraphItem): void {
        super.addItem(item);
        item.connect('onMove', this, this.onItemMove.bind(this));
    }

    /**
     * 添加移动命令到命令栈
    */
    onItemMove(item: SGraphItem, arg: SPoint[]) {
        this.undoStack.push(new SGraphMoveCommand(this, item, arg[0], arg[1]));
    }
}