import { AsyncResult, Result } from ".";

/** @internal */
export function thenPipe<T, U, E>(
  f: (t: T) => Result<U, E>,
): (r: Result<T, E>) => Result<U, E> {
  return (r: Result<T, E>): Result<U, E> => r.andThen(f);
}

/** @internal */
export function thenPipeAsync<T, U, E>(
  f: (t: T) => AsyncResult<U, E>,
): (r: Result<T, E>) => AsyncResult<U, E> {
  return async (r: Result<T, E>): AsyncResult<U, E> => await r.andThenAsync(f);
}

/** @internal */
export function yieldPipe<T, U, E>(
  f: (t: T) => U,
): (r: Result<T, E>) => Result<U, E> {
  return (r: Result<T, E>): Result<U, E> => r.yield(f);
}

/** @internal */
export function yieldOrPipe<T, U, E>(
  u: U,
  f: (t: T) => U,
): (r: Result<T, E>) => Result<U, E> {
  return (r: Result<T, E>): Result<U, E> => r.yieldOr(u, f);
}

/** @internal */
export function yieldOrElsePipe<T, U, E>(
  u: (e: E) => U,
  f: (t: T) => U,
): (r: Result<T, E>) => Result<U, E> {
  return (r: Result<T, E>): Result<U, E> => r.yieldOrElse(u, f);
}

/** @internal */
export function elsePipe<T, E, F>(
  f: (e: E) => Result<T, F>,
): (r: Result<T, E>) => Result<T, F> {
  return (r: Result<T, E>): Result<T, F> => r.orElse(f);
}

/** @internal */
export function elsePipeAsync<T, E, F>(
  f: (e: E) => AsyncResult<T, F>,
): (r: Result<T, E>) => AsyncResult<T, F> {
  return async (r: Result<T, E>): AsyncResult<T, F> => r.orElseAsync(f);
}

/** @internal */
export function yieldPipeAsync<T, U, E>(
  f: (t: T) => Promise<U>,
): (r: Result<T, E>) => AsyncResult<U, E> {
  return async (r: Result<T, E>): AsyncResult<U, E> => r.yieldAsync(f);
}

/** @internal */
export function errPipe<T, E, F>(
  f: (e: E) => F,
): (r: Result<T, E>) => Result<T, F> {
  return (r: Result<T, E>): Result<T, F> => r.yieldErr(f);
}
