import { Resource } from '@ngxp/rest';
import { Observable, map, withLatestFrom } from 'rxjs';
import { StateResource } from '../resource/resource.util';
import { ApiSingleResourceStateService } from './state.service';

export class ApiStateServiceExecuter<B extends Resource, T extends Resource> {
  private stateService: ApiSingleResourceStateService<B, T>;
  private baseResource: Observable<StateResource<T>>;
  shouldExecute: boolean;

  public static init<B extends Resource, T extends Resource>(
    stateService: ApiSingleResourceStateService<B, T>,
  ): ApiStateServiceExecuter<B, T> {
    return new ApiStateServiceExecuter<B, T>(stateService);
  }

  constructor(stateService: ApiSingleResourceStateService<B, T>) {
    this.stateService = stateService;

    this.shouldExecute = true;
  }

  public withBaseResource(baseResource: Observable<StateResource<T>>): this {
    this.baseResource = baseResource;
    return this;
  }

  public execute(runnable: (resource: T) => void): Observable<StateResource<T>> {
    return this.baseResource.pipe(
      withLatestFrom(this.stateService.selectResource()),
      map(([baseStateResource, stateResource]) => {
        if (this.shouldExecute && !baseStateResource.loading) {
          runnable(stateResource.resource);
          this.shouldExecute = false;
          return { ...baseStateResource, loading: true };
        }
        return baseStateResource;
      }),
    );
  }
}