<template>
<div class="container">
  <div id="ganttChart" ref="gantt"/>
  <div @mousedown="mouseDownHandler" class="move-bar" :style="`left: ${left - 2}px`"/>
  <GanttModal v-model="showModal" @save="handleSave" @cancel="handleCancel" @delete="handleDelete" :task="curTask"/>
</div>
</template>

<script>
import gantt from '#/dhtmlx-gantt/codebase/dhtmlxgantt.js'
import '#/dhtmlx-gantt/codebase/ext/dhtmlxgantt_tooltip'
import GanttModal from './gantt-modal'
import './locale_cn'
import {config, template} from './gantt-config'
import '#/dhtmlx-gantt/codebase/dhtmlxgantt.css'
export default {
  name: 'GanttChart',
  components: {
    GanttModal,
  },
  props: {
    tasks: {
      type: Object,
      default() {
        return {
          data: [],
          links: [],
        }
      }
    }
  },
  data() {
    return {
      showModal: false,
      left: config.grid_width,
      curTask: {},
      columns: config.columns,
      event: null,
    }
  },
  mounted() {
    this.initGantt()
  },
  methods: {
    initGantt() {
      for (let key in config) {
        gantt.config[key] = config[key]
      }
      for (let key in template) {
        gantt.templates[key] = template[key]
      }
      this.addEvents()
      gantt.init(this.$refs.gantt)
      this.addBaseline()
      gantt.parse(this.tasks)
    },
    addEvents() { // 添加触发事件
      // 可以添加法定节假日
      this.setHolidays()
      // 显示悬浮窗
      gantt.showLightbox = (id) => {
        const task = gantt.getTask(id)
        this.curTask = task
        this.showModal = true
      }
      // 调整进度或者拖拽柱子触发
      gantt.attachEvent('onAfterTaskDrag', (id, mode, e) => {
        const task = gantt.getTask(id)
        if (mode == 'progress') {
          this.$emit('progressChange', task)
        }
      })
      // 拖拽任务触发
      gantt.attachEvent('onAfterTaskMove', (id, parentId, tindex) =>{
        const task = gantt.getTask(id)
        const parentTask = gantt.getTask(parentId)
        this.$emit('taskChange', {task, parentTask})
      })
      // 任务加载后触发
      gantt.attachEvent('onTaskLoading', task => {
        task.planned_start = gantt.date.parseDate(task.planned_start, 'xml_date')
        task.planned_end = gantt.date.parseDate(task.planned_end, 'xml_date')
        return true
      })
    },
    search(val = null) { // 搜索
      if (this.event) {
        // 移除原先的事件，否则搜索事件会一直叠加
        gantt.detachEvent(this.event)
      }
      gantt.eachTask(function(task){
        task.$open = true
      })
      this.event = gantt.attachEvent('onBeforeTaskDisplay', (id, task) => {
        if (!val) return true
        const taskText = task.text.toLowerCase()
        const taskPerson = task.name.toLowerCase()
        const searchText = val.toLowerCase()
        return (taskText.indexOf(searchText) > -1 || taskPerson.indexOf(searchText) > -1)
      })
      gantt.render()
    },
    reset(config = {}){
      if (gantt.$container) {
        gantt.clearAll()
      }
      gantt.config.columns = config.columns || this.columns
      gantt.init(this.$refs.gantt)
      this.addBaseline()
      gantt.parse(this.tasks)
      gantt.render()
    },
    addBaseline() { // 添加基线
      gantt.addTaskLayer({
        renderer: {
          render: function draw_planned(task) {
            if (task.planned_start && task.planned_end) {
              const sizes = gantt.getTaskPosition(task, task.planned_start, task.planned_end)
              const el = document.createElement('div')
              el.className = 'baseline'
              el.style.left = sizes.left + 'px'
              el.style.width = sizes.width + 'px'
              el.style.height = sizes.height + 'px'
              el.style.top = (sizes.top + 9) + 'px'
              return el
            }
            return false
          },
        }
      })
    },
    handleSave({id, text, name, date}) {
      let task = gantt.getTask(id)
      task = Object.assign(task, {
        name,
        text,
        start_date: gantt.date.parseDate(date[0], 'xml_date'),
        end_date: gantt.date.parseDate(date[1], 'xml_date'),
      })
      if(task.$new) {
        delete task.$new
        gantt.addTask(task, task.parent)
      } else {
        gantt.updateTask(id)
      }
      gantt.render()
    },
    handleDelete({id}) {
      const task = gantt.getTask(id)
      gantt.deleteTask(id)
      this.showModal = false
    },
    handleCancel({id}) {
      const task = gantt.getTask(id)
      if (task.$new) {
        gantt.deleteTask(id)
      }
    },
    mouseDownHandler(){
      document.body.addEventListener('mousemove',this.mouseMoveHandler)
      document.body.addEventListener('mouseup',this.mouseUpHandler)
    },
    mouseUpHandler(){
      document.body.removeEventListener('mousemove',this.mouseMoveHandler)
      document.body.removeEventListener('mouseup',this.mouseUpHandler)
    },
    mouseMoveHandler(e){
      let left = e.clientX
      if (left <= 400) {
        left = 400
      } else if (left >= 800) {
        left = 800
      }
      this.left = left
      gantt.config.grid_width = left
      gantt.render()
    },
    setHolidays(holidays = [new Date(2019,9,1)]){
      holidays.forEach(date => {
        gantt.setWorkTime({date: date, hours: false})
      })
    },
  },
}
</script>

<style>
.weekend {
  background: #f4f7f4;
}
.gantt_selected .weekend {
  /* background: #f7eb91; */
  background: #e4ecf3;
}
.gantt_grid_data .gantt_row.gantt_selected,
.gantt_grid_data .gantt_row.odd.gantt_selected,
.gantt_task_row.gantt_selected,
.gantt_row.gantt_row_task:hover,
.gantt_row.odd.gantt_row_task:hover {
  background: #eff4f9;
}
/* .gantt_row.gantt_row_task:hover > .gantt_cell,
.gantt_row.odd.gantt_row_task:hover > .gantt_cell {
  color: #55bc8a;
} */
.gantt_task_row.gantt_selected .gantt_task_cell {
  border-right-color: #eff4f9;
}
.baseline {
  position: absolute;
  border-radius: 2px;
  opacity: 0.6;
  margin-top: -7px;
  background: rgba(0,0,0,0.5);
  border: 1px solid rgba(0,0,0,0.3);
}
.gantt_side_content.gantt_left {
  padding-right: 10px;
}
</style>
<style scoped>
.container {
  width: 100%;
  height: 100%;
  position: relative;
}
.container > .move-bar {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 5px;
  content: '';
  cursor: col-resize;
}
#ganttChart {
  width: 100%;
  height: 100%;
}
</style>
