Source: index.js

'use strict';

const Op = require('object-path');
const getOrDefault = require('./utils');

/**
 * Represents the report that we are generating
 *
*/
class Report {

  /**
   * Creates an instance of Report.
   *
   * @param {string} notes
   * @param {string} totalLabel
   * @param {any} [timestamp=Date.now()]
   *
   */
  constructor(notes, totalLabel, timestamp = Date.now()) {

    this.report = {
      summary: {
        total: {
          count: 0,
          label: totalLabel
        },
        timestamp,
        notes
      },
      results: {}
    };
  }

  /**
   *
   *
   * @param {string} name
   * @returns a new {@link Section} under that name
   *
   */
  section(name) {

    return new Section(getOrDefault(this.report, name, {}), this.report);
  }

  /**
   *
   *
   * @param {any} value
   *
   */
  setTotal(value) {

    this.report.summary.total.count = value;
    return this;
  }

  /**
   *
   *
   * @param {string} path
   * @param {string} totalRef
   * @returns this
   *
   */
  calcPercentOf(path, totalRef) {

    if (typeof totalRef !== 'string') {
      totalRef = 'summary.total.count'; // default reference is inside summary
    } else {
      totalRef = ['results', totalRef, 'count'].join('.'); // any other ref is under results namespace
    }
    if (typeof path !== 'string' || !Op.get(this.report.results, path) || isNaN(Op.get(this.report, totalRef))) {
      return this;
    }
    const count = Op.get(this.report, ['results', path, 'count'].join('.'));
    const total = Op.get(this.report, totalRef);
    const percent = (count * 100) / total;
    Op.set(this.report.results, `${path}.percent`, percent);
    return this;
  }

  /**
   *
   *
   * @returns internal report
   *
   */
  toJSON() {

    return this.report;
  }
}

/**
 * Class that represents a section of the main report.
 * **You should not try to instantiate it directly**.
 */
class Section {

  /**
   * Creates an instance of Section.
   * This constructor should only be called by the {@link Report} class
   *
   * @param {any} store
   * @param {any} reportTree
   *
   */
  constructor(store, reportTree) {

    this.tree = reportTree;
    this.store = store;
  }

  /**
   *  Returns the object that should be serialized
   *  as a JSON representation of the report
   * @returns internal report
   * @public
   */
  toJSON() {

    return this.tree;
  }


  /**
   * Legacy method from v1.0.0 Will be removed soon
   * @deprecated Legacy method from v1.0.0 Will be removed soon
   * @returns new Section under name
   *
   */
  subSection() {
    return this.section(...arguments);
  }

  /**
   *
   *
   * @param {string} name
   * @returns new Section under name
   *
   */
  section(name) {

    return new Section(getOrDefault(this.store, name, {}), this.tree);
  }

  /**
   *
   *
   * @returns summary Section
   *
   */
  summary() {

    return new Section(this.tree.summary, this.tree);
  }


  /**
   *
   *
   * @param {string} totalRef
   * @returns this
   *
   */
  calcPercent(totalRef) {

    if (typeof this.store.count !== 'number') {
      return this;
    }
    const count = this.store.count;
    const total = typeof totalRef !== 'string'
      ? this.tree.summary.total.count
      : Op.get(this.tree, totalRef);
    this.store.percent = (count * 100) / total;
    return this;
  }

  /**
   *
   *
   * @param {string} path
   * @param {any} value
   * @returns this
   *
   */
  set(path, value) {

    if (!path || !value) {
      return this;
    }
    Op.set(this.store, path, value);
    return this;
  }

  /**
   *
   *
   * @param {string} path
   * @param {number} [value=1]
   * @returns this
   *
   */
  increment(path, value = 1) {

    if (typeof path === 'number') {
      value = path;
      path = 'count';
    } else {
      path = (typeof path === 'string')
        ? path.split('.')
        : [];
      path.push('count');
    }
    const currVal = Op.get(this.store, path, 0);
    Op.set(this.store, path, currVal + value);
    return this;
  }
}

module.exports = Report;
module.exports.Section = Section;