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

export default {

  // 组件名称
  name: ringChart,

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

  // 编辑器右侧块管理器中显示属性配置
  blockOptions() {
    return {
      category: CATEGORIES.ECHARTS,
      label: `
      <svg class="gjs-block-svg" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
        <circle cx="12" cy="12" r="4" strokeWidth="3" stroke="#fff" fill="none"></circle>
      </svg>
      <div class="gjs-block-label">环形图</div>`,
      // attributes: { class: 'fa fa-pie-chart' },
    };
  },

  // 后面板显示属性配置
  spOptions() {
    return {
      label: '环形图',
      icon: 'globe',
      author: '秋水',
      email: 'qiushui.smy@xuelangyun.com',
      inPorts: [
        {
          uuid: 'in1',
          subType: 'json',
          description: {
            zh_CN: '输入1'
          }
        }
      ]
    }
  },

  // 组件属性
  componentOptions() {
    return {
      name: ringChart,
      resizable: true,
      dmode: 'absolute',
      childrenSelectable: false,
      highlightable: false,
      droppable: false,
      traits: [
        {
          name: 'outRadius',
          label: '最大半径(%)',
          changeProp: 1,
          type: 'number'
        }, {
          name: 'strokeWidth',
          label: '环宽(px)',
          type: 'number',
          changeProp: 1
        }, {
          name: 'spaceWidth',
          label: '环间距(px)',
          changeProp: 1,
          type: 'number',
        }, {
          name: 'capRound',
          label: '两端圆形',
          changeProp: 1,
          type: 'checkbox'
        }, {
          name: 'circleColor',
          label: '轨道颜色',
          changeProp: 1,
          type: 'color'
        }
      ],
      'outRadius': 60,
      'strokeWidth': 16,
      'spaceWidth': 8,
      'capRound': true,
      'circleColor': '#dcdcdc'
    }
  },

  onModelScript() {
    const dataSource = '{[ dataSource ]}';
    const bgColor = '{[ bgColor ]}';
    const borderColor = '{[ borderColor ]}';
    const fontColor = '{[ fontColor ]}';
    let colors = '{[ colors ]}';
    const titleText = '{[ titleText ]}';
    const titlePosition = '{[ titlePosition ]}';
    const _legend = ('{[ legend ]}').toString();
    const legendOrient = ('{[ legendOrient ]}').toString();
    const outRadius = Number('{[ outRadius ]}');
    const strokeWidth = Number('{[ strokeWidth ]}');
    const spaceWidth = Number('{[ spaceWidth ]}');
    const capRound = Boolean('{[ capRound ]}') ? 'round' : 'butt';
    const circleColor = '{[ circleColor ]}';
    const legendMap = ('{[ legendMap ]}').toString();

    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];
    } else {
      colors = ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83',  '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3']
    }

    const defaultSource = [["type", "数量"], ["合格", 80]];
    // const defaultSource = [["type", "数学", "语文"], ["小红", 100, 90], ["小兰", 60, 90], ["小绿", 40, 90]];

    const self = this;

    self.innerHTML = '';

    const xmlns = "http://www.w3.org/2000/svg";
    const createSvg = function() {
      var boxWidth = "100%";
      var boxHeight = "100%";
      var svgElem = document.createElementNS (xmlns, "svg");
      svgElem.setAttributeNS (null, "width", boxWidth);
      svgElem.setAttributeNS (null, "height", boxHeight);
      svgElem.style.display = "block";
      return svgElem;
    }

    const svg_width = $(self).width();
    const svg_height = $(self).height();
    const cx = svg_width / 2;
    const cy = svg_height / 2;

    const createCircle = function (parent, options) {
      const circle = document.createElementNS(xmlns, 'circle');
      for (var prop in options) {
        circle.setAttributeNS(null, prop, options[prop])
      }
      if (options['stroke-dashoffset'] && options['stroke-dasharray']) {
        const animation = document.createElementNS(xmlns, 'animate')
        animation.setAttributeNS(null, "attributeName", "stroke-dashoffset")
        animation.setAttributeNS(null, "calcMode", "paced")
        animation.setAttributeNS(null, "begin", "0s")
        animation.setAttributeNS(null, "dur", "0.5s")
        animation.setAttributeNS(null, "from", options['stroke-dasharray'].split(' ')[0])
        animation.setAttributeNS(null, "to", options['stroke-dashoffset'])
        circle.appendChild(animation)
      }
      parent.appendChild(circle)
    }

    const createText = function(text, x, y, fontSize = 14, fontWeight = 'normal', anchor = 'left') {
      const textElm = document.createElementNS(xmlns, "text")
      const textNode = document.createTextNode(text)
      textElm.appendChild(textNode)
      textElm.setAttributeNS(null, "x", x)
      textElm.setAttributeNS(null, "y", y)
      textElm.setAttributeNS(null, "style", "font-family: 'sans-serif'; font-size: " + fontSize + "; font-weight: " + fontWeight + "; text-anchor: " + anchor + "; fill: " + fontColor)
      return textElm
    }

    const createTitle = function () {
      const titlePositionArr = titlePosition.split('-')
      const fontSize = 16
      let x;
      let y;
      let align = 'start';
      if (titlePositionArr[1] == 'left') {
        x = 16
      } else if (titlePositionArr[1] == 'center') {
        x = cx
        align = 'middle'
      } else if (titlePositionArr[1] == 'right') {
        x = svg_width - 16
        align = 'end'
      }
      if (titlePositionArr[0] == 'top') {
        y = 16 + fontSize
      } else if (titlePositionArr[0] == 'center') {
        y = cy + fontSize / 2
      } else if (titlePositionArr[0] == 'bottom') {
        y = svg_width - 16
      }
      return createText(titleText, x, y, fontSize, 'bold', align)
    }

    const strlen = function (str) {
      var len = 0;
      for (var i = 0; i < str.length; i++) {
        var c = str.charCodeAt(i);
        //单字节加1
        if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
          len++;
        }
        else {
          len += 2;
        }
      }
      return len;
    };

    const createLegend = function(source) {
      const g = document.createElementNS (xmlns, "g");
      g.setAttributeNS(null, 'class', 'legend');
      var r = 4;
      source.slice(1).forEach(function(type, index) {
        const _g = document.createElementNS (xmlns, "g");
        const _i = index % colors.length;
        const fill = colors[_i]
        let symbol;
        if (capRound == 'round') {
          symbol = document.createElementNS(xmlns, "circle");
          symbol.setAttributeNS(null, 'cx', r)
          symbol.setAttributeNS(null, 'cy', r)
          symbol.setAttributeNS(null, 'r', r)
        } else {
          symbol = document.createElementNS(xmlns, "rect");
          symbol.setAttributeNS(null, 'x', 0)
          symbol.setAttributeNS(null, 'y', 0)
          symbol.setAttributeNS(null, 'width', r * 2)
          symbol.setAttributeNS(null, 'height', r * 2)
        }
        symbol.setAttributeNS(null, 'fill', fill)
        const text = createText(type[0], r + 10, 8)
        _g.appendChild(symbol)
        _g.appendChild(text)
        if (_legend.split('-')[0] == 'center' || legendOrient == 'vertical') {
          _g.setAttributeNS(null, 'transform', 'translate(0,' + 24 * index + ')')
        } else {
          const text_len = strlen(type[0])
          _g.setAttributeNS(null, 'transform', 'translate(' + (8 * text_len + r * 2 + 10 + 16) * index + ',0)')
        }
        g.appendChild(_g)
      })
      return g
    }

    const getAngle = function(used, total, angle) {
        if (!total) {
            return 0
        }
        return used / total * 360 + angle
    }
    const getOffset = function(used, total, circum) {
        let offset = circum - (used / total) * circum
        if (!total) {
            offset = circum
        } else if (used > total) {
            offset = 0
        }
        return offset
    }

    const setLegendPosition = function(legend) {
      const lgd_rect = legend.getBBox()
      const hr = _legend.split('-')[1]
      const vt = _legend.split('-')[0]
      let lg_x;
      let lg_y;
      const pd = 16;
      if (hr == 'left') {
        lg_x = pd
      } else if (hr == 'right') {
        lg_x = svg_width - lgd_rect.width - pd
      } else {
        lg_x = svg_width / 2 - lgd_rect.width / 2
      }
      if (vt == 'top') {
        lg_y = pd
      } else if (vt == 'bottom') {
        lg_y = svg_height - lgd_rect.height - lgd_rect.y * 2 - pd
      } else {
        lg_y = svg_height / 2 - lgd_rect.height / 2
      }
      legend.setAttributeNS(null, 'transform', 'translate(' + lg_x + ',' + lg_y + ')')
    }

    const renderRings = function(source) {
      $(self).empty();
      const svg = createSvg();
      source[0].slice(1).forEach(function(type, index) {
        const g = document.createElementNS (xmlns, "g");
        g.setAttributeNS(null, 'id', 'column-' + (index + 1));
        const r = svg_width / 2 * outRadius / 100  - strokeWidth / 2 - (strokeWidth + spaceWidth) * index
        const options = {
          cx: cx, cy: cy, r: r, stroke: circleColor, 'stroke-width': strokeWidth, fill: 'none'
        }
        createCircle(g, options)

        let total = 0
        source.slice(1).forEach(function(item, i) {
          total += item[index + 1]
        })
        let angle = 0
        source.slice(1).forEach(function(item, i) {
          const _i = i % colors.length;
          const stroke = colors[_i]
          const circum = r * 2 * Math.PI
          const offset = getOffset(item[index+1], total, circum)
          const degree = angle - 90
          angle = getAngle(item[index+1], total, angle)
          const options = {
            id: 'column-' + (index + 1) + '-row-' + (i + 1), cx: cx, cy: cy, r: r, stroke: stroke, 'stroke-width': strokeWidth, fill: 'none', 'stroke-linecap': capRound, 'stroke-dasharray': circum + ' ' + circum, 'stroke-dashoffset': offset, 'transform': 'rotate(' + degree + ' ' + cx + ' ' + cy + ')'
          }
          createCircle(g, options)
        })
        svg.appendChild(g)
      })
      if (Boolean(titleText)) {
        const title = createTitle()
        svg.appendChild(title)
      }
      self.appendChild(svg)
      if (_legend != 'null') {
        const legend = createLegend(source)
        svg.appendChild(legend)
        setLegendPosition(legend)
      }
    }

    renderRings(defaultSource)


    // 有 dashboardHost 说明是运行模式
    if (window.spSocket) {
      var inited = false;
      var eventName = `call-` + self.getAttribute('id');
      window.spSocket.subscribe({
        eventName: eventName,
        callback: function (_data) {
          const source = JSON.parse(_data.data.in1);
          if (!inited) {
            renderRings(source)
            inited = true
          } else {
            updateRings()
          }

        }
      });
    }

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

  onViewInit() {
    this.updateScript();
    const evn = echartsBasicListen + 'change:outRadius change:strokeWidth change:spaceWidth change:capRound change:circleColor';

    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)));
  }
}
