import { oscilloscope, CATEGORIES } from '../../configuration/constants'
import { throttle } from '../../utils'

export default {

  // 组件名称
  name: oscilloscope,

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

  // 编辑器右侧块管理器中显示属性配置
  blockOptions() {
    return {
      category: CATEGORIES.ECHARTS,
      label: `
      <svg  class="gjs-block-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" ><path d="M408.533 425.173l256.64 213.76 333.44-455.68-34.56-25.173-306.56 418.987-255.36-212.907-248.32 315.947 33.707 26.453 221.013-281.387z" p-id="36183"></path><path d="M42.667 896V85.333H0v853.334h1024V896H42.667z" ></path></svg>
        <div class="gjs-block-label">示波器</div>
      `,
    };
  },

  // 后面板显示属性配置
  spOptions() {
    return {
      label: '示波器',
      icon: 'globe',
      docUrl: 'https://xuelangyun.yuque.com/docs/share/eb810c90-0a58-4b59-a861-f43c9a6e94a8?# 《示波器》',
      author: '秋水',
      email: 'qiushui.smy@xuelangyun.com',
      inPorts: [{
        uuid: 'in1',
        subType: 'json',
        description: {
          zh_CN: '输入1'
        }
      }]
    }
  },

  // 组件属性
  componentOptions() {
    return {
      name: oscilloscope,
      resizable: true,
      dmode: 'absolute',
      droppable: false,
      traits: [
        {
          name: 'gridPadding',
          label: '容器边距(左,上,右,下)',
          changeProp: 1
        }, {
          type: 'color',
          name: 'fontColor',
          label: '字体颜色',
          changeProp: 1,
        }, {
          type: 'number',
          name: 'fontSize',
          label: '字号',
          changeProp: 1,
          min: 10,
          step: 1
        }, {
          name: 'colors',
          label: '图表色系',
          changeProp: 1,
        }, {
          name: 'legendPosition',
          label: '图例位置',
          changeProp: 1,
          type: 'key-value',
          maxLength: 2
        }, {
          name: 'legendFontSize',
          label: '图例字号',
          changeProp: 1,
          type: 'number',
          min: 8
        }, {
          name: 'legendFontFamily',
          label: '图例字体',
          changeProp: 1,
          type: 'select',
          options: [
            { id: 'sans-serif', name: '默认' },
            { id: '庞门正道', name: '庞门正道' },
            { id: 'DS-Digital', name: 'DS-Digital' }
          ]
        }, {
          name: 'legendItemGap',
          label: '图例间隔',
          changeProp: 1,
          type: 'number',
          min: 4
        }, {
          name: 'legendIcon',
          label: '图例标记类型',
          changeProp: 1,
          type: 'select',
          options: [
            { id: 'auto', 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: 'legendItemWidth',
          label: '图例标记宽度',
          changeProp: 1,
          type: 'number',
          min: 4
        }, {
          name: 'legendItemHeight',
          label: '图例标记高度',
          changeProp: 1,
          type: 'number',
          min: 4
        }, {
          name: 'maxLength',
          label: '最大数据量',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 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: 'customHeader',
          label: '自定义表头',
          changeProp: 1,
        }, {
          name: 'xDimension',
          label: 'X轴维度',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'yDimension',
          label: 'Y轴维度',
          changeProp: 1,
        }, {
          name: 'xAxisType',
          label: 'x轴类型',
          changeProp: 1,
          type: 'select',
          options: [{ name: "类目轴", id: "category" }, { name: "数据轴", id: "value" }]
        }, {
          name: 'yAxisType',
          label: 'y轴类型',
          changeProp: 1,
          type: 'select',
          options: [{ name: "类目轴", id: "category" }, { name: "数据轴", id: "value" }]
        }, {
          name: 'xAxisName',
          label: 'x轴名称',
          changeProp: 1
        }, {
          name: 'yAxisName',
          label: 'y轴名称',
          changeProp: 1
        }, {
          name: 'yMax',
          label: 'Y轴最小尺度',
          changeProp: 1,
          type: "number"
        }, {
          name: 'axisColor',
          label: '坐标轴颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'axisLineWidth',
          label: '坐标轴线宽',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        }, {
          name: 'xAxisTick',
          label: 'X轴刻度线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxisTick',
          label: 'Y轴刻度线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'splitLineColor',
          label: '分割线颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'xSplitLine',
          label: 'x轴分割线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'xSplitLineType',
          label: 'x轴分割线类型',
          type: 'select',
          changeProp: 1,
          options: [{ id: 'solid', name: '实线' }, { id: 'dashed', name: '虚线' }, { id: 'dotted', name: '点线' }]
        }, {
          name: 'xSplitArea',
          label: 'x轴分割区域',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'xSplitAreaInterval',
          label: 'x轴分割区域间隔',
          changeProp: 1,
        }, {
          name: 'xSplitAreaColors',
          label: 'x轴分割区域颜色',
          changeProp: 1,
        }, {
          name: 'ySplitLine',
          label: 'y轴分割线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'ySplitLineType',
          label: 'y轴分割线类型',
          type: 'select',
          changeProp: 1,
          options: [{ id: 'solid', name: '实线' }, { id: 'dashed', name: '虚线' }, { id: 'dotted', name: '点线' }]
        }, {
          name: 'ySplitArea',
          label: 'y轴分割区域',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'ySplitAreaColors',
          label: 'y轴分割区域颜色',
          changeProp: 1,
        }, {
          name: 'zoomStart',
          label: '放大镜开始(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'zoomEnd',
          label: '放大镜结束(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'csv',
          label: '示例数据',
          changeProp: 1,
          type: 'csvDownload',
          preFileName: '线形图',
          datas: [["x", "y"], [1, 2], [2, 5], [3, 4], [4, 1], [5, 7]]
        }, {
          name: 'defaultData',
          changeProp: 1,
          type: 'hide'
        }
      ],
      defaultData: JSON.stringify([
        ["x", "y"],
        [1, 2],
        [2, 5],
        [3, 4],
        [4, 1],
        [5, 7]
      ]).replace(/\"/g, "\\\""),
      'gridPadding': '6%,40,6%,40',
      'fontColor': '#333',
      'fontSize': 14,
      'colors': '#0084ff, #339cff',
      "legendPosition": "left: center, bottom: bottom",
      "legendOrient": "horizontal",
      "legendFontSize": 12,
      "legendFontFamily": "sans-serif",
      "legendIcon": "roundRect",
      "legendItemGap": 10,
      "legendItemWidth": 25,
      "legendItemHeight": 14,
      'maxLength': 20,
      'customHeader': null,
      'xDimension': 0,
      'yDimension': '1',
      'smooth': false,
      'lineWidth': 1,
      'symbol': 'emptyCircle',
      'symbolSize': 4,
      'xAxisName': null,
      'yAxisName': null,
      'xAxisType': 'category',
      'yAxisType': 'value',
      'axisColor': '#000',
      'axisLineWidth': 1,
      'splitLineColor': '#d9d9d9',
      'xAxisTick': true,
      'xSplitLine': true,
      'xSplitLineType': 'solid',
      'xSplitArea': false,
      'xSplitAreaInterval': 'auto',
      'xSplitAreaColors': 'rgba(250,250,250,0.3); rgba(200,200,200,0.3)',
      'yAxisTick': true,
      'ySplitLine': true,
      'ySplitLineType': 'dashed',
      'ySplitArea': false,
      'ySplitAreaColors': 'rgba(250,250,250,0.3); rgba(200,200,200,0.3)',
      'zoomStart': -1,
      'zoomEnd': 100,
      'clickEvent': 'null',
    }
  },

  onModelScript() {
    const maxLength = Boolean('{[ maxLength ]}') ? Number('{[ maxLength ]}') : 0;
    let customHeader = Boolean('{[ customHeader ]}') && ('{[ customHeader ]}').toString();
    const xDimension = Boolean('{[ xDimension ]}') ? Number('{[ xDimension ]}') : 0;
    let yDimension = Boolean('{[ yDimension ]}') ? ('{[ yDimension ]}').toString() : 1;
    const fontColor = '{[ fontColor ]}';
    const fontSize = Number('{[ fontSize ]}');
    let colors = '{[ colors ]}';
    let gridPadding = '{[ gridPadding ]}';
    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 legendFontFamily = ('{[ legendFontFamily ]}').toString();
    const smooth = Boolean('{[ smooth ]}');
    const lineWidth = Number('{[ lineWidth ]}');
    const symbol = ('{[ symbol ]}').toString();
    const symbolSize = Number('{[ symbolSize ]}');
    const xAxisName = '{[ xAxisName ]}';
    const yAxisName = '{[ yAxisName ]}';
    const yMax = '{[ yMax ]}';
    const xAxisType = ('{[ xAxisType ]}').toString();
    const yAxisType = ('{[ yAxisType ]}').toString();
    const axisColor = '{[ axisColor ]}';
    const axisLineWidth = Number('{[ axisLineWidth ]}');
    const splitLineColor = '{[ splitLineColor ]}';
    const xAxisTick = Boolean('{[ xAxisTick ]}');
    const yAxisTick = Boolean('{[ yAxisTick ]}');
    const xSplitLine = Boolean('{[ xSplitLine ]}');
    const xSplitLineType = ('{[ xSplitLineType ]}').toString();
    const xSplitArea = Boolean('{[ xSplitArea ]}');
    const xSplitAreaInterval = ('{[ xSplitAreaInterval ]}').toString();
    let xSplitAreaColors = ('{[ xSplitAreaColors ]}').toString();
    const ySplitLine = Boolean('{[ ySplitLine ]}');
    const ySplitLineType = ('{[ ySplitLineType ]}').toString();
    const ySplitArea = Boolean('{[ ySplitArea ]}');
    let ySplitAreaColors = ('{[ ySplitAreaColors ]}').toString();
    const zoomStart = Number('{[ zoomStart ]}');
    const zoomEnd = Number('{[ zoomEnd ]}');
    const defaultData = JSON.parse('{[ defaultData ]}'.replace(/\\\"/g, "\""));
    let source = [];

    const getArrayFromString = function (str, separator) {
      let _arr;
      if (str.indexOf(separator) > -1) {
        _arr = str.split(separator).map(item => item.trim())
      } else if (Boolean(str)) {
        _arr = [str]
      }
      return _arr;
    };
    colors = getArrayFromString(colors, ',');
    xSplitAreaColors = getArrayFromString(xSplitAreaColors, ';');
    ySplitAreaColors = getArrayFromString(ySplitAreaColors, ';');
    if (customHeader) {
      customHeader = getArrayFromString(customHeader, ',');
    }
    if (yDimension.indexOf(',') > 0) {
      yDimension = yDimension.split(',').map(item => {
        return isNaN(Number(item)) ? item.trim() : Number(item)
      });
    } else {
      yDimension = isNaN(Number(yDimension)) ? [yDimension] : [Number(yDimension)];
    }
    const grid = {
      containLabel: true
    };
    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 xAxis = {
      type: xAxisType,
      name: xAxisName,
      boundaryGap: false,
      scale: xAxisType == 'value',
      nameTextStyle: {
        fontSize: Math.floor(fontSize * 8 / 10)
      },
      axisTick: {
        show: xAxisTick,
        lineStyle: {
          width: axisLineWidth,
        }
      },
      axisLine: {
        lineStyle: {
          width: axisLineWidth,
          color: axisColor
        }
      },
      axisLabel: {
        color: fontColor,
        fontSize: fontSize
      },
      splitLine: {
        show: xSplitLine,
        lineStyle: {
          color: splitLineColor,
          type: xSplitLineType
        }
      },
      splitArea: {
        interval: xSplitAreaInterval || 'auto',
        show: xSplitArea,
        areaStyle: {
          color: xSplitAreaColors,
        }
      },
      animation: false,
    };
    const yAxis = {
      type: yAxisType,
      name: yAxisName,
      nameTextStyle: {
        fontSize: Math.floor(fontSize * 8 / 10)
      },
      axisTick: {
        show: yAxisTick,
        lineStyle: {
          width: axisLineWidth,
        }
      },
      axisLine: {
        lineStyle: {
          width: axisLineWidth,
          color: axisColor
        }
      },
      axisLabel: {
        fontSize: fontSize,
        color: fontColor
      },
      splitLine: {
        show: ySplitLine,
        lineStyle: {
          color: splitLineColor,
          type: ySplitLineType
        }
      },
      splitArea: {
        show: ySplitArea,
        areaStyle: {
          color: ySplitAreaColors,
        }
      },
      animation: false,
    };
    if (yMax) yAxis.max = function(value) {
      return Math.max(value.max, yMax)
    };
    if (yMax) yAxis.max = function(value) {
      return Math.max(value.max, yMax)
    };

    const tooltip = {
      trigger: 'axis',
      textStyle: {
        fontSize: fontSize
      },
      axisPointer: {
        type: 'line',
        lineStyle: {
          color: splitLineColor,
          opacity: 0.6
        }
      }
    };

    const dataZoom = [
      {
        show: false,
        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 legendShow = legendOrient != 'null';
    const legend = {
      show: legendShow,
      type: 'scroll',
      itemGap: legendItemGap,
      itemWidth: legendItemWidth,
      itemHeight: legendItemHeight,
      textStyle: {
        fontFamily: legendFontFamily,
        fontSize: legendFontSize || fontSize,
        color: fontColor,
      }
    };
    if (legendIcon !== 'auto') {
      legend.icon = legendIcon;
    }
    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;
    }

    const serieTemp = {
      type: 'line',
      symbol: symbol,
      symbolSize: symbolSize,
      lineStyle: {
        width: lineWidth
      }
    };

    if (smooth) {
      serieTemp.smooth = smooth;
    }

    const self = this;
    const _id = self.getAttribute('id');
    const eventName = `call-${_id}`;
    const myChart = window.echarts.init(self);

    function initChart(source) {
      myChart.clear();
      const series = yDimension.map(item => {
        return Object.assign({}, serieTemp, {
          encode: {
            x: xDimension,
            y: item,
            seriesName: item
          }
        });
      })
      const option = {
        tooltip: tooltip,
        grid: grid,
        legend: legend,
        xAxis: xAxis,
        yAxis: yAxis,
        dataset: {
          source: source
        },
        dataZoom: dataZoom,
        series
      };
      if (customHeader) option.dataset.dimensions = customHeader;

      if (Boolean(colors)) option.color = colors;
      myChart.setOption(option);
      myChart.resize();
    }

    initChart(defaultData);

    window.addEventListener('resize', function () {
      myChart.resize();
    }, false)
    let hasTransfer = false;
    // 有 dashboardHost 说明是运行模式
    if (window.spSocket) {
      window.spSocket.subscribe({
        eventName: eventName,
        callback: function (_data) {
          if (_data.data.in1) {
            const data = JSON.parse(_data.data.in1);

            if (data.length) {
              // 接收到二维数组，作为全量数据
              if (data[0] instanceof Array) {
                source = data;
              } else {
                // 接收到坐标，作为增量数据
                source.push(JSON.parse(_data.data.in1));
              }
            }

            if (source.length > maxLength) {
              source.shift();
            }
            if (!hasTransfer) {
              initChart(source);
              hasTransfer = true
            } else {
              myChart.setOption({
                dataset: {
                  source: source
                }
              })
            }
          }
        }
      });
    }
  },

  onViewInit() {
    this.updateScript();
    const evn = `
    change:defaultData
    change:gridPadding
    change:fontSize
    change:fontColor
    change:colors
    change:legendPosition
    change:legendOrient
    change:legendIcon
    change:legendItemGap
    change:legendItemWidth
    change:legendItemHeight
    change:legendFontSize
    change:legendFontFamily
    change:maxLength
    change:customHeader
    change:xDimension
    change:yDimension
    change:xAxisName
    change:yAxisName
    change:xAxisType
    change:yMax
    change:yAxisType
    change:xAxisTick
    change:yAxisTick
    change:axisColor
    change:axisLineWidth
    change:splitLineColor
    change:xSplitLine
    change:xSplitLineType
    change:xSplitArea
    change:xSplitAreaInterval
    change:xSplitAreaColors
    change:ySplitLine
    change:ySplitLineType
    change:ySplitArea
    change:ySplitAreaColors
    change:smooth
    change:lineWidth
    change:symbol
    change:symbolSize
    change:zoomStart
    change:zoomEnd`;
    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)));
  }
}
