"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ComponentMap = void 0;
/**
 * allows to index components -> values.
 */
class ComponentMap {
  constructor(hashMap) {
    this.hashMap = hashMap;
  }

  /**
   * @deprecated please use `get` instead
   */
  byComponent(component) {
    return this.hashMap.get(component.id.toString());
  }
  get components() {
    return this.toArray().map(([component]) => component);
  }

  /**
   * get a value for a component.
   */
  get(component) {
    return this.hashMap.get(component.id.toString());
  }

  /**
   * get a value by the component-id
   */
  getValueByComponentId(componentId) {
    const tuple = this.hashMap.get(componentId.toString());
    if (!tuple) return null;
    return tuple[1];
  }

  /**
   * returns an array.
   */
  toArray() {
    return Array.from(this.hashMap.values());
  }

  /**
   * map entries and return a new component map.
   */
  map(predicate) {
    const tuples = this.toArray().map(([component, value]) => {
      const newValue = predicate(value, component);
      return [component.id.toString(), [component, newValue]];
    });
    return new ComponentMap(new Map(tuples));
  }

  /**
   * map entries and return a new component map.
   */
  async asyncMap(predicate) {
    const tuplesP = this.toArray().map(async ([component, value]) => {
      const newValue = await predicate(value, component);
      return [component.id.toString(), [component, newValue]];
    });
    const tuples = await Promise.all(tuplesP);

    // @ts-ignore TODO: fix this type
    return new ComponentMap(new Map(tuples));
  }

  /**
   * similar to Array.forEach, but here you get both, the value and the component.
   */
  forEach(predicate) {
    this.toArray().forEach(([component, value]) => {
      predicate(value, component);
    });
  }

  /**
   * flatten values of all components into a single array.
   */
  flattenValue() {
    return this.toArray().reduce((acc, [, value]) => {
      acc = acc.concat(value);
      return acc;
    }, []);
  }

  /**
   * filter all components with empty values and return a new map.
   */
  filter(predicate) {
    const tuples = this.toArray().filter(([, value]) => {
      return predicate(value);
    });
    const asMap = tuples.map(([component, value]) => {
      return [component.id.toString(), [component, value]];
    });
    return new ComponentMap(new Map(asMap));
  }

  /**
   * get all component ids.
   */
  keys() {
    return this.hashMap.keys();
  }
  static create(rawMap) {
    const newMap = rawMap.map(([component, data]) => {
      return [component.id.toString(), [component, data]];
    });
    return new ComponentMap(new Map(newMap));
  }

  /**
   * create a component map from components and a value predicate.
   * @param components components to zip into the map.
   * @param predicate predicate for returning desired value.
   */
  static as(components, predicate) {
    const tuples = components.map(component => {
      return [component.id.toString(), [component, predicate(component)]];
    });
    return new ComponentMap(new Map(tuples));
  }

  /**
   * create a component map from components and a value predicate.
   * @param components components to zip into the map.
   * @param predicate predicate for returning desired value.
   */
  static async asAsync(components, predicate) {
    const tuples = await Promise.all(components.map(async component => {
      return [component.id.toString(), [component, await predicate(component)]];
    }));
    return new ComponentMap(new Map(tuples));
  }
}
exports.ComponentMap = ComponentMap;

//# sourceMappingURL=component-map.js.map