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

export default {

  // 组件名称
  name: barChart,

  // 前面板html模板
  viewTemplate() {
    return `
      <div data-gjs-type="${barChart}" class="${barChart}"></div>
    `
  },
  // 前面板html样式
  viewStyle() {
    return `
      <style>
        .${barChart} {
          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" version="1.1" xmlns="http://www.w3.org/2000/svg" ><path d="M117.333333 85.333333a32 32 0 0 1 32 32v757.333334h757.333334a32 32 0 0 1 0 64H117.333333a32 32 0 0 1-32-32V117.333333a32 32 0 0 1 32-32z" ></path><path d="M234.666667 458.666667h85.333333a21.333333 21.333333 0 0 1 21.333333 21.333333v320a21.333333 21.333333 0 0 1-21.333333 21.333333h-85.333333a21.333333 21.333333 0 0 1-21.333334-21.333333V480a21.333333 21.333333 0 0 1 21.333334-21.333333z m341.333333-106.666667h85.333333a21.333333 21.333333 0 0 1 21.333334 21.333333v426.666667a21.333333 21.333333 0 0 1-21.333334 21.333333h-85.333333a21.333333 21.333333 0 0 1-21.333333-21.333333V373.333333a21.333333 21.333333 0 0 1 21.333333-21.333333zM405.333333 213.333333h85.333334a21.333333 21.333333 0 0 1 21.333333 21.333334v565.333333a21.333333 21.333333 0 0 1-21.333333 21.333333h-85.333334a21.333333 21.333333 0 0 1-21.333333-21.333333V234.666667a21.333333 21.333333 0 0 1 21.333333-21.333334z m341.333334 362.666667h85.333333a21.333333 21.333333 0 0 1 21.333333 21.333333v202.666667a21.333333 21.333333 0 0 1-21.333333 21.333333h-85.333333a21.333333 21.333333 0 0 1-21.333334-21.333333V597.333333a21.333333 21.333333 0 0 1 21.333334-21.333333z" ></path></svg>
        <div class="gjs-block-label">柱形图</div>
      `,
    };
  },

  // 后面板显示属性配置
  spOptions() {
    return {
      label: '柱形图',
      icon: 'globe',
      docUrl: 'https://www.yuque.com/docs/share/dd441d30-d832-435d-a8a9-a0620820c5cd#',
      author: '秋水',
      email: 'qiushui.smy@xuelangyun.com',
      inPorts: [
        {
          uuid: 'in1',
          subType: 'json',
          description: {
            zh_CN: '输入1'
          }
        }],
      outPorts: [{
        uuid: 'out1',
        subType: 'json',
        description: {
          zh_CN: '输出1'
        }
      }
      ]
    }
  },

  // 组件属性
  componentOptions() {
    return {
      name: barChart,
      resizable: true,
      dmode: 'absolute',
      droppable: false,
      traits: [
        {
          name: 'xAxisName',
          label: 'X轴名称',
          changeProp: 1
        }, {
          name: 'yAxisName',
          label: 'Y轴名称',
          changeProp: 1
        }, {
          name: 'yAxisNamePosition',
          label: 'Y轴名称位置',
          changeProp: 1,
          type: 'select',
          options: [{ id: 'start', name: '开始' }, { id: 'center', name: '中间' }, { id: 'end', name: '末尾' }]
        }, {
          name: 'axisNameFontsize',
          label: '轴名称字号',
          changeProp: 1,
          type: 'number',
          min: 9,
          step: 1
        }, {
          name: 'yAxisUnit',
          label: 'Y轴单位',
          changeProp: 1
        }, {
          name: 'yAxis2Show',
          label: '双Y轴',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxis1DataIndex',
          label: '数据索引(y轴0)',
          changeProp: 1,
        }, {
          name: 'xAxisLine',
          label: 'X轴线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxisLine',
          label: 'Y轴线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'xaxisColor',
          label: 'X轴线颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'yaxisColor',
          label: 'Y轴线颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'axisLineWidth',
          label: '坐标轴线宽',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        }, {
          name: 'axisSplitLineColor',
          label: '分割线颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'axisSplitLineType',
          label: '分割线类型',
          changeProp: 1,
          type: 'select',
          options: [{ id: 'solid', name: '实线' }, { id: 'dashed', name: '虚线' }, { id: 'dotted', name: '点线' }]
        }, {
          name: 'xAxisSplitLine',
          label: 'X轴分割线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxisSplitLine',
          label: 'Y轴分割线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'xAxisTick',
          label: 'X轴刻度线',
          changeProp: 1,
          type: 'checkbox'
        },
        {
          name: 'xAxisLabelShow',
          label: 'X轴刻度值显示',
          changeProp: 1,
          type: 'checkbox'
        },
        {
          name: 'yAxisLabelShow',
          label: 'y轴刻度值显示',
          changeProp: 1,
          type: 'checkbox'
        },
        {
          name: 'splitNumber',
          label: 'y轴分隔段数',
          changeProp: 1,
          type: 'number',
          min: 1,
          step: 1
        },
        {
          name: 'max',
          label: 'y轴最大值',
          changeProp: 1,
          type: 'number'
        },
        {
          name: 'thanMax',
          label: '大于最大值',
          changeProp: 1,
          type: 'checkbox'
        },
        {
          name: 'axisLabelFontsize',
          label: '刻度值字号',
          changeProp: 1,
          type: 'number',
          min: 9,
          step: 1
        }, {
          name: 'axisLabelFontFamily',
          label: '刻度值字体',
          changeProp: 1,
          type: 'select',
          options: [
            { id: 'sans-serif', name: '默认' },
            { id: '庞门正道', name: '庞门正道' },
            { id: 'DS-Digital', name: 'DS-Digital' }
          ]
        }, {
          name: 'xAxisInterval',
          label: 'X轴刻度标签间隔(自动)',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'yAxisTick',
          label: 'Y轴刻度线',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'gridPadding',
          label: '容器边距(左,上,右,下)',
          changeProp: 1
        }, {
          name: 'containLabel',
          label: '包含刻度标签',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'xLabelRotate',
          label: 'X轴标签旋转',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'xLabelMap',
          label: 'X轴标签映射',
          changeProp: 1,
        },
        {
          name: 'xLabelInside',
          label: 'X轴标签朝向',
          changeProp: 1,
          type: 'checkbox'
        },
        {
          name: 'xLabelVerticalAlign',
          label: 'X轴标签垂直对齐方式',
          changeProp: 1,
          type: 'select',
          options: [
            {id: "null", name: "默认"},
            {id: "top", name: "顶部"},
            {id: "middle", name: "中间"},
            {id: "bottom", name: "底部"}
          ]
        },
        {
          name: 'xLabellineHeight',
          label: 'X轴标签行高',
          changeProp: 1,
          type: 'number'
        },
        {
          name: 'borderRadius',
          label: '柱形圆角',
          changeProp: 1
        }, {
          name: 'barWidth',
          label: '柱宽',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'barGap',
          label: '柱间距(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'shadowColor',
          label: '阴影颜色',
          changeProp: 1,
        }, {
          name: 'shadowBlur',
          label: '阴影模糊',
          changeProp: 1,
          type: 'number',
          step: 1,
        }, {
          name: 'shadowOffsetX',
          label: '阴影水平偏移',
          changeProp: 1,
          type: 'number',
          step: 1
        }, {
          name: 'shadowOffsetY',
          label: '阴影垂直偏移',
          changeProp: 1,
          type: 'number',
          step: 1
        }, {
          name: 'stack',
          label: '数据堆叠',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'labelPosition',
          label: '标签',
          type: 'select',
          changeProp: 1,
          options: [
            { id: 'null', name: '无标签' },
            { id: 'top', name: '上' },
            { id: 'left', name: '左' },
            { id: 'right', name: '右' },
            { id: 'bottom', name: '下' },
            { id: 'inside', name: '内部' },
            { id: 'insideLeft', name: '内部左侧' },
            { id: 'insideRight', name: '内部右侧' },
            { id: 'insideTop', name: '内部上侧' },
            { id: 'insideBottom', name: '内部下侧' },
            { id: 'insideTopRight', name: '内部右上侧' },
            { id: 'insideBottomRight', name: '内部右下侧' },
            { id: 'insideTopLeft', name: '内部左上侧' },
            { id: 'insideBottomLeft', name: '内部左下侧' }
          ]
        }, {
          name: 'labelFormatter',
          label: '标签内容格式',
          changeProp: 1,
        }, {
          name: 'labelDistance',
          label: '标签边距',
          changeProp: 1,
          type: 'number',
        }, {
          name: 'labelFontsize',
          label: '标签字号',
          changeProp: 1,
          type: 'number',
          min: 9,
        }, {
          name: 'labelFontFamily',
          label: '标签字体',
          changeProp: 1,
          type: 'select',
          options: [
            { id: 'sans-serif', name: '默认' },
            { id: '庞门正道', name: '庞门正道' },
            { id: 'DS-Digital', name: 'DS-Digital' }
          ]
        }, {
          name: 'labelColor',
          label: '标签颜色',
          changeProp: 1,
          type: 'color',
        }, {
          name: 'zoomStart',
          label: '放大镜开始(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'zoomEnd',
          label: '放大镜结束(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'axisType',
          label: '坐标轴对换',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'gradient',
          label: '柱形渐变',
          changeProp: 1,
          type: 'select',
          options: [{ id: 'none', name: '无' }, { id: 'line::0-0-0-1', name: '↓' }, { id: 'line::0-1-0-0', name: '↑' }, { id: 'line::0-0-1-0', name: '→' }, { id: 'line::1-0-0-0', name: '←' }, { id: 'line::0-0-1-1', name: '↘' }, { id: 'line::1-0-0-1', name: '↙' }, { id: 'line::0-1-1-0', name: '↗' }, { id: 'line::1-1-0-0', name: '↖' }]
        }, {
          name: 'positiveGradientColors',
          label: '正数渐变颜色',
          changeProp: 1,
        }, {
          name: 'negativeGradientColors',
          label: '负数渐变颜色',
          changeProp: 1,
        }, {
          name: 'hiddenDimension',
          label: '非渲染数据维度',
          changeProp: 1,
        }, {
          name: 'showBackground',
          label: '柱形背景',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'barBgColor',
          label: '柱形背景颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'barBgBorderRadius',
          label: '柱形背景圆角',
          changeProp: 1,
          type: 'number'
        }, {
          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: [["name", "A", "B", "C"], ["one", 1, 4, 3], ["two", 2, 3, 1], ["three", 3, 0, 5], ["four", 4, 5, 9], ["five", 5, 2, 6]]
        }, {
          name: 'defaultData',
          changeProp: 1,
          type: 'hide'
        }
      ],
      defaultData:JSON.stringify([
        ["name", "A", "B", "C"],
        ["one", 1, 4, 3],
        ["two", 2, 3, 1],
        ["three", 3, 0, 5],
        ["four", 4, 5, 9],
        ["five", 5, 2, 6]
      ]).replace(/\"/g, "\\\""),
      'xAxisName': null,
      'yAxisName': null,
      'yAxisNamePosition': 'end',
      'axisNameFontsize': 12,
      'yAxisUnit': null,
      'yAxis2Show': false,
      'yAxis1DataIndex': '0,1',
      'axisLineWidth': 1,
      'xaxisColor': '#333333',
      'yaxisColor': '#333333',
      'axisSplitLineColor': '#333333',
      'xAxisLabelShow': true,
      'yAxisLabelShow': true,
      'axisLabelFontsize': 12,
      'axisLabelFontFamily': 'sans-serif',
      'xAxisLine': true,
      'xAxisSplitLine': false,
      'xAxisTick': true,
      'xAxisInterval': true,
      'yAxisLine': true,
      'yAxisSplitLine': true,
      'axisSplitLineType': 'dashed',
      'yAxisTick': true,
      'splitNumber': 5,
      'thanMax': false,
      'gridPadding': '10%,60,10%,60',
      'containLabel': true,
      'labelPosition': 'null',
      'labelFormatter': '{c}',
      'labelDistance': 5,
      'labelFontFamily': "sans-serif",
      'labelFontsize': 12,
      'labelColor': '#333333',
      'borderRadius': '0',
      'xLabelRotate': null,
      'xLabelInside': false,
      'xLabelVerticalAlign': 'null',
      'xLabellineHeight': '',
      'xLabelMap': '',
      'barWidth': null,
      'barGap': '30',
      'shadowBlur': 0,
      'shadowOffsetX': 0,
      'shadowOffsetY': 0,
      'stack': false,
      'zoomStart': -1,
      'zoomEnd': 100,
      'axisType': false,
      'gradient': 'none',
      'gradientColors': '#59B5FF|#2263BD::#FF9793|#E7504C::#AE60FA|#6D32C1::#EFCE49|#D79C12::#FFB058|#C56625::#4ACC88|#27A657::#2C989E|#27BCC9::#8A98FF|#2B36A8',
      'showBackground': false,
      'barBgColor': 'rgba(180, 180, 180, 0.2)',
      'barBgBorderRadius': 0,
      'positiveGradientColors': '#59B5FF|#2263BD::#FF9793|#E7504C::#AE60FA|#6D32C1::#EFCE49|#D79C12::#FFB058|#C56625::#4ACC88|#27A657::#2C989E|#27BCC9::#8A98FF|#2B36A8',
      'negativeGradientColors': '#59B5FF|#2263BD::#FF9793|#E7504C::#AE60FA|#6D32C1::#EFCE49|#D79C12::#FFB058|#C56625::#4ACC88|#27A657::#2C989E|#27BCC9::#8A98FF|#2B36A8',
      'inLoader': false,
      'hiddenDimension': null,
      'clickEvent': 'null'
    }
  },

  onModelScript() {
    const dataSource = '{[ dataSource ]}';
    const bgColor = '{[ bgColor ]}';
    const borderColor = '{[ borderColor ]}';
    const fontColor = '{[ fontColor ]}';
    const fontSize = Number('{[ fontSize ]}');
    let colors = '{[ colors ]}';
    let shadowColor = '{[ shadowColor ]}';
    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 labelPosition = ('{[ labelPosition ]}').toString();
    const labelFontFamily = ('{[ labelFontFamily ]}').toString();
    const labelFontsize = Number('{[ labelFontsize ]}');
    const labelFormatter = '{[ labelFormatter ]}';
    const labelDistance = Boolean('{[ labelDistance ]}') ? Number('{[ labelDistance ]}') : 0;
    const labelColor = '{[ labelColor ]}';
    const titleText = '{[ titleText ]}';
    const titleColor = '{[ titleColor ]}';
    const titlePosition = ('{[ titlePosition ]}').toString();
    const xAxisName = '{[ xAxisName ]}';
    let yAxisName = '{[ yAxisName ]}'.toString();
    const yAxisNamePosition = '{[ yAxisNamePosition ]}'.toString();
    const axisNameFontsize = Number('{[ axisNameFontsize ]}');
    const axisLineWidth = Number('{[ axisLineWidth ]}');
    let yAxisUnit = ('{[ yAxisUnit ]}').toString();
    const yAxis2Show = Boolean('{[ yAxis2Show ]}');
    const thanMax = Boolean('{[ thanMax ]}');
    let yAxis1DataIndex = '{[ yAxis1DataIndex ]}'.toString();
    const xaxisColor = '{[ xaxisColor ]}';
    const yaxisColor = '{[ yaxisColor ]}';
    const axisSplitLineColor = '{[ axisSplitLineColor ]}';
    const xAxisLine = Boolean('{[ xAxisLine ]}');
    const xAxisSplitLine = Boolean('{[ xAxisSplitLine ]}');
    const xAxisTick = Boolean('{[ xAxisTick ]}');
    const xAxisInterval = Boolean('{[ xAxisInterval ]}');
    const yAxisLine = Boolean('{[ yAxisLine ]}');
    const yAxisSplitLine = Boolean('{[ yAxisSplitLine ]}');
    const axisSplitLineType = ('{[ axisSplitLineType ]}').toString();
    const yAxisTick = Boolean('{[ yAxisTick ]}');
    const xAxisLabelShow = Boolean('{[ xAxisLabelShow ]}');
    const yAxisLabelShow = Boolean('{[ yAxisLabelShow ]}');
    const axisLabelFontsize = Number('{[ axisLabelFontsize ]}');
    const axisLabelFontFamily = ('{[ axisLabelFontFamily ]}').toString();
    let gridPadding = '{[ gridPadding ]}';
    let borderRadius = '{[ borderRadius ]}';
    const xLabelRotate = '{[ xLabelRotate ]}';
    const barWidth = '{[ barWidth ]}';
    const shadowOffsetX = Boolean('{[ shadowOffsetX ]}') ? Number('{[ shadowOffsetX ]}') : 0;
    const shadowOffsetY = Boolean('{[ shadowOffsetY ]}') ? Number('{[ shadowOffsetY ]}') : 0;
    const shadowBlur = Boolean('{[ shadowBlur ]}') ? Number('{[ shadowBlur ]}') : 0;
    const splitNumber = Boolean('{[ splitNumber ]}') ? Number('{[ splitNumber ]}') : 0;
    const max = Boolean('{[ max ]}') ? Number('{[ max ]}') : 0;
    const barGap = ('{[ barGap ]}').toString() + '%';
    const gradient = ('{[ gradient ]}').toString();
    let positiveGradientColors = '{[ positiveGradientColors ]}';
    let negativeGradientColors = '{[ negativeGradientColors ]}';
    const stack = Boolean('{[ stack ]}');
    const zoomStart = Number('{[ zoomStart ]}');
    const zoomEnd = Number('{[ zoomEnd ]}');
    const legendMap = ('{[ legendMap ]}').toString();
    const xLabelMap = ('{[ xLabelMap ]}').toString();
    const axisType = Boolean('{[ axisType ]}');
    const containLabel = Boolean('{[ containLabel ]}');
    let yAxis;
    let xAxis;
    const inLoader = Boolean('{[ inLoader ]}');
    let hiddenDimension = '{[ hiddenDimension ]}';
    const clickEvent = ('{[ clickEvent ]}').toString();
    const defaultData = JSON.parse('{[ defaultData ]}'.replace(/\\\"/g, "\""));
    const showBackground = Boolean('{[ showBackground ]}');
    const barBgColor = Boolean('{[ barBgColor ]}') ? ('{[ barBgColor ]}').toString() : 'rgba(180, 180, 180, 0.2)';
    const barBgBorderRadius = Boolean('{[ barBgBorderRadius ]}') ? Number('{[ barBgBorderRadius ]}') : 0;
    const xLabelInside = Boolean('{[ xLabelInside ]}');
    const xLabelVerticalAlign = ('{[ xLabelVerticalAlign ]}').toString();
    const xLabellineHeight = Boolean('{[ xLabellineHeight ]}') ? Number('{[ xLabellineHeight ]}') : '';

    let extraData = null;
    let extraIndex = -1;
    let dataset = defaultData;

    if (isNaN(Number(hiddenDimension))) {
      hiddenDimension = hiddenDimension.toString();
    } else if (Boolean(hiddenDimension)) {
      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]
    }
    if (shadowColor.indexOf(';') > -1) {
      shadowColor = shadowColor.split(',').map(item => item.trim())
    } else if (Boolean(shadowColor)) {
      shadowColor = [shadowColor]
    }
    if (borderRadius.indexOf(',') > -1) {
      borderRadius = borderRadius.split(',').map(item => parseInt(item.trim()))
    } else if (Boolean(borderRadius)) {
      borderRadius = Number(borderRadius)
    }

    if (yAxisName.indexOf(',') > -1) {
      yAxisName = yAxisName.split(',').map(item => item.trim())
    } else if (Boolean(yAxisName)) {
      yAxisName = [yAxisName]
    }

    yAxis1DataIndex = yAxis1DataIndex.split(',').map(item => {
      const itemTrim = item.trim()
      return parseInt(itemTrim, 10)
    });

    positiveGradientColors = translateGradientColor(positiveGradientColors);
    negativeGradientColors = translateGradientColor(negativeGradientColors);
    function translateGradientColor(gradientColor) {
      if (gradientColor.indexOf('::') > 0) {
        gradientColor = gradientColor.split('::').map(function(item) {
          if (item.indexOf('|') > 0) {
            const itemColor = item.split('|');
            const len = itemColor.length - 1;
            return itemColor.map(function(stepColor, index) {
              return {
                offset: index / len,
                color: stepColor.trim()
              }
            })
          }
        });
      } else if (gradientColor.indexOf('|') > 0) {
        const itemColor = gradientColor.split('|');
        const len = itemColor.length - 1;
        const _colors = itemColor.map(function(stepColor, index) {
          return {
            offset: index / len,
            color: stepColor.trim()
          }
        });
        gradientColor = [_colors];
      } else {
        gradientColor = null;
      }
      return gradientColor;
    }

    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: fontSize ? fontSize + 4 : 16,
        color: titleColor || fontColor
      }
    };

    const legendShow = legendOrient != 'null';
    const legend = {
      show: legendShow,
      type: 'scroll',
      icon: legendIcon,
      itemGap: legendItemGap,
      itemWidth: legendItemWidth,
      itemHeight: legendItemHeight,
      textStyle: {
        fontFamily: legendFontFamily,
        fontSize: legendFontSize || fontSize,
        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: 'bar',
      label: {
        formatter: labelFormatter,
        show: labelShow,
        color: labelColor,
        distance: labelDistance,
        fontSize: labelFontsize,
        fontFamily: labelFontFamily,
      },
      barWidth: barWidth,
      barGap: barGap,
      itemStyle: {
        shadowOffsetX: shadowOffsetX,
        shadowOffsetY: shadowOffsetY,
        shadowBlur: shadowBlur,
      }
    };
    if (labelShow) {
      serieTemp.label.position = labelPosition
    }
    if (showBackground) {
      serieTemp.showBackground = true;
      serieTemp.backgroundStyle = {
        color: barBgColor,
        barBorderRadius: barBgBorderRadius
      }
    }

    const _xAxis = {
      type: 'category',
      name: xAxisName,
      axisLine: {
        show: xAxisLine,
        lineStyle: {
          color: xaxisColor,
          width: axisLineWidth,
        }
      },
      axisTick: {
        show: xAxisTick,
        lineStyle: {
          width: axisLineWidth,
        }
      },
      axisLabel: {
        show: xAxisLabelShow,
        color: fontColor,
        fontFamily: axisLabelFontFamily,
        fontSize: axisLabelFontsize || fontSize,
        rotate: xLabelRotate,
        interval: xAxisInterval ? 'auto' : 0,
        inside: xLabelInside
      },
      splitLine: {
        show: xAxisSplitLine,
        lineStyle: {
          color: axisSplitLineColor,
          type: axisSplitLineType
        }
      },
    };
    if (Boolean(xAxisName)) {
      _xAxis.nameTextStyle = {
        color: fontColor,
        fontSize: axisNameFontsize
      }
    }
    if (xLabelVerticalAlign !== 'null') {
      _xAxis.axisLabel.verticalAlign = xLabelVerticalAlign
    }
    if (xLabellineHeight !== '') {
      _xAxis.axisLabel.lineHeight = xLabellineHeight
    }

    const yAxis_0 = {
      type: 'value',
      nameLocation: yAxisNamePosition,
      axisLine: {
        show: yAxisLine,
        lineStyle: {
          color: yaxisColor,
          width: axisLineWidth,
        }
      },
      axisTick: {
        show: yAxisTick,
        lineStyle: {
          width: axisLineWidth,
        }
      },
      axisLabel: {
        show: yAxisLabelShow,
        color: fontColor,
        fontFamily: axisLabelFontFamily,
        fontSize: axisLabelFontsize || fontSize
      },
      splitLine: {
        show: yAxisSplitLine,
        lineStyle: {
          color: axisSplitLineColor,
          type: axisSplitLineType
        }
      },
      splitNumber: splitNumber
    };
    if (max) {
      yAxis_0.max = max;
    } else if (thanMax) {
      yAxis_0.max = function(value) {
        const step = Math.ceil(value.max / splitNumber);
        const _max = splitNumber * step;
        return _max > value.max ? _max : _max + step;
      }
    }
    const yAxis_1 = {
      type: 'value',
      nameLocation: yAxisNamePosition,
      axisTick: {
        show: yAxisTick,
        lineStyle: {
          width: axisLineWidth,
        }
      },
      axisLine: {
        show: yAxisLine,
        lineStyle: {
          color: yaxisColor,
          width: axisLineWidth,
        }
      },
      axisLabel: {
        show: yAxisLabelShow,
        color: fontColor,
        fontFamily: axisLabelFontFamily,
        fontSize: axisLabelFontsize || fontSize
      },
      splitLine: {
        show: yAxisSplitLine,
        lineStyle: {
          color: axisSplitLineColor,
          type: axisSplitLineType
        }
      },
      show: yAxis2Show
    };

    if (Boolean(yAxisName)) {
      yAxis_0.name = yAxisName[0];
      if (yAxisName.length > 1) {
        yAxis_1.name = yAxisName[1];
      } else {
        yAxis_1.name = yAxisName[0];
      }
      yAxis_0.nameTextStyle = {
        color: fontColor,
        fontSize: axisNameFontsize || fontSize
      }
      yAxis_1.nameTextStyle = {
        color: fontColor,
        fontSize: axisNameFontsize || fontSize
      }
    }
    if (Boolean(yAxisUnit)) {
      if (yAxisUnit.indexOf(',') > -1) {
        yAxisUnit = yAxisUnit.split(',').map(function (item) { return item.trim() })
      } else {
        yAxisUnit = [yAxisUnit, yAxisUnit];
      }
      yAxis_0.axisLabel.formatter = '{value}' + yAxisUnit[0];
      yAxis_1.axisLabel.formatter = '{value}' + yAxisUnit[1];
    }

    let _xLabelMap;
    if (xLabelMap.indexOf(':') > 0) {
      let _xLabelArr;
      _xLabelMap = {};
      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: 'axis',
      axisPointer: {
        type: 'line'
      },
      lineStyle: {
        color: yaxisColor,
        opacity: 0.6
      },
      textStyle: {
        fontSize: fontSize
      }
    };
    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 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');

    const getXAxisData = function(source) {
      let _xAxisData = [];
      source.forEach((value, flag) => {
        if (flag !== 0) {
          _xAxisData.push(value[0]);
        }
      });
      return _xAxisData;
    }

    const getSeries = function(source) {
      let _stack;
      const sourceHeader = source[0].slice(1);
      const columnsLen = sourceHeader.length;
      const series = sourceHeader.map(function (item, index) {
        const serieBarFinal = JSON.parse(JSON.stringify(serieTemp));
        const axisIndex = (yAxis2Show && yAxis1DataIndex.indexOf(index) !== -1) ? 1 : 0;
        if (axisType) {
          serieBarFinal.xAxisIndex = axisIndex;
        } else {
          serieBarFinal.yAxisIndex = axisIndex;
        }
        if (stack && !index) _stack = item;
        if (stack && _stack) serieBarFinal.stack = _stack;
        serieBarFinal.label.formatter = function(params) {
          if (params.value[params.seriesIndex + 1] == 0) {
            return '';
          }
        };
        if (Boolean(shadowColor)) {
          const _i = index % shadowColor.length;
          serieBarFinal.itemStyle.shadowColor = shadowColor[_i];
        }

        let data = [];
        source.forEach((value, flag) => {
          if (flag !== 0) {
            let object = {
              value: value[index + 1] || 0,
            };
            if (Number(value[index + 1]) >= 0) {
              Object.assign(object, {
                itemStyle: {
                  barBorderRadius: borderRadius,
                }
              });
              if (labelShow) {
                Object.assign(object, {
                  label: {
                    position: labelPosition,
                  }
                });
              }
            } else {
              let newBorderRadius;
              if (typeof borderRadius === 'string') {
                newBorderRadius = borderRadius;
              } else {
                if (borderRadius.length == 2) {
                  newBorderRadius = [borderRadius[1], borderRadius[0]];
                } else if (borderRadius.length == 3) {
                  newBorderRadius = [borderRadius[1], borderRadius[2], borderRadius[0], borderRadius[1]];
                } else if (borderRadius.length >= 4) {
                  newBorderRadius = [borderRadius[3], borderRadius[2], borderRadius[0], borderRadius[1]];
                } else {
                  newBorderRadius = borderRadius;
                }
              }
              Object.assign(object, {
                itemStyle: {
                  barBorderRadius: newBorderRadius,
                }
              });
              if (labelShow) {
                let newLabelPosition;
                switch(labelPosition) {
                  case 'top': newLabelPosition = 'bottom'; break;
                  case 'bottom': newLabelPosition = 'top'; break;
                  case 'insideTop': newLabelPosition = 'insideBottom'; break;
                  case 'insideBottom': newLabelPosition = 'insideTop'; break;
                  case 'insideTopLeft': newLabelPosition = 'insideBottomLeft'; break;
                  case 'insideBottomLeft': newLabelPosition = 'insideTopLeft'; break;
                  case 'insideTopRight': newLabelPosition = 'insideBottomRight'; break;
                  case 'insideBottomRight': newLabelPosition = 'insideTopRight'; break;
                  default: newLabelPosition = labelPosition; break;
                }
                Object.assign(object, {
                  label: {
                    position: newLabelPosition,
                  }
                });
              }
            }
            if (gradient !== 'none' && positiveGradientColors) {
              const _gradient = gradient.split('::');
              const _type = _gradient[0];
              const _line = _gradient[1].split('-');
              const _colorStopsLen = positiveGradientColors.length;
              Object.assign(object.itemStyle, {
                color:  {
                  type: _type,
                  x:_line[0], y:_line[1], x2:_line[2], y2:_line[3],
                  colorStops: Number(value[index + 1]) > 0 ?
                    positiveGradientColors[index < _colorStopsLen ? index : index % _colorStopsLen] :
                    negativeGradientColors[index < _colorStopsLen ? index : index % _colorStopsLen]
                }
              });
            }
            data.push(object);
          }
        });

        return Object.assign({}, { name: item, zlevel: columnsLen + 1 - index }, serieBarFinal, { data } )
      });
      return series;
    }

    function initChart(source) {
      myChart.clear();
      _xAxis.data = getXAxisData(source);

      if (axisType) {
        xAxis = [yAxis_0, yAxis_1];
        yAxis = _xAxis;
      } else {
        xAxis = _xAxis;
        yAxis = [yAxis_0, yAxis_1];
      }
      const option = {
        title: title,
        tooltip: tooltip,
        legend: legend,
        grid: grid,
        xAxis: xAxis,
        yAxis: yAxis,
        dataZoom: dataZoom,
        series: getSeries(source)
      };
      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 = dataset[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);
    // 有 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);
            if (clickEvent != 'null') dataset = data;
            let source;
            if (hiddenDimension) {
              extraIndex = isNaN(hiddenDimension) ? data[0].indexOf(hiddenDimension) : hiddenDimension;
              if (extraIndex > -1) {
                extraData = [];
                source = data.map(function (row) {
                  extraData.push(row[extraIndex]);
                  return row.filter((_, i) => i != extraIndex);
                });
              }
            } else {
              source = data;
            }
            inLoader && window.loader && window.loader.remove(_id);
            initChart(source);
          }
        }
      });
    }

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

  onViewInit() {
    this.updateScript();
    const evn = echartsBasicListen + `
      change:defaultData
      change:yAxis1DataIndex
      change:yAxis2Show
      change:axisSplitLineColor
      change:axisSplitLineType
      change:yAxisUnit
      change:yAxisNamePosition
      change:axisNameFontsize
      change:axisLineWidth
      change:xAxisLine
      change:yAxisLine
      change:xAxisName
      change:yAxisName
      change:xaxisColor
      change:yaxisColor
      change:axisLabelFontFamily
      change:xAxisLabelShow
      change:yAxisLabelShow
      change:axisLabelFontsize
      change:xAxisSplitLine
      change:xAxisTick
      change:xAxisInterval
      change:yAxisSplitLine
      change:yAxisTick
      change:gridPadding
      change:containLabel
      change:labelPosition
      change:labelFormatter
      change:labelDistance
      change:labelFontsize
      change:labelFontFamily
      change:labelColor
      change:borderRadius
      change:xLabelRotate
      change:xLabelInside
      change:xLabelVerticalAlign
      change:xLabellineHeight
      change:barWidth
      change:barGap
      change:shadowOffsetX
      change:shadowOffsetY
      change:shadowBlur
      change:shadowColor
      change:stack
      change:gradient
      change:gradientColors
      change:showBackground
      change:barBgColor
      change:barBgBorderRadius
      change:positiveGradientColors
      change:negativeGradientColors
      change:splitNumber
      change:max
      change:thanMax
      change:zoomStart
      change:zoomEnd change:xLabelMap change:axisType 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)));
  }
}
