/**
 * Serialization/deserialization classes and functions for communication between a main Mocha process and worker processes.
 * @module serializer
 * @private
 */

'use strict';

const {type} = require('../utils');
const {createInvalidArgumentTypeError} = require('../errors');
// this is not named `mocha:parallel:serializer` because it's noisy and it's
// helpful to be able to write `DEBUG=mocha:parallel*` and get everything else.
const debug = require('debug')('mocha:serializer');

const SERIALIZABLE_RESULT_NAME = 'SerializableWorkerResult';
const SERIALIZABLE_TYPES = new Set(['object', 'array', 'function', 'error']);

/**
 * The serializable result of a test file run from a worker.
 * @private
 */
class SerializableWorkerResult {
  /**
   * Creates instance props; of note, the `__type` prop.
   *
   * Note that the failure count is _redundant_ and could be derived from the
   * list of events; but since we're already doing the work, might as well use
   * it.
   * @param {SerializableEvent[]} [events=[]] - Events to eventually serialize
   * @param {number} [failureCount=0] - Failure count
   */
  constructor(events = [], failureCount = 0) {
    /**
     * The number of failures in this run
     * @type {number}
     */
    this.failureCount = failureCount;
    /**
     * All relevant events emitted from the {@link Runner}.
     * @type {SerializableEvent[]}
     */
    this.events = events;

    /**
     * Symbol-like value needed to distinguish when attempting to deserialize
     * this object (once it's been received over IPC).
     * @type {Readonly<"SerializableWorkerResult">}
     */
    Object.defineProperty(this, '__type', {
      value: SERIALIZABLE_RESULT_NAME,
      enumerable: true,
      writable: false
    });
  }

  /**
   * Instantiates a new {@link SerializableWorkerResult}.
   * @param {...any} args - Args to constructor
   * @returns {SerializableWorkerResult}
   */
  static create(...args) {
    return new SerializableWorkerResult(...args);
  }

  /**
   * Serializes each {@link SerializableEvent} in our `events` prop;
   * makes this object read-only.
   * @returns {Readonly<SerializableWorkerResult>}
   */
  serialize() {
    this.events.forEach(event => {
      event.serialize();
    });
    return Object.freeze(this);
  }

  /**
   * Deserializes a {@link SerializedWorkerResult} into something reporters can
   * use; calls {@link SerializableEvent.deserialize} on each item in its
   * `events` prop.
   * @param {SerializedWorkerResult} obj
   * @returns {SerializedWorkerResult}
   */
  static deserialize(obj) {
    obj.events.forEach(event => {
      SerializableEvent.deserialize(event);
    });
    return obj;
  }

  /**
   * Returns `true` if this is a {@link SerializedWorkerResult} or a
   * {@link SerializableWorkerResult}.
   * @param {*} value - A value to check
   * @returns {boolean} If true, it's deserializable
   */
  static isSerializedWorkerResult(value) {
    return (
      value instanceof SerializableWorkerResult ||
      (type(value) === 'object' && value.__type === SERIALIZABLE_RESULT_NAME)
    );
  }
}

/**
 * Represents an event, emitted by a {@link Runner}, which is to be transmitted
 * over IPC.
 *
 * Due to the contents of the event data, it's not possible to send them
 * verbatim. When received by the main process--and handled by reporters--these
 * objects are expected to contain {@link Runnable} instances.  This class
 * provides facilities to perform the translation via serialization and
 * deserialization.
 * @private
 */
class SerializableEvent {
  /**
   * Constructs a `SerializableEvent`, throwing if we receive unexpected data.
   *
   * Practically, events emitted from `Runner` have a minumum of zero (0)
   * arguments-- (for example, {@link Runnable.constants.EVENT_RUN_BEGIN}) and a
   * maximum of two (2) (for example,
   * {@link Runnable.constants.EVENT_TEST_FAIL}, where the second argument is an
   * `Error`).  The first argument, if present, is a {@link Runnable}. This
   * constructor's arguments adhere to this convention.
   * @param {string} eventName - A non-empty event name.
   * @param {any} [originalValue] - Some data. Corresponds to extra arguments
   * passed to `EventEmitter#emit`.
   * @param {Error} [originalError] - An error, if there's an error.
   * @throws If `eventName` is empty, or `originalValue` is a non-object.
   */
  constructor(eventName, originalValue, originalError) {
    if (!eventName) {
      throw createInvalidArgumentTypeError(
        'Empty `eventName` string argument',
        'eventName',
        'string'
      );
    }
    /**
     * The event name.
     * @memberof SerializableEvent
     */
    this.eventName = eventName;
    const originalValueType = type(originalValue);
    if (originalValueType !== 'object' && originalValueType !== 'undefined') {
      throw createInvalidArgumentTypeError(
        `Expected object but received ${originalValueType}`,
        'originalValue',
        'object'
      );
    }
    /**
     * An error, if present.
     * @memberof SerializableEvent
     */
    Object.defineProperty(this, 'originalError', {
      value: originalError,
      enumerable: false
    });

    /**
     * The raw value.
     *
     * We don't want this value sent via IPC; making it non-enumerable will do that.
     *
     * @memberof SerializableEvent
     */
    Object.defineProperty(this, 'originalValue', {
      value: originalValue,
      enumerable: false
    });
  }

  /**
   * In case you hated using `new` (I do).
   *
   * @param  {...any} args - Args for {@link SerializableEvent#constructor}.
   * @returns {SerializableEvent} A new `SerializableEvent`
   */
  static create(...args) {
    return new SerializableEvent(...args);
  }

  /**
   * Used internally by {@link SerializableEvent#serialize}.
   * @ignore
   * @param {Array<object|string>} pairs - List of parent/key tuples to process; modified in-place. This JSDoc type is an approximation
   * @param {object} parent - Some parent object
   * @param {string} key - Key to inspect
   * @param {WeakSet<Object>} seenObjects - For avoiding circular references
   */
  static _serialize(pairs, parent, key, seenObjects) {
    let value = parent[key];
    if (seenObjects.has(value)) {
      parent[key] = Object.create(null);
      return;
    }
    let _type = type(value);
    if (_type === 'error') {
      // we need to reference the stack prop b/c it's lazily-loaded.
      // `__type` is necessary for deserialization to create an `Error` later.
      // `message` is apparently not enumerable, so we must handle it specifically.
      value = Object.assign(Object.create(null), value, {
        stack: value.stack,
        message: value.message,
        __type: 'Error'
      });
      parent[key] = value;
      // after this, set the result of type(value) to be `object`, and we'll throw
      // whatever other junk is in the original error into the new `value`.
      _type = 'object';
    }
    switch (_type) {
      case 'object':
        if (type(value.serialize) === 'function') {
          parent[key] = value.serialize();
        } else {
          // by adding props to the `pairs` array, we will process it further
          pairs.push(
            ...Object.keys(value)
              .filter(key => SERIALIZABLE_TYPES.has(type(value[key])))
              .map(key => [value, key])
          );
        }
        break;
      case 'function':
        // we _may_ want to dig in to functions for some assertion libraries
        // that might put a usable property on a function.
        // for now, just zap it.
        delete parent[key];
        break;
      case 'array':
        pairs.push(
          ...value
            .filter(value => SERIALIZABLE_TYPES.has(type(value)))
            .map((value, index) => [value, index])
        );
        break;
    }
  }

  /**
   * Modifies this object *in place* (for theoretical memory consumption &
   * performance reasons); serializes `SerializableEvent#originalValue` (placing
   * the result in `SerializableEvent#data`) and `SerializableEvent#error`.
   * Freezes this object. The result is an object that can be transmitted over
   * IPC.
   * If this quickly becomes unmaintainable, we will want to move towards immutable
   * objects post-haste.
   */
  serialize() {
    // given a parent object and a key, inspect the value and decide whether
    // to replace it, remove it, or add it to our `pairs` array to further process.
    // this is recursion in loop form.
    const originalValue = this.originalValue;
    const result = Object.assign(Object.create(null), {
      data:
        type(originalValue) === 'object' &&
        type(originalValue.serialize) === 'function'
          ? originalValue.serialize()
          : originalValue,
      error: this.originalError
    });

    const pairs = Object.keys(result).map(key => [result, key]);
    const seenObjects = new WeakSet();

    let pair;
    while ((pair = pairs.shift())) {
      SerializableEvent._serialize(pairs, ...pair, seenObjects);
      seenObjects.add(pair[0]);
    }

    this.data = result.data;
    this.error = result.error;

    return Object.freeze(this);
  }

  /**
   * Used internally by {@link SerializableEvent.deserialize}; creates an `Error`
   * from an `Error`-like (serialized) object
   * @ignore
   * @param {Object} value - An Error-like value
   * @returns {Error} Real error
   */
  static _deserializeError(value) {
    const error = new Error(value.message);
    error.stack = value.stack;
    Object.assign(error, value);
    delete error.__type;
    return error;
  }

  /**
   * Used internally by {@link SerializableEvent.deserialize}; recursively
   * deserializes an object in-place.
   * @param {object|Array} parent - Some object or array
   * @param {string|number} key - Some prop name or array index within `parent`
   */
  static _deserializeObject(parent, key) {
    if (key === '__proto__') {
      delete parent[key];
      return;
    }
    const value = parent[key];
    // keys beginning with `$$` are converted into functions returning the value
    // and renamed, stripping the `$$` prefix.
    // functions defined this way cannot be array members!
    if (type(key) === 'string' && key.startsWith('$$')) {
      const newKey = key.slice(2);
      parent[newKey] = () => value;
      delete parent[key];
      key = newKey;
    }
    if (type(value) === 'array') {
      value.forEach((_, idx) => {
        SerializableEvent._deserializeObject(value, idx);
      });
    } else if (type(value) === 'object') {
      if (value.__type === 'Error') {
        parent[key] = SerializableEvent._deserializeError(value);
      } else {
        Object.keys(value).forEach(key => {
          SerializableEvent._deserializeObject(value, key);
        });
      }
    }
  }

  /**
   * Deserialize value returned from a worker into something more useful.
   * Does not return the same object.
   * @todo do this in a loop instead of with recursion (if necessary)
   * @param {SerializedEvent} obj - Object returned from worker
   * @returns {SerializedEvent} Deserialized result
   */
  static deserialize(obj) {
    if (!obj) {
      throw createInvalidArgumentTypeError('Expected value', obj);
    }

    obj = Object.assign(Object.create(null), obj);

    if (obj.data) {
      Object.keys(obj.data).forEach(key => {
        SerializableEvent._deserializeObject(obj.data, key);
      });
    }

    if (obj.error) {
      obj.error = SerializableEvent._deserializeError(obj.error);
    }

    return obj;
  }
}

/**
 * "Serializes" a value for transmission over IPC as a message.
 *
 * If value is an object and has a `serialize()` method, call that method; otherwise return the object and hope for the best.
 *
 * @param {*} [value] - A value to serialize
 */
exports.serialize = function serialize(value) {
  const result =
    type(value) === 'object' && type(value.serialize) === 'function'
      ? value.serialize()
      : value;
  debug('serialized: %O', result);
  return result;
};

/**
 * "Deserializes" a "message" received over IPC.
 *
 * This could be expanded with other objects that need deserialization,
 * but at present time we only care about {@link SerializableWorkerResult} objects.
 *
 * @param {*} [value] - A "message" to deserialize
 */
exports.deserialize = function deserialize(value) {
  const result = SerializableWorkerResult.isSerializedWorkerResult(value)
    ? SerializableWorkerResult.deserialize(value)
    : value;
  debug('deserialized: %O', result);
  return result;
};

exports.SerializableEvent = SerializableEvent;
exports.SerializableWorkerResult = SerializableWorkerResult;

/**
 * The result of calling `SerializableEvent.serialize`, as received
 * by the deserializer.
 * @private
 * @typedef {Object} SerializedEvent
 * @property {object?} data - Optional serialized data
 * @property {object?} error - Optional serialized `Error`
 */

/**
 * The result of calling `SerializableWorkerResult.serialize` as received
 * by the deserializer.
 * @private
 * @typedef {Object} SerializedWorkerResult
 * @property {number} failureCount - Number of failures
 * @property {SerializedEvent[]} events - Serialized events
 * @property {"SerializedWorkerResult"} __type - Symbol-like to denote the type of object this is
 */
