import { Build, Promised } from "./utils";

declare global {
  interface Generator<T = unknown, TReturn = any, TNext = unknown> {
    /**
     * Returns the number of elements in a sequence.
     * @returns The number of elements in the input sequence.
     */
    count(): number;
    /**
     * Returns a number that represents how many elements in the specified sequence satisfy a condition.
     * @param predicate A number that represents how many elements in the sequence satisfy the condition in the predicate function.
     * @returns A function to test each element for a condition.
     */
    count(predicate: (item: T) => boolean): number;
  }

  interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> {
    count(): Promise<number>;
    count(predicate: (item: T) => Promised<boolean>): Promise<number>;
  }
}

Build(
  "count",
  function (predicate) {
    let pred = predicate ?? ((i) => true);
    let count = 0;
    for (const item of this) {
      if (pred(item)) count++;
    }

    return count;
  },
  async function (predicate) {
    let pred = predicate ?? ((i) => true);
    let count = 0;
    for await (const item of this) {
      if (await Promise.resolve(pred(item))) count++;
    }

    return count;
  }
);
