// console.log('init');
(function($) {
  $.fn.extend({
    dataflow: function(options) {
      let _self = this;
      let _this = $(this);
      let defaults = {
        lineWidth: 2, // 线的宽度 默认为2
        lineHoverColor: "red", // 高亮颜色
        defaultColor: "#61B7CF", // 默认颜色
        lineRadius: 5, // 线拐弯弧度
        pointColor: "rgba(0,0,0,0.5)", // 端点的颜色
        pointWidth: 5, // 连接端点的半径
        pointDistance: 8, // 端点与线的距离
        data: {}, // 渲染的数据源
        id: "chart", // 配置渲染的节点id
        isEdit: true, // 是否可配置模版
        canvas: null, // 画布
        dropElevent: null, // 拖拽的数据源
        template: null, // 可配置的模版
        arrowHeight: 7, // 箭头高度
        arrowWidth: 5, // 箭头宽度
        onRemoveNodeAfter: function() {}, // 删除节点回调,参数为删除节点id和该节点的线条数据
        onCreateNodeAfter: function() {}, // 节点创建初始化后事件回调, 参数为节点id
        onCreateLineAfter: function() {}, // 创建线条后事件回调
        ondrawData: function() {} // 渲染流程后回调
      };

      let settings = $.extend({}, defaults, options);
      settings.sourceEndpoint = {
        endpoint: "Dot",
        paintStyle: {
          stroke: settings.pointColor,
          fill: settings.pointColor,
          radius: settings.pointWidth
        },
        isSource: true,
        isTarget: true,
        connector: [
          "Flowchart",
          {
            stub: [20, 15],
            gap: settings.pointDistance, // 线离开端点距离
            cornerRadius: settings.lineRadius,
            alwaysRespectStubs: true
          }
        ],
        //描绘线的样式
        connectorStyle: {
          strokeWidth: settings.lineWidth, // 线条宽度
          stroke: settings.defaultColor, // 填充颜色
          joinstyle: "round",
          outlineWidth: 0 // 线条外部宽度
        },
        dragOptions: {},
        maxConnections: -1 //是否允许多条线
      };

      settings.targetEndpoint = {
        endpoint: "Dot",
        paintStyle: {
          fill: settings.pointColor,
          radius: settings.pointWidth
        },
        //描绘线的样式
        connectorStyle: {
          strokeWidth: settings.lineWidth, // 线条宽度
          stroke: settings.defaultColor, // 填充颜色
          joinstyle: "round",
          outlineWidth: 0 // 线条外部宽度
        },
        maxConnections: -1,
        isSource: true,
        isTarget: true,
        connector: [
          "Flowchart",
          {
            stub: [20, 15],
            gap: settings.pointDistance,
            cornerRadius: settings.lineRadius,
            alwaysRespectStubs: true
          }
        ]
      };

      // jsplumb插件初始化配置
      let instance = jsPlumb.getInstance({
        Container: "ktj-canvas", // 容器id
        //配置链接线的样式
        ConnectionOverlays: [
          [
            "Arrow",
            {
              location: 1, // 箭头方向 0-1
              width: settings.arrowHeight, // 箭头高度
              length: settings.arrowWidth, // 箭头宽度
              id: "amrrow",
              foldback: 1,
              events: {
                click: function(e) {
                  e.stopPropagation();
                }
              }
            }
          ]
        ]
      });

      let opt = {
        // 拖动插入的模块
        initHtml: function(options) {
          let str = options.str.replace(/\{\w+\}/i, options.id);
          let id = "#" + options.id;
          let data = {
            id: id,
            str: str
          };
          return data;
        },
        // 获取流程的个数
        getId: function() {
          let _window = $(settings.canvas).find(".jtk-window");
          let num = _window.length;
          let arr = [];
          for (let i = 0; i < num; i++) {
            let str = $(_window)
              .eq(i)
              .attr("id");
            arr.push(parseInt(str.slice(2)));
          }

          if (arr.length === 0) {
            arr.push(0);
          }
          let _num = Math.max.apply(null, arr);
          return _num;
        },
        //获取流程的名字
        getName: function(obj) {
          let name = $(obj).attr("data");
          return name;
        }
      };

      let init = function() {
        let self = _this;
        let isMove = false;
        let currentNode = null;
        let _html = null;
        let _obj = null; //是否按下就放开
        self.off();
        let $template = $(settings.template);
        self
          .on("mousedown", settings.el, function(e) {
            let __this = $(this);
            if (!settings.isEdit) {
              return false;
            }
            e.preventDefault(); //禁止移动时出现选择
            let type = __this.attr("data-type");
            let obj = $template.find(".jtk-window");
            $(obj).each(function(val, el) {
              if ($(el).attr("data-type") === type) {
                _html = el.outerHTML;
              }
            });
            $("body").append(_html);
            // let top = $('body').scrollTop();
            let x = e.pageX + 10;
            let y = e.pageY + 10;
            currentNode = $("body >.jtk-window");
            $(currentNode).css({
              left: x,
              top: y,
              position: "fixed",
              opacity: "0.7",
              "z-index": 9999,
              background: "#fafafa"
            });
            isMove = true;
          })
          .on("mousemove", function(e) {
            let top = $("body").scrollTop();
            _obj = $("body >.jtk-window").length;
            if (isMove) {
              $(currentNode).css({
                left: e.pageX + 10 + "px",
                top: e.pageY + 10 - top + "px"
              });
            }
          })
          .on("mouseup", function(e) {
            if (isMove && _obj && settings.isEdit) {
              let obj = opt.initHtml({
                id: settings.id + (opt.getId() + 1),
                str: _html
              });

              let canvas = $(settings.canvas);
              let scroll_top = canvas.scrollTop(); //画布纵向滚动高度
              let scroll_left = canvas.scrollLeft(); //画布横向滚动高度
              let w = parseInt(canvas.width());
              let h = parseInt(canvas.height());
              let left = canvas.offset().left;
              let top = canvas.offset().top;

              let _x = e.pageX - (left + scroll_left);
              let _y = e.pageY - (top + scroll_top);
              if (_x < 0 || _x > w || _y < 0 || _y > h) {
                $("body >.jtk-window").remove("*");
                return false;
              }
              canvas.append(obj.str);

              $(obj.id).css({
                left: e.pageX + 10 - left + scroll_left + "px",
                top: e.pageY + 10 - top + scroll_top + "px"
              });
              $("body >.jtk-window").remove("*");
              // 初始化流程
              _addPointsData(instance); //增加一个流程时重新绘制
            } else {
              $("body >.jtk-window").remove("*");
            }
            isMove = false;
          });

        if (Object.keys(settings.data).length > 0) {
          _drawData(settings.data);
        }

        // 鼠标右键事件
        document.getElementById(
          settings.canvas.substring(1)
        ).oncontextmenu = function() {
          return false;
        };

        $(settings.canvas).on("mousedown", ".jtk-window", function(e) {
          e = e || event;
          let id = $(this).attr("id");
          // 右键
          if (e.which === 3 && settings.isEdit) {
            e.stopPropagation();
            let x = e.pageX + 10;
            let y = e.pageY + 10;
            $(".jtk-delete").css({
              left: x,
              top: y,
              display: "block"
            });
            $(".jtk-delete").off();
            $(".jtk-delete").on("click", function(e) {
              e.stopPropagation();
              _deleteData(id, settings.onRemoveNodeAfter);
              $(".jtk-delete").css("display", "none");
            });
          }
        });
        $("body").click(function() {
          //隐藏右键弹窗事件
          $(".jtk-delete").css("display", "none");
        });
      };

      // 初始化jsplumb插件
      jsPlumb.fire("jsPlumbDemoLoaded", instance);

      /*
       *	删除节点
       *	回调参数为删除节点的id, 与当前节点相关的线数据，可根据此数据找出与删除节点相连的节点
       */
      let _deleteData = function(id, callback) {
        let line = _self.data("dataflow").getLinesByNodeId(id);
        // let conn = instance.connect({
        //   source: id,
        //   target: 'xxxxxx'
        // });
        instance.remove(id);
        if (typeof callback === "function" && callback) {
          callback(id, line);
        }
      };

      /*
       *	如果有数据，则初始化流程节点, 绑定事件
       */
      let _drawData = function(data) {
        instance.batch(function() {
          if (data && Object.keys(data).length > 0) {
            let template = $(settings.template);
            for (let s = 0; s < data.location.length; s++) {
              let str = opt.initHtml({
                id: data.location[s].id,
                str: template.find(
                  "[data-type=" + data.location[s].type + "]"
                )[0].outerHTML
              });
              $(settings.canvas).append(str.str);
              $(str.id).css({
                left: data.location[s].x + "px",
                top: data.location[s].y + "px"
              });
            }
          }

          let windows = jsPlumb.getSelector(
            settings.canvas + " " + ".jtk-window"
          ); //获取流程对象；

          _hightLight(windows);
          _dataConnect(instance, data);

          //拖动连线结束时触发
          instance.bind("connectionDragStop", function(connection) {
            if (connection.sourceId === connection.targetId) {
              instance.detach(connection);
            }
            settings.onCreateLineAfter(connection);
          });

          //拖动线前触发
          instance.bind("connectionDrag", function(conn) {
            if (!settings.isEdit) {
              instance.detach(conn);
              settings.onCreateLineBefore(conn);
              return false;
            }
          });

          // 所有div流程都可拖动
          if (settings.isEdit) {
            // 点击连线
            instance.bind("dblclick", function(conn) {
              // console.log(conn);
              // console.log(conn);
              // 如果条件框在线上，则删除条件框
              if ($("#con_arrow" + conn.targetId)[0]) {
                $("#con_arrow" + conn.targetId).remove();
              }
              instance.detach(conn); //删除连线
            });
            instance.bind("click", function(conn) {
              // console.log(conn);
              // console.log(originalEvent);
              // 判断是否为判断类型
              if (conn.source.dataset.type === "lengxing") {
                // window.myVue.dialogVisible = true;
                // 添加输入框
                // let myCanvas = conn.canvas.parentElement;
                // $(myCanvas).append("<input style='position:absolute;left:"+(originalEvent.x-400)+"px;top:"+(originalEvent.y-200)+"px;' />");
              }
            });
            instance.draggable(
              jsPlumb.getSelector(settings.canvas + " " + ".jtk-window"),
              {
                grid: [20, 20]
              }
            );
          }
          settings.ondrawData();
        });
      };

      /*
       *	数据连线
       */
      let _dataConnect = function(instance, data) {
        let windows = jsPlumb.getSelector(
          settings.canvas + " " + ".jtk-window"
        );
        let windowsLength = windows.length;
        for (let i = 0; i < windowsLength; i++) {
          _addEndpoints(
            instance,
            $(windows[i]).attr("id"),
            ["Top", "Bottom"],
            ["Left", "Right"]
          );
          // 执行回调
          if (typeof settings.onCreateNodeAfter === "function") {
            settings.onCreateNodeAfter($(windows[i]).attr("id"));
          }
        }

        if (data && Object.keys(data).length > 0) {
          for (let s = 0, l = data.line.length; s < l; s++) {
            instance.connect({
              source: data.line[s].source.id,
              target: data.line[s].target.id,
              uuids: [
                data.line[s].source.arrow + data.line[s].source.id,
                data.line[s].target.arrow + data.line[s].target.id
              ],
              type: "Flowchart"
            });
          }
        }
      };

      // 绑定高亮事件
      let _hightLight = function(obj) {
        let flag = false;
        let oldDate = 0;
        $(obj).off();
        $(obj).on("click", ".node-icon", function() {
          // 图元点击弹窗
          // console.log($(this).closest('.workfolw-node')[0].innerText);
          window.myVue.iconClick(this);
          // console.log(window.myVue);
        });
        $(obj)
          .on("mouseover", function() {
            let id = $(this).attr("id");
            let dataflow = _self.data("dataflow");
            let line = dataflow.getLinesByNodeId(id);
            _toggleColor(line, settings.lineHoverColor);
          })
          .on("mousedown", function() {
            oldDate = new Date().getTime();
            flag = true;
          })
          .on("click", function() {
            // 图元点击事件
            // console.log(this.innerText);
            // window.myVue.dialogVisible=true;
            // window.myVue.msg=this.innerText;
          })
          .on("mousemove", function() {
            // if (flag) {
            //     let id = $(this).attr('id');
            //     let dataflow = _self.data('dataflow');
            //     let line = dataflow.getLinesByNodeId(id);
            //     _toggleColor(line, settings.defaultColor);
            // }
            // console.log(122)
            // 若拖动元素为判断目标框，则重新计算判断框定位位置
            let newDate = new Date().getTime();
            if (
              newDate - oldDate > 50 &&
              flag &&
              $("div[targetid=" + this.id + "]")[0]
            ) {
              oldDate = new Date().getTime();
              // 条件框元素
              let conditionBox = $("div[targetid=" + this.id + "]");
              // canvas距离窗口距离
              let canvasOffsetLeft = $("#canvas").offset().left;
              let canvasOffsetTop = $("#canvas").offset().top;
              // 定位位置
              let x = 0;
              let y = 0;
              // 箭头id
              let arrowId = conditionBox.attr("arrowid");

              if (conditionBox.hasClass("rightArrow")) {
                // 右
                x = $("#" + arrowId).offset().left - 2 - canvasOffsetLeft;
                y = $("#" + arrowId).offset().top + 5 - canvasOffsetTop;
              } else if (conditionBox.hasClass("leftArrow")) {
                // 左
                x = $("#" + arrowId).offset().left + 10 - canvasOffsetLeft;
                y = $("#" + arrowId).offset().top + 5 - canvasOffsetTop;
              } else if (conditionBox.hasClass("bottomArrow")) {
                // 下
                x = $("#" + arrowId).offset().left + 4 - canvasOffsetLeft;
                y = $("#" + arrowId).offset().top - 3 - canvasOffsetTop;
              } else if (conditionBox.hasClass("topArrow")) {
                // 上
                x = $("#" + arrowId).offset().left + 4 - canvasOffsetLeft;
                y = $("#" + arrowId).offset().top + 10 - canvasOffsetTop;
              }
              conditionBox.css({
                top: y + "px",
                left: x + "px"
              });
            }
          })
          .on("mouseup", function() {
            flag = false;
          })
          .on("mouseout", function() {
            let id = $(this).attr("id");
            let dataflow = _self.data("dataflow");
            let line = dataflow.getLinesByNodeId(id);
            _toggleColor(line, settings.defaultColor);
          });
      };

      // 流程节点mouseout高亮
      let _toggleColor = function(arr, color) {
        // let self = this;
        let l = arr.length;
        for (let i = 0; i < l; i++) {
          $(arr[i].canvas)
            .find("path")
            .css({
              fill: color,
              stroke: color
            });
        }
      };

      // 添加一个流程节点，使节点可拖拽
      let _addPointsData = function(instance) {
        instance.batch(function() {
          let windows = jsPlumb.getSelector(
            settings.canvas + " " + ".jtk-window"
          ); //获取流程对象；
          let windowsLength = windows.length - 1;

          _addEndpoints(
            instance,
            $(windows[windowsLength]).attr("id"),
            ["Top", "Bottom"],
            ["Left", "Right"]
          );
          instance.draggable(
            jsPlumb.getSelector(settings.canvas + " " + ".jtk-window"),
            {
              grid: [20, 20]
            }
          );

          // 绑定双击节点时，高亮与节点相关的所有线条
          _hightLight(windows);

          if (typeof settings.onCreateNodeAfter === "function") {
            settings.onCreateNodeAfter($(windows[windowsLength]).attr("id"));
          }
        });
      };

      // 初始化流程节点，使节点添加端点
      let _addEndpoints = function(
        instance,
        toId,
        sourceAnchors,
        targetAnchors
      ) {
        // let self = this;
        for (let i = 0; i < sourceAnchors.length; i++) {
          let sourceUUID = sourceAnchors[i] + toId;
          instance.addEndpoint(toId, settings.sourceEndpoint, {
            anchor: sourceAnchors[i],
            uuid: sourceUUID
          });
        }
        for (let j = 0; j < targetAnchors.length; j++) {
          let targetUUID = targetAnchors[j] + toId;
          instance.addEndpoint(toId, settings.targetEndpoint, {
            anchor: targetAnchors[j],
            uuid: targetUUID
          });
        }
      };

      // dataflow初始化
      let dataflow = function() {
        init.call(this);
      };

      /*
       *	id为DOM节点 id
       *	type为线的类型，可选 source，target，默认为 all
       *	返回与节点相关的 全部/出发点/终点 的数据
       */
      dataflow.prototype.getLinesByNodeId = function(id, type) {
        if (!(arguments.length > 0)) {
          return "getLinesByNodeId(id, type)必须传递节点id参数";
        }
        // let id = id,
        type = type || "all";
        let allLine = this.getLines();
        let line = allLine.filter(function(val) {
          switch (type) {
            case "all":
              if (id === val.sourceId || id === val.targetId) {
                return val;
              }
              break;
            case "source":
              if (id === val.sourceId) {
                return val;
              }
              break;
            case "target":
              if (id === val.targetId) {
                return val;
              }
              break;
            default:
              return "getLinesByNodeId(id, type)必须传递节点id参数";
          }
        });
        return line;
      };

      /*
       *	获取所有的线条数据
       */
      dataflow.prototype.getLines = function() {
        let c = this.instance.getAllConnections();
        return c;
      };

      /*
       *	将插件对象添加至原型，可查询插件的配置
       */
      dataflow.prototype.instance = instance;

      dataflow.prototype.getAllData = function() {
        let list = this.instance.getAllConnections();
        // 保存线
        let p = false;
        if (list.length === 0) {
          p = confirm("节点还没创建连线！");
        }
        if (p) {
          return false;
        }
        let line = list.map(function(val) {
          return {
            source: {
              id: val.endpoints[0].anchor.elementId,
              arrow: val.endpoints[0].anchor.type
            },
            target: {
              id: val.endpoints[1].anchor.elementId,
              arrow: val.endpoints[1].anchor.type
            }
          };
        });
        // 保存位置
        let connectionPosition = [];
        $(settings.canvas + " " + ".jtk-window").each(function(index, el) {
          let elem = $(el);
          connectionPosition.push({
            id: elem.attr("id"),
            x: parseInt(elem.css("left")),
            y: parseInt(elem.css("top")),
            // name: elem.find('[data]').attr('data'),
            type: elem.attr("data-type")
          });
        });
        let result = {
          line: line,
          location: connectionPosition
        };
        return result;
      };

      /*
       *	设置某一个节点
       *	{options，x/y可选，设置默认值为15px，type类型为必选项}
       *	x: 新增节点的x坐标，y: 新增节点的y坐标，type: 新增节点的模版类型
       */
      dataflow.prototype.setNode = function(options) {
        let $template = $(settings.template);
        let tem = $template.find(".jtk-window");
        let _html = "";
        $(tem).each(function(val, el) {
          console.log(val);
          if ($(el).attr("data-type") === options.type) {
            _html = el.outerHTML;
          }
        });
        let obj = opt.initHtml({
          id: settings.id + (opt.getId() + 1),
          str: _html
        });
        let canvas = $(settings.canvas);
        canvas.append(obj.str);
        $(obj.id).css({
          left: options.x || 15 + "px",
          top: options.y || 15 + "px"
        });
        _addPointsData(instance);
      };

      /*
       *	连接指定的线；数组的第一个参数为节点id、第二个参数为节点的端点位置, Left, Right, Top, Bottom
       *	数据格式
       *	{
       *		source: ['ch3','Top'],
       * 		target: ['ch2', 'Bottom']
       * 	}
       */
      dataflow.prototype.setLine = function(options) {
        instance.connect({
          source: options.source[0],
          target: options.target[0],
          uuids: [
            options.source[1] + options.source[0],
            options.target[1] + options.target[0]
          ],
          type: "Flowchart"
        });
      };

      /*
       *	重置画布
       */
      dataflow.prototype.resetCanvas = function() {
        settings.data = {};
        let win = $(settings.canvas).find(".jtk-window");
        let _l = win.length;
        for (let i = 0; i < _l; i++) {
          this.deleteNode(
            $(win)
              .eq(i)
              .attr("id")
          );
        }
      };

      /*
       *	删除某个节点
       *	{id}
       */
      dataflow.prototype.deleteNode = function(id) {
        _deleteData(id);
      };

      return $.each(this, function() {
        let $this = $(this);
        if (!$this.data("dataflow")) {
          $this.data("dataflow", new dataflow($this));
        }
      });
    }
  });
})(jQuery);
