import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { map, mergeMap, catchError } from 'rxjs/operators';

import { LoadShoppingItemsAction, ShoppingActionTypes, LoadShoppingItemsSuccessAction,
         LoadShoppingItemsFailureAction, AddItemAction, AddItemSuccessAction, AddItemFailureAction,
         UpdatePriceItemSuccessAction, UpdatePriceItemFailureAction, UpdatePriceItemAction,
         UpdateQuantityItemSuccessAction, UpdateQuantityItemFailureAction, UpdateQuantityItemAction,
         DeleteItemSuccessAction,
         DeleteItemFailureAction, DeleteItemAction, ApplyDiscountOrderAction,
         ApplyDiscountOrderSuccessAction, ApplyDiscountOrderFailureAction, LoadShoppingAction,
         LoadShoppingSuccessAction, LoadShoppingFailureAction, UpdateShoppingAction,
         UpdateShoppingSuccessAction, UpdateShoppingFailureAction, UpdateDeliveryTaxAction,
         UpdateDeliveryTaxSuccessAction, UpdateDeliveryTaxFailureAction} from '../actions/shopping.action';
import { of } from 'rxjs';
import { ShoppingService } from 'src/app/services/shopping.service';

@Injectable()
export class ShoppingEffects {

  constructor(
    private actions$: Actions,
    private shoppingService: ShoppingService
  ) { }

  @Effect() loadShoppingItems$ = this.actions$
    .pipe(
      ofType<LoadShoppingItemsAction>(ShoppingActionTypes.LOAD_SHOPPING_ITEMS),
      mergeMap(
        (data) => this.shoppingService.getShoppingItems(data.payload)
          .pipe(
            map((cart) => {
              return new LoadShoppingItemsSuccessAction(cart);
            }),
            catchError(error => of(new LoadShoppingItemsFailureAction(error)))
          )
      ),
    );

    @Effect() loadShopping$ = this.actions$
    .pipe(
      ofType<LoadShoppingAction>(ShoppingActionTypes.LOAD_SHOPPING),
      mergeMap(
        (data) => this.shoppingService.getShopping(data.payload)
          .pipe(
            map((shopping) => {
              return new LoadShoppingSuccessAction(shopping);
            }),
            catchError(error => of(new LoadShoppingFailureAction(error)))
          )
      ),
    );

    @Effect() updateShopping$ = this.actions$
    .pipe(
      ofType<UpdateShoppingAction>(ShoppingActionTypes.UPDATE_SHOPPING),
      mergeMap(
        (data) => this.shoppingService.updateShopping(data.payload)
          .pipe(
            map((shopping) => {
              return new UpdateShoppingSuccessAction(shopping);
            }),
            catchError(error => of(new UpdateShoppingFailureAction(error)))
          )
      ),
    );

    @Effect() updateDeliveryTax$ = this.actions$
    .pipe(
      ofType<UpdateDeliveryTaxAction>(ShoppingActionTypes.UPDATE_DELIVERY_TAX),
      mergeMap(
        (data) => this.shoppingService.updateDeliveryTax(data.payload)
          .pipe(
            map((shopping) => {
              return new UpdateDeliveryTaxSuccessAction(shopping);
            }),
            catchError(error => of(new UpdateDeliveryTaxFailureAction(error)))
          )
      ),
    );


    @Effect() addShoppingItem$ = this.actions$
    .pipe(
      ofType<AddItemAction>(ShoppingActionTypes.ADD_ITEM),
      mergeMap(
        (data) => this.shoppingService.createItemShopping(data.payload)
          .pipe(
            map(() => new AddItemSuccessAction(data.payload)),
            catchError(error => of(new AddItemFailureAction(error)))
          )
      )
    );

    @Effect() updatePriceShoppingItem$ = this.actions$
    .pipe(
      ofType<UpdatePriceItemAction>(ShoppingActionTypes.UPDATE_PRICE_ITEM),
      mergeMap(
        (data) => this.shoppingService.updatePriceItemShopping(data.payload)
          .pipe(
            mergeMap(() => [
              new UpdatePriceItemSuccessAction(data.payload),
              new LoadShoppingAction(data.payload.idCart)
            ]),
            catchError(error => of(new UpdatePriceItemFailureAction(error)))
          )
      )
    );

    @Effect() applyDiscountOrder$ = this.actions$
    .pipe(
      ofType<ApplyDiscountOrderAction>(ShoppingActionTypes.APPLY_DISCOUNT_ORDER),
      mergeMap(
        (data) => this.shoppingService.applyDiscountOrder(data.payload)
          .pipe(
            mergeMap((items) => [
              new ApplyDiscountOrderSuccessAction(items),
              new LoadShoppingAction(data.payload.id)
            ]),
            catchError(error => of(new ApplyDiscountOrderFailureAction(error)))
          )
      )
    );

    @Effect() updateQuantityShoppingItem$ = this.actions$
    .pipe(
      ofType<UpdateQuantityItemAction>(ShoppingActionTypes.UPDATE_QUANTITY_ITEM),
      mergeMap(
        (data) => this.shoppingService.updateQuantityItemShopping(data.payload)
          .pipe(
            mergeMap(() => [
              new UpdateQuantityItemSuccessAction(data.payload),
              new LoadShoppingAction(data.payload.idCart)
            ]),
            catchError(error => of(new UpdateQuantityItemFailureAction(error)))
          )
      )
    );

    @Effect() deleteShoppingItem$ = this.actions$
    .pipe(
      ofType<DeleteItemAction>(ShoppingActionTypes.DELETE_ITEM),
      mergeMap(
        (data) => this.shoppingService.deleteItemShopping(data.payload)
          .pipe(
            mergeMap((result) => [
              new DeleteItemSuccessAction(result),
              new LoadShoppingAction(localStorage.getItem('cart'))
            ]),
            catchError(error => of(new DeleteItemFailureAction(error)))
          )
      )
    );

}
