/**
 * This file is part of Anis Client.
 *
 * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

import { Injectable } from '@angular/core';

import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { map, tap, mergeMap, catchError } from 'rxjs/operators';
import { ToastrService } from 'ngx-toastr';

import * as coneSearchActions from '../actions/cone-search.actions';
import { ConeSearchService } from '../services/cone-search.service';

/**
 * @class
 * @classdesc Cone search effects.
 */
@Injectable()
export class ConeSearchEffects {

    /**
     * Calls actions to retrieve object coordinates.
     */
    retrieveCoordinates$ = createEffect((): any =>
        this.actions$.pipe(
            ofType(coneSearchActions.retrieveCoordinates),
            mergeMap((action) => this.coneSearchService.retrieveCoordinates(action.name)
                .pipe(
                    map(response => {
                        const parser = new DOMParser();
                        const xml = parser.parseFromString(response,'text/xml');
                        if (xml.getElementsByTagName('Resolver').length === 0) {
                            return coneSearchActions.retrieveCoordinatesFail();
                        }
                        const name = xml.getElementsByTagName('name')[0].childNodes[0].nodeValue;
                        const ra = +xml.getElementsByTagName('jradeg')[0].childNodes[0].nodeValue;
                        const dec = +xml.getElementsByTagName('jdedeg')[0].childNodes[0].nodeValue;
                        const resolver = { name, ra, dec };
                        return coneSearchActions.retrieveCoordinatesSuccess({ resolver });
                    }),
                    catchError(() => of(coneSearchActions.retrieveCoordinatesFail()))
                )
            )
        )
    );

    /**
     * Displays retrieve object coordinates error notification.
     */
    retrieveCoordinatesFail$ = createEffect(() => 
        this.actions$.pipe(
            ofType(coneSearchActions.retrieveCoordinatesFail),
            tap(() => this.toastr.error('Failure to retrieve coordinates', 'The coordinates could not be retrieved'))
        ), { dispatch: false }
    );

    constructor(
        private actions$: Actions,
        private coneSearchService: ConeSearchService,
        private toastr: ToastrService
    ) {}
}