<template>
  <div class="flow-chart-container" :style="{ width: `${width}px`, height: `${height}px` }">
    <div class="flow-chart" ref="flowChart"></div>
    <div :class="['flow-chart-sidebar', { active: isSideBarActive }]" :style="{ width: `${sliderWidth}px` }">
      <slot name="sideBar">
          <input type="text" v-model="node.label" disabled placeholder="请输入标题">
          <input type="text" v-model="node.propertyOne" disabled placeholder="节点属性">
          <input type="text" v-model="node.propertyTwo" disabled placeholder="节点属性">
          <input type="text" v-model="node.propertyThree" disabled placeholder="节点属性">x
      </slot>
    </div>
    <div :class="['flow-chart-mask', { active: isSideBarActive }]" @click="clickMask" :style="{ background: `${maskColor}` }"></div>
  </div>
</template>

<script>
import Chart from './flowChart'

export default {
  name: 'FlowChart',
  // 接收参数，并指定默认值
  props: {
    width: { // 宽度
      type: Number,
      default: 1200
    },
    height: { // 高度
      type: Number,
      default: 600
    },
    sliderWidth: { // 抽屉宽度
      type: Number,
      default: 400
    },
    data: { // 如果不传data,默认展示开始节点
      type: Object,
      default: () => {
        return {
          nodes: [
            {
              id: 'start',
              type: 'flowNode',
              label: '开始',
              state: 'start',
              x: 100,
              y: 100,
              propertyOne: '',
              propertyTwo: '',
              propertyThree: '',
              task: {}
            }
          ],
          edges: []
        }
      }
    },
    statusColor: Object, // 状态颜色配置
    closeSideBarClickMask: { // 惦记mask关闭抽屉
      type: Boolean,
      default: true
    },
    maskColor: { // 抽屉背景颜色
      type: String,
      default: 'rgba(0, 0, 0, 0.3)'
    },
    showBackBtn: { // 反选按钮是否显示
      type: Boolean,
      default: true
    },
    showViewBtn: {
      type: Boolean,
      default: true
    },
    showDelBtn: { // 删除按钮是否显示
      type: Boolean,
      default: true
    },
    showAddBtn: { // 新增按钮是否显示
      type: Boolean,
      default: true
    },
    addFlowNodeText: { // 新增流程节点文案
      type: String,
      default: '新建流程节点'
    },
    addSwitchNodeText: { // 新增条件节点文案
      type: String,
      default: '新建条件节点'
    },
    addShowSwitchNode: { // 新增展示条件节点
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      // 是否显示右边侧边栏
      isSideBarActive: false,
      // 当前节点信息
      node: {}
    }
  },
  watch: {
    data: { // 监听data变化
      handler (val) {
        const data = JSON.parse(JSON.stringify(val))
        this.Chart.init(data)
      },
      deep: true
    },
    width: { // 监听宽度变化
      handler (val) {
        this.Chart.graph.changeSize(val, this.height)
      }
    },
    height: { // 监听高度变化
      handler (val) {
        this.Chart.graph.changeSize(this.width, val)
      }
    },
    showBackBtn: { // 监听高度变化
      handler (val) {
        this.Chart.graph.render()
      }
    },
    showViewBtn: { // 监听高度变化
      handler (val) {
        this.Chart.graph.render()
      }
    },
    showDelBtn: { // 监听高度变化
      handler (val) {
        this.Chart.graph.render()
      }
    },
    showAddBtn: { // 监听高度变化
      handler (val) {
        this.Chart.graph.render()
      }
    },
    addShowSwitchNode: { // 监听高度变化
      handler (val) {
        this.Chart.graph.render()
      }
    }
  },
  mounted () {
    // 如果data时空对象,默认展示开始节点
    let data = JSON.parse(JSON.stringify(this.data))
    if (JSON.stringify(this.data) === '{}') {
      data = {
        nodes: [
          {
            id: 'start',
            type: 'flowNode',
            label: '开始',
            state: 'start',
            x: 100,
            y: 100,
            propertyOne: '',
            propertyTwo: '',
            propertyThree: '',
            task: {}
          }
        ],
        edges: []
      }
    }
    // 实例
    this.Chart = new Chart(this, this.$refs.flowChart)
    this.Chart.init(data)
  },
  methods: {
    /**
     * 供外部父组件调用, 更新节点/边的数据
     * @param {object} node
     * @param {string} node.id
     * @param {string} node.label
     * @param {string} node.state
     * @param {string} node.propertyOne
     * @param {string} node.propertyTwo
     * @param {string} node.propertyThree
     * @param {object} node.task
     */
    updateItem (node) {
      this.Chart.updateItem(node)
    },
    deleteItem (id) {
      this.Chart.deleteNode(id)
    },
    getAllPreNodeList (id) {
      return this.Chart.getAllPreNodeList(id)
    },
    // 供外部父组件调用, 获取流程图完整数据
    getData () {
      return this.Chart.data
    },
    // 供外部父组件调用, 获取流程图完整数据
    fitView (padding) {
      return this.Chart.fitView(padding)
    },
    // 供外部父组件调用, 获取流程图完整数据
    getPreNodeList (id) {
      return this.Chart.getPreNodeList(id)
    },
    // 供外部父组件调用, 更改抽屉的关闭/打开状态
    toggleSidebar () {
      this.isSideBarActive = !this.isSideBarActive
    },
    /**
     * 供flowChart实例调用, 选择节点后
     * @param {object[]} node 此处传入选中的节点数组
     */
    selectedNodeHandler (node) {
      this.node = node
      this.$emit('node-selected', node)
    },
    /**
     * 供flowChart实例调用, 新增节点后
     * @param {object[]} node 此处传入选中的节点数组
     */
    handleAddNode (node) {
      this.$emit('node-add', node)
    },
    /**
     * 供flowChart实例调用, 删除节点后
     * @param {object[]} node 此处传入选中的节点数组
     */
    handleDeleteNode (node) {
      this.$emit('node-delete', node)
    },
    // 供外部父组件调用, 获取流程图完整数据
    // 点击mask的方法
    clickMask () {
      if (this.closeSideBarClickMask) {
        this.toggleSidebar()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.flow-chart-container {
  position: relative;
  border: 1px solid #808080;
  border-radius: 5px;
  overflow: hidden;
  .flow-chart-sidebar{
    overflow-y: auto;
    position: absolute;
    right: -500px;
    top: 0;
    height: 100%;
    min-height: 500px;
    background-color: #fff;
    transform: translateX(100%);
    transition: all .3s ease-out;
    z-index: 1000;
    box-shadow: -5px 0px 19px 0px rgba(0,0,0,0.2);
    &.active{
      right: 0;
      transform: translateX(0);
    }
    input{
      display: block;
      width: 90%;
      margin: 0 auto;
      line-height: 32px;
      border-radius: 3px;
      margin-top: 10px;
      outline: none;
      border: 1px solid #efefef;
      padding: 5px;
      box-sizing: border-box;
    }
  }
  .flow-chart-mask{
    display: none;
    position: absolute;
    top:0;
    bottom:0;
    right:0;
    left:0;
    margin: auto;
    width:100%;
    z-index: 999;
    &.active{
      display: block;
    }
  }
}
</style>
