text: import CoreUtils from './CoreUtils'
  import Dimensions from './Dimensions'
  import Graphics from './Graphics'
  import Pie from '../charts/Pie'
  import Series from './Series'
  import Utils from '../utils/Utils'
  
  /**
   * ApexCharts Legend Class to draw legend.
   *
   * @module Legend
   **/
  
  class Legend {
    constructor(ctx, opts) {
      this.ctx = ctx
      this.w = ctx.w
  
      this.onLegendClick = this.onLegendClick.bind(this)
      this.onLegendHovered = this.onLegendHovered.bind(this)
    }
  
    init() {
      const w = this.w
  
      const gl = w.globals
      const cnf = w.config
  
      const showLegendAlways =
        (cnf.legend.showForSingleSeries && gl.series.length === 1) ||
        gl.series.length > 1
  
      if ((showLegendAlways || !gl.axisCharts) && cnf.legend.show) {
        while (gl.dom.elLegendWrap.firstChild) {
          gl.dom.elLegendWrap.removeChild(gl.dom.elLegendWrap.firstChild)
        }
  
        this.drawLegends()
        if (!Utils.isIE11()) {
          this.appendToForeignObject()
        } else {
          // IE11 doesn't supports foreignObject, hence append it to <head>
          document
            .getElementsByTagName('head')[0]
            .appendChild(this.getLegendStyles())
        }
  
        if (cnf.legend.position === 'bottom' || cnf.legend.position === 'top') {
          this.legendAlignHorizontal()
        } else if (
          cnf.legend.position === 'right' ||
          cnf.legend.position === 'left'
        ) {
          this.legendAlignVertical()
        }
      }
    }
  
    appendToForeignObject() {
      const gl = this.w.globals
  
      gl.dom.elLegendForeign = document.createElementNS(gl.SVGNS, 'foreignObject')
  
      let elForeign = gl.dom.elLegendForeign
  
      elForeign.setAttribute('x', 0)
      elForeign.setAttribute('y', 0)
      elForeign.setAttribute('width', gl.svgWidth)
      elForeign.setAttribute('height', gl.svgHeight)
      gl.dom.elLegendWrap.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
  
      elForeign.appendChild(gl.dom.elLegendWrap)
      elForeign.appendChild(this.getLegendStyles())
  
      gl.dom.Paper.node.insertBefore(elForeign, gl.dom.elGraphical.node)
    }
  
    drawLegends() {
      let self = this
      let w = this.w
  
      let fontFamily = w.config.legend.fontFamily
  
      let legendNames = w.globals.seriesNames
      let fillcolor = w.globals.colors.slice()
  
      if (w.config.chart.type === 'heatmap') {
        const ranges = w.config.plotOptions.heatmap.colorScale.ranges
        legendNames = ranges.map((colorScale) => {
          return colorScale.name
            ? colorScale.name
            : colorScale.from + ' - ' + colorScale.to
        })
        fillcolor = ranges.map((color) => {
          return color.color
        })
      }
      let legendFormatter = w.globals.legendFormatter
  
      for (let i = 0; i <= legendNames.length - 1; i++) {
        let text = legendFormatter(legendNames[i], { seriesIndex: i, w })
  
        let collapsedSeries = false
        let ancillaryCollapsedSeries = false
        if (w.globals.collapsedSeries.length > 0) {
          for (let c = 0; c < w.globals.collapsedSeries.length; c++) {
            if (w.globals.collapsedSeries[c].index === i) {
              collapsedSeries = true
            }
          }
        }
  
        if (w.globals.ancillaryCollapsedSeriesIndices.length > 0) {
          for (
            let c = 0;
            c < w.globals.ancillaryCollapsedSeriesIndices.length;
            c++
          ) {
            if (w.globals.ancillaryCollapsedSeriesIndices[c] === i) {
              ancillaryCollapsedSeries = true
            }
          }
        }
  
        let elMarker = document.createElement('span')
        elMarker.classList.add('apexcharts-legend-marker')
  
        let mOffsetX = w.config.legend.markers.offsetX
        let mOffsetY = w.config.legend.markers.offsetY
        let mHeight = w.config.legend.markers.height
        let mWidth = w.config.legend.markers.width
        let mBorderWidth = w.config.legend.markers.strokeWidth
        let mBorderColor = w.config.legend.markers.strokeColor
        let mBorderRadius = w.config.legend.markers.radius
  
        let mStyle = elMarker.style
  
        mStyle.background = fillcolor[i]
        mStyle.color = fillcolor[i]
        mStyle.height = Array.isArray(mHeight)
          ? parseFloat(mHeight[i]) + 'px'
          : parseFloat(mHeight) + 'px'
        mStyle.width = Array.isArray(mWidth)
          ? parseFloat(mWidth[i]) + 'px'
          : parseFloat(mWidth) + 'px'
        mStyle.left = Array.isArray(mOffsetX) ? mOffsetX[i] : mOffsetX
        mStyle.top = Array.isArray(mOffsetY) ? mOffsetY[i] : mOffsetY
        mStyle.borderWidth = Array.isArray(mBorderWidth)
          ? mBorderWidth[i]
          : mBorderWidth
        mStyle.borderColor = Array.isArray(mBorderColor)
          ? mBorderColor[i]
          : mBorderColor
        mStyle.borderRadius = Array.isArray(mBorderRadius)
          ? parseFloat(mBorderRadius[i]) + 'px'
          : parseFloat(mBorderRadius) + 'px'
  
        if (w.config.legend.markers.customHTML) {
          if (Array.isArray(w.config.legend.markers.customHTML)) {
            elMarker.innerHTML = w.config.legend.markers.customHTML[i]()
          } else {
            elMarker.innerHTML = w.config.legend.markers.customHTML()
          }
        }
  
        Graphics.setAttrs(elMarker, {
          rel: i + 1,
          'data:collapsed': collapsedSeries || ancillaryCollapsedSeries
        })
  
        if (collapsedSeries || ancillaryCollapsedSeries) {
          elMarker.classList.add('inactive-legend')
        }
  
        let elLegend = document.createElement('div')
  
        let elLegendText = document.createElement('span')
        elLegendText.classList.add('apexcharts-legend-text')
        elLegendText.innerHTML = text
  
        let textColor = w.config.legend.labels.useSeriesColors
          ? w.globals.colors[i]
          : w.config.legend.labels.colors
  
        if (!textColor) {
          textColor = w.config.chart.foreColor
        }
  
        elLegendText.style.color = textColor
  
        elLegendText.style.fontSize = parseFloat(w.config.legend.fontSize) + 'px'
        elLegendText.style.fontFamily = fontFamily || w.config.chart.fontFamily
  
        Graphics.setAttrs(elLegendText, {
          rel: i + 1,
          'data:collapsed': collapsedSeries || ancillaryCollapsedSeries
        })
  
        elLegend.appendChild(elMarker)
        elLegend.appendChild(elLegendText)
  
        const coreUtils = new CoreUtils(this.ctx)
        if (!w.config.legend.showForZeroSeries) {
          const total = coreUtils.getSeriesTotalByIndex(i)
  
          if (
            total === 0 &&
            coreUtils.seriesHaveSameValues(i) &&
            !coreUtils.isSeriesNull(i) &&
            w.globals.collapsedSeriesIndices.indexOf(i) === -1 &&
            w.globals.ancillaryCollapsedSeriesIndices.indexOf(i) === -1
          ) {
            elLegend.classList.add('apexcharts-hidden-zero-series')
          }
        }
  
        if (!w.config.legend.showForNullSeries) {
          if (
            coreUtils.isSeriesNull(i) &&
            w.globals.collapsedSeriesIndices.indexOf(i) === -1 &&
            w.globals.ancillaryCollapsedSeriesIndices.indexOf(i) === -1
          ) {
            elLegend.classList.add('apexcharts-hidden-null-series')
          }
        }
  
        w.globals.dom.elLegendWrap.appendChild(elLegend)
        w.globals.dom.elLegendWrap.classList.add(w.config.legend.horizontalAlign)
        // w.globals.dom.elLegendWrap.classList.add(w.config.legend.verticalAlign)
        w.globals.dom.elLegendWrap.classList.add(
          'position-' + w.config.legend.position
        )
  
        elLegend.classList.add('apexcharts-legend-series')
        elLegend.style.margin = `${w.config.legend.itemMargin.horizontal}px ${
          w.config.legend.itemMargin.vertical
        }px`
        w.globals.dom.elLegendWrap.style.width = w.config.legend.width
          ? w.config.legend.width + 'px'
          : ''
        w.globals.dom.elLegendWrap.style.height = w.config.legend.height
          ? w.config.legend.height + 'px'
          : ''
  
        Graphics.setAttrs(elLegend, {
          rel: i + 1,
          'data:collapsed': collapsedSeries || ancillaryCollapsedSeries
        })
  
        if (collapsedSeries || ancillaryCollapsedSeries) {
          elLegend.classList.add('inactive-legend')
        }
  
        if (!w.config.legend.onItemClick.toggleDataSeries) {
          elLegend.classList.add('no-click')
        }
      }
  
      // for now - just prevent click on heatmap legend - and allow hover only
      const clickAllowed = w.config.chart.type !== 'heatmap'
  
      if (clickAllowed && w.config.legend.onItemClick.toggleDataSeries) {
        w.globals.dom.elWrap.addEventListener('click', self.onLegendClick, true)
      }
  
      if (w.config.legend.onItemHover.highlightDataSeries) {
        w.globals.dom.elWrap.addEventListener(
          'mousemove',
          self.onLegendHovered,
          true
        )
        w.globals.dom.elWrap.addEventListener(
          'mouseout',
          self.onLegendHovered,
          true
        )
      }
    }
  
    getLegendBBox() {
      const w = this.w
      let currLegendsWrap = w.globals.dom.baseEl.querySelector(
        '.apexcharts-legend'
      )
      let currLegendsWrapRect = currLegendsWrap.getBoundingClientRect()
  
      let currLegendsWrapWidth = currLegendsWrapRect.width
      let currLegendsWrapHeight = currLegendsWrapRect.height
  
      return {
        clwh: currLegendsWrapHeight,
        clww: currLegendsWrapWidth
      }
    }
  
    setLegendWrapXY(offsetX, offsetY) {
      let w = this.w
  
      let elLegendWrap = w.globals.dom.baseEl.querySelector('.apexcharts-legend')
  
      const legendRect = elLegendWrap.getBoundingClientRect()
  
      let x = 0
      let y = 0
  
      if (w.config.legend.position === 'bottom') {
        y = y + (w.globals.svgHeight - legendRect.height / 2)
      } else if (w.config.legend.position === 'top') {
        const dim = new Dimensions(this.ctx)
        const titleH = dim.getTitleSubtitleCoords('title').height
        const subtitleH = dim.getTitleSubtitleCoords('subtitle').height
  
        y =
          y +
          (titleH > 0 ? titleH - 10 : 0) +
          (subtitleH > 0 ? subtitleH - 10 : 0)
      }
  
      elLegendWrap.style.position = 'absolute'
  
      x = x + offsetX + w.config.legend.offsetX
      y = y + offsetY + w.config.legend.offsetY
  
      elLegendWrap.style.left = x + 'px'
      elLegendWrap.style.top = y + 'px'
  
      if (w.config.legend.position === 'bottom') {
        elLegendWrap.style.top = 'auto'
        elLegendWrap.style.bottom = 10 + w.config.legend.offsetY + 'px'
      } else if (w.config.legend.position === 'right') {
        elLegendWrap.style.left = 'auto'
        elLegendWrap.style.right = 25 + w.config.legend.offsetX + 'px'
      }
  
      if (elLegendWrap.style.width) {
        elLegendWrap.style.width = parseInt(w.config.legend.width) + 'px'
      }
  
      if (elLegendWrap.style.height) {
        elLegendWrap.style.height = parseInt(w.config.legend.height) + 'px'
      }
    }
  
    legendAlignHorizontal() {
      let w = this.w
  
      let elLegendWrap = w.globals.dom.baseEl.querySelector('.apexcharts-legend')
  
      elLegendWrap.style.right = 0
  
      let lRect = this.getLegendBBox()
  
      let dimensions = new Dimensions(this.ctx)
      let titleRect = dimensions.getTitleSubtitleCoords('title')
      let subtitleRect = dimensions.getTitleSubtitleCoords('subtitle')
  
      let offsetX = 20
      let offsetY = 0
  
      // the whole legend box is set to bottom
      if (w.config.legend.position === 'bottom') {
        offsetY = -lRect.clwh / 1.8
      } else if (w.config.legend.position === 'top') {
        offsetY =
          titleRect.height +
          subtitleRect.height +
          w.config.title.margin +
          w.config.subtitle.margin -
          15
      }
  
      this.setLegendWrapXY(offsetX, offsetY)
    }
  
    legendAlignVertical() {
      let w = this.w
  
      let lRect = this.getLegendBBox()
  
      let offsetY = 20
      let offsetX = 0
  
      if (w.config.legend.position === 'left') {
        offsetX = 20
      }
  
      if (w.config.legend.position === 'right') {
        offsetX = w.globals.svgWidth - lRect.clww - 10
      }
  
      this.setLegendWrapXY(offsetX, offsetY)
    }
  
    onLegendHovered(e) {
      const w = this.w
  
      const hoverOverLegend =
        e.target.classList.contains('apexcharts-legend-text') ||
        e.target.classList.contains('apexcharts-legend-marker')
  
      if (w.config.chart.type !== 'heatmap') {
        if (!e.target.classList.contains('inactive-legend') && hoverOverLegend) {
          let series = new Series(this.ctx)
          series.toggleSeriesOnHover(e, e.target)
        }
      } else {
        // for heatmap handling
        if (hoverOverLegend) {
          let seriesCnt = parseInt(e.target.getAttribute('rel')) - 1
          this.ctx.fireEvent('legendHover', [this.ctx, seriesCnt, this.w])
  
          let series = new Series(this.ctx)
          series.highlightRangeInSeries(e, e.target)
        }
      }
    }
  
    onLegendClick(e) {
      if (
        e.target.classList.contains('apexcharts-legend-text') ||
        e.target.classList.contains('apexcharts-legend-marker')
      ) {
        let seriesCnt = parseInt(e.target.getAttribute('rel')) - 1
        let isHidden = e.target.getAttribute('data:collapsed') === 'true'
  
        const legendClick = this.w.config.chart.events.legendClick
        if (typeof legendClick === 'function') {
          legendClick(this.ctx, seriesCnt, this.w)
        }
  
        this.ctx.fireEvent('legendClick', [this.ctx, seriesCnt, this.w])
  
        const markerClick = this.w.config.legend.markers.onClick
        if (
          typeof markerClick === 'function' &&
          e.target.classList.contains('apexcharts-legend-marker')
        ) {
          markerClick(this.ctx, seriesCnt, this.w)
          this.ctx.fireEvent('legendMarkerClick', [this.ctx, seriesCnt, this.w])
        }
  
        this.toggleDataSeries(seriesCnt, isHidden)
      }
    }
  
    getLegendStyles() {
      var stylesheet = document.createElement('style')
      stylesheet.setAttribute('type', 'text/css')
  
      const text = `
      
        .apexcharts-legend {
          display: flex;
          overflow: auto;
          padding: 0 10px;
        }
  
        .apexcharts-legend.position-bottom, .apexcharts-legend.position-top {
          flex-wrap: wrap
        }
        .apexcharts-legend.position-right, .apexcharts-legend.position-left {
          flex-direction: column;
          bottom: 0;
        }
  
        .apexcharts-legend.position-bottom.left, .apexcharts-legend.position-top.left, .apexcharts-legend.position-right, .apexcharts-legend.position-left {
          justify-content: flex-start;
        }
  
        .apexcharts-legend.position-bottom.center, .apexcharts-legend.position-top.center {
          justify-content: center;  
        }
  
        .apexcharts-legend.position-bottom.right, .apexcharts-legend.position-top.right {
          justify-content: flex-end;
        }
  
        .apexcharts-legend-series {
          cursor: pointer;
          line-height: normal;
        }
  
        .apexcharts-legend.position-bottom .apexcharts-legend-series, .apexcharts-legend.position-top .apexcharts-legend-series{
          display: flex;
          align-items: center;
        }
  
        .apexcharts-legend-text {
          position: relative;
          font-size: 14px;
        }
  
        .apexcharts-legend-text *, .apexcharts-legend-marker * {
          pointer-events: none;
        }
  
        .apexcharts-legend-marker {
          position: relative;
          display: inline-block;
          cursor: pointer;
          margin-right: 3px;
        }
        
        .apexcharts-legend.right .apexcharts-legend-series, .apexcharts-legend.left .apexcharts-legend-series{
          display: inline-block;
        }
  
        .apexcharts-legend-series.no-click {
          cursor: auto;
        }
  
        .apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {
          display: none !important;
        }
  
        .inactive-legend {
          opacity: 0.45;
        }`
  
      var rules = document.createTextNode(text)
  
      stylesheet.appendChild(rules)
  
      return stylesheet
    }
  
    toggleDataSeries(seriesCnt, isHidden) {
      const w = this.w
      if (w.globals.axisCharts || w.config.chart.type === 'radialBar') {
        w.globals.resized = true // we don't want initial animations again
  
        let seriesEl = null
  
        let realIndex = null
  
        // yes, make it null. 1 series will rise at a time
        w.globals.risingSeries = []
  
        if (w.globals.axisCharts) {
          seriesEl = w.globals.dom.baseEl.querySelector(
            `.apexcharts-series[data\\:realIndex='${seriesCnt}']`
          )
          realIndex = parseInt(seriesEl.getAttribute('data:realIndex'))
        } else {
          seriesEl = w.globals.dom.baseEl.querySelector(
            `.apexcharts-series[rel='${seriesCnt + 1}']`
          )
          realIndex = parseInt(seriesEl.getAttribute('rel')) - 1
        }
  
        if (isHidden) {
          this.riseCollapsedSeries(
            w.globals.collapsedSeries,
            w.globals.collapsedSeriesIndices,
            realIndex
          )
          this.riseCollapsedSeries(
            w.globals.ancillaryCollapsedSeries,
            w.globals.ancillaryCollapsedSeriesIndices,
            realIndex
          )
        } else {
          if (w.globals.axisCharts) {
            let shouldNotHideYAxis = false
  
            if (
              w.config.yaxis[realIndex] &&
              w.config.yaxis[realIndex].show &&
              w.config.yaxis[realIndex].showAlways
            ) {
              shouldNotHideYAxis = true
              if (
                w.globals.ancillaryCollapsedSeriesIndices.indexOf(realIndex) < 0
              ) {
                w.globals.ancillaryCollapsedSeries.push({
                  index: realIndex,
                  data: w.config.series[realIndex].data.slice(),
                  type: seriesEl.parentNode.className.baseVal.split('-')[1]
                })
                w.globals.ancillaryCollapsedSeriesIndices.push(realIndex)
              }
            }
  
            if (!shouldNotHideYAxis) {
              w.globals.collapsedSeries.push({
                index: realIndex,
                data: w.config.series[realIndex].data.slice(),
                type: seriesEl.parentNode.className.baseVal.split('-')[1]
              })
              w.globals.collapsedSeriesIndices.push(realIndex)
  
              let removeIndexOfRising = w.globals.risingSeries.indexOf(realIndex)
  
              w.globals.risingSeries.splice(removeIndexOfRising, 1)
            }
  
            // TODO: AVOID mutating the user's config object below
            w.config.series[realIndex].data = []
          } else {
            w.globals.collapsedSeries.push({
              index: realIndex,
              data: w.config.series[realIndex]
            })
            w.globals.collapsedSeriesIndices.push(realIndex)
            w.config.series[realIndex] = 0
          }
  
          let seriesChildren = seriesEl.childNodes
          for (let sc = 0; sc < seriesChildren.length; sc++) {
            if (
              seriesChildren[sc].classList.contains(
                'apexcharts-series-markers-wrap'
              )
            ) {
              if (seriesChildren[sc].classList.contains('apexcharts-hide')) {
                seriesChildren[sc].classList.remove('apexcharts-hide')
              } else {
                seriesChildren[sc].classList.add('apexcharts-hide')
              }
            }
          }
  
          w.globals.allSeriesCollapsed =
            w.globals.collapsedSeries.length === w.globals.series.length
  
          this.ctx._updateSeries(
            w.config.series,
            w.config.chart.animations.dynamicAnimation.enabled
          )
        }
      } else {
        // for non-axis charts i.e pie / donuts
        let seriesEl = w.globals.dom.Paper.select(
          ` .apexcharts-series[rel='${seriesCnt + 1}'] path`
        )
  
        const type = w.config.chart.type
        if (type === 'pie' || type === 'donut') {
          let dataLabels = w.config.plotOptions.pie.donut.labels
  
          const graphics = new Graphics(this.ctx)
          const pie = new Pie(this.ctx)
          graphics.pathMouseDown(seriesEl.members[0], null)
          pie.printDataLabelsInner(seriesEl.members[0].node, dataLabels)
        }
  
        seriesEl.fire('click')
      }
    }
  
    riseCollapsedSeries(series, seriesIndices, realIndex) {
      const w = this.w
  
      if (series.length > 0) {
        for (let c = 0; c < series.length; c++) {
          if (series[c].index === realIndex) {
            if (w.globals.axisCharts) {
              w.config.series[realIndex].data = series[c].data.slice()
              series.splice(c, 1)
              seriesIndices.splice(c, 1)
              w.globals.risingSeries.push(realIndex)
            } else {
              w.config.series[realIndex] = series[c].data
              series.splice(c, 1)
              seriesIndices.splice(c, 1)
              w.globals.risingSeries.push(realIndex)
            }
            this.ctx._updateSeries(
              w.config.series,
              w.config.chart.animations.dynamicAnimation.enabled
            )
          }
        }
      }
    }
  }
  
  export default Legend
  