import {
    Component,
    ElementRef,
    EventEmitter,
    forwardRef,
    HostListener,
    Input,
    Output,
    ViewChild,
    ViewEncapsulation,
} from '@angular/core';
import { CitiesSearchService } from './cities-search-service/cities-search.service';
import { Language } from '@shared/enumerators';
import { LocalizationService } from '@shared/services';
import { DictionariesService } from '@modules/components/page-filters/services/dictionaries-service';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AutoComplete } from 'primeng/autocomplete';
import { Destroyable } from '@shared/destroyable';
import {
    AirportModel,
    CityModel,
} from '@modules/components/page-filters/models';
import { ruKeyboardLayout } from '@shared/helpers/keyboardLayoutConverter';

type AutocompleteItem = CityModel | AirportModel;

@Component({
    selector: 'city-autocomplete',
    templateUrl: 'city-autocomplete.component.html',
    styleUrls: ['./city-autocomplete.component.scss'],
    encapsulation: ViewEncapsulation.None,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => CityAutocompleteComponent), // replace name as appropriate
            multi: true,
        },
    ],
})
export class CityAutocompleteComponent
    extends Destroyable
    implements ControlValueAccessor
{
    openedPopup = false;

    items: AutocompleteItem[];
    regions: any[];
    countres: any[];
    airports: any[];
    city: CityModel | AirportModel;

    @Input() label: string;
    @Input() placeholder: string;
    @Input() error: string;
    @Output() errorChange = new EventEmitter<string>();

    @ViewChild('autocomplite') autocomplite: AutoComplete;

    @HostListener('document:click', ['$event'])
    clickout(event) {
        if (!this.eRef.nativeElement.contains(event.target)) {
            this.focusOut();
        }
    }

    constructor(
        private localizationService: LocalizationService,
        private dictService: DictionariesService,
        private eRef: ElementRef,
        private citiesSearch: CitiesSearchService,
    ) {
        super();
    }

    writeValue(value: string) {
        this.city = this.dictService.getCityOrAirport(value);
    }

    onTouched = () => {};
    onChange = (_: string) => {};

    registerOnChange(fn: (value: string) => void) {
        this.onChange = fn;
    }

    registerOnTouched(fn: () => void) {
        this.onTouched = fn;
    }

    async onLocate() {
        const city = await this.dictService.locate();
        if (city) {
            this.selectLocation(city);
        }
    }

    onCityChange() {
        if (!this.city || typeof this.city === 'string') {
            this.onChange(undefined);
        }
    }

    focusOut() {
        this.openedPopup = false;
    }

    filterCity(event) {
        const text: string = event.query;
        //this.onChange(text);

        if (!this.dictService.citiesAll) {
            return;
        }

        if (text.length === 3) {
            const byCityCode = this.citiesSearch.findCitiesByCode(text);
            if (byCityCode.length) {
                this.items = byCityCode;
                return;
            }
        }

        const byName = this.citiesSearch.findCitiesByName(
            this.convertText(text),
        );

        // If there is full match - select city and hide autocomplete menu
        if (
            byName.length &&
            text.toLowerCase() === byName[0].name.toLowerCase()
        ) {
            setTimeout(() => {
                this.autocomplite.hide();

                this.selectLocation(byName[0]);
                this.autocomplite.loading = false;
            }, 100);

            return;
        }

        if (byName.length) {
            this.items = byName;
            return;
        }

        const byCityCode = this.citiesSearch.findCitiesByCode(text);
        if (byCityCode.length) {
            this.items = byCityCode;
            return;
        }

        this.items = this.citiesSearch.findCitiesByAirportCode(text);
    }

    convertText(text: string) {
        return this.localizationService.Language === Language.ru
            ? ruKeyboardLayout.fromEn(text)
            : text;
    }

    selectLocation(value?: CityModel | AirportModel) {
        this.city = value;
        this.onChange(value?.code);
        this.openedPopup = false;

        if (!value) {
            return;
        }

        this.resetError();
    }

    openPopUp() {
        this.openedPopup = !this.openedPopup;
        this.resetError();
    }

    clearInput() {
        this.selectLocation(null);
    }

    inputChange() {
        this.openedPopup = false;
        this.resetError();
    }

    private resetError() {
        this.error = undefined;
        this.errorChange.emit(undefined);
    }
}
