/*******************************************************************************
 * Licensed Materials - Property of IBM
 * (c) Copyright IBM Corporation 2018, 2019. All Rights Reserved.
 * Copyright (c) 2020 Red Hat, Inc.
 *
 * Note to U.S. Government Users Restricted Rights:
 * Use, duplication or disclosure restricted by GSA ADP Schedule
 * Contract with IBM Corp.
 *******************************************************************************/
'use strict'

import * as d3 from 'd3'
import 'd3-selection-multi'
import SVG from 'svg.js'
import { counterZoom } from '../../utils/diagram-helpers'

export default class TitleHelper {
  /**
   * Helper class to be used by TopologyDiagram.
   *
   * Contains functions to draw and manage nodes in the diagram.
   */
  constructor(svg, titles) {
    this.svg = svg
    this.titles = titles
  }

  updateDiagramTitles = currentZoom => {
    const draw =
      typeof SVG === 'function'
        ? SVG(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
        : undefined

    // Add title groups to diagram
    const titles = this.svg
      .select('g.titles')
      .selectAll('g.title')
      .data(this.titles, t => {
        return t.hashCode
      })

    // remove titles that no longer have data (in exit array)
    titles.exit().remove()

    // add new titles
    const newTitles = titles
      .enter()
      .append('g')
      .style('opacity', 0.0)
      .attr('class', 'title')
      .attr('transform', currentZoom)

    newTitles.append('title').text(t => {
      return t.title
    })

    // create label
    newTitles
      .append('g')
      .attr('class', 'titleLabel')
      .html(d => {
        const { title } = d
        const text = draw.text(add => {
          title.split('\n').forEach((line, idx) => {
            if (line) {
              add
                .tspan(line)
                .addClass('counter-zoom')
                .addClass(idx === 0 ? 'first-line' : '')
                .newLine()
            }
          })
        })
        return text.svg()
      })
  };

  moveTitles = (transition, currentZoom, searchChanged) => {
    const titles = this.svg
      .select('g.titles')
      .selectAll('g.title')
      .attr('transform', currentZoom)
      .styles(() => {
        return {
          opacity: searchChanged ? 0.0 : 1.0
        }
      })

    titles.transition(transition).styles(() => {
      return {
        opacity: 1.0
      }
    })

    titles.selectAll('g.titleLabel').each((d, i, ns) => {
      const { x, y } = d
      const titleLabel = d3.select(ns[i])
      titleLabel.selectAll('text').attrs(() => {
        return {
          x: x,
          y: y
        }
      })
      titleLabel.selectAll('tspan').attr('x', () => {
        return x
      })
    })
  };
}

// interrupt any transition and make sure it has its final value
export const interruptTitles = svg => {
  svg
    .select('g.titles')
    .selectAll('g.title')
    .interrupt()
    .call(selection => {
      selection.each((d, i, ns) => {
        d3.select(ns[i]).style('opacity', 1.0)
      })
    })
}

export const counterZoomTitles = (svg, currentZoom) => {
  if (svg) {
    const fontSize = counterZoom(currentZoom.k, 0.2, 0.85, 14, 32)
    const titles = svg.select('g.titles')
    titles.selectAll('tspan.counter-zoom').style('font-size', `${fontSize}px`)
    titles
      .selectAll('tspan.first-line.counter-zoom')
      .style('font-size', `${fontSize + 5}px`)
      .style('font-weight', 'bold')
  }
}
