/**
*
*  Maybe Monad
*  @Source: https://codewithstyle.info/advanced-functional-programming-in-typescript-maybe-monad/
*  @Modified by: @lucascalion - 28/08/2019
*
**/
export class Maybe<T> {
  private constructor(private value: T | null) {}

  static some<T> (value: T): Maybe<T> {
    if (!value) {
      throw Error("Provided value must not be empty");
    }
    return new Maybe(value);
  }

  static none<T> (): Maybe<T> {
    return new Maybe<T>(null);
  }

  static fromValue<T> (value: T): Maybe<T> {
    return value ? Maybe.some(value) : Maybe.none<T>();
  }

  getOrElse(defaultValue: T): T {
    return this.value === null ? defaultValue : this.value;
  }

  map<R>(f: (wrapped: T) => R): Maybe<R> {
    if (this.value === null) {
      return Maybe.none<R>();
    } else {
      return Maybe.fromValue(f(this.value));
    }
  }
}