import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectorRef, ViewChild } from '@angular/core';
import { CountryCode } from './models/country-code.model';
import { OptionModel } from 'src/app/hmg-common/ui/searchable-select/option.model';
import { InputData } from 'src/app/hmg-common/services/common/models/input-data';
import { CommonService } from 'src/app/hmg-common/services/common/common.service';
import { TranslatorService } from 'src/app/hmg-common/services/translator/translator.service';
import { ConnectorService } from 'src/app/hmg-common/services/connector/connector.service';
import { SelectComponent } from '../../select/select.component';
import { SearchableSelectComponent } from '../../searchable-select/searchable-select/searchable-select.component';

@Component({
    selector: 'international-mobile',
    templateUrl: './international-mobile.component.html',
    styleUrls: ['./international-mobile.component.scss']
})
export class InternationalMobileComponent implements OnInit {
    public static SAUDI_DIAL_CODE = '+966';
    public static SAUDI_CODE = 'SA';
    public static EMIRATE_DIAL_CODE = '+971';
    public static EMIRATE_CODE = 'AE';

    public static sharedCodes: CountryCode[];
    public static sharedOptions: OptionModel[];
    public mobileNumber: InputData = new InputData();
    @Output() changed = new EventEmitter();
    public selectedDialCode: string;
    public selectedDialCodePattern: string;
    public number: string;
    public numberMax: number;
    public numberPattern: string;
    public numberPlaceholder: string;
    public selectedCountryCode: string;
    public codes: CountryCode[];
    public options: OptionModel[];
    private dataLoaded = false;
    private phoneSetProgramatically = false;
    @ViewChild( SearchableSelectComponent) searchableSelectComponent: SearchableSelectComponent;
    constructor(
        public cs: CommonService,
        public ts: TranslatorService,
        public con: ConnectorService,
        public changeDetector: ChangeDetectorRef
    ) { }

    ngOnInit() {
        this.numberPlaceholder = 'Mobile';
        if (InternationalMobileComponent.sharedCodes) {
            this.codes = InternationalMobileComponent.sharedCodes;
            this.options = InternationalMobileComponent.sharedOptions;
            this.initializeOptions();
            this.selectDefaultCountry();
        } else {
            this.cs.startLoading();
            this.con.getLocalResrouce('assets/data/select/country-code.json').subscribe(result => {
                InternationalMobileComponent.sharedCodes = result.codes;
                this.codes = result.codes;
                this.initializeOptions();
                this.selectDefaultCountry();
                this.cs.stopLoading();
            });
        }
    }

    private initializeOptions() {
        InternationalMobileComponent.sharedOptions = [];
        for ( const code of this.codes ){
            InternationalMobileComponent.sharedOptions.push ( new OptionModel(code.name, code));
        }
        this.options = InternationalMobileComponent.sharedOptions;
    }

    private selectDefaultCountry() {
        setTimeout(() => {
            this.dataLoaded = true;
            this.selectedCountryCode = InternationalMobileComponent.SAUDI_CODE;
            // this.changeDetector.detectChanges();
            this.countrySelected();
        }, 40);
    }
    private findCountryByDialCode(targetCode: string) {
        for (const code of this.codes) {
            if (targetCode === code.code) {
                return code;
            }
        }
        return null;
    }
    private findCountryByCountryCode(targetCode: string) {
        for (const code of this.codes) {
            if (targetCode === code.countryCode) {
                return code;
            }
        }
        return null;
    }

    /*
    the country code selected
    */
    public countrySelected() {
        const country = this.findCountryByCountryCode(this.selectedCountryCode);
        this.setSelectedDialCodePattern(country.code);
        this.selectedDialCode = country.code;
        this.number = null;
        this.updateNumberUI(country);
        this.searchableSelectComponent.setDefault( country.name);
    }

    public optionSelected(option: OptionModel) {
        const country = this.findCountryByCountryCode( option.data.countryCode);
        this.setSelectedDialCodePattern(country.code);
        this.selectedDialCode = country.code;
        this.number = null;
        this.updateNumberUI(country);
    }

    public optionCanceled() {
        // this.selectDefaultCountry();
    }

    private setSelectedDialCodePattern(code: string) {
        let length = code.length - 1;
        length = length < 1 ? 1 : length;
        this.selectedDialCodePattern = '^[+]([0-9]{' + length + '})';
    }
    /*
    the dial code selected
    */
    public codeSelected() {
        if (this.phoneSetProgramatically) {
            this.phoneSetProgramatically = false;
        } else {
            this.number = null;
        }

        const country = this.findCountryByDialCode(this.selectedDialCode);
        // update the country only if the country is different
        if (country.countryCode !== this.selectedCountryCode) {
            this.selectedCountryCode = country.countryCode;
        }

        this.trigerInformation(this.findCountryByDialCode(this.selectedDialCode));
    }

    /*
    the input phone number entered by user
    */
    public numberChanged() {
        this.trigerInformation(this.findCountryByDialCode(this.selectedDialCode));
    }

    private updateNumberUI(country: CountryCode) {
        this.numberPlaceholder = country.pattern || this.ts.trPK('general', 'mobile');
        if (country.maxLength) {
            this.numberMax = country.maxLength;
            this.numberPattern = '([0-9]{' + (this.numberMax) + '})';
        } else {
            this.numberMax = country.maxLength || 15;
            this.numberPattern = '([0-9]{3,15})';
        }
    }

    private trigerInformation(country: CountryCode) {
        if (country) {
            /* update ui */
            this.updateNumberUI(country);
            /* trigger information */
            country.number = this.number;
            country.isValid = this.isValid(country);
            this.changed.emit(this.number ? country : null);
        }
    }

    public isValid(country: CountryCode) {
        return this.number != null && this.isValidLength(country);
    }

    private isValidLength(country: CountryCode) {
        if (country.maxLength) {
            return this.number.toString().length === country.maxLength;
        } else {
            return this.number.toString().length > 0;
        }
    }

    /*
      code must start with +
    */
    public setMobileNumber(code, number) {
        setTimeout(() => {
            if (!this.dataLoaded) {
                this.setMobileNumber(code, number);
            } else {
                this.phoneSetProgramatically = true;
                this.number = number;
                this.selectedDialCode = code;
                this.setSelectedDialCodePattern(code);
                const country = this.findCountryByDialCode(code);
                this.updateNumberUI(country);
                this.searchableSelectComponent.setDefault( country.name);
            }
        }, 50);
    }

}
