/**
 * Utility functions for working with enums.
 */
export class Enum {
  /**
   * Return all keys from an enumeration.
   *
   * @param enumType The enumeration type.
   */
  static keys<T>(enumType: T): (keyof T)[] {
    return Object.keys(enumType) as (keyof typeof enumType)[];
  }

  /**
   * Return all values from an enumeration.
   *
   * @param enumType The enumeration type.
   */
  static values<T>(enumType: T): T[keyof T][] {
    return Object.keys(enumType).map(
      key => enumType[key as keyof typeof enumType],
    );
  }

  /**
   * Returns an enumeration type from a case-insensitive string.
   *
   * @param enumType The enumeration type.
   * @param value The value to normalize to an enumeration type.
   */
  static getValueFromString<T>(enumType: T, value: string): T[keyof T] {
    const corrected = Enum.values(enumType).filter(
      v => ((v as any) as string).toLowerCase() === value.toLowerCase(),
    );
    if (corrected.length !== 1) {
      throw Error(`${value} is not an ${enumType}`);
    }
    return corrected[0];
  }
}
