UNPKG

ionic5-international-input

Version:

An Ionic component for International Phone Number Input, that allows all countries, validation with google phone lib, limited countries, preferred countries, virtual scrolling and much more.

1,217 lines 87.8 kB
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
import { Component, Input, forwardRef, Output, EventEmitter, ViewChild, ElementRef, HostBinding, } from '@angular/core';
import { NG_VALUE_ACCESSOR, } from '@angular/forms';
import { IonInput, Platform } from '@ionic/angular';
import { PhoneNumberFormat, PhoneNumberUtil, } from 'google-libphonenumber';
import { IonIntlTelInputService } from '../ion-intl-tel-input.service';
// import { ionIntlTelInputValidator } from '../ion-intl-tel-input.directive';
import { raf } from '../util/util';
/**
 * @ignore
 */
/**
 * @author Azzam Asghar <azzam.asghar@interstellus.com>
 */
export class IonIntlTelInputComponent {
    /**
     * @param {?} el
     * @param {?} platform
     * @param {?} ionIntlTelInputService
     */
    constructor(el, platform, ionIntlTelInputService) {
        this.el = el;
        this.platform = platform;
        this.ionIntlTelInputService = ionIntlTelInputService;
        this.cssClass = true;
        /**
         * Iso Code of default selected Country.
         * See more on.
         *
         * \@default ''
         * \@memberof IonIntlTelInputComponent
         */
        this.defaultCountryiso = '';
        /**
         * Determines whether to use `00` or `+` as dial code prefix.
         * Available attributes are '+' | '00'.
         * See more on.
         *
         * \@default +
         * \@memberof IonIntlTelInputComponent
         */
        this.dialCodePrefix = '+';
        /**
         * Determines whether to select automatic country based on user input.
         * See more on.
         *
         * \@default false
         * \@memberof IonIntlTelInputComponent
         */
        this.enableAutoCountrySelect = false;
        /**
         * Determines whether an example number will be shown as a placeholder in input.
         * See more on.
         *
         * \@default true
         * \@memberof IonIntlTelInputComponent
         */
        this.enablePlaceholder = true;
        /**
         * A fallaback placeholder to be used if no example number is found for a country.
         * See more on.
         *
         * \@default ''
         * \@memberof IonIntlTelInputComponent
         */
        this.fallbackPlaceholder = '';
        /**
         * If a custom placeholder is needed for input.
         * If this property is set it will override `enablePlaceholder` and only this placeholder will be shown.
         * See more on.
         *
         * \@default ''
         * \@memberof IonIntlTelInputComponent
         */
        this.inputPlaceholder = '';
        /**
         * Maximum Length for input.
         * See more on.
         *
         * \@default '15'
         * \@memberof IonIntlTelInputComponent
         */
        this.maxLength = '15';
        /**
         * Title of modal opened to select country dial code.
         * See more on.
         *
         * \@default 'Select Country'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalTitle = 'Select Country';
        /**
         * CSS class to attach to dial code selectionmodal.
         * See more on.
         *
         * \@default ''
         * \@memberof IonIntlTelInputComponent
         */
        this.modalCssClass = '';
        /**
         * Placeholder for input in dial code selection modal.
         * See more on.
         *
         * \@default 'Enter country name'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalSearchPlaceholder = 'Enter country name';
        /**
         * Text for close button in dial code selection modal.
         * See more on.
         *
         * \@default 'Close'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalCloseText = 'Close';
        /**
         * Slot for close button in dial code selection modal. [Ionic slots](https://ionicframework.com/docs/api/item) are supported
         * See more on.
         *
         * \@default 'end'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalCloseButtonSlot = 'end';
        /**
         * Determines whether dial code selection modal should be searchable or not.
         * See more on.
         *
         * \@default 'true'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalCanSearch = true;
        /**
         * Determines whether dial code selection modal is closed on backdrop click.
         * See more on.
         *
         * \@default 'true'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalShouldBackdropClose = true;
        /**
         * Determines whether input should be focused when dial code selection modal is opened.
         * See more on.
         *
         * \@default 'true'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalShouldFocusSearchbar = true;
        /**
         * Message to show when no countries are found for search in dial code selection modal.
         * See more on.
         *
         * \@default 'true'
         * \@memberof IonIntlTelInputComponent
         */
        this.modalSearchFailText = 'No countries found';
        /**
         * List of iso codes of manually selected countries as string, which will appear in the dropdown.
         * **Note**: `onlyCountries` should be a string array of country iso codes.
         * See more on.
         *
         * \@default null
         * \@memberof IonIntlTelInputComponent
         */
        this.onlyCountries = [];
        /**
         * List of iso codesn as string of  countries, which will appear at the top in dial code selection modal.
         * **Note**: `preferredCountries` should be a string array of country iso codes.
         * See more on.
         *
         * \@default null
         * \@memberof IonIntlTelInputComponent
         */
        this.preferredCountries = [];
        /**
         * Determines whether first country should be selected in dial code select or not.
         * See more on.
         *
         * \@default true
         * \@memberof IonIntlTelInputComponent
         */
        this.selectFirstCountry = true;
        /**
         * Determines whether to visually separate dialcode into the drop down element.
         * See more on.
         *
         * \@default true
         * \@memberof IonIntlTelInputComponent
         */
        this.separateDialCode = true;
        /**
         * Fires when the Phone number Input is changed.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.numberChange = new EventEmitter();
        /**
         * Fires when the Phone number Input is blurred.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.numberBlur = new EventEmitter();
        /**
         * Fires when the Phone number Input is focused.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.numberFocus = new EventEmitter();
        /**
         * Fires when the user is typing in Phone number Input.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.numberInput = new EventEmitter();
        /**
         * Fires when the dial code selection is changed.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.codeChange = new EventEmitter();
        /**
         * Fires when the dial code selection modal is opened.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.codeOpen = new EventEmitter();
        /**
         * Fires when the dial code selection modal is closed.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.codeClose = new EventEmitter();
        /**
         * Fires when a dial code is selected in dial code selection modal.
         * See more on.
         *
         * \@memberof IonIntlTelInputComponent
         */
        this.codeSelect = new EventEmitter();
        // tslint:disable-next-line: variable-name
        this._value = null;
        this.phoneNumber = '';
        this.countries = [];
        this.disabled = false;
        this.phoneUtil = PhoneNumberUtil.getInstance();
        this.onTouched = (/**
         * @return {?}
         */
        () => { });
        this.propagateChange = (/**
         * @param {?} _
         * @return {?}
         */
        (_) => { });
        this.startsWith = (/**
         * @param {?} input
         * @param {?} search
         * @return {?}
         */
        (input, search) => {
            return input.substr(0, search.length) === search;
        });
        this.getClasses = (/**
         * @param {?} element
         * @return {?}
         */
        (element) => {
            /** @type {?} */
            const classList = element.classList;
            /** @type {?} */
            const classes = [];
            for (let i = 0; i < classList.length; i++) {
                /** @type {?} */
                const item = classList.item(i);
                if (item !== null && this.startsWith(item, 'ng-')) {
                    classes.push(`ion-${item.substr(3)}`);
                }
            }
            return classes;
        });
        this.setClasses = (/**
         * @param {?} element
         * @param {?} classes
         * @return {?}
         */
        (element, classes) => {
            /** @type {?} */
            const classList = element.classList;
            [
                'ion-valid',
                'ion-invalid',
                'ion-touched',
                'ion-untouched',
                'ion-dirty',
                'ion-pristine',
            ].forEach((/**
             * @param {?} c
             * @return {?}
             */
            (c) => classList.remove(c)));
            classes.forEach((/**
             * @param {?} c
             * @return {?}
             */
            (c) => classList.add(c)));
        });
        this.setIonicClasses = (/**
         * @param {?} element
         * @return {?}
         */
        (element) => {
            raf((/**
             * @return {?}
             */
            () => {
                /** @type {?} */
                const input = (/** @type {?} */ (element.nativeElement));
                /** @type {?} */
                const classes = this.getClasses(input);
                this.setClasses(input, classes);
                /** @type {?} */
                const item = input.closest('ion-item');
                if (item) {
                    this.setClasses(item, classes);
                }
            }));
        });
        this.setItemClass = (/**
         * @param {?} element
         * @param {?} className
         * @param {?} addClass
         * @return {?}
         */
        (element, className, addClass) => {
            /** @type {?} */
            const input = (/** @type {?} */ (element.nativeElement));
            /** @type {?} */
            const item = input.closest('ion-item');
            if (item) {
                /** @type {?} */
                const classList = item.classList;
                if (addClass) {
                    classList.add(className);
                }
                else {
                    classList.remove(className);
                }
            }
        });
    }
    /**
     * @return {?}
     */
    get hasValueCssClass() {
        return this.hasValue();
    }
    /**
     * @return {?}
     */
    get isEnabled() {
        return !this.disabled;
    }
    /**
     * @return {?}
     */
    get value() {
        return this._value;
    }
    /**
     * @param {?} value
     * @return {?}
     */
    set value(value) {
        this._value = value;
        this.setIonicClasses(this.el);
    }
    /**
     * @param {?} change
     * @return {?}
     */
    emitValueChange(change) {
        this.propagateChange(change);
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.isIos = this.platform.is('ios');
        this.isMD = !this.isIos;
        this.setItemClass(this.el, 'item-interactive', true);
        this.fetchAllCountries();
        this.setPreferredCountries();
        if (this.onlyCountries.length) {
            this.countries = this.countries.filter((/**
             * @param {?} country
             * @return {?}
             */
            (country) => this.onlyCountries.includes(country.isoCode)));
        }
        if (this.selectFirstCountry) {
            if (this.defaultCountryiso) {
                this.setCountry(this.getCountryByIsoCode(this.defaultCountryiso));
            }
            else {
                if (this.preferredCountries.length &&
                    this.preferredCountries.includes(this.defaultCountryiso)) {
                    this.setCountry(this.getCountryByIsoCode(this.preferredCountries[0]));
                }
                else {
                    this.setCountry(this.countries[0]);
                }
            }
        }
    }
    /**
     * @param {?} changes
     * @return {?}
     */
    ngOnChanges(changes) {
        if (this.countries &&
            changes.defaulyCountryisoCode &&
            changes.defaulyCountryisoCode.currentValue !==
                changes.defaulyCountryisoCode.previousValue) {
            this.setCountry(changes.defaulyCountryisoCode.currentValue);
        }
    }
    /**
     * @param {?} fn
     * @return {?}
     */
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    /**
     * @param {?} fn
     * @return {?}
     */
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    /**
     * @param {?} obj
     * @return {?}
     */
    writeValue(obj) {
        this.fillValues(obj);
    }
    /**
     * @param {?} isDisabled
     * @return {?}
     */
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
    /**
     * @param {?} value
     * @return {?}
     */
    fillValues(value) {
        if (value &&
            value !== null &&
            typeof value === 'object' &&
            !this.isNullOrWhiteSpace(value)) {
            this.phoneNumber = value.nationalNumber;
            this.setCountry(this.getCountryByIsoCode(value.isoCode));
            this.value = value;
        }
        else if (this.value &&
            this.value !== null &&
            typeof this.value === 'object' &&
            !this.isNullOrWhiteSpace(this.value)) {
            this.phoneNumber = this.value.nationalNumber;
            this.setCountry(this.getCountryByIsoCode(this.value.isoCode));
        }
        setTimeout((/**
         * @return {?}
         */
        () => {
            this.onNumberChange();
        }), 1);
    }
    /**
     * @return {?}
     */
    hasValue() {
        return !this.isNullOrWhiteSpace(this.value);
    }
    /**
     * @return {?}
     */
    onCodeOpen() {
        this.codeOpen.emit();
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onCodeChange(event) {
        if (this.isNullOrWhiteSpace(this.phoneNumber)) {
            this.emitValueChange(null);
        }
        else {
            /** @type {?} */
            let googleNumber;
            try {
                googleNumber = this.phoneUtil.parse(this.phoneNumber, this.country.isoCode.toUpperCase());
            }
            catch (e) { }
            /** @type {?} */
            const internationallNo = googleNumber
                ? this.phoneUtil.format(googleNumber, PhoneNumberFormat.INTERNATIONAL)
                : '';
            /** @type {?} */
            const nationalNo = googleNumber
                ? this.phoneUtil.format(googleNumber, PhoneNumberFormat.NATIONAL)
                : '';
            if (this.separateDialCode && internationallNo) {
                this.phoneNumber = this.removeDialCode(internationallNo);
            }
            this.emitValueChange({
                internationalNumber: internationallNo,
                nationalNumber: nationalNo,
                isoCode: this.country.isoCode,
                dialCode: this.dialCodePrefix + this.country.dialCode,
            });
            this.codeChange.emit();
        }
        setTimeout((/**
         * @return {?}
         */
        () => {
            this.numberInputEl.setFocus();
        }), 400);
    }
    /**
     * @return {?}
     */
    onCodeClose() {
        this.onTouched();
        this.setIonicClasses(this.el);
        this.hasFocus = false;
        this.setItemClass(this.el, 'item-has-focus', false);
        this.codeClose.emit();
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onCodeSearchCountries(event) {
        /** @type {?} */
        const text = event.text.trim().toLowerCase();
        event.component.startSearch();
        event.component.items = this.filterCountries(text);
        event.component.endSearch();
    }
    /**
     * @return {?}
     */
    onCodeSelect() {
        this.codeSelect.emit();
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onIonNumberChange(event) {
        this.setIonicClasses(this.el);
        this.numberChange.emit(event);
    }
    /**
     * @return {?}
     */
    onIonNumberBlur() {
        this.onTouched();
        this.setIonicClasses(this.el);
        this.hasFocus = false;
        this.setItemClass(this.el, 'item-has-focus', false);
        this.numberBlur.emit();
    }
    /**
     * @return {?}
     */
    onIonNumberFocus() {
        this.hasFocus = true;
        this.setItemClass(this.el, 'item-has-focus', true);
        this.numberFocus.emit();
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onIonNumberInput(event) {
        this.numberInput.emit(event);
    }
    /**
     * @return {?}
     */
    onNumberChange() {
        if (!this.phoneNumber) {
            this.value = null;
            this.emitValueChange(null);
            return;
        }
        if (this.country) {
            this.emitValueChange({
                internationalNumber: this.dialCodePrefix + this.country.dialCode + ' ' + this.phoneNumber,
                nationalNumber: this.phoneNumber,
                isoCode: this.country.isoCode,
                dialCode: this.dialCodePrefix + this.country.dialCode,
            });
        }
        /** @type {?} */
        let googleNumber;
        try {
            googleNumber = this.phoneUtil.parse(this.phoneNumber, this.country.isoCode.toUpperCase());
        }
        catch (e) {
            return;
        }
        /** @type {?} */
        let isoCode = this.country ? this.country.isoCode : null;
        // auto select country based on the extension (and areaCode if needed) (e.g select Canada if number starts with +1 416)
        if (this.enableAutoCountrySelect) {
            isoCode =
                googleNumber && googleNumber.getCountryCode()
                    ? this.getCountryIsoCode(googleNumber.getCountryCode(), googleNumber)
                    : this.country.isoCode;
            if (isoCode && isoCode !== this.country.isoCode) {
                /** @type {?} */
                const newCountry = this.countries.find((/**
                 * @param {?} country
                 * @return {?}
                 */
                (country) => country.isoCode === isoCode));
                if (newCountry) {
                    this.country = newCountry;
                }
            }
        }
        isoCode = isoCode ? isoCode : this.country ? this.country.isoCode : null;
        if (!this.phoneNumber || !isoCode) {
            this.emitValueChange(null);
        }
        else {
            /** @type {?} */
            const internationallNo = googleNumber
                ? this.phoneUtil.format(googleNumber, PhoneNumberFormat.INTERNATIONAL)
                : '';
            /** @type {?} */
            const nationalNo = googleNumber
                ? this.phoneUtil.format(googleNumber, PhoneNumberFormat.NATIONAL)
                : '';
            if (this.separateDialCode && internationallNo) {
                this.phoneNumber = this.removeDialCode(internationallNo);
            }
            this.emitValueChange({
                internationalNumber: internationallNo,
                nationalNumber: nationalNo,
                isoCode: this.country.isoCode,
                dialCode: this.dialCodePrefix + this.country.dialCode,
            });
        }
    }
    /**
     * @param {?} event
     * @return {?}
     */
    onNumberKeyDown(event) {
        /** @type {?} */
        const allowedChars = /^[0-9\+\-\ ]/;
        /** @type {?} */
        const allowedCtrlChars = /[axcv]/;
        /** @type {?} */
        const allowedOtherKeys = [
            'ArrowLeft',
            'ArrowUp',
            'ArrowRight',
            'ArrowDown',
            'Home',
            'End',
            'Insert',
            'Delete',
            'Backspace',
        ];
        if (!allowedChars.test(event.key) &&
            !(event.ctrlKey && allowedCtrlChars.test(event.key)) &&
            !allowedOtherKeys.includes(event.key)) {
            event.preventDefault();
        }
    }
    /**
     * @private
     * @param {?} text
     * @return {?}
     */
    filterCountries(text) {
        return this.countries.filter((/**
         * @param {?} country
         * @return {?}
         */
        (country) => {
            return (country.name.toLowerCase().indexOf(text) !== -1 ||
                country.name.toLowerCase().indexOf(text) !== -1 ||
                country.dialCode.toString().toLowerCase().indexOf(text) !== -1);
        }));
    }
    /**
     * @private
     * @param {?} countryCode
     * @param {?} googleNumber
     * @return {?}
     */
    getCountryIsoCode(countryCode, googleNumber) {
        /** @type {?} */
        const rawNumber = ((/** @type {?} */ (googleNumber))).values_[2].toString();
        /** @type {?} */
        const countries = this.countries.filter((/**
         * @param {?} country
         * @return {?}
         */
        (country) => country.dialCode === countryCode.toString()));
        /** @type {?} */
        const mainCountry = countries.find((/**
         * @param {?} country
         * @return {?}
         */
        (country) => country.areaCodes === undefined));
        /** @type {?} */
        const secondaryCountries = countries.filter((/**
         * @param {?} country
         * @return {?}
         */
        (country) => country.areaCodes !== undefined));
        /** @type {?} */
        let matchedCountry = mainCountry ? mainCountry.isoCode : undefined;
        secondaryCountries.forEach((/**
         * @param {?} country
         * @return {?}
         */
        (country) => {
            country.areaCodes.forEach((/**
             * @param {?} areaCode
             * @return {?}
             */
            (areaCode) => {
                if (rawNumber.startsWith(areaCode)) {
                    matchedCountry = country.isoCode;
                }
            }));
        }));
        return matchedCountry;
    }
    /**
     * @private
     * @return {?}
     */
    fetchAllCountries() {
        this.countries = this.ionIntlTelInputService.getListOfCountries();
    }
    /**
     * @private
     * @param {?} isoCode
     * @return {?}
     */
    getCountryByIsoCode(isoCode) {
        for (const country of this.countries) {
            if (country.isoCode === isoCode) {
                return country;
            }
        }
        return;
    }
    /**
     * @private
     * @param {?} value
     * @return {?}
     */
    isNullOrWhiteSpace(value) {
        if (value === null || value === undefined) {
            return true;
        }
        if (typeof value === 'string' && value === '') {
            return true;
        }
        if (typeof value === 'object' && Object.keys(value).length === 0) {
            return true;
        }
        return false;
    }
    /**
     * @private
     * @param {?} phoneNumber
     * @return {?}
     */
    removeDialCode(phoneNumber) {
        if (this.separateDialCode && phoneNumber) {
            phoneNumber = phoneNumber.substr(phoneNumber.indexOf(' ') + 1);
        }
        return phoneNumber;
    }
    /**
     * @private
     * @param {?} country
     * @return {?}
     */
    setCountry(country) {
        this.country = country;
        this.codeChange.emit(this.country);
    }
    /**
     * @private
     * @return {?}
     */
    setPreferredCountries() {
        for (const preferedCountryIsoCode of this.preferredCountries) {
            /** @type {?} */
            const country = this.getCountryByIsoCode(preferedCountryIsoCode);
            country.priority = country ? 1 : country.priority;
        }
        this.countries.sort((/**
         * @param {?} a
         * @param {?} b
         * @return {?}
         */
        (a, b) => a.priority > b.priority ? -1 : a.priority < b.priority ? 1 : 0));
    }
}
IonIntlTelInputComponent.decorators = [
    { type: Component, args: [{
                // tslint:disable-next-line: component-selector
                selector: 'ion-intl-tel-input',
                template: "<div class=\"ion-intl-tel-input-code\">\n  <ionic-selectable\n    #codeSelect\n    [(ngModel)]=\"country\"\n    [canSearch]=\"modalCanSearch\"\n    closeButtonText=\"{{modalCloseText}}\"\n    closeButtonSlot=\"{{modalCloseButtonSlot}}\"\n    [disabled] = \"disabled\"\n    [hasVirtualScroll]=\"true\"\n    itemTextField=\"name\"\n    [items]=\"countries\"\n    itemValueField=\"isoCode\"\n    modalCssClass=\"ionic-tel-input-modal {{modalCssClass}}\"\n    placeholder=\"Country\"\n    searchFailText=\"{{modalSearchFailText}}\"\n    searchPlaceholder=\"{{modalSearchPlaceholder}}\"\n    [shouldBackdropClose]=\"modalShouldBackdropClose\"\n    [shouldFocusSearchbar]=\"modalShouldFocusSearchbar\"\n    (onChange)=\"onCodeChange($event)\"\n    (onClose)=\"onCodeClose()\"\n    (onOpen)=\"onCodeOpen()\"\n    (onSearch)=\"onCodeSearchCountries($event)\"\n    (onSelect)=\"onCodeSelect()\"\n  >\n    <ng-template ionicSelectableTitleTemplate>\n      {{modalTitle}}\n    </ng-template>\n    <ng-template ionicSelectableValueTemplate let-country=\"value\">\n      <span class=\"flag-icon flag-icon-{{country.flagClass}}\"></span>\n      <span *ngIf=\"separateDialCode\">{{dialCodePrefix}}{{country.displayDialCode}}</span>\n    </ng-template>\n    <ng-template ionicSelectableItemTemplate let-country=\"item\">\n        <span class=\"ion-margin-end\">{{country.name}}</span>\n        <span *ngIf=\"separateDialCode\">{{dialCodePrefix}}{{country.displayDialCode}}</span>\n    </ng-template>\n    <ng-template ionicSelectableItemEndTemplate let-country=\"item\">\n      <span class=\"flag-icon flag-icon-{{country.flagClass}}\"></span>\n    </ng-template>\n  </ionic-selectable>\n</div>\n\n<div class=\"ion-intl-tel-input-number\">\n  <ion-input\n    #numberInput\n    [(ngModel)]=\"phoneNumber\"\n    autocomplete=\"off\"\n    [disabled] = \"disabled\" \n    [attr.maxLength]=\"maxLength\"\n    type=\"tel\"\n    (ionBlur)=\"onIonNumberBlur()\"\n    (ionChange)=\"onIonNumberChange($event)\"\n    (ionFocus)=\"onIonNumberFocus()\"\n    (ionInput)=\"onIonNumberInput($event)\"\n    (keydown)=\"onNumberKeyDown($event)\"\n    (ngModelChange)=\"onNumberChange()\"\n    placeholder=\"{{country | countryPlaceholder: inputPlaceholder:separateDialCode:fallbackPlaceholder}}\" >\n  </ion-input>\n</div>\n",
                providers: [
                    {
                        provide: NG_VALUE_ACCESSOR,
                        useExisting: forwardRef((/**
                         * @return {?}
                         */
                        () => IonIntlTelInputComponent)),
                        multi: true,
                    },
                ],
                styles: [":host{width:100%;display:-webkit-box;display:flex;-webkit-box-align:end;align-items:flex-end}:host .ion-intl-tel-input-code{position:relative}:host .ion-intl-tel-input-number{-webkit-box-flex:1;flex:1}:host .ionic-selectable-label-default,:host .ionic-selectable-label-fixed{max-width:100%}:host .ionic-selectable:not(:host.ionic-selectable-label-stacked):not(:host.ionic-selectable-label-floating) ::ng-deep .ionic-selectable-inner .ionic-selectable-value{padding-top:10px;padding-bottom:10px}:host .ionic-selectable:not(:host.ionic-selectable-label-stacked):not(:host.ionic-selectable-label-floating) ::ng-deep .ionic-selectable-icon-inner{top:17px}:host .flag-icon{margin-right:5px}"]
            }] }
];
/** @nocollapse */
IonIntlTelInputComponent.ctorParameters = () => [
    { type: ElementRef },
    { type: Platform },
    { type: IonIntlTelInputService }
];
IonIntlTelInputComponent.propDecorators = {
    cssClass: [{ type: HostBinding, args: ['class.ion-intl-tel-input',] }],
    isIos: [{ type: HostBinding, args: ['class.ion-intl-tel-input-ios',] }],
    isMD: [{ type: HostBinding, args: ['class.ion-intl-tel-input-md',] }],
    hasFocus: [{ type: HostBinding, args: ['class.has-focus',] }],
    hasValueCssClass: [{ type: HostBinding, args: ['class.ion-intl-tel-input-has-value',] }],
    isEnabled: [{ type: HostBinding, args: ['class.ion-intl-tel-input-is-enabled',] }, { type: Input, args: ['isEnabled',] }],
    defaultCountryiso: [{ type: Input }],
    dialCodePrefix: [{ type: Input }],
    enableAutoCountrySelect: [{ type: Input }],
    enablePlaceholder: [{ type: Input }],
    fallbackPlaceholder: [{ type: Input }],
    inputPlaceholder: [{ type: Input }],
    maxLength: [{ type: Input }],
    modalTitle: [{ type: Input }],
    modalCssClass: [{ type: Input }],
    modalSearchPlaceholder: [{ type: Input }],
    modalCloseText: [{ type: Input }],
    modalCloseButtonSlot: [{ type: Input }],
    modalCanSearch: [{ type: Input }],
    modalShouldBackdropClose: [{ type: Input }],
    modalShouldFocusSearchbar: [{ type: Input }],
    modalSearchFailText: [{ type: Input }],
    onlyCountries: [{ type: Input }],
    preferredCountries: [{ type: Input }],
    selectFirstCountry: [{ type: Input }],
    separateDialCode: [{ type: Input }],
    numberChange: [{ type: Output }],
    numberBlur: [{ type: Output }],
    numberFocus: [{ type: Output }],
    numberInput: [{ type: Output }],
    codeChange: [{ type: Output }],
    codeOpen: [{ type: Output }],
    codeClose: [{ type: Output }],
    codeSelect: [{ type: Output }],
    numberInputEl: [{ type: ViewChild, args: ['numberInput', { static: false },] }]
};
if (false) {
    /** @type {?} */
    IonIntlTelInputComponent.prototype.cssClass;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.isIos;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.isMD;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.hasFocus;
    /**
     * Iso Code of default selected Country.
     * See more on.
     *
     * \@default ''
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.defaultCountryiso;
    /**
     * Determines whether to use `00` or `+` as dial code prefix.
     * Available attributes are '+' | '00'.
     * See more on.
     *
     * \@default +
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.dialCodePrefix;
    /**
     * Determines whether to select automatic country based on user input.
     * See more on.
     *
     * \@default false
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.enableAutoCountrySelect;
    /**
     * Determines whether an example number will be shown as a placeholder in input.
     * See more on.
     *
     * \@default true
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.enablePlaceholder;
    /**
     * A fallaback placeholder to be used if no example number is found for a country.
     * See more on.
     *
     * \@default ''
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.fallbackPlaceholder;
    /**
     * If a custom placeholder is needed for input.
     * If this property is set it will override `enablePlaceholder` and only this placeholder will be shown.
     * See more on.
     *
     * \@default ''
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.inputPlaceholder;
    /**
     * Maximum Length for input.
     * See more on.
     *
     * \@default '15'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.maxLength;
    /**
     * Title of modal opened to select country dial code.
     * See more on.
     *
     * \@default 'Select Country'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalTitle;
    /**
     * CSS class to attach to dial code selectionmodal.
     * See more on.
     *
     * \@default ''
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalCssClass;
    /**
     * Placeholder for input in dial code selection modal.
     * See more on.
     *
     * \@default 'Enter country name'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalSearchPlaceholder;
    /**
     * Text for close button in dial code selection modal.
     * See more on.
     *
     * \@default 'Close'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalCloseText;
    /**
     * Slot for close button in dial code selection modal. [Ionic slots](https://ionicframework.com/docs/api/item) are supported
     * See more on.
     *
     * \@default 'end'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalCloseButtonSlot;
    /**
     * Determines whether dial code selection modal should be searchable or not.
     * See more on.
     *
     * \@default 'true'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalCanSearch;
    /**
     * Determines whether dial code selection modal is closed on backdrop click.
     * See more on.
     *
     * \@default 'true'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalShouldBackdropClose;
    /**
     * Determines whether input should be focused when dial code selection modal is opened.
     * See more on.
     *
     * \@default 'true'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalShouldFocusSearchbar;
    /**
     * Message to show when no countries are found for search in dial code selection modal.
     * See more on.
     *
     * \@default 'true'
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.modalSearchFailText;
    /**
     * List of iso codes of manually selected countries as string, which will appear in the dropdown.
     * **Note**: `onlyCountries` should be a string array of country iso codes.
     * See more on.
     *
     * \@default null
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.onlyCountries;
    /**
     * List of iso codesn as string of  countries, which will appear at the top in dial code selection modal.
     * **Note**: `preferredCountries` should be a string array of country iso codes.
     * See more on.
     *
     * \@default null
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.preferredCountries;
    /**
     * Determines whether first country should be selected in dial code select or not.
     * See more on.
     *
     * \@default true
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.selectFirstCountry;
    /**
     * Determines whether to visually separate dialcode into the drop down element.
     * See more on.
     *
     * \@default true
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.separateDialCode;
    /**
     * Fires when the Phone number Input is changed.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.numberChange;
    /**
     * Fires when the Phone number Input is blurred.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.numberBlur;
    /**
     * Fires when the Phone number Input is focused.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.numberFocus;
    /**
     * Fires when the user is typing in Phone number Input.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.numberInput;
    /**
     * Fires when the dial code selection is changed.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.codeChange;
    /**
     * Fires when the dial code selection modal is opened.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.codeOpen;
    /**
     * Fires when the dial code selection modal is closed.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.codeClose;
    /**
     * Fires when a dial code is selected in dial code selection modal.
     * See more on.
     *
     * \@memberof IonIntlTelInputComponent
     * @type {?}
     */
    IonIntlTelInputComponent.prototype.codeSelect;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.numberInputEl;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype._value;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.country;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.phoneNumber;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.countries;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.disabled;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.phoneUtil;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.onTouched;
    /** @type {?} */
    IonIntlTelInputComponent.prototype.propagateChange;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.startsWith;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.getClasses;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.setClasses;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.setIonicClasses;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.setItemClass;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.el;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.platform;
    /**
     * @type {?}
     * @private
     */
    IonIntlTelInputComponent.prototype.ionIntlTelInputService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW9uLWludGwtdGVsLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lvbmljNS1pbnRlcm5hdGlvbmFsLWlucHV0LyIsInNvdXJjZXMiOlsibGliL2lvbi1pbnRsLXRlbC1pbnB1dC9pb24taW50bC10ZWwtaW5wdXQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULEtBQUssRUFDTCxVQUFVLEVBQ1YsTUFBTSxFQUNOLFlBQVksRUFHWixTQUFTLEVBQ1QsVUFBVSxFQUNWLFdBQVcsR0FDWixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQ0wsaUJBQWlCLEdBR2xCLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdwRCxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLGVBQWUsR0FDaEIsTUFBTSx1QkFBdUIsQ0FBQztBQUkvQixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7QUFFdkUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGNBQWMsQ0FBQzs7OztBQW1CbkM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sd0JBQXdCOzs7Ozs7SUFzVG5DLFlBQ1UsRUFBYyxFQUNkLFFBQWtCLEVBQ2xCLHNCQUE4QztRQUY5QyxPQUFFLEdBQUYsRUFBRSxDQUFZO1FBQ2QsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNsQiwyQkFBc0IsR0FBdEIsc0JBQXNCLENBQXdCO1FBdFR4RCxhQUFRLEdBQUcsSUFBSSxDQUFDOzs7Ozs7OztRQXlCaEIsc0JBQWlCLEdBQUcsRUFBRSxDQUFDOzs7Ozs7Ozs7UUFXdkIsbUJBQWMsR0FBZSxHQUFHLENBQUM7Ozs7Ozs7O1FBVWpDLDRCQUF1QixHQUFHLEtBQUssQ0FBQzs7Ozs7Ozs7UUFVaEMsc0JBQWlCLEdBQUcsSUFBSSxDQUFDOzs7Ozs7OztRQVV6Qix3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bnQsXG4gIE9uSW5pdCxcbiAgSW5wdXQsXG4gIGZvcndhcmRSZWYsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbiAgRWxlbWVudFJlZixcbiAgSG9zdEJpbmRpbmcsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge1xuICBOR19WQUxVRV9BQ0NFU1NPUixcbiAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gIE5HX1ZBTElEQVRPUlMsXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgSW9uSW5wdXQsIFBsYXRmb3JtIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuXG5pbXBvcnQgeyBJb25pY1NlbGVjdGFibGVDb21wb25lbnQgfSBmcm9tICdpb25pYy1zZWxlY3RhYmxlJztcbmltcG9ydCB7XG4gIFBob25lTnVtYmVyLFxuICBQaG9uZU51bWJlckZvcm1hdCxcbiAgUGhvbmVOdW1iZXJVdGlsLFxufSBmcm9tICdnb29nbGUtbGlicGhvbmVudW1iZXInO1xuXG5pbXBvcnQgeyBDb3VudHJ5SSB9IGZyb20gJy4uL21vZGVscy9jb3VudHJ5Lm1vZGVsJztcbmltcG9ydCB7IElvbkludGxUZWxJbnB1dE1vZGVsIH0gZnJvbSAnLi4vbW9kZWxzL2lvbi1pbnRsLXRlbC1pbnB1dC5tb2RlbCc7XG5pbXBvcnQgeyBJb25JbnRsVGVsSW5wdXRTZXJ2aWNlIH0gZnJvbSAnLi4vaW9uLWludGwtdGVsLWlucHV0LnNlcnZpY2UnO1xuLy8gaW1wb3J0IHsgaW9uSW50bFRlbElucHV0VmFsaWRhdG9yIH0gZnJvbSAnLi4vaW9uLWludGwtdGVsLWlucHV0LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyByYWYgfSBmcm9tICcuLi91dGlsL3V0aWwnO1xuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuQENvbXBvbmVudCh7XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogY29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnaW9uLWludGwtdGVsLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2lvbi1pbnRsLXRlbC1pbnB1dC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2lvbi1pbnRsLXRlbC1pbnB1dC5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IElvbkludGxUZWxJbnB1dENvbXBvbmVudCksXG4gICAgICBtdWx0aTogdHJ1ZSxcbiAgICB9LFxuICBdLFxufSlcblxuLyoqXG4gKiBAYXV0aG9yIEF6emFtIEFzZ2hhciA8YXp6YW0uYXNnaGFyQGludGVyc3RlbGx1cy5jb20+XG4gKi9cbmV4cG9ydCBjbGFzcyBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25Jbml0LCBPbkNoYW5nZXMge1xuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmlvbi1pbnRsLXRlbC1pbnB1dCcpXG4gIGNzc0NsYXNzID0gdHJ1ZTtcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5pb24taW50bC10ZWwtaW5wdXQtaW9zJylcbiAgaXNJb3M6IGJvb2xlYW47XG4gIEBIb3N0QmluZGluZygnY2xhc3MuaW9uLWludGwtdGVsLWlucHV0LW1kJylcbiAgaXNNRDogYm9vbGVhbjtcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5oYXMtZm9jdXMnKVxuICBoYXNGb2N1cztcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5pb24taW50bC10ZWwtaW5wdXQtaGFzLXZhbHVlJylcbiAgZ2V0IGhhc1ZhbHVlQ3NzQ2xhc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaGFzVmFsdWUoKTtcbiAgfVxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmlvbi1pbnRsLXRlbC1pbnB1dC1pcy1lbmFibGVkJylcbiAgQElucHV0KCdpc0VuYWJsZWQnKVxuICBnZXQgaXNFbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5kaXNhYmxlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJc28gQ29kZSBvZiBkZWZhdWx0IHNlbGVjdGVkIENvdW50cnkuXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnJ1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBkZWZhdWx0Q291bnRyeWlzbyA9ICcnO1xuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdG8gdXNlIGAwMGAgb3IgYCtgIGFzIGRpYWwgY29kZSBwcmVmaXguXG4gICAqIEF2YWlsYWJsZSBhdHRyaWJ1dGVzIGFyZSAnKycgfCAnMDAnLlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgK1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBkaWFsQ29kZVByZWZpeDogJysnIHwgJzAwJyA9ICcrJztcblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRvIHNlbGVjdCBhdXRvbWF0aWMgY291bnRyeSBiYXNlZCBvbiB1c2VyIGlucHV0LlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgZW5hYmxlQXV0b0NvdW50cnlTZWxlY3QgPSBmYWxzZTtcblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIGFuIGV4YW1wbGUgbnVtYmVyIHdpbGwgYmUgc2hvd24gYXMgYSBwbGFjZWhvbGRlciBpbiBpbnB1dC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgZW5hYmxlUGxhY2Vob2xkZXIgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBBIGZhbGxhYmFjayBwbGFjZWhvbGRlciB0byBiZSB1c2VkIGlmIG5vIGV4YW1wbGUgbnVtYmVyIGlzIGZvdW5kIGZvciBhIGNvdW50cnkuXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnJ1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBmYWxsYmFja1BsYWNlaG9sZGVyID0gJyc7XG5cbiAgLyoqXG4gICAqIElmIGEgY3VzdG9tIHBsYWNlaG9sZGVyIGlzIG5lZWRlZCBmb3IgaW5wdXQuXG4gICAqIElmIHRoaXMgcHJvcGVydHkgaXMgc2V0IGl0IHdpbGwgb3ZlcnJpZGUgYGVuYWJsZVBsYWNlaG9sZGVyYCBhbmQgb25seSB0aGlzIHBsYWNlaG9sZGVyIHdpbGwgYmUgc2hvd24uXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnJ1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBpbnB1dFBsYWNlaG9sZGVyID0gJyc7XG5cbiAgLyoqXG4gICAqIE1heGltdW0gTGVuZ3RoIGZvciBpbnB1dC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0ICcxNSdcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbWF4TGVuZ3RoID0gJzE1JztcblxuICAvKipcbiAgICogVGl0bGUgb2YgbW9kYWwgb3BlbmVkIHRvIHNlbGVjdCBjb3VudHJ5IGRpYWwgY29kZS5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0ICdTZWxlY3QgQ291bnRyeSdcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbW9kYWxUaXRsZSA9ICdTZWxlY3QgQ291bnRyeSc7XG5cbiAgLyoqXG4gICAqIENTUyBjbGFzcyB0byBhdHRhY2ggdG8gZGlhbCBjb2RlIHNlbGVjdGlvbm1vZGFsLlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgJydcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbW9kYWxDc3NDbGFzcyA9ICcnO1xuXG4gIC8qKlxuICAgKiBQbGFjZWhvbGRlciBmb3IgaW5wdXQgaW4gZGlhbCBjb2RlIHNlbGVjdGlvbiBtb2RhbC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0ICdFbnRlciBjb3VudHJ5IG5hbWUnXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG1vZGFsU2VhcmNoUGxhY2Vob2xkZXIgPSAnRW50ZXIgY291bnRyeSBuYW1lJztcblxuICAvKipcbiAgICogVGV4dCBmb3IgY2xvc2UgYnV0dG9uIGluIGRpYWwgY29kZSBzZWxlY3Rpb24gbW9kYWwuXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnQ2xvc2UnXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIG1vZGFsQ2xvc2VUZXh0ID0gJ0Nsb3NlJztcblxuICAvKipcbiAgICogU2xvdCBmb3IgY2xvc2UgYnV0dG9uIGluIGRpYWwgY29kZSBzZWxlY3Rpb24gbW9kYWwuIFtJb25pYyBzbG90c10oaHR0cHM6Ly9pb25pY2ZyYW1ld29yay5jb20vZG9jcy9hcGkvaXRlbSkgYXJlIHN1cHBvcnRlZFxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgJ2VuZCdcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbW9kYWxDbG9zZUJ1dHRvblNsb3Q6ICdzdGFydCcgfCAnZW5kJyB8ICdwcmltYXJ5JyB8ICdzZWNvbmRhcnknID0gJ2VuZCc7XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsIHNob3VsZCBiZSBzZWFyY2hhYmxlIG9yIG5vdC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0ICd0cnVlJ1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBtb2RhbENhblNlYXJjaCA9IHRydWU7XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsIGlzIGNsb3NlZCBvbiBiYWNrZHJvcCBjbGljay5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0ICd0cnVlJ1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBtb2RhbFNob3VsZEJhY2tkcm9wQ2xvc2UgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgaW5wdXQgc2hvdWxkIGJlIGZvY3VzZWQgd2hlbiBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsIGlzIG9wZW5lZC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBkZWZhdWx0ICd0cnVlJ1xuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBtb2RhbFNob3VsZEZvY3VzU2VhcmNoYmFyID0gdHJ1ZTtcblxuICAvKipcbiAgICogTWVzc2FnZSB0byBzaG93IHdoZW4gbm8gY291bnRyaWVzIGFyZSBmb3VuZCBmb3Igc2VhcmNoIGluIGRpYWwgY29kZSBzZWxlY3Rpb24gbW9kYWwuXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAndHJ1ZSdcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgbW9kYWxTZWFyY2hGYWlsVGV4dCA9ICdObyBjb3VudHJpZXMgZm91bmQnO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIGlzbyBjb2RlcyBvZiBtYW51YWxseSBzZWxlY3RlZCBjb3VudHJpZXMgYXMgc3RyaW5nLCB3aGljaCB3aWxsIGFwcGVhciBpbiB0aGUgZHJvcGRvd24uXG4gICAqICoqTm90ZSoqOiBgb25seUNvdW50cmllc2Agc2hvdWxkIGJlIGEgc3RyaW5nIGFycmF5IG9mIGNvdW50cnkgaXNvIGNvZGVzLlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgbnVsbFxuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBvbmx5Q291bnRyaWVzOiBBcnJheTxzdHJpbmc+ID0gW107XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgaXNvIGNvZGVzbiBhcyBzdHJpbmcgb2YgIGNvdW50cmllcywgd2hpY2ggd2lsbCBhcHBlYXIgYXQgdGhlIHRvcCBpbiBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsLlxuICAgKiAqKk5vdGUqKjogYHByZWZlcnJlZENvdW50cmllc2Agc2hvdWxkIGJlIGEgc3RyaW5nIGFycmF5IG9mIGNvdW50cnkgaXNvIGNvZGVzLlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgbnVsbFxuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBwcmVmZXJyZWRDb3VudHJpZXM6IEFycmF5PHN0cmluZz4gPSBbXTtcblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIGZpcnN0IGNvdW50cnkgc2hvdWxkIGJlIHNlbGVjdGVkIGluIGRpYWwgY29kZSBzZWxlY3Qgb3Igbm90LlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBzZWxlY3RGaXJzdENvdW50cnkgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdG8gdmlzdWFsbHkgc2VwYXJhdGUgZGlhbGNvZGUgaW50byB0aGUgZHJvcCBkb3duIGVsZW1lbnQuXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHNlcGFyYXRlRGlhbENvZGUgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBGaXJlcyB3aGVuIHRoZSBQaG9uZSBudW1iZXIgSW5wdXQgaXMgY2hhbmdlZC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBudW1iZXJDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEV2ZW50PigpO1xuXG4gIC8qKlxuICAgKiBGaXJlcyB3aGVuIHRoZSBQaG9uZSBudW1iZXIgSW5wdXQgaXMgYmx1cnJlZC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBudW1iZXJCbHVyID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIC8qKlxuICAgKiBGaXJlcyB3aGVuIHRoZSBQaG9uZSBudW1iZXIgSW5wdXQgaXMgZm9jdXNlZC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBudW1iZXJGb2N1cyA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKipcbiAgICogRmlyZXMgd2hlbiB0aGUgdXNlciBpcyB0eXBpbmcgaW4gUGhvbmUgbnVtYmVyIElucHV0LlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHJlYWRvbmx5IG51bWJlcklucHV0ID0gbmV3IEV2ZW50RW1pdHRlcjxLZXlib2FyZEV2ZW50PigpO1xuXG4gIC8qKlxuICAgKiBGaXJlcyB3aGVuIHRoZSBkaWFsIGNvZGUgc2VsZWN0aW9uIGlzIGNoYW5nZWQuXG4gICAqIFNlZSBtb3JlIG9uLlxuICAgKlxuICAgKiBAbWVtYmVyb2YgSW9uSW50bFRlbElucHV0Q29tcG9uZW50XG4gICAqL1xuICBAT3V0cHV0KClcbiAgcmVhZG9ubHkgY29kZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIC8qKlxuICAgKiBGaXJlcyB3aGVuIHRoZSBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsIGlzIG9wZW5lZC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBjb2RlT3BlbiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIC8qKlxuICAgKiBGaXJlcyB3aGVuIHRoZSBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsIGlzIGNsb3NlZC5cbiAgICogU2VlIG1vcmUgb24uXG4gICAqXG4gICAqIEBtZW1iZXJvZiBJb25JbnRsVGVsSW5wdXRDb21wb25lbnRcbiAgICovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBjb2RlQ2xvc2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICAvKipcbiAgICogRmlyZXMgd2hlbiBhIGRpYWwgY29kZSBpcyBzZWxlY3RlZCBpbiBkaWFsIGNvZGUgc2VsZWN0aW9uIG1vZGFsLlxuICAgKiBTZWUgbW9yZSBvbi5cbiAgICpcbiAgICogQG1lbWJlcm9mIElvbkludGxUZWxJbnB1dENvbXBvbmVudFxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHJlYWRvbmx5IGNvZGVTZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBAVmlld0NoaWxkKCdudW1iZXJJbnB1dCcsIHsgc3RhdGljOiBmYWxzZSB9KSBudW1iZXJJbnB1dEVsOiBJb25JbnB1dDtcblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IHZhcmlhYmxlLW5hbWVcbiAgcHJpdmF0ZSBfdmFsdWU6IElvbkludGxUZWxJbnB1dE1vZGVsID0gbnVsbDtcblxuICBjb3VudHJ5OiBDb3VudHJ5STtcbiAgcGhvbmVOdW1iZXIgPSAnJztcbiAgY291bnRyaWVzOiBDb3VudHJ5SVtdID0gW107XG4gIGRpc2FibGVkID0gZmFsc2U7XG4gIHBob25lVXRpbDogYW55ID0gUGhvbmVOdW1iZXJVdGlsLmdldEluc3RhbmNlKCk7XG5cbiAgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIHByb3BhZ2F0ZUNoYW5nZSA9IChfOiBJb25JbnRsVGVsSW5wdXRNb2RlbCB8IG51bGwpID0+IHt9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBwbGF0Zm9ybTogUGxhdGZvcm0sXG4gICAgcHJpdmF0ZSBpb25JbnRsVGVsSW5wdXRTZXJ2aWNlOiBJb25JbnRsVGVsSW5wdXRTZXJ2aWNlXG4gICkge31cblxuICBnZXQgdmFsdWUoKTogSW9uSW50bFRlbElucHV0TW9kZWwgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gIH1cblxuICBzZXQgdmFsdWUodmFsdWU6IElvbkludGxUZWxJbnB1dE1vZGVsIHwgbnVsbCkge1xuICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5zZXRJb25pY0NsYXNzZXModGhpcy5lbCk7XG4gIH1cblxuICBlbWl0VmFsdWVDaGFuZ2UoY2hhbmdlOiBJb25JbnRsVGVsSW5wdXRNb2RlbCB8IG51bGwpIHtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZShjaGFuZ2UpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5pc0lvcyA9IHRoaXMucGxhdGZvcm0uaXMoJ2lvcycpO1xuICAgIHRoaXMuaXNNRCA9ICF0aGlzLmlzSW9zO1xuICAgIHRoaXMuc2V0SXRlbUNsYXNzKHRoaXMuZWwsICdpdGVtLWludGVyYWN0aXZlJywgdHJ1ZSk7XG5cbiAgICB0aGlzLmZldGNoQWxsQ291bnRyaWVzKCk7XG4gICAgdGhpcy5zZXRQcmVmZXJyZWRDb3VudHJpZXMoKTtcblxuICAgIGlmICh0aGlzLm9ubHlDb3VudHJpZXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmNvdW50cmllcyA9IHRoaXMuY291bnRyaWVzLmZpbHRlcigoY291bnRyeTogQ291bnRyeUkpID0+XG4gICAgICAgIHRoaXMub25seUNvdW50cmllcy5pbmNsdWRlcyhjb3VudHJ5Lmlzb0NvZGUpXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNlbGVjdEZpcnN0Q291bnRyeSkge1xuICAgICAgaWYgKHRoaXMuZGVmYXVsdENvdW50cnlpc28pIHtcbiAgICAgICAgdGhpcy5zZXRDb3VudHJ5KHRoaXMuZ2V0Q291bnRyeUJ5SXNvQ29kZSh0aGlzLmRlZmF1bHRDb3VudHJ5aXNvKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgdGhpcy5wcmVmZXJyZWRDb3VudHJpZXMubGVuZ3RoICYmXG4gICAgICAgICAgdGhpcy5wcmVmZXJyZWRDb3VudHJpZXMuaW5jbHVkZXModGhpcy5kZWZhdWx0Q291bnRyeWlzbylcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhpcy5zZXRDb3VudHJ5KHRoaXMuZ2V0Q291bnRyeUJ5SXNvQ29kZSh0aGlzLnByZWZlcnJlZENvdW50cmllc1swXSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2V0Q291bnRyeSh0aGlzLmNvdW50cmllc1swXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5jb3VudHJpZXMgJiZcbiAgICAgIGNoYW5nZXMuZGVmYXVseUNvdW50cnlpc29Db2RlICYmXG4gICAgICBjaGFuZ2VzLmRlZmF1bHlDb3VudHJ5aXNvQ29kZS5jdXJyZW50VmFsdWUgIT09XG4gICAgICAgIGNoYW5nZXMuZGVmYXVseUNvdW50cnlpc29Db2RlLnByZXZpb3VzVmFsdWVcbiAgICApIHtcbiAgICAgIHRoaXMuc2V0Q291bnRyeShjaGFuZ2VzLmRlZmF1bHlDb3VudHJ5aXNvQ29kZS5jdXJyZW50VmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHdyaXRlVmFsdWUob2JqOiBJb25JbnRsVGVsSW5wdXRNb2RlbCk6IHZvaWQge1xuICAgIHRoaXMuZmlsbFZhbHVlcyhvYmopO1xuICB9XG5cbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gIH1cblxuICBmaWxsVmFsdWVzKHZhbHVlOiBJb25JbnRsVGVsSW5wdXRNb2RlbCkge1xuICAgIGlmIChcbiAgICAgIHZhbHVlICYmXG4gICAgICB2YWx1ZSAhPT0gbnVsbCAmJlxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgIXRoaXMuaXNOdWxsT3JXaGl0ZVNwYWNlKHZhbHVlKVxuICAgICkge1xuICAgICAgdGhpcy5waG9uZU51bWJlciA9IHZhbHVlLm5hdGlvbmFsTnVtYmVyO1xuICAgICAgdGhpcy5zZXRDb3VudHJ5KHRoaXMuZ2V0Q291bnRyeUJ5SXNvQ29kZSh2YWx1ZS5pc29Db2RlKSk7XG4gICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIHRoaXMudmFsdWUgJiZcbiAgICAgIHRoaXMudmFsdWUgIT09IG51bGwgJiZcbiAgICAgIHR5cGVvZiB0aGlzLnZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgIXRoaXMuaXNOdWxsT3JXaGl0ZVNwYWNlKHRoaXMudmFsdWUpXG4gICAgKSB7XG4gICAgICB0aGlzLnBob25lTnVtYmVyID0gdGhpcy52YWx1ZS5uYXRpb25hbE51bWJlcjtcbiAgICAgIHRoaXMuc2V0Q291bnRyeSh0aGlzLmdldENvdW50cnlCeUlzb0NvZGUodGhpcy52YWx1ZS5pc29Db2RlKSk7XG4gICAgfVxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5vbk51bWJlckNoYW5nZSgpO1xuICAgIH0sIDEpO1xuICB9XG5cbiAgaGFzVmFsdWUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmlzTnVsbE9yV2hpdGVTcGFjZSh0aGlzLnZhbHVlKTtcbiAgfVxuXG4gIG9uQ29kZU9wZW4oKSB7XG4gICAgdGhpcy5jb2RlT3Blbi5lbWl0KCk7XG4gIH1cblxuICBvbkNvZGVDaGFuZ2UoZXZlbnQ6IHtcbiAgICBjb21wb25lbnQ6IElvbmljU2VsZWN0YWJsZUNvbXBvbmVudDtcbiAgICB2YWx1ZTogYW55O1xuICB9KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNOdWxsT3JXaGl0ZVNwYWNlKHRoaXMucGhvbmVOdW1iZXIpKSB7XG4gICAgICB0aGlzLmVtaXRWYWx1ZUNoYW5nZShudWxsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGdvb2dsZU51bWJlcjogUGhvbmVOdW1iZXI7XG4gICAgICB0cnkge1xuICAgICAgICBnb29nbGVOdW1iZXIgPSB0aGlzLnBob25lVXRpbC5wYXJzZShcbiAgICAgICAgICB0aGlzLnBob25lTnVtYmVyLFxuICAgICAgICAgIHRoaXMuY291bnRyeS5pc29Db2RlLnRvVXBwZXJDYXNlKClcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgIGNvbnN0IGludGVybmF0aW9uYWxsTm8gPSBnb29nbGVOdW1iZXJcbiAgICAgICAgPyB0aGlzLnBob25lVXRpbC5mb3JtYXQoZ29vZ2xlTnVtYmVyLCBQaG9uZU51bWJlckZvcm1hdC5JTlRFUk5BVElPTkFMKVxuICAgICAgICA6ICcnO1xuICAgICAgY29uc3QgbmF0aW9uYWxObyA9IGdvb2dsZU51bWJlclxuICAgICAgICA/IHRoaXMucGhvbmVVdGlsLmZvcm1hdChnb29nbGVOdW1iZXIsIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMKVxuICAgICAgICA6ICcnO1xuXG4gICAgICBpZiAodGhpcy5zZXBhcmF0ZURpYWxDb2RlICYmIGludGVybmF0aW9uYWxsTm8pIHtcbiAgICAgICAgdGhpcy5waG9uZU51bWJlciA9IHRoaXMucmVtb3ZlRGlhbENvZGUoaW50ZXJuYXRpb25hbGxObyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZW1pdFZhbHVlQ2hhbmdlKHtcbiAgICAgICAgaW50ZXJuYXRpb25hbE51bWJlcjogaW50ZXJuYXRpb25hbGxObyxcbiAgICAgICAgbmF0aW9uYWxOdW1iZXI6IG5hdGlvbmFsTm8sXG4gICAgICAgIGlzb0NvZGU6IHRoaXMuY291bnRyeS5pc29Db2RlLFxuICAgICAgICBkaWFsQ29kZTogdGhpcy5kaWFsQ29kZVByZWZpeCArIHRoaXMuY291bnRyeS5kaWFsQ29kZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jb2RlQ2hhbmdlLmVtaXQoKTtcbiAgICB9XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLm51bWJlcklucHV0RWwuc2V0Rm9jdXMoKTtcbiAgICB9LCA0MDApO1xuICB9XG5cbiAgb25Db2RlQ2xvc2UoKSB7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB0aGlzLnNldElvbmljQ2xhc3Nlcyh0aGlzLmVsKTtcbiAgICB0aGlzLmhhc0ZvY3VzID0gZmFsc2U7XG4gICAgdGhpcy5zZXRJdGVtQ2xhc3ModGhpcy5lbCwgJ2l0ZW0taGFzLWZvY3VzJywgZmFsc2UpO1xuICAgIHRoaXMuY29kZUNsb3NlLmVtaXQoKTtcbiAgfVxuXG4gIHB1YmxpYyBvbkNvZGVTZWFyY2hDb3VudHJpZXMoZXZlbnQ6IHtcbiAgICBjb21wb25lbnQ6IElvbmljU2VsZWN0YWJsZUNvbXBvbmVudDtcbiAgICB0ZXh0OiBzdHJpbmc7XG4gIH0pOiB2b2lkIHtcbiAgICBjb25zdCB0ZXh0ID0gZXZlbnQudGV4dC50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICBldmVudC5jb21wb25lbnQuc3RhcnRTZWFyY2goKTtcblxuICAgIGV2ZW50LmNvbXBvbmVudC5pdGVtcyA9IHRoaXMuZmlsdGVyQ291bnRyaWVzKHRleHQpO1xuICAgIGV2ZW50LmNvbXBvbmVudC5lbmRTZWFyY2goKTtcbiAgfVxuXG4gIG9uQ29kZVNlbGVjdCgpIHtcbiAgICB0aGlzLmNvZGVTZWxlY3QuZW1pdCgpO1xuICB9XG5cbiAgb25Jb25OdW1iZXJDaGFuZ2UoZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy5zZXRJb25pY0NsYXNzZXModGhpcy5lbCk7XG4gICAgdGhpcy5udW1iZXJDaGFuZ2UuZW1pdChldmVudCk7XG4gIH1cblxuICBvbklvbk51bWJlckJsdXIoKSB7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB0aGlzLnNldElvbmljQ2xhc3Nlcyh0aGlzLmVsKTtcbiAgICB0aGlzLmhhc0ZvY3VzID0gZmFsc2U7XG4gICAgdGhpcy5zZXRJdGVtQ2xhc3ModGhpcy5lbCwgJ2l0ZW0taGFzLWZvY3VzJywgZmFsc2UpO1xuICAgIHRoaXMubnVtYmVyQmx1ci5lbWl0KCk7XG4gIH1cblxuICBvbklvbk51bWJlckZvY3VzKCkge1xuICAgIHRoaXMuaGFzRm9jdXMgPSB0cnVlO1xuICAgIHRoaXMuc2V0SXRlbUNsYXNzKHRoaXMuZWwsICdpdGVtLWhhcy1mb2N1cycsIHRydWUpO1xuICAgIHRoaXMubnVtYmVyRm9jdXMuZW1pdCgpO1xuICB9XG5cbiAgb25Jb25OdW1iZXJJbnB1dChldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIHRoaXMubnVtYmVySW5wdXQuZW1pdChldmVudCk7XG4gIH1cblxuICBvbk51bWJlckNoYW5nZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucGhvbmVOdW1iZXIpIHtcbiAgICAgIHRoaXMudmFsdWUgPSBudWxsO1xuICAgICAgdGhpcy5lbWl0VmFsdWVDaGFuZ2UobnVsbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLmNvdW50cnkpIHtcbiAgICAgIHRoaXMuZW1pdFZhbHVlQ2hhbmdlKHtcbiAgICAgICAgaW50ZXJuYXRpb25hbE51bWJlcjpcbiAgICAgICAgICB0aGlzLmRpYWxDb2RlUHJlZml4ICsgdGhpcy5jb3VudHJ5LmRpYWxDb2RlICsgJyAnICsgdGhpcy5waG9uZU51bWJlcixcbiAgICAgICAgbmF0aW9uYWxOdW1iZXI6IHRoaXMucGhvbmVOdW1iZXIsXG4gICAgICAgIGlzb0NvZGU6IHRoaXMuY291bnRyeS5pc29Db2RlLFxuICAgICAgICBkaWFsQ29kZTogdGhpcy5kaWFsQ29kZVByZWZpeCArIHRoaXMuY291bnRyeS5kaWFsQ29kZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBsZXQgZ29vZ2xlTnVtYmVyOiBQaG9uZU51bWJlcjtcbiAgICB0cnkge1xuICAgICAgZ29vZ2xlTnVtYmVyID0gdGhpcy5waG9uZVV0aWwucGFyc2UoXG4gICAgICAgIHRoaXMucGhvbmVOdW1iZXIsXG4gICAgICAgIHRoaXMuY291bnRyeS5pc29Db2RlLnRvVXBwZXJDYXNlKClcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBpc29Db2RlID0gdGhpcy5jb3VudHJ5ID8gdGhpcy5jb3VudHJ5Lmlzb0NvZGUgOiBudWxsO1xuICAgIC8vIGF1dG8gc2VsZWN0IGNvdW50cnkgYmFzZWQgb24gdGhlIGV4dGVuc2lvbiAoYW5kIGFyZWFDb2RlIGlmIG5lZWRlZCkgKGUuZyBzZWxlY3QgQ2FuYWRhIGlmIG51bWJlciBzdGFydHMgd2l0aCArMSA0MTYpXG4gICAgaWYgKHRoaXMuZW5hYmxlQXV0b0NvdW50cnlTZWxlY3QpIHtcbiAgICAgIGlzb0NvZGUgPVxuICAgICAgICBnb29nbGVOdW1iZXIgJiYgZ29vZ2xlTnVtYmVyLmdldENvdW50cnlDb2RlKClcbiAgICAgICAgICA/IHRoaXMuZ2V0Q291bnRyeUlzb0NvZGUoZ29vZ2xlTnVtYmVyLmdldENvdW50cnlDb2RlKCksIGdvb2dsZU51bWJlcilcbiAgICAgICAgICA6IHRoaXMuY291bnRyeS5pc29Db2RlO1xuICAgICAgaWYgKGlzb0NvZGUgJiYgaXNvQ29kZSAhPT0gdGhpcy5jb3VudHJ5Lmlzb0NvZGUpIHtcbiAgICAgICAgY29uc3QgbmV3Q291bnRyeSA9IHRoaXMuY291bnRyaWVzLmZpbmQoXG4gICAgICAgICAgKGNvdW50cnk6IENvdW50cnlJKSA9PiBjb3VudHJ5Lmlzb0NvZGUgPT09IGlzb0NvZGVcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKG5ld0NvdW50cnkpIHtcbiAgICAgICAgICB0aGlzLmNvdW50cnkgPSBuZXdDb3VudHJ5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlzb0NvZGUgPSBpc29Db2RlID8gaXNvQ29kZSA6IHRoaXMuY291bnRyeSA/IHRoaXMuY291bnRyeS5pc29Db2RlIDogbnVsbDtcblxuICAgIGlmICghdGhpcy5waG9uZU51bWJlciB8fCAhaXNvQ29kZSkge1xuICAgICAgdGhpcy5lbWl0VmFsdWVDaGFuZ2UobnVsbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGludGVybmF0aW9uYWxsTm8gPSBnb29nbGVOdW1iZXJcbiAgICAgICAgPyB0aGlzLnBob25lVXRpbC5mb3JtYXQoZ29vZ2xlTnVtYmVyLCBQaG9uZU51bWJlckZvcm1hdC5JTlRFUk5BVElPTkFMKVxuICAgICAgICA6ICcnO1xuICAgICAgY29uc3QgbmF0aW9uYWxObyA9IGdvb2dsZU51bWJlclxuICAgICAgICA/IHRoaXMucGhvbmVVdGlsLmZvcm1hdChnb29nbGVOdW1iZXIsIFBob25lTnVtYmVyRm9ybWF0Lk5BVElPTkFMKVxuICAgICAgICA6ICcnO1xuXG4gICAgICBpZiAodGhpcy5zZXBhcmF0ZURpYWxDb2RlICYmIGludGVybmF0aW9uYWxsTm8pIHtcbiAgICAgICAgdGhpcy5waG9uZU51bWJlciA9IHRoaXMucmVtb3ZlRGlhbENvZGUoaW50ZXJuYXRpb25hbGxObyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZW1pdFZhbHVlQ2hhbmdlKHtcbiAgICAgICAgaW50ZXJuYXRpb25hbE51bWJlcjogaW50ZXJuYXRpb25hbGxObyxcbiAgICAgICAgbmF0aW9uYWxOdW1iZXI6IG5hdGlvbmFsTm8sXG4gICAgICAgIGlzb0NvZGU6IHRoaXMuY291bnRyeS5pc29Db2RlLFxuICAgICAgICBkaWFsQ29kZTogdGhpcy5kaWFsQ29kZVByZWZpeCArIHRoaXMuY291bnRyeS5kaWFsQ29kZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uTnVtYmVyS2V5RG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIGNvbnN0IGFsbG93ZWRDaGFycyA9IC9eWzAtOVxcK1xcLVxcIF0vO1xuICAgIGNvbnN0IGFsbG93ZWRDdHJsQ2hhcnMgPSAvW2F4Y3ZdLztcbiAgICBjb25zdCBhbGxvd2VkT3RoZXJLZXlzID0gW1xuICAgICAgJ0Fycm93TGVmdCcsXG4gICAgICAnQXJyb3dVcCcsXG4gICAgICAnQXJyb3dSaWdodCcsXG4gICAgICAnQXJyb3dEb3duJyxcbiAgICAgICdIb21lJyxcbiAgICAgICdFbmQnLFxuICAgICAgJ0luc2VydCcsXG4gICAgICAnRGVsZXRlJyxcbiAgICAgICdCYWNrc3BhY2UnLFxuICAgIF07XG5cbiAgICBpZiAoXG4gICAgICAhYWxsb3dlZENoYXJzLnRlc3QoZXZlbnQua2V5KSAmJlxuICAgICAgIShldmVudC5jdHJsS2V5ICYmIGFsbG93ZWRDdHJsQ2hhcnMudGVzdChldmVudC5rZXkpKSAmJlxuICAgICAgIWFsbG93ZWRPdGhlcktleXMuaW5jbHVkZXMoZXZlbnQua2V5KVxuICAgICkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbHRlckNvdW50cmllcyh0ZXh0OiBzdHJpbmcpOiBDb3VudHJ5SVtdIHtcbiAgICByZXR1cm4gdGhpcy5jb3VudHJpZXMuZmlsdGVyKChjb3VudHJ5KSA9PiB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBjb3VudHJ5Lm5hbWUudG9Mb3dlckNhc2UoKS5pbmRleE9mKHRleHQpICE9PSAtMSB8fFxuICAgICAgICBjb3VudHJ5Lm5hbWUudG9Mb3dlckNhc2UoKS5pbmRleE9mKHRleHQpICE9PSAtMSB8fFxuICAgICAgICBjb3VudHJ5LmRpYWxDb2RlLnRvU3RyaW5nKCkudG9Mb3dlckNhc2UoKS5pbmRleE9mKHRleHQpICE9PSAtMVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q291bnRyeUlzb0NvZGUoXG4gICAgY291bnRyeUNvZGU6IG51bWJlcixcbiAgICBnb29nbGVOdW1iZXI6IFBob25lTnVtYmVyXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgcmF3TnVtYmVyID0gKGdvb2dsZU51bWJlciBhcyBhbnkpLnZhbHVlc19bMl0udG9TdHJpbmcoKTtcblxuICAgIGNvbnN0IGNvdW50cmllcyA9IHRoaXMuY291bnRyaWVzLmZpbHRlcihcbiAgICAgIChjb3VudHJ5OiBDb3VudHJ5SSkgPT4gY291bnRyeS5kaWFsQ29kZSA9PT0gY291bnRyeUNvZGUudG9TdHJpbmcoKVxuICAgICk7XG4gICAgY29uc3QgbWFpbkNvdW50cnkgPSBjb3VudHJpZXMuZmluZChcbiAgICAgIChjb3VudHJ5OiBDb3VudHJ5SSkgPT4gY291bnRyeS5hcmVhQ29kZXMgPT09IHVuZGVmaW5lZFxuICAgICk7XG4gICAgY29uc3Qgc2Vjb25kYXJ5Q291bnRyaWVzID0gY291bnRyaWVzLmZpbHRlcihcbiAgICAgIChjb3VudHJ5OiBDb3VudHJ5SSkgPT4gY291bnRyeS5hcmVhQ29kZXMgIT09IHVuZGVmaW5lZFxuICAgICk7XG5cbiAgICBsZXQgbWF0Y2hlZENvdW50cnkgPSBtYWluQ291bnRyeSA/IG1haW5Db3VudHJ5Lmlzb0NvZGUgOiB1bmRlZmluZWQ7XG5cbiAgICBzZWNvbmRhcnlDb3VudHJpZXMuZm9yRWFjaCgoY291bnRyeSkgPT4ge1xuICAgICAgY291bnRyeS5hcmVhQ29kZXMuZm9yRWFjaCgoYXJlYUNvZGUpID0+IHtcbiAgICAgICAgaWYgKHJhd051bWJlci5zdGFydHNXaXRoKGFyZWFDb2RlKSkge1xuICAgICAgICAgIG1hdGNoZWRDb3VudHJ5ID0gY291bnRyeS5pc29Db2RlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbWF0Y2hlZENvdW50cnk7XG4gIH1cblxuICBwcml2YXRlIGZldGNoQWxsQ291bnRyaWVzKCkge1xuICAgIHRoaXMuY291bnRyaWVzID0gdGhpcy5pb25JbnRsVGVsSW5wdXRTZXJ2aWNlLmdldExpc3RPZkNvdW50cmllcygpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb3VudHJ5QnlJc29Db2RlKGlzb0NvZGU6IHN0cmluZyk6IENvdW50cnlJIHtcbiAgICBmb3IgKGNvbnN0IGNvdW50cnkgb2YgdGhpcy5jb3VudHJpZXMpIHtcbiAgICAgIGlmIChjb3VudHJ5Lmlzb0NvZGUgPT09IGlzb0NvZGUpIHtcbiAgICAgICAgcmV0dXJuIGNvdW50cnk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIHByaXZhdGUgaXNOdWxsT3JXaGl0ZVNwYWNlKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlID09PSAnJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIE9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZURpYWxDb2RlKHBob25lTnVtYmVyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnNlcGFyYXRlRGlhbENvZGUgJiYgcGhvbmVOdW1iZXIpIHtcbiAgICAgIHBob25lTnVtYmVyID0gcGhvbmVOdW1iZXIuc3Vic3RyKHBob25lTnVtYmVyLmluZGV4T2YoJyAnKSArIDEpO1xuICAgIH1cbiAgICByZXR1cm4gcGhvbmVOdW1iZXI7XG4gIH1cblxuICBwcml2YXRlIHNldENvdW50cnkoY291bnRyeTogQ291bnRyeUkpOiB2b2lkIHtcbiAgICB0aGlzLmNvdW50cnkgPSBjb3VudHJ5O1xuICAgIHRoaXMuY29kZUNoYW5nZS5lbWl0KHRoaXMuY291bnRyeSk7XG4gIH1cblxuICBwcml2YXRlIHNldFByZWZlcnJlZENvdW50cmllcygpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IHByZWZlcmVkQ291bnRyeUlzb0NvZGUgb2YgdGhpcy5wcmVmZXJyZWRDb3VudHJpZXMpIHtcbiAgICAgIGNvbnN0IGNvdW50cnkgPSB0aGlzLmdldENvdW50cnlCeUlzb0NvZGUocHJlZmVyZWRDb3VudHJ5SXNvQ29kZSk7XG4gICAgICBjb3VudHJ5LnByaW9yaXR5ID0gY291bnRyeSA/IDEgOiBjb3VudHJ5LnByaW9yaXR5O1xuICAgIH1cbiAgICB0aGlzLmNvdW50cmllcy5zb3J0KChhLCBiKSA9PlxuICAgICAgYS5wcmlvcml0eSA+IGIucHJpb3JpdHkgPyAtMSA6IGEucHJpb3JpdHkgPCBiLnByaW9yaXR5ID8gMSA6IDBcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGFydHNXaXRoID0gKGlucHV0OiBzdHJpbmcsIHNlYXJjaDogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gICAgcmV0dXJuIGlucHV0LnN1YnN0cigwLCBzZWFyY2gubGVuZ3RoKSA9PT0gc2VhcmNoO1xuICB9O1xuXG4gIHByaXZhdGUgZ2V0Q2xhc3NlcyA9IChlbGVtZW50OiBIVE1MRWxlbWVudCkgPT4ge1xuICAgIGNvbnN0IGNsYXNzTGlzdCA9IGVsZW1lbnQuY2xhc3NMaXN0O1xuICAgIGNvbnN0IGNsYXNzZXMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNsYXNzTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgaXRlbSA9IGNsYXNzTGlzdC5pdGVtKGkpO1xuICAgICAgaWYgKGl0ZW0gIT09IG51bGwgJiYgdGhpcy5zdGFydHNXaXRoKGl0ZW0sICduZy0nKSkge1xuICAgICAgICBjbGFzc2VzLnB1c2goYGlvbi0ke2l0ZW0uc3Vic3RyKDMpfWApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xhc3NlcztcbiAgfTtcblxuICBwcml2YXRlIHNldENsYXNzZXMgPSAoZWxlbWVudDogSFRNTEVsZW1lbnQsIGNsYXNzZXM6IHN0cmluZ1tdKSA9PiB7XG4gICAgY29uc3QgY2xhc3NMaXN0ID0gZWxlbWVudC5jbGFzc0xpc3Q7XG4gICAgW1xuICAgICAgJ2lvbi12YWxpZCcsXG4gICAgICAnaW9uLWludmFsaWQnLFxuICAgICAgJ2lvbi10b3VjaGVkJyxcbiAgICAgICdpb24tdW50b3VjaGVkJyxcbiAgICAgICdpb24tZGlydHknLFxuICAgICAgJ2lvbi1wcmlzdGluZScsXG4gICAgXS5mb3JFYWNoKChjKSA9PiBjbGFzc0xpc3QucmVtb3ZlKGMpKTtcblxuICAgIGNsYXNzZXMuZm9yRWFjaCgoYykgPT4gY2xhc3NMaXN0LmFkZChjKSk7XG4gIH07XG5cbiAgcHJpdmF0ZSBzZXRJb25pY0NsYXNzZXMgPSAoZWxlbWVudDogRWxlbWVudFJlZikgPT4ge1xuICAgIHJhZigoKSA9PiB7XG4gICAgICBjb25zdCBpbnB1dCA9IGVsZW1lbnQubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGNvbnN0IGNsYXNzZXMgPSB0aGlzLmdldENsYXNzZXMoaW5wdXQpO1xuICAgICAgdGhpcy5zZXRDbGFzc2VzKGlucHV0LCBjbGFzc2VzKTtcblxuICAgICAgY29uc3QgaXRlbSA9IGlucHV0LmNsb3Nlc3QoJ2lvbi1pdGVtJyk7XG4gICAgICBpZiAoaXRlbSkge1xuICAgICAgICB0aGlzLnNldENsYXNzZXMoaXRlbSwgY2xhc3Nlcyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgcHJpdmF0ZSBzZXRJdGVtQ2xhc3MgPSAoXG4gICAgZWxlbWVudDogRWxlbWVudFJlZixcbiAgICBjbGFzc05hbWU6IHN0cmluZyxcbiAgICBhZGRDbGFzczogYm9vbGVhblxuICApID0+IHtcbiAgICBjb25zdCBpbnB1dCA9IGVsZW1lbnQubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcbiAgICBjb25zdCBpdGVtID0gaW5wdXQuY2xvc2VzdCgnaW9uLWl0ZW0nKTtcbiAgICBpZiAoaXRlbSkge1xuICAgICAgY29uc3QgY2xhc3NMaXN0ID0gaXRlbS5jbGFzc0xpc3Q7XG4gICAgICBpZiAoYWRkQ2xhc3MpIHtcbiAgICAgICAgY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbn1cbiJdfQ==