import { Result } from "./result";

export interface IResultCollection<T, E extends Error = Error> {
  add(result: Result<T, E>): void;
  hasSomeFaultyResult(): boolean;
  getFirstFaultyResult(): Result<T, E>;
}

export class ResultCollection<T, E extends Error = Error> implements IResultCollection<T, E> {
  private _collection: Result<T, E>[] = [];

  constructor(results?: Result<T, E>[]) {
    this._collection = results ?? [];
  }

  public add(result: Result<T, E>): void {
    this._collection.push(result);
  }

  public reset(): void {
    this._collection = [];
  }

  public hasSomeFaultyResult(): boolean {
    return this._collection.some((result) => result.isFailure);
  }

  public getFirstFaultyResult(): Result<never, E> {
    const firstFaultyResult = this._collection.find((result) => result.isFailure);
    return Result.fail(firstFaultyResult?.error);
  }

  public getAllFaultyResults(): Result<T, E>[] {
    return this._collection.filter((result) => result.isFailure);
  }

  public get objects(): T[] {
    return this._collection.filter((result) => result.isSuccess).map((result) => result.data);
  }

  public get errors(): E[] {
    return this._collection.filter((result) => result.isFailure).map((result) => result.error);
  }
}
