"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.DurationDistributionChart = DurationDistributionChart;
exports.replaceHistogramZerosWithMinimumDomainValue = void 0;
var _react = _interopRequireWildcard(require("react"));
var _lodash = require("lodash");
var _charts = require("@elastic/charts");
var _eui = require("@elastic/eui");
var _i18n = require("@kbn/i18n");
var _public = require("@kbn/observability-shared-plugin/public");
var _common = require("@kbn/observability-plugin/common");
var _formatters = require("../../../../../common/utils/formatters");
var _constants = require("../../../../../common/correlations/constants");
var _use_theme = require("../../../../hooks/use_theme");
var _chart_container = require("../chart_container");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

const NUMBER_OF_TRANSACTIONS_LABEL = _i18n.i18n.translate('xpack.apm.durationDistribution.chart.numberOfTransactionsLabel', {
  defaultMessage: 'Transactions'
});
const NUMBER_OF_SPANS_LABEL = _i18n.i18n.translate('xpack.apm.durationDistribution.chart.numberOfSpansLabel', {
  defaultMessage: 'Spans'
});
const getAnnotationsStyle = (color = 'gray') => ({
  line: {
    strokeWidth: 1,
    stroke: color,
    opacity: 0.8
  }
});

// With a log based y axis in combination with the `CURVE_STEP_AFTER` style,
// the line of an area would not go down to 0 but end on the y axis at the last value >0.
// By replacing the 0s with a small value >0 the line will be drawn as intended.
// This is just to visually fix the line, for tooltips, that number will be again rounded down to 0.
// Note this workaround is only safe to use for this type of chart because it works with
// count based values and not a float based metric for example on the y axis.
const Y_AXIS_MIN_DOMAIN = 0.5;
const Y_AXIS_MIN_VALUE = 0.0001;
const replaceHistogramZerosWithMinimumDomainValue = histogramItems => histogramItems.reduce((histogramItem, _, i) => {
  if (histogramItem[i].doc_count === 0) {
    histogramItem[i].doc_count = Y_AXIS_MIN_VALUE;
  }
  return histogramItem;
}, histogramItems);

// Create and call a duration formatter for every value since the durations for the
// x axis might have a wide range of values e.g. from low milliseconds to large seconds.
// This way we can get different suitable units across ticks.
exports.replaceHistogramZerosWithMinimumDomainValue = replaceHistogramZerosWithMinimumDomainValue;
const xAxisTickFormat = d => (0, _formatters.getDurationFormatter)(d, 0.9999)(d).formatted;
function DurationDistributionChart({
  data,
  hasData,
  markerCurrentEvent,
  markerValue,
  onChartSelection,
  selection,
  status,
  eventType
}) {
  var _Math$max;
  const chartTheme = (0, _public.useChartTheme)();
  const euiTheme = (0, _use_theme.useTheme)();
  const markerPercentile = _constants.DEFAULT_PERCENTILE_THRESHOLD;
  const annotationsDataValues = [{
    dataValue: markerValue,
    details: _i18n.i18n.translate('xpack.apm.durationDistribution.chart.percentileMarkerLabel', {
      defaultMessage: '{markerPercentile}th percentile',
      values: {
        markerPercentile
      }
    })
  }];

  // This will create y axis ticks for 1, 10, 100, 1000 ...
  const yMax = (_Math$max = Math.max(...(0, _lodash.flatten)(data.map(d => d.histogram)).map(d => d.doc_count))) !== null && _Math$max !== void 0 ? _Math$max : 0;
  const yTicks = Math.max(1, Math.ceil(Math.log10(yMax)));
  const yAxisMaxDomain = Math.pow(10, yTicks);
  const yAxisDomain = {
    min: Y_AXIS_MIN_DOMAIN,
    max: yAxisMaxDomain
  };
  const selectionAnnotation = selection !== undefined ? [{
    coordinates: {
      x0: selection[0],
      x1: selection[1],
      y0: 0,
      y1: yAxisMaxDomain
    },
    details: 'selection'
  }] : undefined;
  const chartData = (0, _react.useMemo)(() => data.map(d => ({
    ...d,
    histogram: replaceHistogramZerosWithMinimumDomainValue(d.histogram)
  })), [data]);
  return /*#__PURE__*/_react.default.createElement("div", {
    "data-test-subj": "apmCorrelationsChart",
    style: {
      overflow: 'hidden',
      textOverflow: 'ellipsis'
    }
  }, /*#__PURE__*/_react.default.createElement(_chart_container.ChartContainer, {
    height: 250,
    hasData: hasData,
    status: status
  }, /*#__PURE__*/_react.default.createElement(_charts.Chart, null, /*#__PURE__*/_react.default.createElement(_charts.Settings, {
    rotation: 0,
    theme: [{
      legend: {
        spacingBuffer: 100
      },
      areaSeriesStyle: {
        line: {
          visible: true
        },
        point: {
          visible: false,
          radius: 0
        }
      },
      axes: {
        tickLine: {
          visible: true,
          size: 5,
          padding: 10
        },
        tickLabel: {
          fontSize: 10,
          fill: euiTheme.eui.euiColorMediumShade,
          padding: 0
        }
      }
    }, ...chartTheme],
    showLegend: true,
    legendPosition: _charts.Position.Bottom,
    onBrushEnd: onChartSelection
  }), selectionAnnotation !== undefined && /*#__PURE__*/_react.default.createElement(_charts.RectAnnotation, {
    dataValues: selectionAnnotation,
    id: "rect_annotation_1",
    style: {
      strokeWidth: 1,
      stroke: euiTheme.eui.euiColorLightShade,
      fill: euiTheme.eui.euiColorLightShade,
      opacity: 0.9
    },
    hideTooltips: true
  }), typeof markerCurrentEvent === 'number' && /*#__PURE__*/_react.default.createElement(_charts.LineAnnotation, {
    id: "annotation_current_event",
    domainType: _charts.AnnotationDomainType.XDomain,
    dataValues: [{
      dataValue: markerCurrentEvent,
      details: _i18n.i18n.translate('xpack.apm.durationDistribution.chart.currentEventMarkerLabel', {
        defaultMessage: 'Current sample'
      })
    }],
    style: getAnnotationsStyle((0, _eui.euiPaletteColorBlind)()[0]),
    marker: _i18n.i18n.translate('xpack.apm.durationDistribution.chart.currentEventMarkerLabel', {
      defaultMessage: 'Current sample'
    }),
    markerPosition: 'bottom'
  }), /*#__PURE__*/_react.default.createElement(_charts.LineAnnotation, {
    id: "apmCorrelationsChartPercentileAnnotation",
    domainType: _charts.AnnotationDomainType.XDomain,
    dataValues: annotationsDataValues,
    style: getAnnotationsStyle(),
    marker: `${markerPercentile}p`,
    markerPosition: 'top'
  }), /*#__PURE__*/_react.default.createElement(_charts.Axis, {
    id: "x-axis",
    title: _i18n.i18n.translate('xpack.apm.durationDistribution.chart.latencyLabel', {
      defaultMessage: 'Latency'
    }),
    position: _charts.Position.Bottom,
    tickFormat: xAxisTickFormat,
    gridLine: {
      visible: false
    }
  }), /*#__PURE__*/_react.default.createElement(_charts.Axis, {
    id: "y-axis",
    domain: yAxisDomain,
    title: eventType === _common.ProcessorEvent.transaction ? NUMBER_OF_TRANSACTIONS_LABEL : NUMBER_OF_SPANS_LABEL,
    position: _charts.Position.Left,
    ticks: yTicks,
    gridLine: {
      visible: true
    }
  }), chartData.map(d => /*#__PURE__*/_react.default.createElement(_charts.AreaSeries, {
    key: d.id,
    id: d.id,
    xScaleType: _charts.ScaleType.Log,
    yScaleType: _charts.ScaleType.Log,
    data: d.histogram,
    curve: _charts.CurveType.CURVE_STEP_AFTER,
    xAccessor: "key",
    yAccessors: ['doc_count'],
    color: d.areaSeriesColor,
    fit: "linear",
    areaSeriesStyle: {
      fit: {
        line: {
          visible: true
        }
      }
    }
    // To make the area appear with a continuous line,
    // we changed the original data to replace values of 0 with Y_AXIS_MIN_DOMAIN.
    // To show the correct values again in tooltips, we use a custom tickFormat to round values.
    // We can safely do this because all duration values above 0 are without decimal points anyway.
    ,
    tickFormat: p => `${Math.floor(p)}`
  })))));
}