import { HttpParams } from "@angular/common/http";

export class QueryStringBuilder {
  static buildFromObj<T>(obj: T): HttpParams {
    const params: HttpParams = new HttpParams();

    if (obj == null) {
      return params;
    }

    return QueryStringBuilder.populateSearchParams(params, '', obj);
  }

  private static populateArray<T>(params: HttpParams, prefix: string, val: Array<T>): HttpParams {
    for (const index in val) {
      const key = prefix + '[' + index + ']';
      const value: unknown = val[index];
      params = QueryStringBuilder.populateSearchParams(params, key, value);
    }
    return params;
  }

  private static populateObject<T>(params: HttpParams, prefix: string, val: T): HttpParams {
    const objectKeys = Object.keys(val) as Array<keyof T>;

    for (const objKey of objectKeys) {
      const value = val[objKey];
      let key = prefix;
      if (prefix) {
        key += '[' + objKey.toString() + ']';
      } else {
        key += objKey.toString();
      }

      params = QueryStringBuilder.populateSearchParams(params, key, value);
    }
    return params;
  }

  private static populateSearchParams(params: HttpParams, key: string, value: unknown): HttpParams {
    if (Array.isArray(value)) {
      return QueryStringBuilder.populateArray(params, key, value);
    }
    else if (value instanceof Date) {
      return params.append(key, value.toISOString());
    }
    else if (value instanceof Object) {
      return QueryStringBuilder.populateObject(params, key, value);
    }
    else if ('undefined' !== typeof value && null !== value) {
      return params.append(key, value.toString());
    }
    return params;
  }
}
