//
// Copyright 2014 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//

part of charted.charts;

/// Displays either one or two dimension axes and zero or more measure axis.
/// The number of measure axes displayed is zero in charts like bubble chart
/// which contain two dimension axes.
class DefaultCartesianAreaImpl implements CartesianArea {
  /// Default identifiers used by the measure axes
  static const MEASURE_AXIS_IDS = const <String>['_default'];

  /// Orientations used by measure axes. First, when "x" axis is the primary
  /// and the only dimension. Second, when "y" axis is the primary and the only
  /// dimension.
  static const MEASURE_AXIS_ORIENTATIONS = const [
    const [ORIENTATION_LEFT, ORIENTATION_RIGHT],
    const [ORIENTATION_BOTTOM, ORIENTATION_TOP]
  ];

  /// Orientations used by the dimension axes. First, when "x" is the
  /// primary dimension and the last one for cases where "y" axis is primary
  /// dimension.
  static const DIMENSION_AXIS_ORIENTATIONS = const [
    const [ORIENTATION_BOTTOM, ORIENTATION_LEFT],
    const [ORIENTATION_LEFT, ORIENTATION_BOTTOM]
  ];

  /// Mapping of measure axis Id to it's axis.
  final _measureAxes = new LinkedHashMap<String, DefaultChartAxisImpl>();

  /// Mapping of dimension column index to it's axis.
  final _dimensionAxes = new LinkedHashMap<int, DefaultChartAxisImpl>();

  /// Disposer for all change stream subscriptions related to data.
  final _dataEventsDisposer = new SubscriptionsDisposer();

  /// Disposer for all change stream subscriptions related to config.
  final _configEventsDisposer = new SubscriptionsDisposer();

  @override
  final Element host;

  @override
  final bool useTwoDimensionAxes;

  @override
  final bool useRowColoring;

  /// Indicates whether any renderers need bands on primary dimension
  final List<int> dimensionsUsingBands = [];

  @override
  final ChartState state;

  @override
  _ChartAreaLayout layout = new _ChartAreaLayout();

  @override
  Selection upperBehaviorPane;

  @override
  Selection lowerBehaviorPane;

  @override
  bool isReady = false;

  @override
  ChartTheme theme;

  ChartData _data;
  ChartConfig _config;
  bool _autoUpdate = false;

  SelectionScope _scope;
  Selection _svg;
  Selection visualization;

  Iterable<ChartSeries> _series;

  bool _pendingLegendUpdate = false;
  bool _pendingAxisConfigUpdate = false;
  List<ChartBehavior> _behaviors = [];
  Map<ChartSeries, _ChartSeriesInfo> _seriesInfoCache = {};

  StreamController<ChartEvent> _valueMouseOverController;
  StreamController<ChartEvent> _valueMouseOutController;
  StreamController<ChartEvent> _valueMouseClickController;
  StreamController<ChartArea> _chartAxesUpdatedController;

  DefaultCartesianAreaImpl(
      this.host,
      ChartData data,
      ChartConfig config,
      bool autoUpdate,
      this.useTwoDimensionAxes,
      this.useRowColoring,
      this.state)
      : _autoUpdate = autoUpdate {
    assert(host != null);
    assert(isNotInline(host));

    this.data = data;
    this.config = config;
    theme = new QuantumChartTheme();

    Transition.defaultEasingType = theme.transitionEasingType;
    Transition.defaultEasingMode = theme.transitionEasingMode;
    Transition.defaultDurationMilliseconds =
        theme.transitionDurationMilliseconds;
  }

  void dispose() {
    _configEventsDisposer.dispose();
    _dataEventsDisposer.dispose();
    _config?.legend?.dispose();

    if (_valueMouseOverController != null) {
      _valueMouseOverController.close();
      _valueMouseOverController = null;
    }
    if (_valueMouseOutController != null) {
      _valueMouseOutController.close();
      _valueMouseOutController = null;
    }
    if (_valueMouseClickController != null) {
      _valueMouseClickController.close();
      _valueMouseClickController = null;
    }
    if (_chartAxesUpdatedController != null) {
      _chartAxesUpdatedController.close();
      _chartAxesUpdatedController = null;
    }
    if (_behaviors.isNotEmpty) {
      _behaviors.forEach((behavior) => behavior.dispose());
    }
  }

  static bool isNotInline(Element e) =>
      e != null && e.getComputedStyle().display != 'inline';

  /// Set new data for this chart. If [value] is [Observable], subscribes to
  /// changes and updates the chart when data changes.
  @override
  set data(ChartData value) {
    _data = value;
    _dataEventsDisposer.dispose();
    _pendingLegendUpdate = true;

    if (autoUpdate && _data != null && _data is Observable) {
      _dataEventsDisposer.add((_data as Observable).changes.listen((_) {
        _pendingLegendUpdate = true;
        draw();
      }));
    }
  }

  @override
  ChartData get data => _data;

  /// Set new config for this chart. If [value] is [Observable], subscribes to
  /// changes and updates the chart when series or dimensions change.
  @override
  set config(ChartConfig value) {
    _config = value;
    _configEventsDisposer.dispose();
    _pendingLegendUpdate = true;
    _pendingAxisConfigUpdate = true;

    if (_config != null && _config is Observable) {
      _configEventsDisposer.add((_config as Observable).changes.listen((_) {
        _pendingAxisConfigUpdate = true;
        _pendingLegendUpdate = true;
        draw();
      }));
    }
  }

  @override
  ChartConfig get config => _config;

  @override
  set autoUpdate(bool value) {
    if (_autoUpdate != value) {
      _autoUpdate = value;
      this.data = _data;
      this.config = _config;
    }
  }

  @override
  bool get autoUpdate => _autoUpdate;

  /// Gets measure axis from cache - creates a new instance of _ChartAxis
  /// if one was not already created for the given [axisId].
  DefaultChartAxisImpl _getMeasureAxis(String axisId) {
    _measureAxes.putIfAbsent(axisId, () {
      var axisConf = config.getMeasureAxis(axisId),
          axis = axisConf != null
              ? new DefaultChartAxisImpl.withAxisConfig(this, axisConf)
              : new DefaultChartAxisImpl(this);
      return axis;
    });

    return _measureAxes[axisId];
  }

  /// Gets a dimension axis from cache - creates a new instance of _ChartAxis
  /// if one was not already created for the given dimension [column].
  DefaultChartAxisImpl _getDimensionAxis(int column) {
    _dimensionAxes.putIfAbsent(column, () {
      var axisConf = config.getDimensionAxis(column);
      var axis = axisConf != null
              ? new DefaultChartAxisImpl.withAxisConfig(this, axisConf)
              : new DefaultChartAxisImpl(this);
      return axis;
    });
    return _dimensionAxes[column];
  }

  /// All columns rendered by a series must be of the same type.
  bool _isSeriesValid(ChartSeries s) {
    var first = data.columns.elementAt(s.measures.first).type;
    return s.measures.every((i) =>
        (i < data.columns.length) && data.columns.elementAt(i).type == first);
  }

  @override
  Iterable<Scale> get dimensionScales =>
      config.dimensions.map((int column) => _getDimensionAxis(column).scale);

  @override
  Iterable<Scale> measureScales(ChartSeries series) {
    var axisIds = isNullOrEmpty(series.measureAxisIds)
        ? MEASURE_AXIS_IDS
        : series.measureAxisIds;
    return axisIds.map((String id) => _getMeasureAxis(id).scale);
  }

  /// Computes the size of chart and if changed from the previous time
  /// size was computed, sets attributes on svg element
  Rect _computeChartSize() {
    int width = host.clientWidth, height = host.clientHeight;

    if (config.minimumSize != null) {
      width = max([width, config.minimumSize.width]).toInt();
      height = max([height, config.minimumSize.height]).toInt();
    }

    AbsoluteRect padding = theme.padding;
    num paddingLeft = config.isRTL ? padding.end : padding.start;
    Rect current = new Rect(
        paddingLeft,
        padding.top,
        width - (padding.start + padding.end),
        height - (padding.top + padding.bottom));
    if (layout.chartArea == null || layout.chartArea != current) {
      _svg.attr('width', width.toString());
      _svg.attr('height', height.toString());
      layout.chartArea = current;

      var transform = 'translate(${paddingLeft},${padding.top})';
      visualization.first.attributes['transform'] = transform;
      lowerBehaviorPane.first.attributes['transform'] = transform;
      upperBehaviorPane.first.attributes['transform'] = transform;
    }
    return layout.chartArea;
  }

  @override
  draw({bool preRender: false, Future schedulePostRender}) {
    assert(data != null && config != null);
    assert(config.series != null && config.series.isNotEmpty);

    // One time initialization.
    // Each [ChartArea] has it's own [SelectionScope]
    if (_scope == null) {
      _scope = new SelectionScope.element(host);
      _svg = _scope.append('svg:svg')..classed('chart-canvas');
      if (!isNullOrEmpty(theme.filters)) {
        var element = _svg.first,
            defs = Namespace.createChildElement('defs', element)
              ..append(new SvgElement.svg(theme.filters,
                  treeSanitizer: new NullTreeSanitizer()));
        _svg.first.append(defs);
      }

      lowerBehaviorPane = _svg.append('g')..classed('lower-render-pane');
      visualization = _svg.append('g')..classed('chart-render-pane');
      upperBehaviorPane = _svg.append('g')..classed('upper-render-pane');

      if (_behaviors.isNotEmpty) {
        _behaviors
            .forEach((b) => b.init(this, upperBehaviorPane, lowerBehaviorPane));
      }
    }

    // Compute chart sizes and filter out unsupported series
    _computeChartSize();
    var series = config.series
            .where((s) => _isSeriesValid(s) && s.renderer.prepare(this, s)),
        selection = visualization
            .selectAll('.series-group')
            .data(series, (x) => x.hashCode),
        axesDomainCompleter = new Completer();

    // Wait till the axes are rendered before rendering series.
    // In an SVG, z-index is based on the order of nodes in the DOM.
    axesDomainCompleter.future.then((_) {
      selection.enter.append('svg:g')..classed('series-group');
      String transform =
          'translate(${layout.renderArea.x},${layout.renderArea.y})';

      selection.each((_s, _, Element group) {
        ChartSeries s = _s;
        _ChartSeriesInfo info = _seriesInfoCache[s];
        if (info == null) {
          info = _seriesInfoCache[s] = new _ChartSeriesInfo(this, s);
        }
        info.check();
        group.attributes['transform'] = transform;
        (s.renderer as CartesianRenderer)
            ?.draw(group, schedulePostRender: schedulePostRender);
      });

      // A series that was rendered earlier isn't there anymore, remove it
      selection.exit
        ..each((_s, _, __) {
          ChartSeries s = _s;
          var info = _seriesInfoCache.remove(s);
          info?.dispose();
        })
        ..remove();

      // Notify on the stream that the chart has been updated.
      isReady = true;
      _chartAxesUpdatedController?.add(this);
    });

    // Save the list of valid series and initialize axes.
    _series = series;
    _updateAxisConfig();
    _initAxes(preRender: preRender);

    // Render the chart, now that the axes layer is already in DOM.
    axesDomainCompleter.complete();

    // Updates the legend if required.
    _updateLegend();
  }

  String _orientRTL(String orientation) => orientation;

  /// Initialize the axes - required even if the axes are not being displayed.
  _initAxes({bool preRender: false}) {
    var measureAxisUsers = <String, List<ChartSeries>>{};
    var keysToRemove = _measureAxes.keys.toList();

    // Create necessary measures axes.
    // If measure axes were not configured on the series, default is used.
    _series.forEach((ChartSeries s) {
      var measureAxisIds =
          isNullOrEmpty(s.measureAxisIds) ? MEASURE_AXIS_IDS : s.measureAxisIds;
      measureAxisIds.forEach((axisId) {
        if (keysToRemove.contains(axisId)) {
          keysToRemove.remove(axisId);
        }
        _getMeasureAxis(axisId); // Creates axis if required
        var users = measureAxisUsers[axisId];
        if (users == null) {
          measureAxisUsers[axisId] = [s];
        } else {
          users.add(s);
        }
      });
    });

    for (var key in keysToRemove) {
      _measureAxes.remove(key);
    }

    // Now that we know a list of series using each measure axis, configure
    // the input domain of each axis.
    measureAxisUsers.forEach((String id, List<ChartSeries> listOfSeries) {
      var sampleCol = listOfSeries.first.measures.first,
          sampleColSpec = data.columns.elementAt(sampleCol),
          axis = _getMeasureAxis(id);
      List<num> domain;

      if (sampleColSpec.useOrdinalScale) {
        throw new UnsupportedError(
            'Ordinal measure axes are not currently supported.');
      } else {
        // Extent is available because [ChartRenderer.prepare] was already
        // called (when checking for valid series in [draw].
        var extents = listOfSeries
            .map((s) => (s.renderer as CartesianRenderer).extent)
            .toList();
        var lowest = min(extents.map((e) => e.min as num));
        var highest = max(extents.map((e) => e.max as num));

        // Use default domain if lowest and highest are the same, right now
        // lowest is always 0 unless it is less than 0 - change to lowest when
        // we make use of it.
        domain = highest == lowest
            ? (highest == 0
                ? [0, 1]
                : (highest < 0 ? [highest, 0] : [0, highest]))
            : (lowest <= 0 ? [lowest, highest] : [0, highest]);
      }
      axis.initAxisDomain(sampleCol, false, domain);
    });

    // Configure dimension axes.
    int dimensionAxesCount = useTwoDimensionAxes ? 2 : 1;
    config.dimensions.take(dimensionAxesCount).forEach((int column) {
      var axis = _getDimensionAxis(column);
      var sampleColumnSpec = data.columns.elementAt(column);

      Iterable values = data.rows
          .map((row) => row.elementAt(column));

      if (sampleColumnSpec.useOrdinalScale) {
        List<String> domain = values.map((v) => v.toString()).toList();
        axis.initAxisDomain(column, true, domain);
      } else {
        var extent = new Extent.items(values.cast<num>());
        List<num> domain = [extent.min, extent.max];
        axis.initAxisDomain(column, true, domain);
      }
    });

    // See if any dimensions need "band" on the axis.
    dimensionsUsingBands.clear();
    List<bool> usingBands = [false, false];
    _series.forEach((ChartSeries s) =>
        (s.renderer as CartesianRenderer).dimensionsUsingBand.forEach((x) {
          if (x <= 1 && !(usingBands[x])) {
            usingBands[x] = true;
            dimensionsUsingBands.add(config.dimensions.elementAt(x));
          }
        }));

    // List of measure and dimension axes that are displayed
    assert(isNullOrEmpty(config.displayedMeasureAxes) ||
        config.displayedMeasureAxes.length < 2);
    var measureAxesCount = dimensionAxesCount == 1 ? 2 : 0;
    var displayedMeasureAxes = (isNullOrEmpty(config.displayedMeasureAxes)
                ? _measureAxes.keys.take(measureAxesCount)
                : config.displayedMeasureAxes.take(measureAxesCount))
            .toList(growable: false);
    var displayedDimensionAxes =
            config.dimensions.take(dimensionAxesCount).toList(growable: false);

    // Compute size of the dimension axes
    if (config.renderDimensionAxes != false) {
      var dimensionAxisOrientations = config.isLeftAxisPrimary
          ? DIMENSION_AXIS_ORIENTATIONS.last
          : DIMENSION_AXIS_ORIENTATIONS.first;
      for (int i = 0, len = displayedDimensionAxes.length; i < len; ++i) {
        var axis = _dimensionAxes[displayedDimensionAxes[i]],
            orientation = _orientRTL(dimensionAxisOrientations[i]);
        axis.prepareToDraw(orientation);
        layout._axes[orientation] = axis.size;
      }
    }

    // Compute size of the measure axes
    if (displayedMeasureAxes.isNotEmpty) {
      var measureAxisOrientations = config.isLeftAxisPrimary
          ? MEASURE_AXIS_ORIENTATIONS.last
          : MEASURE_AXIS_ORIENTATIONS.first;
      displayedMeasureAxes.asMap().forEach((int index, String key) {
        var axis = _measureAxes[key];
        var orientation = _orientRTL(measureAxisOrientations[index]);
        axis.prepareToDraw(orientation);
        layout._axes[orientation] = axis.size;
      });
    }

    // Consolidate all the information that we collected into final layout
    _computeLayout(
        displayedMeasureAxes.isEmpty && config.renderDimensionAxes == false);

    // Domains for all axes have been taken care of and _ChartAxis ensures
    // that the scale is initialized on visible axes. Initialize the scale on
    // all invisible measure scales.
    if (_measureAxes.length != displayedMeasureAxes.length) {
      _measureAxes.keys.forEach((String axisId) {
        if (displayedMeasureAxes.contains(axisId)) return;
        _getMeasureAxis(axisId).initAxisScale([layout.renderArea.height, 0]);
      });
    }

    // Draw the visible measure axes, if any.
    if (displayedMeasureAxes.isNotEmpty) {
      var axisGroups = visualization
          .selectAll('.measure-axis-group')
          .data(displayedMeasureAxes);
      // Update measure axis (add/remove/update)
      axisGroups.enter.append('svg:g');
      axisGroups.each((_axisId, index, group) {
        String axisId = _axisId;
        _getMeasureAxis(axisId).draw(group, _scope, preRender: preRender);
        group.attributes['class'] = 'measure-axis-group measure-${index}';
      });
      axisGroups.exit.remove();
    }

    // Draw the dimension axes, unless asked not to.
    if (config.renderDimensionAxes != false) {
      var dimAxisGroups = visualization
          .selectAll('.dimension-axis-group')
          .data(displayedDimensionAxes);
      // Update dimension axes (add/remove/update)
      dimAxisGroups.enter.append('svg:g');
      dimAxisGroups.each((_column, index, group) {
        int column = _column;
        _getDimensionAxis(column).draw(group, _scope, preRender: preRender);
        group.attributes['class'] = 'dimension-axis-group dim-${index}';
      });
      dimAxisGroups.exit.remove();
    } else {
      // Initialize scale on invisible axis
      var dimensionAxisOrientations = config.isLeftAxisPrimary
          ? DIMENSION_AXIS_ORIENTATIONS.last
          : DIMENSION_AXIS_ORIENTATIONS.first;
      for (int i = 0; i < dimensionAxesCount; ++i) {
        var column = config.dimensions.elementAt(i),
            axis = _dimensionAxes[column],
            orientation = dimensionAxisOrientations[i];
        axis.initAxisScale(orientation == ORIENTATION_LEFT
            ? [layout.renderArea.height, 0]
            : [0, layout.renderArea.width]);
      }
    }
  }

  // Compute chart render area size and positions of all elements
  _computeLayout(bool notRenderingAxes) {
    if (notRenderingAxes) {
      layout.renderArea =
          new Rect(0, 0, layout.chartArea.height, layout.chartArea.width);
      return;
    }

    var top = layout.axes[ORIENTATION_TOP],
        left = layout.axes[ORIENTATION_LEFT],
        bottom = layout.axes[ORIENTATION_BOTTOM],
        right = layout.axes[ORIENTATION_RIGHT];

    var renderAreaHeight = layout.chartArea.height -
            (top.height + layout.axes[ORIENTATION_BOTTOM].height),
        renderAreaWidth = layout.chartArea.width -
            (left.width + layout.axes[ORIENTATION_RIGHT].width);

    layout.renderArea =
        new Rect(left.width, top.height, renderAreaWidth, renderAreaHeight);

    layout._axes
      ..[ORIENTATION_TOP] = new Rect(left.width, 0, renderAreaWidth, top.height)
      ..[ORIENTATION_RIGHT] = new Rect(
          left.width + renderAreaWidth, top.y, right.width, renderAreaHeight)
      ..[ORIENTATION_BOTTOM] = new Rect(left.width,
          top.height + renderAreaHeight, renderAreaWidth, bottom.height)
      ..[ORIENTATION_LEFT] =
          new Rect(left.width, top.height, left.width, renderAreaHeight);
  }

  // Updates the legend, if configuration changed since the last
  // time the legend was updated.
  _updateLegend() {
    if (!_pendingLegendUpdate) return;
    if (_config == null || _config.legend == null || _series.isEmpty) return;

    var legend = <ChartLegendItem>[];
    List<List<ChartSeries>> seriesByColumn =
        new List<List<ChartSeries>>.generate(
            data.columns.length, (_) => <ChartSeries>[]);

    _series.forEach((s) => s.measures.forEach((m) => seriesByColumn[m].add(s)));

    seriesByColumn.asMap().forEach((int i, List<ChartSeries> s) {
      if (s.length == 0) return;
      legend.add(new ChartLegendItem(
          index: i,
          label: data.columns.elementAt(i).label,
          series: s,
          color: theme.getColorForKey(i)));
    });

    _config.legend.update(legend, this);
    _pendingLegendUpdate = false;
  }

  // Updates the AxisConfig, if configuration chagned since the last time the
  // AxisConfig was updated.
  void _updateAxisConfig() {
    if (!_pendingAxisConfigUpdate) return;
    _series.forEach((ChartSeries s) {
      var measureAxisIds =
          isNullOrEmpty(s.measureAxisIds) ? MEASURE_AXIS_IDS : s.measureAxisIds;
      measureAxisIds.forEach((axisId) {
        var axis = _getMeasureAxis(axisId); // Creates axis if required
        axis.config = config.getMeasureAxis(axisId);
      });
    });

    int dimensionAxesCount = useTwoDimensionAxes ? 2 : 1;
    config.dimensions.take(dimensionAxesCount).forEach((int column) {
      var axis = _getDimensionAxis(column);
      axis.config = config.getDimensionAxis(column);
    });

    _pendingAxisConfigUpdate = false;
  }

  @override
  Stream<ChartEvent> get onMouseUp =>
      host.onMouseUp.map((MouseEvent e) => new DefaultChartEventImpl(e, this));

  @override
  Stream<ChartEvent> get onMouseDown => host.onMouseDown
      .map((MouseEvent e) => new DefaultChartEventImpl(e, this));

  @override
  Stream<ChartEvent> get onMouseOver => host.onMouseOver
      .map((MouseEvent e) => new DefaultChartEventImpl(e, this));

  @override
  Stream<ChartEvent> get onMouseOut =>
      host.onMouseOut.map((MouseEvent e) => new DefaultChartEventImpl(e, this));

  @override
  Stream<ChartEvent> get onMouseMove => host.onMouseMove
      .map((MouseEvent e) => new DefaultChartEventImpl(e, this));

  @override
  Stream<ChartEvent> get onValueClick {
    if (_valueMouseClickController == null) {
      _valueMouseClickController = new StreamController.broadcast(sync: true);
    }
    return _valueMouseClickController.stream;
  }

  @override
  Stream<ChartEvent> get onValueMouseOver {
    if (_valueMouseOverController == null) {
      _valueMouseOverController = new StreamController.broadcast(sync: true);
    }
    return _valueMouseOverController.stream;
  }

  @override
  Stream<ChartEvent> get onValueMouseOut {
    if (_valueMouseOutController == null) {
      _valueMouseOutController = new StreamController.broadcast(sync: true);
    }
    return _valueMouseOutController.stream;
  }

  @override
  Stream<ChartArea> get onChartAxesUpdated {
    if (_chartAxesUpdatedController == null) {
      _chartAxesUpdatedController = new StreamController.broadcast(sync: true);
    }
    return _chartAxesUpdatedController.stream;
  }

  @override
  void addChartBehavior(ChartBehavior behavior) {
    if (behavior == null || _behaviors.contains(behavior)) return;
    _behaviors.add(behavior);
    if (upperBehaviorPane != null && lowerBehaviorPane != null) {
      behavior.init(this, upperBehaviorPane, lowerBehaviorPane);
    }
  }

  @override
  void removeChartBehavior(ChartBehavior behavior) {
    if (behavior == null || !_behaviors.contains(behavior)) return;
    if (upperBehaviorPane != null && lowerBehaviorPane != null) {
      behavior.dispose();
    }
    _behaviors.remove(behavior);
  }
}

class _ChartAreaLayout implements ChartAreaLayout {
  final _axes = <String, Rect>{
    ORIENTATION_LEFT: const Rect(),
    ORIENTATION_RIGHT: const Rect(),
    ORIENTATION_TOP: const Rect(),
    ORIENTATION_BOTTOM: const Rect()
  };

  UnmodifiableMapView<String, Rect> _axesView;

  @override
  get axes => _axesView;

  @override
  Rect renderArea = const Rect();

  @override
  Rect chartArea = const Rect();

  _ChartAreaLayout() {
    _axesView = new UnmodifiableMapView(_axes);
  }
}

class _ChartSeriesInfo {
  CartesianRenderer _renderer;
  SubscriptionsDisposer _disposer = new SubscriptionsDisposer();

  ChartSeries _series;
  DefaultCartesianAreaImpl _area;
  _ChartSeriesInfo(this._area, this._series);

  _click(ChartEvent e) {
    var state = _area.state;
    if (state != null) {
      if (state.isHighlighted(e.column, e.row)) {
        state.unhighlight(e.column, e.row);
      } else {
        state.highlight(e.column, e.row);
      }
    }
    if (_area._valueMouseClickController != null) {
      _area._valueMouseClickController.add(e);
    }
  }

  _mouseOver(ChartEvent e) {
    var state = _area.state;
    if (state != null) {
      state.hovered = new Pair(e.column, e.row);
    }
    if (_area._valueMouseOverController != null) {
      _area._valueMouseOverController.add(e);
    }
  }

  _mouseOut(ChartEvent e) {
    var state = _area.state;
    if (state != null) {
      var current = state.hovered;
      if (current != null &&
          current.first == e.column &&
          current.last == e.row) {
        state.hovered = null;
      }
    }
    if (_area._valueMouseOutController != null) {
      _area._valueMouseOutController.add(e);
    }
  }

  check() {
    if (_renderer != _series.renderer) {
      dispose();
      if (_series.renderer is ChartRendererBehaviorSource) {
        _disposer.addAll([
          _series.renderer.onValueClick.listen(_click),
          _series.renderer.onValueMouseOver.listen(_mouseOver),
          _series.renderer.onValueMouseOut.listen(_mouseOut)
        ]);
      }
    }
    _renderer = _series.renderer as CartesianRenderer;
  }

  dispose() {
    _renderer?.dispose();
    _disposer.dispose();
  }
}
