import { closeLineChart, CATEGORIES } from '../../configuration/constants'
import { echartsBasicListen } from '../../feature/traits/common'
import { throttle } from '../../utils'

export default {

  // 组件名称
  name: closeLineChart,

  // 前面板html模板
  viewTemplate() {
    return `
      <div data-gjs-type="${closeLineChart}" class="${closeLineChart}"></div>
    `
  },
  // 前面板html样式
  viewStyle() {
    return `
      <style>
        .${closeLineChart} {
          position: absolute;
          border-radius: 5px;
          border-style: solid;
          border-width: 1px;
          border-color: transparent;
          padding: 10px;
          width: 600px;
          height: 400px;
        }
      </style>
    `
  },

  // 编辑器右侧块管理器中显示属性配置
  blockOptions() {
    return {
      category: CATEGORIES.ECHARTS,
      label: `
      <svg class="gjs-block-svg" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" ><path d="M884.7 128H359.8L95.5 420v476h789.2L522.1 490.7 884.7 128z m-72.5 736h-74.6L410.4 489l329.1-329h74.6L478.3 489l333.9 375z"></path><path d="M954.3 928H64V408.2L344.8 96H960L564.1 491.9 954.3 928z m-829.2-64h688.2L478.1 489.4 807.5 160H373L125.1 431.8V864z" fill="#BFD1EB"></path></svg>
        <div class="gjs-block-label">包线图</div>
      `,
    };
  },

  // 后面板显示属性配置
  spOptions() {
    return {
      label: '包线图',
      icon: 'globe',
      docUrl: 'https://xuelangyun.yuque.com/docs/share/ed6c0826-fcff-49f9-991e-803e6c1c7fe4',
      author: '陈亚楠',
      email: '878493162@qq.com',
      inPorts: [{
        uuid: 'in1',
        subType: 'json',
        description: {
          zh_CN: '输入1'
        }
      }],
      outPorts: [{
        uuid: 'out1',
        subType: 'json',
        description: {
          zh_CN: '输出1'
        }
      }]
    }
  },

  // 组件属性
  componentOptions() {
    return {
      name: closeLineChart,
      resizable: true,
      dmode: 'absolute',
      droppable: false,
      traits: [
        {
          name: 'xAxisName',
          label: 'x轴名称',
          changeProp: 1
        }, {
          name: 'xAxisNameColor',
          label: 'x轴名称颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'yAxisName',
          label: 'y轴名称',
          changeProp: 1
        }, {
          name: 'yAxisNameColor',
          label: 'y轴名称颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'AxisNameFontSize',
          label: '坐标轴名称字号',
          changeProp: 1,
          type: 'number',
          min: 10
        }, {
          name: 'yAxisUnit',
          label: 'y轴单位',
          changeProp: 1
        }, {
          name: 'axisColor',
          label: '坐标轴颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'axisLineWidth',
          label: '坐标轴线宽',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        }, {
          name: 'axisLabelFontsize',
          label: '刻度值字号',
          changeProp: 1,
          type: 'number',
          min: 9,
          step: 1
        }, {
          name: 'xAxisTick',
          label: 'x轴刻度线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxisTick',
          label: 'y轴刻度线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'axisTickLength',
          label: '刻度线长度',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        }, {
          name: 'showMinorTick',
          label: '次刻度线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'minorTickLength',
          label: '次刻度线长度',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        }, {
          name: 'xAxisSplitLine',
          label: 'x轴分割线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'xAxisSplitLineType',
          label: 'x轴分割线类型',
          type: 'select',
          changeProp: 1,
          options: [{ id: 'solid', name: '实线' }, { id: 'dashed', name: '虚线' }, { id: 'dotted', name: '点线' }]
        }, {
          name: 'yAxisSplitLine',
          label: 'y轴分割线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxisSplitLineType',
          label: 'y轴分割线类型',
          type: 'select',
          changeProp: 1,
          options: [{ id: 'solid', name: '实线' }, { id: 'dashed', name: '虚线' }, { id: 'dotted', name: '点线' }]
        }, {
          name: 'gridPadding',
          label: '容器边距(左,上,右,下)',
          changeProp: 1
        }, {
          name: 'containLabel',
          label: '包含刻度标签',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'labelPosition',
          label: '标签',
          type: 'select',
          changeProp: 1,
          options: [{ id: 'null', name: '无' }, { id: 'top', name: '上' }, { id: 'bottom', name: '下' }, { id: 'left', name: '左' }, { id: 'right', name: '右' }]
        }, {
          name: 'xLabelRotate',
          label: 'x轴刻度值旋转',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'xLabelMap',
          label: 'X轴标签映射',
          changeProp: 1,
        }, {
          name: 'smooth',
          label: '平滑',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'lineWidth',
          label: '线宽',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'symbol',
          label: '节点',
          type: 'select',
          changeProp: 1,
          options: [{ id: 'emptyCircle', name: '空心圆' }, { id: 'circle', name: '圆形' }, { id: 'rect', name: '矩形' }, { id: 'roundRect', name: '圆角矩形' }, { id: 'triangle', name: '三角形' }, { id: 'diamond', name: '菱形' }, { id: 'pin', name: '大头针' }, { id: 'arrow', name: '箭头' }, { id: 'none', name: '无' }]
        }, {
          name: 'symbolSize',
          label: '节点大小(px)',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        }, {
          name: 'zoomStart',
          label: '放大镜开始(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'zoomEnd',
          label: '放大镜结束(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'hiddenDimension',
          label: '非渲染数据维度',
          changeProp: 1,
        }, {
          name: 'inLoader',
          label: '包含Loading',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'clickEvent',
          label: '鼠标事件',
          changeProp: 1,
          type: 'select',
          options: [{ id: 'null', name: '无' }, { id: 'click', name: '单击' }, { id: 'dblclick', name: '双击' }, { id: 'mousedown', name: '按下' }, { id: 'mouseup', name: '松开' }, { id: 'mouseover', name: '滑过' }, { id: 'mouseout', name: '滑出' }]
        }, {
          name: 'csv',
          label: '示例数据',
          changeProp: 1,
          type: 'csvDownload',
          preFileName: '线形图',
          datas: [['x', 'y', 'category'],[15, 15, 'a'],[19.5, 15, 'a'],[19.5, 40, 'a'],[15,40, 'a'],[15,15, 'a'],[20, 15, 'b'],[20, 60, 'b'], [25, 60, 'b'], [29, 50, 'b'], [29, 15, 'b'], [20, 15, 'b']]
        }, {
          name: 'defaultData',
          changeProp: 1,
          type: 'hide'
        }
      ],
      defaultData:JSON.stringify([
        ['x', 'y', 'category'],
        [15, 15, 'a'],
        [19.5, 15, 'a'],
        [19.5, 40, 'a'],
        [15,40, 'a'],
        [15,15, 'a'],
        [20, 15, 'b'],
        [20, 60, 'b'], 
        [25, 60, 'b'],
        [29, 50, 'b'],
        [29, 15, 'b'], 
        [20, 15, 'b']
      ]).replace(/\"/g, "\\\""),
      'xAxisName': null,
      'yAxisName': null,
      'xAxisNameColor': '#333',
      'yAxisNameColor': '#333',
      'AxisNameFontSize': 12,
      'axisColor': '#333333',
      'axisLineWidth': 1,
      'yAxisUnit': null,
      'xAxisSplitLine': true,
      'xAxisTick': true,
      'axisTickLength': 5,
      'yAxisSplitLine': true,
      'yAxisTick': true,
      'showMinorTick': true,
      'minorTickLength': 3,
      'axisLabelFontsize': 12,
      'yAxisSplitLineType': 'dashed',
      'xAxisSplitLineType': 'dashed',
      'gridPadding': '10%,60,10%,60',
      'containLabel': true,
      'labelPosition': 'null',
      'xLabelRotate': null,
      'xLabelMap': null,
      'smooth': false,
      'lineWidth': 1,
      'symbol': 'emptyCircle',
      'symbolSize': 4,
      'zoomStart': -1,
      'zoomEnd': 100,
      'inLoader': false,
      'hiddenDimension': null,
      'clickEvent': 'null',
    }
  },

  onModelScript() {
    const dataSource = '{[ dataSource ]}';
    const bgColor = '{[ bgColor ]}';
    const borderColor = '{[ borderColor ]}';
    const fontColor = '{[ fontColor ]}';
    let colors = '{[ colors ]}';
    let legendPosition = ('{[ legendPosition ]}').toString();
    const legendOrient = ('{[ legendOrient ]}').toString();
    const legendIcon = ('{[ legendIcon ]}').toString();
    const legendItemGap = Number('{[ legendItemGap ]}');
    const legendItemWidth = Number('{[ legendItemWidth ]}');
    const legendItemHeight = Number('{[ legendItemHeight ]}');
    const legendFontSize = Number('{[ legendFontSize ]}');
    const labelPosition = ('{[ labelPosition ]}').toString();
    const titleText = '{[ titleText ]}';
    const titleColor = '{[ titleColor ]}';
    const titlePosition = ('{[ titlePosition ]}').toString();
    const xAxisName = '{[ xAxisName ]}';
    const yAxisName = '{[ yAxisName ]}';
    const xAxisNameColor = '{[ xAxisNameColor ]}';
    const yAxisNameColor = '{[ yAxisNameColor ]}';
    const AxisNameFontSize = Number('{[ AxisNameFontSize ]}');
    const minorTickLength = Number('{[ minorTickLength ]}');
    const axisTickLength = Number('{[ axisTickLength ]}');
    const yAxisUnit = ('{[ yAxisUnit ]}').toString();
    const axisColor = '{[ axisColor ]}';
    const axisLineWidth = Number('{[ axisLineWidth ]}');
    const xAxisSplitLine = Boolean('{[ xAxisSplitLine ]}');
    const xAxisTick = Boolean('{[ xAxisTick ]}');
    const yAxisTick = Boolean('{[ yAxisTick ]}');
    const showMinorTick = Boolean('{[ showMinorTick ]}');
    const yAxisSplitLine = Boolean('{[ yAxisSplitLine ]}');
    const yAxisSplitLineType = ('{[ yAxisSplitLineType ]}').toString();
    const xAxisSplitLineType = ('{[ xAxisSplitLineType ]}').toString();
    const axisLabelFontsize = Number('{[ axisLabelFontsize ]}');
    let gridPadding = '{[ gridPadding ]}';
    const xLabelRotate = '{[ xLabelRotate ]}';
    const smooth = Boolean('{[ smooth ]}');
    const lineWidth = Number('{[ lineWidth ]}');
    const symbol = ('{[ symbol ]}').toString();
    const symbolSize = Number('{[ symbolSize ]}');
    const zoomStart = Number('{[ zoomStart ]}');
    const zoomEnd = Number('{[ zoomEnd ]}');
    const containLabel = Boolean('{[ containLabel ]}');
    const legendMap = ('{[ legendMap ]}').toString();
    const xLabelMap = ('{[ xLabelMap ]}').toString();
    const clickEvent = ('{[ clickEvent ]}').toString();
    const inLoader = Boolean('{[ inLoader ]}');
    let hiddenDimension = '{[ hiddenDimension ]}';
    const defaultData = JSON.parse('{[ defaultData ]}'.replace(/\\\"/g, "\""));
    
    let extraData = null;
    let extraIndex = -1;

    if (isNaN(Number(hiddenDimension))) {
      hiddenDimension = hiddenDimension.toString();
    } else {
      hiddenDimension = parseInt(hiddenDimension);
    }

    Boolean(bgColor) ? $(this).css({ backgroundColor: bgColor }) : $(this).css({ backgroundColor: 'transparent' });
    Boolean(borderColor) ? $(this).css({ borderColor: borderColor }) : $(this).css({ borderColor: 'transparent' });
    if (colors.indexOf(',') > -1) {
      colors = colors.split(',').map(item => item.trim())
    } else if (Boolean(colors)) {
      colors = [colors]
    }

    const grid = {
      containLabel: containLabel,
    };
    if (gridPadding.indexOf(',') > -1) {
      gridPadding = gridPadding.split(',').map(item => item.trim());
      grid.left = gridPadding[0];
      grid.top = gridPadding[1];
      grid.right = gridPadding[2] || gridPadding[0];
      grid.bottom = gridPadding[3] || gridPadding[1];
    } else if (Boolean(gridPadding)) {
      grid.left = gridPadding;
      grid.top = gridPadding;
      grid.right = gridPadding;
      grid.bottom = gridPadding;
    }

    const titlePositionArr = titlePosition.split(',');
    const title = {
      text: titleText,
      left: titlePositionArr[0],
      top: titlePosition.indexOf(',') > 0 ? titlePositionArr[1] : titlePositionArr[0],
      textStyle: {
        fontSize: 16,
        color: titleColor || fontColor
      }
    };

    const legendShow = legendOrient != 'null';
    const legend = {
      show: legendShow,
      type: 'scroll',
      icon: legendIcon,
      itemGap: legendItemGap,
      itemWidth: legendItemWidth,
      itemHeight: legendItemHeight,
      textStyle: {
        fontSize: legendFontSize,
        color: fontColor,
      }
    };
    if (Boolean(legendPosition)) {
      legendPosition.split(',').forEach((item, i) => {
        if (item.indexOf(':') > 0) {
          const key = item.split(':')[0].trim();
          const value = item.split(':')[1].trim();
          legend[`${key}`] = value;
        } else {
          legend[`${i ? 'top' : 'left'}`] = item.trim();
        }
      });
    }
    if (legendShow) {
      legend.orient = legendOrient;
    } else {
      legend.show = false;
    }
    let _legendMap;
    if (legendMap.indexOf(':') > 0) {
      _legendMap = {};
      let _legendArr;
      if (legendMap.indexOf(',') > 0) {
        _legendArr = legendMap.split(',');
      } else {
        _legendArr = [legendMap]
      }
      _legendArr.forEach(function (item) {
        if (item.indexOf(':') > 0) {
          const _item = item.trim().split(':').map(v => v.trim());
          _legendMap[_item[0].toString().toLocaleLowerCase()] = _item[1];
        }
      });
      legend.formatter = function (name) {
        return _legendMap[name.toString().toLocaleLowerCase()] || name
      }
    } else {
      legend.formatter = null
    }

    const labelShow = labelPosition != 'null'

    const serieTemp = {
      type: 'line',
      symbol: symbol,
      symbolSize: symbolSize,
      lineStyle: {
        width: lineWidth
      },
      label: {
        normal: {
          show: labelShow
        }
      },
      data: [],
      name: ""
    };

    if (smooth) {
      serieTemp.smooth = smooth;
    }
    if (labelShow) {
      serieTemp.label.normal.position = labelPosition
    }

    const xAxis = {
      name: xAxisName,
      nameTextStyle: {
        color: xAxisNameColor,
        fontSize: AxisNameFontSize,
      },
      boundaryGap: false,
      axisTick: {
        show: xAxisTick,
        length: axisTickLength,
        lineStyle: {
          width: axisLineWidth,
        },
      },
      minorTick: { show: showMinorTick, length: minorTickLength },
      axisLine: {
        lineStyle: {
          width: axisLineWidth,
          color: axisColor
        },
        onZero: false
      },
      axisLabel: {
        color: fontColor,
        fontSize: axisLabelFontsize,
        rotate: xLabelRotate
      },
      splitLine: {
        show: xAxisSplitLine,
        lineStyle: {
          color: axisColor,
          opacity: 0.4,
          type: xAxisSplitLineType
        }
      },
    };
    const yAxis = {
      type: 'value',
      name: yAxisName,
      nameTextStyle: {
        color: yAxisNameColor,
        fontSize: AxisNameFontSize,
      },
      axisTick: {
        show: yAxisTick,
        length: axisTickLength,
        lineStyle: {
          width: axisLineWidth,
        },
      },
      minorTick: { show: showMinorTick, length: minorTickLength },
      axisLine: {
        lineStyle: {
          width: axisLineWidth,
          color: axisColor
        },
        onZero: false
      },
      axisLabel: {
        fontSize: axisLabelFontsize,
        color: fontColor
      },
      splitLine: {
        show: yAxisSplitLine,
        lineStyle: {
          color: axisColor,
          opacity: 0.4,
          type: yAxisSplitLineType
        }
      }
    };
    yAxis.axisLabel.formatter = '{value}' + yAxisUnit;

    let _xLabelMap;
    if (xLabelMap.indexOf(':') > 0) {
      _xLabelMap = {};
      let _xLabelArr;
      if (xLabelMap.indexOf(',') > 0) {
        _xLabelArr = xLabelMap.split(',');
      } else {
        _xLabelArr = [xLabelMap]
      }
      _xLabelArr.forEach(function (item) {
        if (item.indexOf(':') > 0) {
          const _item = item.trim().split(':').map(v => v.trim());
          _xLabelMap[_item[0].toString().toLocaleLowerCase()] = _item[1];
        }
      });
      xAxis.axisLabel.formatter = function (name) {
        return _xLabelMap[name.toString().toLocaleLowerCase()] || name
      }
    } else {
      xAxis.axisLabel.formatter = null
    }

    const tooltip = {
      trigger: 'item',
      axisPointer: {
        type: 'line',
        lineStyle: {
          color: axisColor,
          opacity: 0.6
        }
      }
    };
    if (_xLabelMap || _legendMap) {
      tooltip.formatter = function (params) {
        if (params.length) {
          const xAxisName = _xLabelMap ? _xLabelMap[params[0].name.toString().toLocaleLowerCase()] || params[0].name : params[0].name;
          const list = params.map(function (item, index) {
            const seriesName = _legendMap ? _legendMap[item.seriesName.toString().toLocaleLowerCase()] || item.seriesName : item.seriesName;
            return "<br /><span style='display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:" + item.color + "'></span>" + seriesName + ": " + item.data[index+1]
          })
          return xAxisName + list.join(' ')
        }
      }
    }

    const dataZoom = [
      {
        show: false,
        // borderColor: fontColor,
        start: zoomStart,
        end: zoomEnd
      }, {
        type: 'inside',
        start: zoomStart,
        end: zoomEnd
      }
    ];
    if (zoomStart < 0 || zoomEnd < 100) {
      dataZoom[1].disabled = true
    } else {
      dataZoom[1].disabled = false
    }

    // const defaultSource = [['x', 'y', 'category'],[15, 15, 'a'],[19.5, 15, 'a'],[19.5, 40, 'a'],[15,40, 'a'],[15,15, 'a'],[20, 15, 'b'],[20, 60, 'b'], [25, 60, 'b'], [29, 50, 'b'], [29, 15, 'b'], [20, 15, 'b']];

    const self = this;
    const _id = self.getAttribute('id');
    const eventName = `call-${_id}`;
    const myChart = window.echarts.init(self);
    inLoader ? $(self).attr('loader', 'in') : $(self).removeAttr('loader');
    
    function transferData(source) {
      let datas = {};
      $.each(source, function(index, arr) {
        if (index !== 0) {
          const coordinate = arr.slice(0);
          coordinate.pop();
          if (datas.hasOwnProperty(arr[2])) {
            datas[arr[2]].push(coordinate);
          } else {
            datas[arr[2]] = [coordinate];
          }
        }
      });
      return datas;
    }

    function initChart(source) {
      myChart.clear()
      const data = transferData(source);
      const series = Object.keys(data).map(function (item, index) {
        const serieLineFinal = JSON.parse(JSON.stringify(serieTemp));
        serieLineFinal.data = data[item];
        serieLineFinal.name = item;
        return serieLineFinal
      });
      const option = {
        title: title,
        tooltip: tooltip,
        legend: legend,
        grid: grid,
        xAxis: xAxis,
        yAxis: yAxis,
        dataZoom: dataZoom,
        series: series
      };

      if (Boolean(colors)) option.color = colors;

      myChart.setOption(option);
      myChart.resize();

      if (window.prevEventType && window.prevEventType[eventName]) {
        myChart.off(window.prevEventType[eventName]);
      }
      if (clickEvent != 'null') {
        myChart.on(clickEvent, function (params) {
          var _data = params.data;
          if (extraIndex > -1 && extraData && extraData.length) {
            _data.splice(extraIndex, 0, extraData[params.dataIndex + 1]);
          }
          if (window.spSocket && clickEvent != 'null') {
            inLoader && window.loader && window.loader.add(_id);
            window.spSocket.send({
              eventName: eventName,
              data: {
                success: true,
                out1: JSON.stringify(_data)
              }
            });
          }
        });
        if (!window.prevEventType) {
          window.prevEventType = {};
        }
        window.prevEventType[eventName] = clickEvent;
      }
    }

    initChart(defaultData);

    window.addEventListener('resize', function () {
      myChart.resize();
    }, false)
    let hasTransfer = false;
    // 有 dashboardHost 说明是运行模式
    if (window.spSocket) {
      inLoader && window.loader && $(self).append($(window.loader.ele));
      window.spSocket.subscribe({
        eventName: eventName,
        callback: function (_data) {
          let _in1Str = _data.data.in1;
          if (_in1Str) {
            const data = JSON.parse(_in1Str);
            let source = data;
            if (hiddenDimension) {
              extraIndex = isNaN(hiddenDimension) ? data[0].indexOf(hiddenDimension) : hiddenDimension;
              if (extraIndex > -1) {
                extraData = [];
                source = data.map(function(row) {
                  extraData.push(row[extraIndex]);
                  row.splice(extraIndex, 1);
                  return row;
                });
              }
            }
            inLoader && window.loader && window.loader.remove(_id);
            if (!hasTransfer) {
              initChart(source);
              hasTransfer = true
            } else {
              myChart.setOption({
                dataset: {
                  source: source
                }
              })
            }
          }
        }
      });
    }

    Boolean(dataSource) && $.get(dataSource, function (ds) {
      myChart.hideLoading();
      initChart(JSON.parse(ds))
    });
  },

  onViewInit() {
    this.updateScript();
    const evn = echartsBasicListen + `
      change:defaultData
      change:xAxisNameColor
      change:yAxisNameColor
      change:AxisNameFontSize
      change:xAxisTick
      change:showMinorTick
      change:yAxisTick
      change:yAxisSplitLineType
      change:xAxisSplitLineType
      change:axisTickLength
      change:minorTickLength
      change:yAxisUnit
      change:xAxisName
      change:yAxisName
      change:axisColor
      change:axisLineWidth
      change:xAxisSplitLine
      change:yAxisSplitLine
      change:axisLabelFontsize
      change:gridPadding
      change:containLabel
      change:labelPosition
      change:labelFormatter
      change:xLabelRotate
      change:smooth
      change:lineWidth
      change:symbol
      change:symbolSize
      change:zoomStart
      change:zoomEnd
      change:xLabelMap
      change:inLoader
      change:hiddenDimension
      change:clickEvent
    `;
    this.listenTo(this.model, evn, this.updateScript);
    this.listenTo(this.model, evn, this.em.handleUpdates.bind(this.em));
    this.listenTo(this.em, 'update:component:style:height update:component:style:width', throttle.bind(this, this.updateScript.bind(this)));
  }
}
