/**
 * 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, concatLatestFrom } from '@ngrx/effects';
import { Store, Action  } from '@ngrx/store';
import { of } from 'rxjs';
import { map, tap, mergeMap, catchError } from 'rxjs/operators';
import { ToastrService } from 'ngx-toastr';

import { criterionToString, stringToCriterion } from '../models';
import { SearchService } from '../services/search.service';
import * as documentationActions from '../actions/documentation.actions';
import * as searchActions from '../actions/search.actions';
import * as attributeActions from 'src/app/metamodel/actions/attribute.actions';
import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector';
import * as criteriaFamilyActions from 'src/app/metamodel/actions/criteria-family.actions';
import * as outputFamilyActions from 'src/app/metamodel/actions/output-family.actions';
import * as outputCategoryActions from 'src/app/metamodel/actions/output-category.actions';
import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector';
import * as searchSelector from '../selectors/search.selector';

@Injectable()
export class DocumentationEffects {
    loadAttributeList$ = createEffect(() =>
        this.actions$.pipe(
            ofType(documentationActions.loadAttributeList),
            concatLatestFrom(() => this.store.select(datasetSelector.selectDatasetNameByRoute)),
            mergeMap(([action, datasetName]) => {
                console.log('ok');
                return of(attributeActions.loadAttributeList());
            })
        )
    );

    // initSearch$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.initSearch),
    //         concatLatestFrom(() => [
    //             this.store.select(datasetSelector.selectDatasetNameByRoute),
    //             this.store.select(searchSelector.selectCurrentDataset),
    //             this.store.select(searchSelector.selectPristine),
    //             this.store.select(searchSelector.selectStepsByRoute)
    //         ]),
    //         mergeMap(([action, datasetName, currentDataset, pristine, steps]) => {
    //             // User has changed dataset: reload initial state + init search
    //             if (datasetName && currentDataset && datasetName !== currentDataset) {
    //                 return of(searchActions.restartSearch());
    //             }
    //
    //             // User has selected a dataset or page is reloaded: load dataset metamodel
    //             if (datasetName && pristine) {
    //                 let actions: Action[] = [
    //                     searchActions.changeCurrentDataset({ currentDataset: datasetName }),
    //                     attributeActions.loadAttributeList(),
    //                     criteriaFamilyActions.loadCriteriaFamilyList(),
    //                     outputFamilyActions.loadOutputFamilyList(),
    //                     outputCategoryActions.loadOutputCategoryList()
    //                 ];
    //                 if (steps) {
    //                     if(steps[0] === '1') {
    //                         actions.push(searchActions.checkCriteria());
    //                     }
    //                     if(steps[1] === '1') {
    //                         actions.push(searchActions.checkOutput());
    //                     }
    //                     if(steps[2] === '1') {
    //                         actions.push(searchActions.checkResult());
    //                     }
    //                 }
    //                 return actions;
    //             }
    //
    //             // User come back to the search module: reload initial state
    //             if(!datasetName && !pristine) {
    //                 return of(searchActions.resetSearch());
    //             }
    //
    //             // User change step and it's the same search: No action
    //             return of({ type: '[No Action] Init Search' });
    //         })
    //     )
    // );
    //
    // restartSearch$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.restartSearch),
    //         map(() => searchActions.initSearch())
    //     )
    // );
    //
    // loadDefaultFormParameters$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.loadDefaultFormParameters),
    //         concatLatestFrom(() => [
    //             this.store.select(attributeSelector.selectAllAttributes),
    //             this.store.select(searchSelector.selectCriteriaListByRoute),
    //             this.store.select(searchSelector.selectOutputListByRoute)
    //         ]),
    //         mergeMap(([action, attributeList, criteriaList, outputList]) => {
    //             // Update criteria list
    //             let defaultCriteriaList = [];
    //             if (criteriaList) {
    //                 // Build criteria list with the URL query parameters (c)
    //                 defaultCriteriaList = criteriaList.split(';').map((c: string) => {
    //                     const params = c.split('::');
    //                     const attribute = attributeList.find(a => a.id === parseInt(params[0], 10));
    //                     return stringToCriterion(attribute, params);
    //                 });
    //             } else {
    //                 // Build default criteria list with the attribute list metamodel configuration
    //                 defaultCriteriaList = attributeList
    //                     .filter(attribute => attribute.id_criteria_family && attribute.search_type && attribute.min)
    //                     .map(attribute => stringToCriterion(attribute));
    //             }
    //
    //             // Update output list
    //             let defaultOutputList = [];
    //             if (outputList) {
    //                 // Build output list with the URL query parameters (a)
    //                 defaultOutputList = outputList.split(';').map((o: string) => parseInt(o, 10));
    //             } else {
    //                 // Build default output list with the attribute list metamodel configuration
    //                 defaultOutputList = attributeList
    //                     .filter(attribute => attribute.selected && attribute.id_output_category)
    //                     .map(attribute => attribute.id);
    //             }
    //
    //             // Returns actions and mark the form as dirty
    //             return [
    //                 searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }),
    //                 searchActions.updateOutputList({ outputList: defaultOutputList }),
    //                 searchActions.markAsDirty()
    //             ];
    //         })
    //     )
    // );
    //
    // retrieveDataLength$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.retrieveDataLength),
    //         concatLatestFrom(() => [
    //             this.store.select(datasetSelector.selectDatasetNameByRoute),
    //             this.store.select(searchSelector.selectCriteriaList)
    //         ]),
    //         mergeMap(([action, datasetName, criteriaList]) => {
    //             let query = datasetName + '?a=count';
    //             if (criteriaList.length > 0) {
    //                 query += '&c=' + criteriaList.map(criterion => criterionToString(criterion)).join(';');
    //             }
    //
    //             return this.searchService.retrieveDataLength(query)
    //                 .pipe(
    //                     map((response: { nb: number }[]) => searchActions.retrieveDataLengthSuccess({ length: response[0].nb })),
    //                     catchError(() => of(searchActions.retrieveDataLengthFail()))
    //                 )
    //         })
    //     )
    // );
    //
    // retrieveDataLengthFail$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.retrieveDataLengthFail),
    //         tap(() => this.toastr.error('Loading Failed', 'The search data length loading failed'))
    //     ), { dispatch: false}
    // );
    //
    // retrieveData$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.retrieveData),
    //         concatLatestFrom(() => [
    //             this.store.select(datasetSelector.selectDatasetNameByRoute),
    //             this.store.select(searchSelector.selectCriteriaList),
    //             this.store.select(searchSelector.selectOutputList)
    //         ]),
    //         mergeMap(([action, datasetName, criteriaList, outputList]) => {
    //             let query = datasetName + '?a=' + outputList.join(';');
    //             if (criteriaList.length > 0) {
    //                 query += '&c=' + criteriaList.map(criterion => criterionToString(criterion)).join(';');
    //             }
    //             query += '&p=' + action.pagination.nbItems + ':' + action.pagination.page;
    //             query += '&o=' + action.pagination.sortedCol + ':' + action.pagination.order;
    //
    //             return this.searchService.retrieveData(query)
    //                 .pipe(
    //                     map((data: any[]) => searchActions.retrieveDataSuccess({ data })),
    //                     catchError(() => of(searchActions.retrieveDataFail()))
    //                 )
    //         })
    //     )
    // );
    //
    // retrieveDataFail$ = createEffect(() =>
    //     this.actions$.pipe(
    //         ofType(searchActions.retrieveDataFail),
    //         tap(() => this.toastr.error('Loading Failed', 'The search data loading failed'))
    //     ), { dispatch: false}
    // );

    constructor(
        private actions$: Actions,
        private store: Store<{ }>
    ) {}
}