import { singleRingChart, CATEGORIES } from '../../configuration/constants'
import { throttle } from '../../utils'
import { IMG_DATAURL, POINTER_DATAURL } from '../../assets/singleRingDataUrls'

export default {
  // 组件名称
  name: singleRingChart,

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

  // 编辑器右侧块管理器中显示属性配置
  blockOptions() {
    return {
      category: CATEGORIES.ECHARTS,
      label: `
        <svg class="gjs-block-svg" viewBox="-4 -4 32 32" xmlns="http://www.w3.org/2000/svg">
          <path d="M12,2v1.5c4.7,0,8.5,3.8,8.5,8.5s-3.8,8.5-8.5,8.5S3.5,16.7,3.5,12H2c0,5.5,4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z"/>
        </svg>
        <div class="gjs-block-label">占比单环</div>
      `
    };
  },

  // 后面板显示属性配置
  spOptions() {
    return {
      label: '占比单环',
      icon: 'globe',
      docUrl: 'https://xuelangyun.yuque.com/docs/share/ecde9048-f4ea-4d39-b238-b445932d46db?# 《占比单环》',
      author: '秋水',
      email: 'qiushui.smy@xuelangyun.com',
      inPorts: [{
        uuid: 'in1',
        subType: 'json',
        description: {
          zh_CN: '输入1'
        }
      }]
    }
  },

  // 组件属性
  componentOptions() {
    return {
      name: singleRingChart,
      resizable: true,
      dmode: 'absolute',
      droppable: false,
      traits: [
        {
          name: 'titleShow',
          label: '显示大标题',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'titleColor',
          label: '大标题颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'titleFontsize',
          label: '大标题字号',
          changeProp: 1,
          type: 'number',
          min: 12,
          step: 1
        }, {
          name: 'titleFontfamily',
          label: '大标题字体',
          changeProp: 1,
          type: 'select',
          options: [
            { id: 'sans-serif', name: '默认' },
            { id: '庞门正道', name: '庞门正道' },
            { id: 'DS-Digital', name: 'DS-Digital' }
          ]
        }, {
          name: 'titleFontweight',
          label: '大标题加粗',
          changeProp: 1,
          type: 'number',
          min: 400,
          step: 100
        }, {
          name: 'titleTop',
          label: '大标题垂直位置 %',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'subTitleShow',
          label: '显示副标题',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'subTitleColor',
          label: '副标题颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'subTitleFontsize',
          label: '副标题字号',
          changeProp: 1,
          type: 'number',
          min: 12,
          step: 1
        }, {
          name: 'subTitleTop',
          label: '副标题垂直位置 %',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'subTitleText',
          label: '自定义副标题',
          changeProp: 1,
        }, {
          name: 'polarRadiusStart',
          label: '极坐标内半径 %',
          changeProp: 1,
          type: 'number',
          min: 0
        }, {
          name: 'polarRadiusEnd',
          label: '极坐标外半径 %',
          changeProp: 1,
          type: 'number',
          min: 0
        }, {
          name: 'startAngle',
          label: '开始位置',
          changeProp: 1,
          type: 'select',
          options: [{ id: '90', name: '上' }, { id: '0', name: '右' }, { id: '-90', name: '下' }, { id: '180', name: '左' }]
        }, {
          name: 'barWidth',
          label: '环条宽度',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'barColor',
          label: '环条颜色',
          changeProp: 1,
          type: 'color'
        }, {
          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: 'gradientColors',
          label: '渐变颜色',
          changeProp: 1,
        }, {
          name: 'backgroundStyle',
          label: '环条背景色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'imgSrc',
          label: '末端光斑URL',
          changeProp: 1,
          type: 'textarea'
        }, {
          name: 'imgWidth',
          label: '末端光斑宽度',
          changeProp: 1,
          type: 'number',
          min: 0
        }, {
          name: 'imgHeight',
          label: '末端光斑高度',
          changeProp: 1,
          type: 'number',
          min: 0
        }, {
          name: 'gaugeRadius',
          label: '刻度环半径 %',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'gaugeSplit',
          label: '刻度分隔数',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'gaugeSplitLength',
          label: '刻度线长',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'gaugeSplitWidth',
          label: '刻度线宽',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'gaugeSplitColor',
          label: '刻度线颜色',
          changeProp: 1,
          type: 'color'
        }, {
          name: 'gaugeSplitType',
          label: '刻度线类型',
          changeProp: 1,
          type: 'select',
          options: [{ id: 'solid', name: '实线' }, { id: 'dashed', name: '虚线' }, { id: 'dotted', name: '点线' }]
        }, {
          name: 'gaugeRadialWidth',
          label: '内发光宽度',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'gaugeRadialStart',
          label: '内发光渐变起始 %',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'pointerSrc',
          label: '刻度指示器URL',
          changeProp: 1,
          type: 'textarea'
        }, {
          name: 'pointerWidth',
          label: '指示器宽度',
          changeProp: 1,
          type: 'number',
          min: 0
        }, {
          name: 'pointerHeight',
          label: '指示器高度',
          changeProp: 1,
          type: 'number',
          min: 0
        }, {
          name: 'divisor',
          label: '比数维度',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'dividend',
          label: '总数维度',
          changeProp: 1,
          type: 'number',
          min: 0,
          step: 1
        }, {
          name: 'csv',
          label: '示例数据',
          changeProp: 1,
          type: 'csvDownload',
          preFileName: '极坐标柱形图',
          datas: [["完成数", "计划数"], [80, 120]]
        }, {
          name: 'defaultData',
          changeProp: 1,
          type: 'hide'
        }
      ],
      defaultData: JSON.stringify([["完成数", "计划数"], [80, 120]]).replace(/\"/g, "\\\""),
      'titleShow': true,
      'subTitleShow': true,
      'subTitleText': null,
      'titleColor': '#1df08b',
      'titleFontfamily': 'DS-Digital',
      'titleFontsize': 58,
      'titleFontweight': 600,
      'titleTop': 38,
      'subTitleColor': '#fff',
      'subTitleFontsize': 20,
      'subTitleTop': 55,
      'polarRadiusStart': 70,
      'polarRadiusEnd': 90,
      'startAngle': '-90',
      'barWidth': 30,
      'backgroundStyle': 'rgba(255, 255, 255, .3)',
      'barColor': '#3aaff5',
      'gradient': 'none',
      'gradientColors': '#59B5FF|#2263BD',
      'imgSrc': IMG_DATAURL,
      'pointerSrc': POINTER_DATAURL,
      'imgWidth': 60,
      'imgHeight': 60,
      'gaugeRadius': 67,
      'gaugeSplit': 200,
      'gaugeSplitLength': 2,
      'gaugeSplitWidth': 2,
      'gaugeRadialStart': 95,
      'gaugeRadialWidth': 20,
      'gaugeSplitColor': '#37a9f2',
      'gaugeSplitType': 'solid',
      'pointerWidth': 20,
      'pointerHeight': 20,
      'divisor': 0,
      'dividend': 1,
    }
  },

  onModelScript() {
    const titleShow = Boolean('{[ titleShow ]}');
    const titleColor = '{[ titleColor ]}';
    const titleFontsize = Number('{[ titleFontsize ]}');
    const titleFontweight = Number('{[ titleFontweight ]}');
    const titleTop = Boolean('{[ titleTop ]}') ? Number('{[ titleTop ]}') : 0;
    const subTitleShow = Boolean('{[ subTitleShow ]}');
    const titleFontfamily = ('{[ titleFontfamily ]}').toString();
    const subTitleText = ('{[ subTitleText ]}').toString();
    const subTitleColor = '{[ subTitleColor ]}';
    const subTitleFontsize = Number('{[ subTitleFontsize ]}');
    const subTitleTop = Boolean('{[ subTitleTop ]}') ? Number('{[ subTitleTop ]}') : 0;
    const polarRadiusStart = Boolean('{[ polarRadiusStart ]}') ? Number('{[ polarRadiusStart ]}') : 0;
    const polarRadiusEnd = Boolean('{[ polarRadiusEnd ]}') ? Number('{[ polarRadiusEnd ]}') : 0;
    const startAngle = Number('{[ startAngle ]}');
    const barWidth = Boolean('{[ barWidth ]}') ? Number('{[ barWidth ]}') : 0;
    const backgroundStyle = '{[ backgroundStyle ]}';
    const barColor = '{[ barColor ]}';
    const gradient = ('{[ gradient ]}').toString();
    let gradientColors = ('{[ gradientColors ]}').toString();
    const imgSrc = ('{[ imgSrc ]}').toString();
    const imgWidth = Boolean('{[ imgWidth ]}') ? Number('{[ imgWidth ]}') : 0;
    const imgHeight = Boolean('{[ imgHeight ]}') ? Number('{[ imgHeight ]}') : 0;
    const gaugeRadius = Boolean('{[ gaugeRadius ]}') ? Number('{[ gaugeRadius ]}') : 0;
    const gaugeSplit = Boolean('{[ gaugeSplit ]}') ? Number('{[ gaugeSplit ]}') : 0;
    const gaugeSplitLength = Boolean('{[ gaugeSplitLength ]}') ? Number('{[ gaugeSplitLength ]}') : 0;
    const gaugeSplitWidth = Boolean('{[ gaugeSplitWidth ]}') ? Number('{[ gaugeSplitWidth ]}') : 0;
    const gaugeRadialWidth = Boolean('{[ gaugeRadialWidth ]}') ? Number('{[ gaugeRadialWidth ]}') : 0;
    const gaugeRadialStart = Boolean('{[ gaugeRadialStart ]}') ? Number('{[ gaugeRadialStart ]}') : 0;
    const gaugeSplitColor = '{[ gaugeSplitColor ]}';
    const gaugeSplitType = ('{[ gaugeSplitType ]}').toString();
    const pointerSrc = ('{[ pointerSrc ]}').toString();
    const pointerWidth = Boolean('{[ pointerWidth ]}') ? Number('{[ pointerWidth ]}') : 0;
    const pointerHeight = Boolean('{[ pointerHeight ]}') ? Number('{[ pointerHeight ]}') : 0;
    const divisor = Boolean('{[ divisor ]}') ? Number('{[ divisor ]}') : 0;
    const dividend = Boolean('{[ dividend ]}') ? Number('{[ dividend ]}') : 0;
    const defaultData = JSON.parse('{[ defaultData ]}'.replace(/\\\"/g, "\""));

    const myChart = window.echarts.init(this);
    const self = this;

    const title = [{
      show: titleShow,
      x: 'center',
      top: titleTop + '%',
      textStyle: {
        color: titleColor,
        fontSize: titleFontsize,
        fontWeight: titleFontweight,
        fontFamily: titleFontfamily
      }
    }, {
      show: subTitleShow,
      x: 'center',
      top: subTitleTop + '%',
      textStyle: {
        color: subTitleColor,
        fontSize: subTitleFontsize,
        fontWeight: 'normal'
      }
    }];

    const polar = {
      radius: [polarRadiusStart + '%', polarRadiusEnd + '%'],
      center: ['50%', '50%'],
    };
    const radiusAxis = {
      type: 'category',
      show: false,
    };

    const angleAxis = {
      max: 100,
      show: false,
      startAngle: startAngle,
    };

    const barTemp = {
      type: 'bar',
      roundCap: true,
      barWidth: barWidth,
      showBackground: true,
      backgroundStyle: {
        color: backgroundStyle,
      },
      coordinateSystem: 'polar',
      itemStyle: {
        color: barColor
      },
    };

    if (gradient !== 'none' && gradientColors) {
      const _gradient = gradient.split('::');
      const _type = _gradient[0];
      const _line = _gradient[1].split('-');
      const itemColor = gradientColors.split('|');
      const len = itemColor.length - 1;
      const colorStops = itemColor.map(function (stepColor, index) {
        return {
          offset: index / len,
          color: stepColor.trim()
        }
      });
      barTemp.itemStyle.color = {
        type: _type,
        x: _line[0], y: _line[1], x2: _line[2], y2: _line[3],
        colorStops: colorStops
      };
    }
    function transferColorToRgba(color, alpha = 1) {
      if (typeof color !== 'string' && !(color instanceof String)) return console.error("请输入16进制字符串形式的颜色值");
      color = color.charAt(0) === '#' ? color.substring(1) : color;
      if (color.length !== 6 && color.length !== 3) return console.error("请输入正确的颜色值")
      if (color.length === 3) {
        color = color.replace(/(\w)(\w)(\w)/, '$1$1$2$2$3$3')
      }
      var reg = /\w{2}/g;
      var colors = color.match(reg);
      for (var i = 0; i < colors.length; i++) {
        colors[i] = parseInt(colors[i], 16).toString();
      }
      return 'rgba(' + colors.join() + ',' + alpha + ')';
    }
    let gaugeAxisLineColorStart;
    let gaugeAxisLineColorEnd;
    if (gaugeSplitColor.indexOf('#') == 0) {
      gaugeAxisLineColorStart = transferColorToRgba(gaugeSplitColor, 0);
      gaugeAxisLineColorEnd = transferColorToRgba(gaugeSplitColor, 0.36);
    } else if (gaugeSplitColor.indexOf('rgba') == 0) {
      gaugeAxisLineColorStart = gaugeSplitColor.split(',').splice(3, 1, '0)').join(',');
      gaugeAxisLineColorEnd = gaugeSplitColor.split(',').splice(3, 1, '36)').join(',');
    } else if (gaugeSplitColor.indexOf('rgb') == 0) {
      const _rgb_i_start = gaugeSplitColor.indexOf('(');
      const _rgb_i_end = gaugeSplitColor.indexOf(')');
      const _rgb = gaugeSplitColor.slice(_rgb_i_start + 1, _rgb_i_end);
      gaugeAxisLineColorStart = 'rgba(' + _rgb + ',0)';
      gaugeAxisLineColorEnd = 'rgba(' + _rgb + ',.36)';
    }
    const guageTemp = {
      type: 'gauge',
      radius: gaugeRadius + '%',
      startAngle: startAngle,
      endAngle: startAngle - 359.99,
      splitNumber: gaugeSplit,
      center: ['50%', '50%'],
      pointer: {
        show: false
      },
      title: {
        show: false
      },
      detail: {
        show: false
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: [
            [1, {
              type: 'radial',
              x: 0.5,
              y: 0.5,
              r: 0.5,
              colorStops: [{
                offset: gaugeRadialStart / 100, color: gaugeAxisLineColorStart // 0% 处的颜色
              }, {
                offset: 1, color: gaugeAxisLineColorEnd // 100% 处的颜色
              }]
            }
            ]
          ],
          width: gaugeRadialWidth,
        }
      },
      axisTick: {
        show: false
      },
      splitLine: {
        show: true,
        length: gaugeSplitLength,
        lineStyle: {
          color: gaugeSplitColor,
          width: gaugeSplitWidth,
          type: gaugeSplitType,
        },
      },
      axisLabel: {
        show: false
      }
    };

    const customTemp = {
      type: 'custom',
      coordinateSystem: "none",
      data: [0]
    };

    function initChart(source) {
      myChart.clear();
      const used = source[1][divisor];
      const total = source[1][dividend];
      const percent = used / total;
      barTemp.data = [percent * 100];
      const imgCustom = Object.assign({}, customTemp, {
        renderItem: function (params, api) {
          const x = api.getWidth() / 2;
          const y = api.getHeight() / 2;
          const r = y * (polarRadiusStart + (polarRadiusEnd - polarRadiusStart) / 2) / 100;
          const angle = percent * 360;
          const rad = -angle * Math.PI / 180;
          const x0 = x + r * Math.cos(-startAngle * Math.PI / 180);
          const y0 = y + r * Math.sin(-startAngle * Math.PI / 180);
          return {
            type: 'image',
            origin: [x, y],
            rotation: rad,
            z2: 99,
            style: {
              image: imgSrc,
              x: x0 - imgWidth / 2,
              y: y0 - imgHeight / 2,
              width: imgWidth,
              height: imgHeight,
            },
            silent: true
          };
        }
      });
      const pointerCustom = Object.assign({}, customTemp, {
        renderItem: function (params, api) {
          const x = api.getWidth() / 2;
          const y = api.getHeight() / 2;
          const r = y * gaugeRadius / 100;
          const angle = percent * 360;
          const rad = -angle * Math.PI / 180;
          const x0 = x + r * Math.cos(-startAngle * Math.PI / 180);
          const y0 = y + r * Math.sin(-startAngle * Math.PI / 180);
          let styleX;
          let styleY;
          switch (startAngle) {
            case 90:
              styleX = x0 - pointerWidth / 2;
              styleY = y0;
              break;
            case 0:
              styleX = x0 - pointerWidth;
              styleY = y0 - pointerHeight / 2;
              break;
            case -90:
              styleX = x0 - pointerWidth / 2;
              styleY = y0 - pointerHeight;
              break;
            case 180:
              styleX = x0;
              styleY = y0 - pointerHeight / 2;
              break;
          }
          return {
            type: 'image',
            origin: [x, y],
            rotation: rad,
            z2: 99,
            style: {
              image: pointerSrc,
              x: styleX,
              y: styleY,
              width: pointerWidth,
              height: pointerHeight,
            },
            silent: true
          };
        }
      });
      title[0].text = used + '/' + total;
      if (Boolean(subTitleText)) {
        title[1].text = subTitleText;
      } else {
        title[1].text = source[0][divisor] + '/' + source[0][dividend];
      }

      const option = {
        title: title,
        polar: polar,
        radiusAxis: radiusAxis,
        angleAxis: angleAxis,
        series: [barTemp, guageTemp, pointerCustom, imgCustom]
      };
      myChart.setOption(option);
      myChart.resize();
    }

    initChart(defaultData);

    const loader = $('<div class="loader"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>')

    window.addEventListener('resize', function () {
      myChart.resize();
    }, false);
    // 有 dashboardHost 说明是运行模式
    if (window.spSocket) {
      var eventName = `call-` + self.getAttribute('id');
      window.spSocket.subscribe({
        eventName: eventName,
        callback: function (_data) {
          let _in1Str = _data.data.in1;
          if (_in1Str) {
            const source = JSON.parse(_in1Str);
            initChart(source);
          }
        }
      });
    }
  },

  onViewInit() {
    this.updateScript();
    const evn = `
      change:titleShow
      change:subTitleText
      change:subTitleShow
      change:titleColor
      change:titleFontfamily
      change:titleFontsize
      change:titleFontweight
      change:titleTop
      change:subTitleColor
      change:subTitleFontsize
      change:subTitleTop
      change:polarRadiusStart
      change:polarRadiusEnd
      change:startAngle
      change:barWidth
      change:backgroundStyle
      change:barColor
      change:gradient
      change:gradientColors
      change:imgSrc
      change:imgWidth
      change:imgHeight
      change:gaugeRadius
      change:gaugeSplit
      change:gaugeSplitLength
      change:gaugeSplitWidth
      change:gaugeRadialWidth
      change:gaugeRadialStart
      change:gaugeSplitColor
      change:gaugeSplitType
      change:pointerSrc
      change:pointerWidth
      change:pointerHeight
      change:divisor
      change:dividend
    `;
    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)));
  }
}
