import { Api, RouteOptions } from './Api';
import { FetchOptions, Gateway } from '../types/Gateway';
import { Uri } from '../types/Uri';
import { PageList, toPageList } from '../types/PageList';
import { Json } from '../types/Json';
import { use } from '../types/Constructor';
import { Optional } from '../types/Types';
import { RequestOptions } from '../http/RequestOptions';

export class ApiGateway extends Gateway<RouteOptions> {
  constructor(readonly api: Api = new Api()) {
    super();
  }

  get(uri: Uri, options?: RouteOptions): Promise<PageList<Json>> {
    return this.api.get(uri, options).then(r => use(r.body.data, d => toPageList(d?.items, { total: d?.totalItems, ...d?.meta })));
  }

  getOne(uri: Uri, options?: RouteOptions): Promise<Optional<Json>> {
    return this.get(uri, options).then(r => r.first());
  }

  post(uri: Uri, item?: Json, options?: RouteOptions): Promise<Json> {
    return this.api.post(uri, item, options).then(r => r.body.data?.items.first() ?? {});
  }

  postSearch(uri: Uri, options?: RequestOptions | FetchOptions): Promise<PageList<Json>> {
    return this.api.post(uri, options).then(r => use(r.body.data, d => toPageList(d?.items, { total: d?.totalItems, ...d?.meta })));
  }

  patch(uri: Uri, item?: Json, options?: RouteOptions): Promise<Json> {
    return this.api.patch(uri, item, options).then(r => r.body.data?.items.first() ?? {});
  }

  put(uri: Uri, item?: Json, options?: RouteOptions): Promise<Json> {
    return this.api.put(uri, item, options).then(r => r.body.data?.items.first() ?? {});
  }

  delete(uri: Uri, options?: RouteOptions): Promise<boolean> {
    return this.api.delete(uri, options).then(() => true);
  }
}
