text: import Graphics from '../Graphics'
  import Utils from '../../utils/Utils'
  import AxesUtils from './AxesUtils'
  
  /**
   * ApexCharts YAxis Class for drawing Y-Axis.
   *
   * @module YAxis
   **/
  
  export default class YAxis {
    constructor(ctx) {
      this.ctx = ctx
      this.w = ctx.w
      const w = this.w
  
      this.xaxisFontSize = w.config.xaxis.labels.style.fontSize
      this.axisFontFamily = w.config.xaxis.labels.style.fontFamily
  
      this.xaxisForeColors = w.config.xaxis.labels.style.colors
      this.isCategoryBarHorizontal =
        w.config.chart.type === 'bar' && w.config.plotOptions.bar.horizontal
  
      this.xAxisoffX = 0
      if (w.config.xaxis.position === 'bottom') {
        this.xAxisoffX = w.globals.gridHeight
      }
      this.drawnLabels = []
      this.axesUtils = new AxesUtils(ctx)
    }
  
    drawYaxis(realIndex) {
      let w = this.w
      let graphics = new Graphics(this.ctx)
  
      const yaxisStyle = w.config.yaxis[realIndex].labels.style
      let yaxisFontSize = yaxisStyle.fontSize
      let yaxisFontFamily = yaxisStyle.fontFamily
      let yaxisFontWeight = yaxisStyle.fontWeight
  
      let elYaxis = graphics.group({
        class: 'apexcharts-yaxis',
        rel: realIndex,
        transform: 'translate(' + w.globals.translateYAxisX[realIndex] + ', 0)'
      })
  
      if (this.axesUtils.isYAxisHidden(realIndex)) {
        return elYaxis
      }
  
      let elYaxisTexts = graphics.group({
        class: 'apexcharts-yaxis-texts-g'
      })
  
      elYaxis.add(elYaxisTexts)
  
      let tickAmount = w.globals.yAxisScale[realIndex].result.length - 1
  
      // labelsDivider is simply svg height/number of ticks
      let labelsDivider = w.globals.gridHeight / tickAmount
  
      // initial label position = 0;
      let l = w.globals.translateY
      let lbFormatter = w.globals.yLabelFormatters[realIndex]
  
      let labels = w.globals.yAxisScale[realIndex].result.slice()
  
      labels = this.axesUtils.checkForReversedLabels(realIndex, labels)
  
      let firstLabel = ''
      if (w.config.yaxis[realIndex].labels.show) {
        for (let i = tickAmount; i >= 0; i--) {
          let val = labels[i]
  
          val = lbFormatter(val, i, w)
  
          let xPad = w.config.yaxis[realIndex].labels.padding
          if (w.config.yaxis[realIndex].opposite && w.config.yaxis.length !== 0) {
            xPad = xPad * -1
          }
  
          const yColors = this.axesUtils.getYAxisForeColor(
            yaxisStyle.colors,
            realIndex
          )
          const getForeColor = () => {
            return Array.isArray(yColors) ? yColors[i] : yColors
          }
  
          let label = graphics.drawText({
            x: xPad,
            y: l + tickAmount / 10 + w.config.yaxis[realIndex].labels.offsetY + 1,
            text: val,
            textAnchor: w.config.yaxis[realIndex].opposite ? 'start' : 'end',
            fontSize: yaxisFontSize,
            fontFamily: yaxisFontFamily,
            fontWeight: yaxisFontWeight,
            foreColor: getForeColor(),
            isPlainText: false,
            cssClass: 'apexcharts-yaxis-label ' + yaxisStyle.cssClass
          })
          if (i === tickAmount) {
            firstLabel = label
          }
          elYaxisTexts.add(label)
  
          let elTooltipTitle = document.createElementNS(w.globals.SVGNS, 'title')
          elTooltipTitle.textContent = Array.isArray(val) ? val.join(' ') : val
          label.node.appendChild(elTooltipTitle)
  
          if (w.config.yaxis[realIndex].labels.rotate !== 0) {
            let firstabelRotatingCenter = graphics.rotateAroundCenter(
              firstLabel.node
            )
            let labelRotatingCenter = graphics.rotateAroundCenter(label.node)
            label.node.setAttribute(
              'transform',
              `rotate(${w.config.yaxis[realIndex].labels.rotate} ${firstabelRotatingCenter.x} ${labelRotatingCenter.y})`
            )
          }
          l = l + labelsDivider
        }
      }
  
      if (w.config.yaxis[realIndex].title.text !== undefined) {
        let elYaxisTitle = graphics.group({
          class: 'apexcharts-yaxis-title'
        })
  
        let x = 0
        if (w.config.yaxis[realIndex].opposite) {
          x = w.globals.translateYAxisX[realIndex]
        }
        let elYAxisTitleText = graphics.drawText({
          x,
          y:
            w.globals.gridHeight / 2 +
            w.globals.translateY +
            w.config.yaxis[realIndex].title.offsetY,
          text: w.config.yaxis[realIndex].title.text,
          textAnchor: 'end',
          foreColor: w.config.yaxis[realIndex].title.style.color,
          fontSize: w.config.yaxis[realIndex].title.style.fontSize,
          fontWeight: w.config.yaxis[realIndex].title.style.fontWeight,
          fontFamily: w.config.yaxis[realIndex].title.style.fontFamily,
          cssClass:
            'apexcharts-yaxis-title-text ' +
            w.config.yaxis[realIndex].title.style.cssClass
        })
  
        elYaxisTitle.add(elYAxisTitleText)
  
        elYaxis.add(elYaxisTitle)
      }
  
      let axisBorder = w.config.yaxis[realIndex].axisBorder
  
      let x = 31 + axisBorder.offsetX
      if (w.config.yaxis[realIndex].opposite) {
        x = -31 - axisBorder.offsetX
      }
  
      if (axisBorder.show) {
        let elVerticalLine = graphics.drawLine(
          x,
          w.globals.translateY + axisBorder.offsetY - 2,
          x,
          w.globals.gridHeight + w.globals.translateY + axisBorder.offsetY + 2,
          axisBorder.color,
          0,
          axisBorder.width
        )
  
        elYaxis.add(elVerticalLine)
      }
      if (w.config.yaxis[realIndex].axisTicks.show) {
        this.axesUtils.drawYAxisTicks(
          x,
          tickAmount,
          axisBorder,
          w.config.yaxis[realIndex].axisTicks,
          realIndex,
          labelsDivider,
          elYaxis
        )
      }
  
      return elYaxis
    }
  
    // This actually becomes horizontal axis (for bar charts)
    drawYaxisInversed(realIndex) {
      let w = this.w
      let graphics = new Graphics(this.ctx)
  
      let elXaxis = graphics.group({
        class: 'apexcharts-xaxis apexcharts-yaxis-inversed'
      })
  
      let elXaxisTexts = graphics.group({
        class: 'apexcharts-xaxis-texts-g',
        transform: `translate(${w.globals.translateXAxisX}, ${w.globals.translateXAxisY})`
      })
  
      elXaxis.add(elXaxisTexts)
  
      let tickAmount = w.globals.yAxisScale[realIndex].result.length - 1
  
      // labelsDivider is simply svg width/number of ticks
      let labelsDivider = w.globals.gridWidth / tickAmount + 0.1
  
      // initial label position;
      let l = labelsDivider + w.config.xaxis.labels.offsetX
  
      let lbFormatter = w.globals.xLabelFormatter
  
      let labels = w.globals.yAxisScale[realIndex].result.slice()
  
      let timescaleLabels = w.globals.timescaleLabels
      if (timescaleLabels.length > 0) {
        this.xaxisLabels = timescaleLabels.slice()
        labels = timescaleLabels.slice()
        tickAmount = labels.length
      }
  
      labels = this.axesUtils.checkForReversedLabels(realIndex, labels)
  
      const tl = timescaleLabels.length
  
      if (w.config.xaxis.labels.show) {
        for (let i = tl ? 0 : tickAmount; tl ? i < tl : i >= 0; tl ? i++ : i--) {
          let val = labels[i]
          val = lbFormatter(val, i, w)
  
          let x =
            w.globals.gridWidth +
            w.globals.padHorizontal -
            (l - labelsDivider + w.config.xaxis.labels.offsetX)
  
          if (timescaleLabels.length) {
            let label = this.axesUtils.getLabel(
              labels,
              timescaleLabels,
              x,
              i,
              this.drawnLabels,
              this.xaxisFontSize
            )
            x = label.x
            val = label.text
            this.drawnLabels.push(label.text)
  
            if (i === 0 && w.globals.skipFirstTimelinelabel) {
              val = ''
            }
            if (i === labels.length - 1 && w.globals.skipLastTimelinelabel) {
              val = ''
            }
          }
          let elTick = graphics.drawText({
            x,
            y:
              this.xAxisoffX +
              w.config.xaxis.labels.offsetY +
              30 -
              (w.config.xaxis.position === 'top'
                ? w.globals.xAxisHeight + w.config.xaxis.axisTicks.height - 2
                : 0),
            text: val,
            textAnchor: 'middle',
            foreColor: Array.isArray(this.xaxisForeColors)
              ? this.xaxisForeColors[realIndex]
              : this.xaxisForeColors,
            fontSize: this.xaxisFontSize,
            fontFamily: this.xaxisFontFamily,
            fontWeight: w.config.xaxis.labels.style.fontWeight,
            isPlainText: false,
            cssClass:
              'apexcharts-xaxis-label ' + w.config.xaxis.labels.style.cssClass
          })
  
          elXaxisTexts.add(elTick)
  
          elTick.tspan(val)
  
          let elTooltipTitle = document.createElementNS(w.globals.SVGNS, 'title')
          elTooltipTitle.textContent = val
          elTick.node.appendChild(elTooltipTitle)
  
          l = l + labelsDivider
        }
      }
  
      this.inversedYAxisTitleText(elXaxis)
      this.inversedYAxisBorder(elXaxis)
  
      return elXaxis
    }
  
    inversedYAxisBorder(parent) {
      const w = this.w
      const graphics = new Graphics(this.ctx)
  
      let axisBorder = w.config.xaxis.axisBorder
      if (axisBorder.show) {
        let lineCorrection = 0
        if (w.config.chart.type === 'bar' && w.globals.isXNumeric) {
          lineCorrection = lineCorrection - 15
        }
        let elHorzLine = graphics.drawLine(
          w.globals.padHorizontal + lineCorrection + axisBorder.offsetX,
          this.xAxisoffX,
          w.globals.gridWidth,
          this.xAxisoffX,
          axisBorder.color,
          0,
          axisBorder.height
        )
  
        parent.add(elHorzLine)
      }
    }
  
    inversedYAxisTitleText(parent) {
      const w = this.w
      const graphics = new Graphics(this.ctx)
      if (w.config.xaxis.title.text !== undefined) {
        let elYaxisTitle = graphics.group({
          class: 'apexcharts-xaxis-title apexcharts-yaxis-title-inversed'
        })
  
        let elYAxisTitleText = graphics.drawText({
          x: w.globals.gridWidth / 2 + w.config.xaxis.title.offsetX,
          y:
            this.xAxisoffX +
            parseFloat(this.xaxisFontSize) +
            parseFloat(w.config.xaxis.title.style.fontSize) +
            w.config.xaxis.title.offsetY +
            20,
          text: w.config.xaxis.title.text,
          textAnchor: 'middle',
          fontSize: w.config.xaxis.title.style.fontSize,
          fontFamily: w.config.xaxis.title.style.fontFamily,
          fontWeight: w.config.xaxis.title.style.fontWeight,
          foreColor: w.config.xaxis.title.style.color,
          cssClass:
            'apexcharts-xaxis-title-text ' + w.config.xaxis.title.style.cssClass
        })
  
        elYaxisTitle.add(elYAxisTitleText)
  
        parent.add(elYaxisTitle)
      }
    }
  
    yAxisTitleRotate(realIndex, yAxisOpposite) {
      let w = this.w
  
      let graphics = new Graphics(this.ctx)
  
      let yAxisLabelsCoord = {
        width: 0,
        height: 0
      }
      let yAxisTitleCoord = {
        width: 0,
        height: 0
      }
  
      let elYAxisLabelsWrap = w.globals.dom.baseEl.querySelector(
        ` .apexcharts-yaxis[rel='${realIndex}'] .apexcharts-yaxis-texts-g`
      )
  
      if (elYAxisLabelsWrap !== null) {
        yAxisLabelsCoord = elYAxisLabelsWrap.getBoundingClientRect()
      }
  
      let yAxisTitle = w.globals.dom.baseEl.querySelector(
        `.apexcharts-yaxis[rel='${realIndex}'] .apexcharts-yaxis-title text`
      )
  
      if (yAxisTitle !== null) {
        yAxisTitleCoord = yAxisTitle.getBoundingClientRect()
      }
  
      if (yAxisTitle !== null) {
        let x = this.xPaddingForYAxisTitle(
          realIndex,
          yAxisLabelsCoord,
          yAxisTitleCoord,
          yAxisOpposite
        )
  
        yAxisTitle.setAttribute('x', x.xPos - (yAxisOpposite ? 10 : 0))
      }
  
      if (yAxisTitle !== null) {
        let titleRotatingCenter = graphics.rotateAroundCenter(yAxisTitle)
        yAxisTitle.setAttribute(
          'transform',
          `rotate(${
            yAxisOpposite
              ? w.config.yaxis[realIndex].title.rotate * -1
              : w.config.yaxis[realIndex].title.rotate
          } ${titleRotatingCenter.x} ${titleRotatingCenter.y})`
        )
      }
    }
  
    xPaddingForYAxisTitle(
      realIndex,
      yAxisLabelsCoord,
      yAxisTitleCoord,
      yAxisOpposite
    ) {
      let w = this.w
      let oppositeAxisCount = 0
  
      let x = 0
      let padd = 10
  
      if (w.config.yaxis[realIndex].title.text === undefined || realIndex < 0) {
        return {
          xPos: x,
          padd: 0
        }
      }
  
      if (yAxisOpposite) {
        x =
          yAxisLabelsCoord.width +
          w.config.yaxis[realIndex].title.offsetX +
          yAxisTitleCoord.width / 2 +
          padd / 2
  
        oppositeAxisCount += 1
  
        if (oppositeAxisCount === 0) {
          x = x - padd / 2
        }
      } else {
        x =
          yAxisLabelsCoord.width * -1 +
          w.config.yaxis[realIndex].title.offsetX +
          padd / 2 +
          yAxisTitleCoord.width / 2
  
        if (w.globals.isBarHorizontal) {
          padd = 25
          x =
            yAxisLabelsCoord.width * -1 -
            w.config.yaxis[realIndex].title.offsetX -
            padd
        }
      }
  
      return {
        xPos: x,
        padd
      }
    }
  
    // sets the x position of the y-axis by counting the labels width, title width and any offset
    setYAxisXPosition(yaxisLabelCoords, yTitleCoords) {
      let w = this.w
  
      let xLeft = 0
      let xRight = 0
      let leftOffsetX = 18
      let rightOffsetX = 1
  
      if (w.config.yaxis.length > 1) {
        this.multipleYs = true
      }
  
      w.config.yaxis.map((yaxe, index) => {
        let shouldNotDrawAxis =
          w.globals.ignoreYAxisIndexes.indexOf(index) > -1 ||
          !yaxe.show ||
          yaxe.floating ||
          yaxisLabelCoords[index].width === 0
  
        let axisWidth = yaxisLabelCoords[index].width + yTitleCoords[index].width
  
        if (!yaxe.opposite) {
          xLeft = w.globals.translateX - leftOffsetX
  
          if (!shouldNotDrawAxis) {
            leftOffsetX = leftOffsetX + axisWidth + 20
          }
  
          w.globals.translateYAxisX[index] = xLeft + yaxe.labels.offsetX
        } else {
          if (w.globals.isBarHorizontal) {
            xRight = w.globals.gridWidth + w.globals.translateX - 1
  
            w.globals.translateYAxisX[index] = xRight - yaxe.labels.offsetX
          } else {
            xRight = w.globals.gridWidth + w.globals.translateX + rightOffsetX
  
            if (!shouldNotDrawAxis) {
              rightOffsetX = rightOffsetX + axisWidth + 20
            }
  
            w.globals.translateYAxisX[index] = xRight - yaxe.labels.offsetX + 20
          }
        }
      })
    }
  
    setYAxisTextAlignments() {
      const w = this.w
  
      let yaxis = w.globals.dom.baseEl.getElementsByClassName(`apexcharts-yaxis`)
      yaxis = Utils.listToArray(yaxis)
      yaxis.forEach((y, index) => {
        const yaxe = w.config.yaxis[index]
        // proceed only if user has specified alignment
        if (yaxe && yaxe.labels.align !== undefined) {
          const yAxisInner = w.globals.dom.baseEl.querySelector(
            `.apexcharts-yaxis[rel='${index}'] .apexcharts-yaxis-texts-g`
          )
          let yAxisTexts = w.globals.dom.baseEl.querySelectorAll(
            `.apexcharts-yaxis[rel='${index}'] .apexcharts-yaxis-label`
          )
  
          yAxisTexts = Utils.listToArray(yAxisTexts)
  
          const rect = yAxisInner.getBoundingClientRect()
  
          if (yaxe.labels.align === 'left') {
            yAxisTexts.forEach((label, lI) => {
              label.setAttribute('text-anchor', 'start')
            })
            if (!yaxe.opposite) {
              yAxisInner.setAttribute('transform', `translate(-${rect.width}, 0)`)
            }
          } else if (yaxe.labels.align === 'center') {
            yAxisTexts.forEach((label, lI) => {
              label.setAttribute('text-anchor', 'middle')
            })
            yAxisInner.setAttribute(
              'transform',
              `translate(${(rect.width / 2) * (!yaxe.opposite ? -1 : 1)}, 0)`
            )
          } else if (yaxe.labels.align === 'right') {
            yAxisTexts.forEach((label, lI) => {
              label.setAttribute('text-anchor', 'end')
            })
            if (yaxe.opposite) {
              yAxisInner.setAttribute('transform', `translate(${rect.width}, 0)`)
            }
          }
        }
      })
    }
  }
  