import { Injectable } from '@angular/core'
import { Actions, Effect, ofType } from '@ngrx/effects'
import { catchError, map, switchMap } from 'rxjs/operators'
import { of } from 'rxjs/internal/observable/of'

import { <%= classify(name) %>Network } from '../../domain/gateways/network/<%= dasherize(name) %>.network'
import {
  Create<%= classify(name) %>,
  Create<%= classify(name) %>s, Delete<%= classify(name) %>, Delete<%= classify(name) %>s,
  Load<%= classify(name) %>s, Remove<%= classify(name) %>, Remove<%= classify(name) %>s,
  Update<%= classify(name) %>, Update<%= classify(name) %>s,
  Upsert<%= classify(name) %>,
  Upsert<%= classify(name) %>s,
  <%= classify(name) %>ActionTypes,
} from './<%= dasherize(name) %>.actions'
import { <%= classify(name) %> } from '../../entity/<%= dasherize(name) %>.entity'

@Injectable()
export class <%= classify(name) %>Effects {

  constructor(private actions$: Actions, private network: <%= classify(name) %>Network) {}

  @Effect()
  load<%= classify(name) %>s$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Load<%= classify(name) %>s),
    switchMap((action: Load<%= classify(name) %>s) => this.network.readList().pipe(
      map((<%= camelize(name) %>s: <%= classify(name) %>[]) => new Upsert<%= classify(name) %>s({ <%= camelize(name) %>s: <%= camelize(name) %>s })),
      catchError(error => {
        return of({
          type: '[Error] Load <%= classify(name) %>s',
          payload: error
        })
      })
    ))
  )

  @Effect()
  create<%= classify(name) %>$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Create<%= classify(name) %>),
    switchMap((action: Create<%= classify(name) %>) => this.network.create(action.payload.<%= camelize(name) %>).pipe(
      map((<%= camelize(name) %>: <%= classify(name) %>) => new Upsert<%= classify(name) %>({ <%= camelize(name) %>: <%= camelize(name) %> })),
      catchError(error => {
        return of({
          type: '[Error] Create <%= classify(name) %>',
          payload: error
        })
      })
    ))
  )

  @Effect()
  create<%= classify(name) %>s$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Create<%= classify(name) %>s),
    switchMap((action: Create<%= classify(name) %>s) => this.network.createList(action.payload.<%= camelize(name) %>s).pipe(
      map((<%= camelize(name) %>s: <%= classify(name) %>[]) => new Upsert<%= classify(name) %>s({ <%= camelize(name) %>s: <%= camelize(name) %>s })),
      catchError(error => {
        return of({
          type: '[Error] Create <%= classify(name) %>s',
          payload: error
        })
      })
    ))
  )

  @Effect()
  update<%= classify(name) %>$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Update<%= classify(name) %>),
    switchMap((action: Update<%= classify(name) %>) => this.network.update(action.payload.<%= camelize(name) %>).pipe(
      map((<%= camelize(name) %>: <%= classify(name) %>) => new Upsert<%= classify(name) %>({ <%= camelize(name) %>: <%= camelize(name) %> })),
      catchError(error => {
        return of({
          type: '[Error] Update <%= classify(name) %>',
          payload: error
        })
      })
    ))
  )

  @Effect()
  update<%= classify(name) %>s$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Update<%= classify(name) %>s),
    switchMap((action: Update<%= classify(name) %>s) => this.network.updateList(action.payload.<%= camelize(name) %>s).pipe(
      map((<%= camelize(name) %>s: <%= classify(name) %>[]) => new Upsert<%= classify(name) %>s({ <%= camelize(name) %>s: <%= camelize(name) %>s })),
      catchError(error => {
        return of({
          type: '[Error] Update <%= classify(name) %>s',
          payload: error
        })
      })
    ))
  )

  @Effect()
  delete<%= classify(name) %>$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Delete<%= classify(name) %>),
    switchMap((action: Delete<%= classify(name) %>) => this.network.delete(action.payload.<%= camelize(name) %>).pipe(
      map((<%= camelize(name) %>: <%= classify(name) %>) => new Remove<%= classify(name) %>({ id: <%= camelize(name) %>.id })),
      catchError(error => {
        return of({
          type: '[Error] Delete <%= classify(name) %>',
          payload: error
        })
      })
    ))
  )

  @Effect()
  delete<%= classify(name) %>s$ = this.actions$.pipe(
    ofType(<%= classify(name) %>ActionTypes.Delete<%= classify(name) %>s),
    switchMap((action: Delete<%= classify(name) %>s) => this.network.deleteList(action.payload.<%= camelize(name) %>s).pipe(
      map((<%= camelize(name) %>s: <%= classify(name) %>[]) => new Remove<%= classify(name) %>s({ ids: <%= camelize(name) %>s.map(<%= camelize(name) %> => <%= camelize(name) %>.id) })),
      catchError(error => {
        return of({
          type: '[Error] Delete <%= classify(name) %>s',
          payload: error
        })
      })
    ))
  )
}
