text: /**
   * @module meteoJS/thermodynamicDiagram/axis
   */
  import {
    getNormalizedTextOptions
  } from './Functions.js';
  import PlotArea from './PlotArea.js';
  
  /**
   * Definitions for the labels of an axis.
   * 
   * @typedef {module:meteoJS/thermodynamicDiagram~textOptions}
   *   module:meteoJS/thermodynamicDiagram/axis~labelsOptions
   * @property {number} [interval] - Interval between the labels.
   * @property {string} [unit] - Unit of the label values.
   * @property {string} [prefix=''] - Prefix of the label text.
   * @property {integer} [decimalPlaces=0]
   *   Number of digits to appear after the decimal point of the label values.
   */
  
  /**
   * Title definition for an axis.
   * 
   * @typedef {module:meteoJS/thermodynamicDiagram~textOptions}
   *   module:meteoJS/thermodynamicDiagram/axis~titleOptions
   * @property {string} [text=''] - Title text.
   */
  
  /**
   * Options for the constructor.
   * 
   * @typedef {module:meteoJS/thermodynamicDiagram/plotArea~options}
   *   module:meteoJS/thermodynamicDiagram/axis~options
   * @property {module:meteoJS/thermodynamicDiagram/axis~labelsOptions} labels
   *   Options for the yAxis Labels.
   * @property {module:meteoJS/thermodynamicDiagram/axis~titleOptions} title
   *   Options for the title of the Axis.
   * @property {boolean} [isHorizontal=true]
   *   Internal. Is the axis horizontal or vertical.
   */
  
  /**
   * Abstract class to draw an axis with labelling.
   * 
   * @extends module:meteoJS/thermodynamicDiagram/plotArea.PlotArea
   * @abstract
   */
  export class Axis extends PlotArea {
  
    /**
     * @param {module:meteoJS/thermodynamicDiagram/axis~options} options
     *   Options.
     */
    constructor({
      svgNode = undefined,
      coordinateSystem,
      x,
      y,
      width,
      height,
      style = {},
      visible = true,
      events = {},
      labels = {},
      title = {},
      isHorizontal = true
    }) {
      if (style.overflow === undefined)
        style.overflow = 'visible';
      
      super({
        svgNode,
        coordinateSystem,
        x,
        y,
        width,
        height,
        style,
        visible,
        events
      });
      
      /**
       * @type Object
       * @private
       */
      this._labelsOptions = this.getNormalizedLabelsOptions(labels);
      
      /**
       * @type Object
       * @private
       */
      this._titleOptions = getNormalizedTitleOptions(title);
  
      /**
       * @type boolean
       * @private
       */
      this._isHorizontal = isHorizontal;
      
      this.init();
    }
  
    /**
     * Normalize the options for the labels.
     * 
     * @param {module:meteoJS/thermodynamicDiagram/axis~labelsOptions}
     *   options - Options.
     * @returns {module:meteoJS/thermodynamicDiagram/axis~labelsOptions}
     *   Normalized options.
     */
    getNormalizedLabelsOptions({
      interval = undefined,
      unit = '',
      prefix = '',
      decimalPlaces = 0,
      ...rest
    }) {
      const options = getNormalizedTextOptions({ ...rest }, {
        font: {
          size: 11,
          anchor: 'middle'
        }
      });
      options.interval = interval;
      options.unit = unit;
      options.prefix = prefix;
      options.decimalPlaces = decimalPlaces;
      return options;
    }
  
    /**
     * Draws the labels of the axis.
     * 
     * @param {external:SVG} svgNode - Node to draw into.
     * @param {number} min - Minimum value for the labels.
     * @param {number} max - Maximum value for the labels.
     * @param {Function} getTextByInterval
     *   Returns the text representation of the label value (its argument).
     * @param {Function} getPositionByInterval
     *   Returns the position in pixels of the label value (its argument).
     * @internal
     */
    drawLabels({
      svgNode,
      min,
      max,
      getTextByInterval =
      i => Number.parseFloat(i).toFixed(this._labelsOptions.decimalPlaces),
      getPositionByInterval
    }) {
      for (let i=min; i<=max; i+=this._labelsOptions.interval) {
        let text = getTextByInterval(i);
        text += this._labelsOptions.prefix;
        let fontColor = undefined;
        const font = {...this._labelsOptions.font};
        if ('color' in font) {
          fontColor = font.color;
          delete font.color;
        }
        if (!this._isHorizontal)
          font['anchor'] = 'end';
        const textNode = svgNode
          .plain(text)
          .font(font);
        if (this._isHorizontal) {
          textNode.center(
            getPositionByInterval(i),
            font.size
          );
          if (font['anchor'] == 'end')
            textNode.dx(-textNode.bbox().width/2);
          else if (font['anchor'] == 'start')
            textNode.dx(+textNode.bbox().width/2);
        }
        else
          textNode
            .x(this.width)
            .cy(getPositionByInterval(i))
            .dx(-textNode.bbox().width);
        if (fontColor !== undefined)
          textNode.fill(fontColor);
      }
    }
  
    /**
     * Draws a title for the axis.
     * 
     * @param {Object} options - Options.
     * @param {external:SVG} svgNode - Node to insert into.
     * @param {external:SVG} svgLabelsNode - Node of the axis labels.
     * @private
     */
    _drawTitle({
      svgNode,
      svgLabelsNode
    }) {
      let rotation = 0;
      if (!this._isHorizontal)
        rotation = -90;
      let margin = 0;
      if (svgLabelsNode !== undefined)
        margin = (rotation == -90)
          ? svgLabelsNode.bbox().width
          : svgLabelsNode.bbox().height;
      
      let fontColor = undefined;
      const font = {...this._titleOptions.font};
      if ('color' in font) {
        fontColor = font.color;
        delete font.color;
      }
      let cxText = this.width/2;
      let cyText = font.size + margin;
      if (rotation == -90) {
        cxText = this.width - font.size - margin;
        cyText = this.height/2;
      }
      const textNode = svgNode
        .plain(this._titleOptions.text)
        .font(font)
        .center(cxText, cyText)
        .rotate(rotation);
      if (fontColor !== undefined)
        textNode.fill(fontColor);
      if (rotation == -90) {
        if (font['anchor'] == 'end')
          textNode.dy(-textNode.bbox().height/2);
        else if (font['anchor'] == 'start')
          textNode.dy(+textNode.bbox().height/2);
      }
      else {
        if (font['anchor'] == 'end')
          textNode.dx(-textNode.bbox().width/2);
        else if (font['anchor'] == 'start')
          textNode.dx(+textNode.bbox().width/2);
      }
    }
    
    /**
     * Draw background into SVG group.
     * 
     * @override
     */
    _drawBackground(svgNode) {
      super._drawBackground(svgNode);
      
      let svgLabelsGroup = undefined;
      if (this._labelsOptions.visible) {
        svgLabelsGroup = svgNode.group();
        this.drawLabels({
          svgNode: svgLabelsGroup
        });
      }
      
      if (this._titleOptions.visible)
        this._drawTitle({
          svgNode: svgNode.group(),
          svgLabelsNode: svgLabelsGroup
        });
    }
    
  }
  export default Axis;
  
  /**
   * Normalize the options for the title.
   * 
   * @param {module:meteoJS/thermodynamicDiagram/axis~titleOptions}
   *   options - Options.
   * @returns {module:meteoJS/thermodynamicDiagram/axis~titleOptions}
   *   Normalized options.
   */
  function getNormalizedTitleOptions({
    text = '',
    ...rest
  }) {
    const options = getNormalizedTextOptions({...rest}, {
      font: {
        anchor: 'middle'
      }
    });
    options.text = text;
    return options;
  }