import {Component, OnDestroy} from '@angular/core';
import {FormControl, FormGroup} from "@angular/forms";
import {select, Store} from "@ngrx/store";
import {debounceTime, Observable, Subscription, tap} from "rxjs";
import {List} from 'projects/mastodon-api/src/public-api';
import {fromFilters, selectFiltersForForm, selectLists} from "../../state/store";

interface FiltersForForm {
    fullText: string | undefined;
    lists: ReadonlyArray<string>;
    unlisted: boolean;
}

@Component({
    selector: 'app-filters',
    templateUrl: './filters.component.html',
    styleUrls: ['./filters.component.scss']
})
export class FiltersComponent implements OnDestroy {
    filtersForm = new FormGroup({
        text: new FormControl(),
        lists: new FormControl([] as string[]),
        unlisted: new FormControl(false),
    });
    currentFilter: { fullText: string | undefined; lists: string[]; unlisted: boolean; } = {fullText: undefined, lists: [], unlisted: false};

    lists$: Observable<List[]>;
    filters$: Observable<FiltersForForm>;
    formSubscription: Subscription;
    filterSubscription: Subscription;

    constructor(private store: Store) {
        this.lists$ = this.store.pipe(select(selectLists));
        this.filters$ = this.store.pipe(
            select(selectFiltersForForm),
            tap(filters => {
                this.currentFilter = {...filters, lists: [...filters.lists]};
                this.filtersForm.patchValue({
                    text: filters.fullText,
                    lists: filters.lists as string[],
                    unlisted: filters.unlisted,
                }, {emitEvent: false, onlySelf: true});
            }),
        );
        this.filterSubscription = this.filters$.subscribe();
        this.formSubscription = this.filtersForm.valueChanges
            .pipe(debounceTime(500))
            .subscribe(value => {
                if (value['unlisted'] && !this.currentFilter.unlisted) {
                    if (this.currentFilter.lists && this.currentFilter.lists.length > 0) {
                        this.filtersForm.patchValue({
                            lists: [],
                        }, {emitEvent: false, onlySelf: true});
                        value['lists'] = [];
                        this.store.dispatch(fromFilters.setLists({lists: []}));
                    }
                    this.store.dispatch(fromFilters.setUnlisted({unlisted: true}));
                } else if (this.currentFilter.unlisted) {
                    this.store.dispatch(fromFilters.setUnlisted({unlisted: false}));
                }
                if (value['lists'] && value['lists'].length > 0) {
                    this.store.dispatch(fromFilters.setLists({lists: value.lists}));
                    if (this.currentFilter.unlisted) {
                        this.store.dispatch(fromFilters.setUnlisted({unlisted: false}));
                    }
                }
                if (!value['lists'] || value['lists'].length === 0) {
                    this.store.dispatch(fromFilters.setLists({lists: []}));
                }
                if (value['text']) {
                    const text = value['text'];
                    if (text.length > 0) {
                        const parts = text.split(/[\s,]+/);
                        if (parts.some((part: string) => part.startsWith('@'))) {
                            const username = parts.find((part: string) => part.startsWith('@'));
                            this.store.dispatch(fromFilters.setUsername({username: username.substring(1)}));
                        } else {
                            this.store.dispatch(fromFilters.setUsername({username: ''}));
                        }
                        this.store.dispatch(fromFilters.setFreeText({freeText: parts.filter((part: string) => !part.startsWith('@'))}));
                    } else {
                        this.store.dispatch(fromFilters.setUsername({username: ''}));
                        this.store.dispatch(fromFilters.setFreeText({freeText: []}));
                    }
                } else {
                    if (this.currentFilter.fullText && this.currentFilter.fullText.length > 0) {
                        this.store.dispatch(fromFilters.setUsername({username: ''}));
                        this.store.dispatch(fromFilters.setFreeText({freeText: []}));
                    }
                }
            });
    }

    ngOnDestroy(): void {
        this.formSubscription.unsubscribe();
        this.filterSubscription.unsubscribe();
    }

    clearFilter() {
        this.store.dispatch(fromFilters.clearFilters());
    }
}
