import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType, OnInitEffects } from '@ngrx/effects';
import {
  EISPublicService,
  ListResponseArgsOfDisplayInfoDTO,
  StrictHttpResponse,
  ResponseArgsOfEntityDTOContainerOfBranchDTO,
  ResponseArgsOfConfirmationDTO,
  ResponseArgs,
} from '@swagger/eis';
import * as actions from './task-calendar.actions';
import { TaskCalendarFacade } from './task-calendar.facade';
import { withLatestFrom, switchMap, catchError, map, flatMap } from 'rxjs/operators';
import { of, NEVER, Observable } from 'rxjs';

@Injectable()
export class TaskCalendarEffects implements OnInitEffects {
  constructor(private actions$: Actions, private taskCalendarFacade: TaskCalendarFacade, private eisPublicService: EISPublicService) {}

  getTasksRequest$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.getTasksRequest),
      withLatestFrom(this.taskCalendarFacade.filter$),
      switchMap(([action, data]) =>
        this.eisPublicService
          .EISPublicGetDisplayInfosResponse({ data })
          .pipe(catchError((err) => of<StrictHttpResponse<ListResponseArgsOfDisplayInfoDTO>>(err)))
      ),
      map((response) => actions.getTasksResponse({ response }))
    )
  );

  getTasksResponse$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.getTasksResponse),
      flatMap(({ response }) => {
        if (response.ok) {
          return [actions.setTasks({ tasks: response.body.result })];
        }
        return [];
      })
    )
  );

  setFilterOrPatchFilter$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.setFilter, actions.patchFilter),
      map(() => actions.getTasksRequest())
    )
  );

  getCurrentBranchRequest$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.getCurrentBranchRequest),
      switchMap(() =>
        this.eisPublicService
          .EISPublicGetCurrentBranchResponse({})
          .pipe(catchError((err) => of<StrictHttpResponse<ResponseArgsOfEntityDTOContainerOfBranchDTO>>(err)))
      ),
      map((response) => actions.getCurrentBranchResponse({ response }))
    )
  );

  getCurrentBranchResponse$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.getCurrentBranchResponse),
      flatMap(({ response }) => {
        if (response.ok) {
          return [actions.patchFilter({ filter: { branchId: response.body.result.id } })];
        }

        return [];
      })
    )
  );

  patchTaskStatus$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskStatus),
      flatMap((action) => {
        if (action.state === 'complete') {
          return [actions.patchTaskCompleteRequest({ taskId: action.taskId, file: action.file })];
        } else if (action.state === 'edit') {
          return [actions.patchTaskEditRequest({ taskId: action.taskId })];
        } else if (action.state === 'reset') {
          return [actions.patchTaskResetRequest({ taskId: action.taskId })];
        }
        return NEVER;
      })
    )
  );

  patchTaskEditRequest$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskEditRequest),
      flatMap((action) =>
        this.eisPublicService
          .EISPublicSetInfoToEditResponse({ infoId: action.taskId })
          .pipe(catchError((err) => of<StrictHttpResponse<ResponseArgsOfConfirmationDTO>>(err)))
      ),
      map((response) => actions.patchTaskEditResponse({ response }))
    )
  );

  patchTaskEditResponse$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskEditResponse),
      flatMap((action) => {
        if (action.response.ok) {
          return [actions.getTaskRequest({ taskId: action.response.body.result.id })];
        }
        return NEVER;
      })
    )
  );

  patchTaskResetRequest$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskResetRequest),
      flatMap((action) =>
        this.eisPublicService
          .EISPublicResetConfirmationResponse({ infoId: action.taskId })
          .pipe(catchError((err) => of<StrictHttpResponse<ResponseArgsOfConfirmationDTO>>(err)))
      ),
      map((response) => actions.patchTaskResetResponse({ response }))
    )
  );

  patchTaskResetResponse$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskResetResponse),
      flatMap((action) => {
        if (action.response.ok) {
          return [actions.getTaskRequest({ taskId: action.response.body.result.id })];
        }
        return NEVER;
      })
    )
  );

  patchTaskCompleteRequest$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskCompleteRequest),
      flatMap((action) =>
        this.eisPublicService.EISPublicCompleteConfirmationResponse({ infoId: action.taskId, file: action.file }).pipe(
          catchError((err) => of<StrictHttpResponse<ResponseArgs>>(err)),
          map((response) => actions.patchTaskCompleteResponse({ taskId: action.taskId, response }))
        )
      )
    )
  );

  patchTaskCompleteResponse$ = createEffect(() =>
    this.actions$.pipe(
      ofType(actions.patchTaskCompleteResponse),
      flatMap((action) => {
        if (action.response.ok) {
          return [actions.getTaskRequest({ taskId: action.taskId })];
        }
        return NEVER;
      })
    )
  );

  ngrxOnInitEffects() {
    return actions.getCurrentBranchRequest();
  }
}
