import moment from 'moment';
/**
 * 甘特图
 * @param {} options 
 */
export function GanttChartMonth(options) {
  // 任务列表
  this.tasks = options.tasks || [];
  // AntVG Canvas
  this.gCanvas = null;
  // 视口宽度 800,可视区域
  this.viewWidth = options['viewWidth'] || 800;
  // 物理画布宽度 800
  this.cWidth = options['cWidth'] || 2400;
  this.cHeight = options['cHeight'] || 1600;
  // 画布偏移位置
  this.startPos = 0;
  // 是否拖动中
  this.draging = false;
  // 开始拖动事件
  this.startEvent = null;
  // 结束拖动事件
  this.endEvent = null;
  // 拖动过程事件
  this.dragingEvent = null;
  // 拖动偏移量
  this.offsetDis = (options['viewWidth']/2) || 800;
  // 拖动定时器
  this.dragTimer = null;
  // 每天的间隔宽度
  this.dayStep = parseInt(this.cWidth/365*2/3);
  // 分组标题高度
  this.groupTitleHeight = 18;
  // 任务矩形高度
  this.taskRowHeight = 16;
  // 每行任务的纵向间距
  this.rowSpanDis = 22;
  // 总天数
  this.daysCount = options['daysCount'] || 365;
  // 任务图距离顶部高度
  this.graphTopDis = 60
  // 任务矩形最小宽度
  this.minTaskRectWidth = 5
  
  // 每像素代表的小时数
  this.timePerPix = this.cWidth/this.daysCount/24/3600
  // 当前视图开始时间,向前推N天
  this.startAt = moment().startOf('year')
  this.endAt = moment().endOf('year')
  this.graphDiv = document.getElementById(options['chartParentContainer']);
  this.chartContainer = options['chartContainer']
  // 图形容器组
  this.graphGroup = null;
  // 上一次拖动的事件
  this.lastDragEv = null;
  // 当日刻度线
  this.todayTimeLineEl = null;
  // 点击回调事件
  this.callback = options.callback || null;
  // 翻页时间回调
  this.pageToCallback = options.pageToCallback || null;
}


/**
 * 设置数据
 * @param {*} _tasks 
 */
GanttChartMonth.prototype.changeTasks = function(_tasks){
  this.tasks = _tasks
  console.error('change tasks data here....', this.tasks)
  this.forceRefreshGraph()
}

/**
 * 打开关闭分组
 */

GanttChartMonth.prototype.toggle = function(index) {
  if (this.tasks[index].open) {
    this.tasks[index].open = false;
  } else {
    this.tasks[index].open = true;
  }
  this.processData();
  this.drawTasks();
}

/**
 * 预处理数据
 */
GanttChartMonth.prototype.processData = function() {
  for (let i = 0; i < this.tasks.length; i++) {
    let currentTopTask = this.tasks[i];
    let lastTopTask = null;
    currentTopTask.renderOptions = {};
    // 设置StartY
    if (i != 0) {
      // 非0个,要补上前面的数据
      lastTopTask = this.tasks[i - 1];
      currentTopTask.renderOptions.startY = lastTopTask.renderOptions.endY + 20;
    } else {
      // 第一个
      currentTopTask.renderOptions.startY = this.graphTopDis;
    }
    // 设置EndY
    // 当有数据 且 打开时,
    //     EndY = StartY + 标题上间距 + 标题 高度 + 任务个数 * (任务高度)
    if (currentTopTask.dataList.length >0 && currentTopTask.open) {
      currentTopTask.renderOptions.endY =
        currentTopTask.renderOptions.startY  + this.groupTitleHeight + currentTopTask.dataList.length * 38;
    } else {
      currentTopTask.renderOptions.endY = currentTopTask.renderOptions.startY + this.groupTitleHeight;
    }
  }
}

/**
 * 强制清空图像,重绘
 */
GanttChartMonth.prototype.forceRefreshGraph = function() {
  this.tasks.forEach((topTask) => {
    topTask.gGroup = null;
  });
  this.todayTimeLineEl = null
  this.gCanvas.destroy();
  this.initDrawingReady();
}

/**
 * 准备绘制,用于初始化和强制刷新
 */
GanttChartMonth.prototype.initDrawingReady = function() {
  this.initCanvas();
  setTimeout(() => {
    this.initDragHandler();
    this.drawTimeZone();
    this.processData();
    this.drawTasks();
    this.graphGroup = null
  }, 200);
}

/**
 * 翻页
 */
GanttChartMonth.prototype.pageTo = function(dir = 'next') {
  this.draging = false;
  this.endEvent = null;
  if (dir == 'next') {
    // 向后翻页`
    this.startAt = this.startAt.add(this.daysCount, 'days');
    this.offsetDis = 0
  } else {
    // 向前翻页
    this.startAt = this.startAt.subtract(this.daysCount, 'days');
    this.offsetDis = 2*this.viewWidth
  }
  this.endAt = moment(this.startAt).add(this.daysCount, 'days');
  this.pageToCallback({dir: dir, startAt: this.startAt.format('YYYY-MM-DD'), endAt: this.endAt.format('YYYY-MM-DD')})
  console.log('已翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'), this.offsetDis);
  // offsetDis = viewWidth;
  this.forceRefreshGraph();
}
// 上次点击时间,用于滚动时误触停止
let lastClickAt = null;
/**
 * 执行拖动
 * 改变graphDiv 滚动距离
 * 到达边界距离后,刷新页面
 */
GanttChartMonth.prototype.doDrag = function(sEvent, eEvent) {  
  if (sEvent == null) {
    sEvent = this.startEvent;
  }
  let sPos = sEvent.clientX;
  let cPos = eEvent.clientX;
  // 滚动距离
  let dis = cPos - sPos;
  let tempDis = this.offsetDis
  // console.log('offsetDis before:', this.offsetDis, dis)
  this.offsetDis = this.offsetDis - dis / 2;
  // console.log('draging...',tempDis, this.offsetDis, dis)
  if (this.offsetDis <= -20) {
    // 向前滑动,向前翻页
    console.log('此处应该向前翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'),this.offsetDis);
    this.offsetDis = this.viewWidth;
    this.pageTo('prev');
  }
  if ((this.offsetDis - 20) >= this.viewWidth*2.2 ){ //cWidth - viewWidth) {
    // 向后滑动,向后翻页
    console.log('此处应该向后翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'),this.offsetDis);
    this.offsetDis = this.viewWidth;
    this.pageTo('next');
  }
  this.graphDiv.scrollLeft = this.offsetDis;
}

/**
 * 初始化抓取拖动事件
 */
GanttChartMonth.prototype.initDragHandler = function() {
  this.graphDiv.scrollLeft = this.offsetDis;
  let _canvas = this._canvas
  _canvas.addEventListener('mousedown', (ev) => {
    this.draging = true;
    this.startEvent = ev;
    this.dragingEvent = null;
    this.endEvent = null;
    this.lastClickAt = new Date();
    this.lastClickAt = ev;
    this.lastDragEv = ev;
  });


  _canvas.addEventListener('mouseleave', (ev) => {
    console.log('leave...恢复')
    this.draging = false;
    this.endEvent = ev;
  });

  _canvas.addEventListener('mouseup', (ev) => {
    this.draging = false;
    this.endEvent = ev;
  });

  _canvas.addEventListener('mousemove', (ev) => {
    // console.log('this over', this)
    if (this.draging) {
      if (new Date() - this.lastClickAt < 20) {
        return false;
      }
      this.dragingEvent = ev;
      this.doDrag(this.lastDragEv, ev);
      this.lastDragEv = ev;
    }
  });
}
/**
 * 初始化画布
 *
 */

GanttChartMonth.prototype.initCanvas = function() {
  console.error('初始化画布...')
  this.gCanvas = new G.Canvas({
    container: this.chartContainer,
    width: this.cWidth,
    height: this.cHeight,
  });
  this._canvas = document.querySelector('#ganttContainer>canvas');
}

/**
 * 绘制时间区域
 */

GanttChartMonth.prototype.drawTimeZone = function() {
  console.log('时间段', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'));
  let start = moment(this.startAt);
  let timeGroup = this.gCanvas.addGroup();
  this.timeGroupEl = timeGroup
  timeGroup._tname = 'TimeGroup';
  let startSecond = moment(this.startAt);

  // 顶部底部边框
  timeGroup.addShape('rect',{
    attrs: {
      x: 0,
      y: 0,
      width: this.cWidth,
      height: 52,
      fill: '#F8F9FA',
      radius: [2, 4],
    },
  })
  // 绘制第二级
  let nowAtStr = moment().format('YYYY-MM-DD')
  let year = this.startAt.format('YYYY')
  this.timeZoneLineEls = []
  for (let i = 1; i < 13; i++) {
    let tempAt = moment(`${year}-${i}`)
    let timeText = tempAt.format('MM');
    if(timeText == '01'){
      // 第一天,顶部需要绘制年月
      timeGroup.addShape('text', {
        attrs: {
          x: this.dayStep * i,
          y: 20,
          fontSize: 12,
          text: tempAt.format('YYYY'),
          lineDash: [10, 10],
          fill: '#8D9399',
        },
      });
      
    }
    let isToday = nowAtStr == tempAt.format('YYYY-MM-DD')
    if(isToday){
      //是今日,需要画线
      console.log('绘制 当日刻度线')
      this.todayTimeLineOffsetPos = this.dayStep * i
      timeGroup.addShape('rect',{
        attrs: {
          x: this.dayStep * i-10,
          y: 25,
          width: 30,
          height: 16,
          fill: '#0091FF',
          radius: [2, 4],
        },
      })

      this.todayTimeLineEl = this.gCanvas.addShape('rect',{
        attrs: {
          x: this.todayTimeLineOffsetPos,
          y: 40,
          width: 4,
          height: this.cHeight,
          fill: '#CDE9FF',
          radius: [2, 4],
        }
      })
      // this.todayTimeLineEl.setZIndex(3)
    }

    // 当月天数
    let daysCount = moment(`${year}-${i}`).dayOfYear()
    timeGroup.addShape('text', {
      attrs: {
        x: this.dayStep * daysCount + 180,
        y: 40,
        fontSize: 10,
        text: timeText,
        lineDash: [10, 10],
        fill: '#8D9399',
      },
    });
  }
}

/**
 * 处理点击
 */
GanttChartMonth.prototype.handleClick = function(task, flag, ev) {
  // let detailDiv = document.getElementById('detailDiv')
  if(flag == 'enter'){
    // detailDiv.style.display = 'block'
    // detailDiv.style.left = ev.clientX+'px';
    // detailDiv.style.top = ev.clientY+'px';
    // document.getElementById('detailTaskName').textContent = task._pdata.description
    // document.getElementById('detailTaskStatus').textContent = task._pdata.status
    // document.getElementById('detailTaskStartDate').textContent = task._pdata.startDate
    // document.getElementById('detailTaskEndDate').textContent = task._pdata.endDate
    console.log('show:', task);
  } else if (flag === 'leave'){
    // detailDiv.style.display = 'none'
    console.log('hide:', task);
  } else {
    this.callback(task);
    console.log('click:', task);
  }
}


/**
 * 根据任务状态区分颜色
 * 
 */
GanttChartMonth.prototype.statusColor =function(task) {
  switch (task.statusType) {
    case 1:
      return ['#e7e9ea', '#c3c7cb'];
    case 2:
      return ['#dee9fe', '#5b8ff9'];
    case 3:
      return ['#fbce99', '#f58300'];
    case 4:
      return ['#fbb8b5', '#f54e45'];
    default:
      return ['#fbb8b5', '#f54e45'];
  }
}

/**
 * 判断任务是否在视图内
 * 
 */ 
GanttChartMonth.prototype.isInView = function(task) {
  let isLessThanEndAt = (task.endDate <= this.startAt.format('YYYY-MM-DD'))
  let isGreaterThanStartAt = task.startDate >= this.endAt.format('YYYY-MM-DD')

  if(task.startDate == task.endDate){
    // console.error('任务宽度为0',task)
    return true
  }
  // console.log('isInView', `${task.startDate} -- ${task.endDate}`, this.startAt.format('YYYY-MM-DD'), this.endAt.format('YYYY-MM-DD'), (!(isLessThanEndAt || isGreaterThanStartAt)))
  return !(isLessThanEndAt || isGreaterThanStartAt)
}

/**
 * 绘制完成之后的回调,用于某些工具缺陷的hack写法
 */
GanttChartMonth.prototype.postDrawTasksCallBack = function(){
  // 画当前线条 TODO,放前面不行
  if(true){
    let todayAt = new Date()
    if(this.startAt < todayAt && this.endAt > todayAt){
      let duraStartAt = new Date() - new Date(this.startAt.format('YYYY-MM-DD'));
      let secondsStartAt = duraStartAt/1000
      this.todayTimeLineOffsetPos = secondsStartAt*this.timePerPix
      this.todayTimeLineEl = this.gCanvas.addShape('rect',{
        attrs: {
          x: this.todayTimeLineOffsetPos,
          y: 50,
          width: 4,
          height: this.cHeight,
          fill: '#CDE9FF',
          radius: [2, 4],
        }
      })
      this.todayTimeLineEl.setZIndex(3)
    }
  }

  if(true){
    let year = this.startAt.format('YYYY')
    for (let i = 1; i < 13; i++) {
      // 当月天数
    let daysCount = moment(`${year}-${i}`).dayOfYear()
      let lineEl = this.timeGroupEl.addShape('rect', {
        attrs: {
          x: this.dayStep * daysCount,
          y: 20,
          width: 1,
          height: this.cHeight,
          fill: '#deebeb',
          radius: [2, 4],
        },
      });
      lineEl.setZIndex(200)
    }
  }
}

/**
 * 分组绘制任务块
 *
 */

GanttChartMonth.prototype.drawTasks = function() {  
  this.graphGroup = this.gCanvas.addGroup();
  this.graphGroup._tname = 'graphGroup';  
  // 第一层循环,用于分组,例如,维保--xxxx
  this.tasks.forEach((topTask, topIndex) => {
    try {      
      if (topTask.open) {
        let taskGroup = null;
        taskGroup = this.graphGroup.addGroup();
        taskGroup._tname = 'TaskGroup_' + topTask.id;
        topTask.gGroup = taskGroup;
  
        if(false){
          // 组名背景矩形
          let TopGroupRectEl = taskGroup.addShape('rect', {
            attrs: {
              x: 0,
              y: topTask.renderOptions.startY,
              width: this.cWidth,
              height: this.taskRowHeight,
              fill: '#F5F6F7',
              radius: [2, 4],
            },
          });
          TopGroupRectEl.setZIndex(-1)
        }
        // 第二层循环,用于 区分具体多少任务,例如,维保-商管1/商管2...
        topTask.dataList.forEach((taskP, index) => {
          let taskPGroup = taskGroup.addGroup()
          taskGroup.addGroup(taskPGroup);
          // 任务背景矩形,主要用于Hover效果变更颜色
          if(true){
            let tempTaskContainerEl = taskPGroup.addShape('rect', {
              attrs: {
                x: 0,
                y: topTask.renderOptions.startY + ((index+1)* (this.taskRowHeight + this.rowSpanDis))-5,
                width: this.cWidth,
                height: this.taskRowHeight+10,
                fill: '#fff',
                // stroke: 'black',
                radius: [2, 4],
              },
            });
            tempTaskContainerEl.setZIndex(1)
            tempTaskContainerEl._pdata = taskP
            tempTaskContainerEl.on('mouseenter',(ev)=>{
              tempTaskContainerEl.attr({fill: '#F5F6F7'})
              tempTaskContainerEl._pdata.tasks.forEach(_tempTask=>{
                if(_tempTask._rectEl){
                  _tempTask._rectEl.setZIndex(5)
                }
              })
            })
            tempTaskContainerEl.on('mouseleave',(ev)=>{
              tempTaskContainerEl.attr({fill: '#fff'})
              tempTaskContainerEl._pdata.tasks.forEach(_tempTask=>{
                if(_tempTask._rectEl){
                  _tempTask._rectEl.setZIndex(5)
                }
              })
            })
            taskP._containerEl = tempTaskContainerEl
          }
          // 第三层循环,用户区分每个子任务的执行时间段,例如:维保-商管1-2020.05-2020.06 / 2020.08- 2020.09
          taskP.tasks.forEach((_taskItem, _index) => {
            let _isInView = this.isInView(_taskItem)
            // 在视图中才显示
            if(_isInView){
              let pos = this.calRectPos(_taskItem);
              // console.log('render rect:', _taskItem, pos, topTask.renderOptions.startY + index * taskRowHeight);
              let rectEl = taskPGroup.addShape('rect', {
                attrs: {
                  x: pos.x,
                  y: topTask.renderOptions.startY + ((index + 1)* (this.taskRowHeight + this.rowSpanDis)),
                  width: pos.width,
                  height: this.taskRowHeight,
                  fill: this.statusColor(_taskItem)[0],
                  stroke: this.statusColor(_taskItem)[1],
                  radius: [2, 4],
                },
              });
              rectEl.setZIndex(50)
              rectEl._pdata = _taskItem;
              _taskItem._rectEl = rectEl
              rectEl.on('mouseover', (ev) => {
                this.handleClick(ev.target, 'enter', ev);
              });
              rectEl.on('mouseleave', (ev) => {
                this.handleClick(ev.target, 'leave', ev);
              });
              rectEl.on('click', (ev) => {
                this.handleClick(ev.target, 'click', ev);
              });
            }
          });
        });
  
        taskGroup.show();
      } else {
        if (topTask.gGroup) {
          // topTask.gGroup.hide()
          topTask.gGroup = null;
        }
      }
    } catch (error) {      
      console.error('drawTasks error:', error)
    }
  });

  this.postDrawTasksCallBack()
}

/**
 * 根据 Task 计算矩形位置
 *
 */
GanttChartMonth.prototype.calRectPos = function(taskItem) {
  let duraStartAt = new Date(taskItem.startDate) - new Date(this.startAt.format('YYYY-MM-DD'));
  let secondsStartAt = duraStartAt/1000

  let duraEndAt = new Date(taskItem.endDate) - new Date(taskItem.startDate);
  let secondsEndAt = duraEndAt/1000
  let width = secondsEndAt * this.timePerPix
  if(width < this.minTaskRectWidth){
    width = this.minTaskRectWidth
  }
  // console.error('task rect width:', width)
  return {
    x: secondsStartAt * this.timePerPix,
    y: 0,
    width: width,
    height: 0,
  };
}

/**
 * 主函数
 *
 */

GanttChartMonth.prototype.main = function() {  
  this.initDrawingReady();
}