import { Component, OnInit, ViewChild, ElementRef, EventEmitter, Output, Input, QueryList, ViewChildren } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { TranslateService } from '@ngx-translate/core';
import { AppService } from '../../../service/app.service';
import { FunctionsService } from '../../../service/functions.service';
import { Observable, of } from 'rxjs';
import { FormControl } from '@angular/forms';
import { startWith, map, tap, filter, exhaustMap, catchError } from 'rxjs/operators';
import { LatinisePipe } from 'ngx-pipes';
import { MatExpansionPanel } from '@angular/material/expansion';
import { IndexingFieldsService } from '../../../service/indexing-fields.service';
import { ActivatedRoute } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmComponent } from '../../../plugins/modal/confirm.component';
import { NotificationService } from '../../../service/notification/notification.service';
import { AddSearchTemplateModalComponent } from './search-template/search-template-modal.component';
import { DatePipe } from '@angular/common';
import { ContactAutocompleteComponent } from '@appRoot/contact/autocomplete/contact-autocomplete.component';
import { PluginSelectAutocompleteSearchComponent } from '@plugins/select-autocomplete-search/plugin-select-autocomplete-search.component';
import { FolderInputComponent } from '@appRoot/folder/indexing/folder-input.component';
import { TagInputComponent } from '@appRoot/tag/indexing/tag-input.component';
import { IssuingSiteInputComponent } from '@appRoot/administration/registered-mail/issuing-site/indexing/issuing-site-input.component';

@Component({
    selector: 'app-criteria-tool',
    templateUrl: 'criteria-tool.component.html',
    styleUrls: ['criteria-tool.component.scss', '../../indexation/indexing-form/indexing-form.component.scss'],
    providers: [DatePipe]
})
export class CriteriaToolComponent implements OnInit {

    loading: boolean = true;
    criteria: any = [];
    searchTemplates: any;

    currentCriteria: any = [];

    filteredCriteria: Observable<string[]>;

    searchTermControl = new FormControl();
    searchCriteria = new FormControl();

    hideCriteriaList: boolean = true;

    @Input() searchTerm: string = 'Foo';
    @Input() defaultCriteria: any = [];

    @Output() searchUrlGenerated = new EventEmitter<any>();
    @Output() loaded = new EventEmitter<any>();

    @ViewChild('criteriaTool', { static: false }) criteriaTool: MatExpansionPanel;
    @ViewChild('searchCriteriaInput', { static: false }) searchCriteriaInput: ElementRef;
    @ViewChild('appFolderInput', { static: false }) appFolderInput: FolderInputComponent;
    @ViewChild('appTagInput', { static: false }) appTagInput: TagInputComponent;
    @ViewChild('appIssuingSiteInput', { static: false }) appIssuingSiteInput: IssuingSiteInputComponent;

    @ViewChildren('appContactAutocomplete') appContactAutocomplete: QueryList<ContactAutocompleteComponent>;
    @ViewChildren('pluginSelectAutocompleteSearch') pluginSelectAutocompleteSearch: QueryList<PluginSelectAutocompleteSearchComponent>;


    constructor(
        private _activatedRoute: ActivatedRoute,
        public translate: TranslateService,
        public http: HttpClient,
        public appService: AppService,
        public functions: FunctionsService,
        public indexingFields: IndexingFieldsService,
        private dialog: MatDialog,
        private notify: NotificationService,
        private datePipe: DatePipe,
        private latinisePipe: LatinisePipe) {
            _activatedRoute.queryParams.subscribe(
                params => {
                    this.searchTerm = params.value;
                }
            );
        }

    async ngOnInit(): Promise<void> {
        this.searchTermControl.setValue(this.searchTerm);

        this.criteria = await this.indexingFields.getAllFields();

        this.criteria.forEach((element: any) => {
            if (this.defaultCriteria.indexOf(element.identifier) > -1) {
                element.control = new FormControl('');
                this.addCriteria(element, false);
            }
        });

        this.loaded.emit(true);

        this.filteredCriteria = this.searchCriteria.valueChanges
            .pipe(
                startWith(''),
                map(value => this._filter(value))
            );
        this.loading = false;
        setTimeout(() => {
            this.searchTermControl.valueChanges
            .pipe(
                startWith(''),
                map(value => {
                    if (typeof value === 'string' && !this.functions.empty(value)) {
                        this.searchTerm = value;
                    }
                })
            ).subscribe();
        }, 500);
        this.getSearchTemplates();
    }

    private _filter(value: string): string[] {
        if (typeof value === 'string') {
            const filterValue = this.latinisePipe.transform(value.toLowerCase());
            return this.criteria.filter((option: any) => this.latinisePipe.transform(option['label'].toLowerCase()).includes(filterValue));
        } else {
            return this.criteria;
        }
    }

    isCurrentCriteria(criteriaId: string) {
        return this.currentCriteria.filter((currCrit: any) => currCrit.identifier === criteriaId).length > 0;
    }

    async addCriteria(criteria: any, openPanel: boolean = true) {
        if (this.functions.empty(criteria.control) || this.functions.empty(criteria.control.value)) {
            criteria.control = criteria.type === 'date' ? new FormControl({}) : new FormControl('');
        }
        this.initField(criteria);
        this.currentCriteria.push(criteria);
        this.searchTermControl.setValue(this.searchTerm);
        this.searchCriteria.reset();
        // this.searchCriteriaInput.nativeElement.blur();
        if (openPanel) {
            setTimeout(() => {
                this.criteriaTool.open();
            }, 0);
        }
    }

    initField(field: any) {
        try {
            const regex = /role_[.]*/g;
            if (field.identifier.match(regex) !== null) {
                this['set_role_field'](field);
            } else {
                this['set_' + field.identifier + '_field'](field);

            }
        } catch (error) {
            // console.log(error);
        }
    }

    removeCriteria(index: number) {
        this.currentCriteria.splice(index, 1);
        if (this.currentCriteria.length === 0) {
            this.criteriaTool.close();
        }
    }

    getFilterControl() {
        return this.searchCriteria;
    }

    getCriterias() {
        return this.criteria;
    }

    getFilteredCriterias() {
        return this.filteredCriteria;
    }

    focusFilter() {
        this.hideCriteriaList = false;
        setTimeout(() => {
            this.searchCriteriaInput.nativeElement.focus();
        }, 100);
    }

    getCurrentCriteriaValues() {
        const objCriteria = {};
        if (!this.functions.empty(this.searchTermControl.value)) {
            objCriteria['meta'] = {
                values: this.searchTermControl.value
            };
        }
        this.currentCriteria.forEach((field: any) => {
            if (field.type === 'date') {
                if (!this.functions.empty(field.control.value.start) || !this.functions.empty(field.control.value.end)) {
                    objCriteria[field.identifier] = {
                        values: field.control.value
                    };
                }
            } else {
                if (!this.functions.empty(field.control.value)) {
                    objCriteria[field.identifier] = {
                        values: field.control.value
                    };
                }
            }
        });
        this.searchUrlGenerated.emit(objCriteria);
    }

    toggleTool(state: boolean) {
        if (state) {
            this.criteriaTool.open();
        } else {
            this.criteriaTool.close();
        }

    }

    getLabelValue(identifier: string, value: any) {
        if (this.functions.empty(value)) {
            return this.translate.instant('lang.undefined');
        } else  if (['doctype', 'destination'].indexOf(identifier) > -1) {
            return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => val.id === value)[0].title;
        } else {
            if (this.criteria.filter((field: any) => field.identifier === identifier)[0].type === 'contact' || ['registeredMail_recipient', 'senders', 'recipients'].indexOf(this.criteria.filter((field: any) => field.identifier === identifier)[0].identifier)  > -1 ) {
                return this.appContactAutocomplete.toArray().filter((component: any) => component.id === identifier)[0].getFormatedContact(value.id);
            } else
            if (this.criteria.filter((field: any) => field.identifier === identifier)[0].identifier === 'folders') {
                return this.appFolderInput.getFolderLabel(value);
            } else
            if (this.criteria.filter((field: any) => field.identifier === identifier)[0].identifier === 'tags') {
                return this.appTagInput.getTagLabel(value);
            } else
            if (this.criteria.filter((field: any) => field.identifier === identifier)[0].type === 'banAutocomplete') {
                return `${value.addressNumber} ${value.addressStreet}, ${value.addressTown} (${value.addressPostcode})`;
            } else
            if (this.criteria.filter((field: any) => field.identifier === identifier)[0].type === 'selectAutocomplete') {
                return this.pluginSelectAutocompleteSearch.toArray().filter((component: any) => component.id === identifier)[0].getDataLabel(value);
            } else {
                return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => val.id === value)[0].label;

            }
        }
    }

    getFormatLabel(identifier: string, value: any) {
        if (typeof value === 'object') {
            return `${this.datePipe.transform(value.start, 'dd/MM/y') } - ${this.datePipe.transform(value.end, 'dd/MM/y')}`;
        } else {
            if (identifier === 'registeredMail_issuingSite') {
                return this.appIssuingSiteInput.getSiteLabel(value);
            } else {
                return value;
            }
        }
    }

    getLabelValues(identifier: string, values: string[]) {
        if (values.length === 0) {
            return this.translate.instant('lang.undefined');
        } else  if (['doctype', 'destination'].indexOf(identifier) > -1) {
            return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => values.indexOf(val.id) > -1).map((val: any) => val.title);
        } else {
            return this.criteria.filter((field: any) => field.identifier === identifier)[0].values.filter((val: any) => values.indexOf(val.id) > -1).map((val: any) => val.label);
        }
    }

    refreshCriteria(criteria: any) {
        this.currentCriteria.forEach((field: any, index: number) => {
            if (criteria[field.identifier] !== undefined) {
                if (this.currentCriteria[index].type === 'date' && this.functions.empty(criteria[field.identifier].values)) {
                    field.control.setValue({
                        start: null,
                        end: null
                    });
                } else {
                    field.control.setValue(criteria[field.identifier].values);
                }
            }
        });

        if (Object.keys(criteria)[0] === 'meta') {
            this.searchTermControl.setValue(criteria['meta'].values);
        }
        this.getCurrentCriteriaValues();
    }

    searchInAttachments(identifier: string) {
        return ['subject', 'chrono', 'fulltext'].indexOf(identifier) > -1;
    }

    displayInfoSearch(infoSearchNumber: number) {
        if (infoSearchNumber === 1 && (this.isCurrentCriteria('subject') || this.isCurrentCriteria('chrono') || this.isCurrentCriteria('fulltext') )) {
            return true;
        } else if (infoSearchNumber === 2 && this.isCurrentCriteria('fulltext')) {
            return true;
        }
        return false;
    }

    set_meta_field(value: any) {
        this.searchTermControl.setValue(value);
    }

    set_doctype_field(elem: any) {
        return new Promise((resolve, reject) => {
            this.http.get(`../rest/doctypes`).pipe(
                tap((data: any) => {
                    let arrValues: any[] = [];
                    data.structure.forEach((doctype: any) => {
                        if (doctype['doctypes_second_level_id'] === undefined) {
                            arrValues.push({
                                id: doctype.doctypes_first_level_id,
                                label: doctype.doctypes_first_level_label,
                                title: doctype.doctypes_first_level_label,
                                disabled: true,
                                isTitle: true,
                                color: doctype.css_style
                            });
                            data.structure.filter((info: any) => info.doctypes_first_level_id === doctype.doctypes_first_level_id && info.doctypes_second_level_id !== undefined && info.description === undefined).forEach((secondDoctype: any) => {
                                arrValues.push({
                                    id: secondDoctype.doctypes_second_level_id,
                                    label: '&nbsp;&nbsp;&nbsp;&nbsp;' + secondDoctype.doctypes_second_level_label,
                                    title: secondDoctype.doctypes_second_level_label,
                                    disabled: true,
                                    isTitle: true,
                                    color: secondDoctype.css_style
                                });
                                arrValues = arrValues.concat(data.structure.filter((infoDoctype: any) => infoDoctype.doctypes_second_level_id === secondDoctype.doctypes_second_level_id && infoDoctype.description !== undefined).map((infoType: any) => {
                                    return {
                                        id: infoType.type_id,
                                        label: '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' + infoType.description,
                                        title: infoType.description,
                                        disabled: false,
                                        isTitle: false,
                                    };
                                }));
                            });
                        }
                    });
                    elem.values = arrValues;
                    elem.event = 'calcLimitDate';
                    resolve(true);
                })
            ).subscribe();
        });
    }

    set_priority_field(elem: any) {
        return new Promise((resolve, reject) => {
            this.http.get(`../rest/priorities`).pipe(
                tap((data: any) => {
                    elem.values = data.priorities;
                    resolve(true);
                })
            ).subscribe();
        });
    }

    set_status_field(elem: any) {
        return new Promise((resolve, reject) => {
            this.http.get(`../rest/statuses`).pipe(
                tap((data: any) => {
                    elem.values = data.statuses.map((val: any) => {
                        return {
                            id: val.identifier,
                            label: val.label_status
                        };
                    });
                    resolve(true);
                })
            ).subscribe();
        });
    }

    set_category_field(elem: any) {
        return new Promise((resolve, reject) => {
            this.http.get(`../rest/categories`).pipe(
                tap((data: any) => {
                    elem.values = data.categories.map((val: any) => {
                        return {
                            id: val.id,
                            label: val.label
                        };
                    });
                    resolve(true);
                })
            ).subscribe();
        });
    }

    set_destination_field(elem: any) {
        return new Promise((resolve, reject) => {
            this.http.get(`../rest/indexingModels/entities`).pipe(
                tap((data: any) => {
                        let title = '';
                        elem.values = elem.values.concat(data.entities.map((entity: any) => {
                            title = entity.entity_label;

                            for (let index = 0; index < entity.level; index++) {
                                entity.entity_label = '&nbsp;&nbsp;&nbsp;&nbsp;' + entity.entity_label;
                            }
                            return {
                                id: entity.id,
                                title: title,
                                label: entity.entity_label,
                                disabled: false
                            };
                        }));
                    resolve(true);
                })
            ).subscribe();
        });
    }

    set_initiator_field(elem: any) {
        return new Promise((resolve, reject) => {
            this.http.get(`../rest/indexingModels/entities`).pipe(
                tap((data: any) => {
                        let title = '';
                        elem.values = elem.values.concat(data.entities.map((entity: any) => {
                            title = entity.entity_label;

                            for (let index = 0; index < entity.level; index++) {
                                entity.entity_label = '&nbsp;&nbsp;&nbsp;&nbsp;' + entity.entity_label;
                            }
                            return {
                                id: entity.id,
                                title: title,
                                label: entity.entity_label,
                                disabled: false
                            };
                        }));
                    resolve(true);
                })
            ).subscribe();
        });
    }

    set_role_field(elem: any) {
        elem.type = 'selectAutocomplete';
        elem.routeDatas = elem.identifier === 'role_dest' ? ['/rest/autocomplete/users'] : ['/rest/autocomplete/users', '/rest/autocomplete/entities'];

        /*return new Promise((resolve, reject) => {
            this.http.get(`../rest/users`).pipe(
                tap((data: any) => {
                    const arrValues: any[] = [];
                    data.users.forEach((user: any) => {
                        arrValues.push({
                            id: user.id,
                            label: `${user.firstname} ${user.lastname}`,
                            title: `${user.firstname} ${user.lastname}`,
                        });
                    });
                    elem.values = arrValues;
                    resolve(true);
                })
            ).subscribe();
        });*/
    }

    getSearchTemplates() {
        this.http.get(`../rest/searchTemplates`).pipe(
            tap((data: any) => {
                this.searchTemplates = data.searchTemplates;
            })
        ).subscribe();
    }

    saveSearchTemplate() {
        let query: any = [];
        this.currentCriteria.forEach((field: any, index: number) => {
            query.push({'identifier': field.identifier, 'values': field.control.value});
        });

        query.push({'identifier': 'searchTerm', 'values': this.searchTermControl.value});

        const dialogRef = this.dialog.open(
            AddSearchTemplateModalComponent,
            {
                panelClass: 'maarch-modal',
                autoFocus: true,
                disableClose: true,
                data: {
                    searchTemplate: {query: query}
                }
            }
        );

        dialogRef.afterClosed().pipe(
            filter((data: any) => data !== undefined),
            tap((data) => {
                this.searchTemplates.push(data.searchTemplate);
            }),
            catchError((err: any) => {
                this.notify.handleErrors(err);
                return of(false);
            })
        ).subscribe();
    }

    deleteSearchTemplate(id: number, index: number) {
        const dialogRef = this.dialog.open(
            ConfirmComponent,
            {
                panelClass: 'maarch-modal',
                autoFocus: false,
                disableClose: true,
                data: {
                    title: this.translate.instant('lang.delete'),
                    msg: this.translate.instant('lang.confirmAction')
                }
            }
        );

        dialogRef.afterClosed().pipe(
            filter((data: string) => data === 'ok'),
            exhaustMap(() => this.http.delete(`../rest/searchTemplates/${id}`)),
            tap(() => {
                this.searchTemplates.splice(index, 1);
                this.notify.success(this.translate.instant('lang.searchTemplateDeleted'));
            }),
            catchError((err: any) => {
                this.notify.handleErrors(err);
                return of(false);
            })
        ).subscribe();
    }

    selectSearchTemplate(searchTemplate: any, openPanel: boolean = true) {
        this.currentCriteria = [];
        this.criteria.forEach((element: any) => {
            let index = searchTemplate.query.map((field: any) => field.identifier).indexOf(element.identifier);
            if (index > -1) {
                element.control = new FormControl({ value: searchTemplate.query[index].values, disabled: false });
                element.control.value = searchTemplate.query[index].values;
                this.addCriteria(element, openPanel);
            }
        });

        let index = searchTemplate.query.map((field: any) => field.identifier).indexOf('searchTerm');
        if (index > -1) {
            this.searchTermControl.setValue(searchTemplate.query[index].values);
        }
    }
}