
// utils
import Map from '@schematize/refs/js/Map.mjs';

// Instance
import dispatch from '@schematize/instance.js/src/EventTarget/dispatch.mjs';

const fireModifyAndChangeEvents = (
  instance,
  propertyName,
  value,
  previousValue,
  _skipChange,
) => {
  dispatch({
    type: `modify`,
    detail: {
      instance: instance,
      property: propertyName,
      value: value,
      previousValue: previousValue,
    },
  }, instance);

  !_skipChange && 
  dispatch({
    type: `change`,
    detail: {
      instance: instance,
      changes: new Map([
        [propertyName, {
          to: value,
          from: previousValue,
        }]
      ]),
    },
  }, instance);
};

/**
 * @function set
 * @desc A paired down version of the set function from @schematize/instance.js
 * 
 * @param {Object} instance The instance.
 * @param {String} propertyName The property name to set on the instance.
 * @param {mixed} value The value to set on the instance.
 */
export const set = (
  instance, propertyName, value, _skipChange,
  // variables
  previousValue = instance[propertyName],
) => {

  // TODO: decide if I want to dispatch the "set" event

  // set the value
  instance[propertyName] = value;

  fireModifyAndChangeEvents(
    instance,
    propertyName,
    value,
    previousValue, 
    (
      _skipChange ||
      value === previousValue
    )
  );

  return value;
};

/**
 * @function deleteProperty
 * @desc A paired down version of the deleteProperty function from @schematize/instance.js
 * 
 * @param {Object} instance The instance.
 * @param {String} propertyName The property name to delete from the instance.
 */
export const deleteProperty = (
  instance, propertyName, _skipChange,
  // variables
  previousValue = instance[propertyName],
  response,
) => {

  // TODO: decide if I want to dispatch the "deleteProperty" event

  // delete the property
  response = delete instance[propertyName];

  fireModifyAndChangeEvents(
    instance,
    propertyName,
    undefined,
    previousValue,
    _skipChange
  );

  return response;
};