'use strict';

const flatten = require('../../support/flattenMessage'),
  util = require('util'),
  graphiteUtil = require('../../support/tsdbUtil'),
  reduce = require('lodash.reduce'),
  formatEntry = require('./helpers/format-entry'),
  isStatsd = require('./helpers/is-statsd');

const STATSD = 'statsd';
const GRAPHITE = 'graphite';

function keyPathFromMessage(message, options, includeQueryParams, alias) {
  let typeParts = message.type.split('.');
  typeParts.push(typeParts.shift());

  // always have browser and connectivity in Browsertime and related tools
  if (
    message.type.match(
      /(^pagexray|^coach|^browsertime|^largestassets|^slowestassets|^aggregateassets|^domains|^thirdparty|^axe)/
    )
  ) {
    // if we have a friendly name for your connectivity, use that!
    let connectivity = graphiteUtil.getConnectivity(options);

    typeParts.splice(1, 0, connectivity);
    typeParts.splice(1, 0, options.browser);
  } else if (message.type.match(/(^webpagetest)/)) {
    if (message.connectivity) {
      typeParts.splice(2, 0, message.connectivity);
    }
    if (message.location) {
      typeParts.splice(2, 0, graphiteUtil.toSafeKey(message.location));
    }
  }
  // if we get a URL type, add the URL
  if (message.url) {
    typeParts.splice(
      1,
      0,
      graphiteUtil.getURLAndGroup(
        options,
        message.group,
        message.url,
        includeQueryParams,
        alias
      )
    );
  } else if (message.group) {
    // add the group of the summary message
    typeParts.splice(1, 0, graphiteUtil.toSafeKey(message.group));
  }
  // if we are sending run metrics and we have an iteration
  if (
    options.graphite &&
    options.graphite.experimental &&
    options.graphite.experimental.perIteration &&
    message.type.endsWith('run') &&
    message.iteration
  ) {
    typeParts.splice(0, 1, 'run-' + message.iteration);
  }

  return typeParts.join('.');
}

class GraphiteDataGenerator {
  constructor(namespace, includeQueryParams, options) {
    this.namespace = namespace;
    this.includeQueryParams = !!includeQueryParams;
    this.options = options;
    this.entryFormat = isStatsd(options.graphite) ? STATSD : GRAPHITE;
  }

  dataFromMessage(message, time, alias) {
    const timestamp = Math.round(time.valueOf() / 1000);

    const keypath = keyPathFromMessage(
      message,
      this.options,
      this.includeQueryParams,
      alias
    );

    return reduce(
      flatten.flattenMessageData(message),
      (entries, value, key) => {
        const fullKey = util.format('%s.%s.%s', this.namespace, keypath, key);
        const args = [formatEntry(this.entryFormat), fullKey, value];
        this.entryFormat === GRAPHITE && args.push(timestamp);

        entries.push(util.format.apply(util, args));
        return entries;
      },
      []
    );
  }
}

module.exports = GraphiteDataGenerator;

@@ -2518,16 +2518,1330 @@
 y) =%3E %7B%0A
+        if (%0A          this.options.graphite &&%0A          this.options.graphite.experimental &&%0A          this.options.graphite.experimental.perIteration%0A        ) %7B%0A          if (message.type === 'browsertime.run') %7B%0A            if (key.includes('timings') && key.includes('marks')) %7B%0A              key = key.replace(/marks%5C.(%5Cd+)/, function(match, idx) %7B%0A                return (%0A                  'marks.' + message.data.timings.userTimings.marks%5Bidx%5D.name%0A                );%0A              %7D);%0A            %7D%0A%0A            if (key.includes('timings') && key.includes('measures')) %7B%0A              key = key.replace(/measures%5C.(%5Cd+)/, function(match, idx) %7B%0A                return (%0A                  'measures.' +%0A                  message.data.timings.userTimings.measures%5Bidx%5D.name%0A                );%0A              %7D);%0A            %7D%0A          %7D%0A          if (message.type === 'pagexray.run') %7B%0A            if (key.includes('assets')) %7B%0A              key = key.replace(%0A                /assets%5C.(%5Cd+)/,%0A                function(match, idx) %7B%0A                  let url = new URL(message.data.assets%5Bidx%5D.url);%0A                  url.search = '';%0A                  return 'assets.' + graphiteUtil.toSafeKey(url.toString());%0A                %7D,%0A                %7B%7D%0A              );%0A            %7D%0A          %7D%0A        %7D%0A%0A
         

update indexed keys with names (#2701)