UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

576 lines • 55.5 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { ChangeDetectorRef, Component, ContentChild, ElementRef, forwardRef, Inject, QueryList, ContentChildren } from '@angular/core'; import { takeUntil, take } from 'rxjs/operators'; import { IgxForOfDirective } from '../directives/for-of/for_of.directive'; import { IGX_COMBO_COMPONENT } from './combo.common'; import { Navigate } from '../drop-down/drop-down.common'; import { IGX_DROPDOWN_BASE } from '../drop-down/drop-down.common'; import { IgxDropDownComponent } from '../drop-down/drop-down.component'; import { DropDownActionKey } from '../drop-down/drop-down.common'; import { IgxComboAddItemComponent } from './combo-add-item.component'; import { IgxComboAPIService } from './combo.api'; import { IgxSelectionAPIService } from '../core/selection'; import { IgxComboItemComponent } from './combo-item.component'; /** * @hidden */ export class IgxComboDropDownComponent extends IgxDropDownComponent { /** * @param {?} elementRef * @param {?} cdr * @param {?} selection * @param {?} combo * @param {?} comboAPI */ constructor(elementRef, cdr, selection, combo, comboAPI) { super(elementRef, cdr, selection); this.elementRef = elementRef; this.cdr = cdr; this.selection = selection; this.combo = combo; this.comboAPI = comboAPI; this._scrollPosition = 0; /** * @hidden * \@internal */ this.children = null; this.scrollHandler = () => { this.comboAPI.disableTransitions = true; }; } /** * @protected * @return {?} */ get scrollContainer() { return this.verticalScrollContainer.dc.location.nativeElement; } /** * @protected * @return {?} */ get isScrolledToLast() { /** @type {?} */ const scrollTop = this.verticalScrollContainer.getVerticalScroll().scrollTop; /** @type {?} */ const scrollHeight = this.verticalScrollContainer.getVerticalScroll().scrollHeight; return Math.floor(scrollTop + this.verticalScrollContainer.igxForContainerSize) === scrollHeight; } /** * @protected * @return {?} */ get lastVisibleIndex() { return this.combo.totalItemCount ? Math.floor(this.combo.itemsMaxHeight / this.combo.itemHeight) : this.items.length - 1; } /** * @hidden \@internal * @return {?} */ onFocus() { this._focusedItem = this._focusedItem || this.items[0]; if (this._focusedItem) { this._focusedItem.focused = true; } } /** * @hidden \@internal * @param {?=} evt * @return {?} */ onBlur(evt) { if (this._focusedItem) { this._focusedItem.focused = false; this._focusedItem = null; } } /** * @hidden \@internal * @return {?} */ onToggleOpened() { this.onOpened.emit(); } /** * @hidden * @return {?} */ navigatePrev() { if (this._focusedItem.itemIndex === 0 && this.verticalScrollContainer.state.startIndex === 0) { this.combo.focusSearchInput(false); } else { super.navigatePrev(); } } /** * @hidden \@internal * @return {?} */ navigateFirst() { /** @type {?} */ const vContainer = this.verticalScrollContainer; if (vContainer.state.startIndex === 0) { super.navigateItem(0); return; } vContainer.scrollTo(0); this.subscribeNext(vContainer, () => { this.combo.triggerCheck(); super.navigateItem(0); this.combo.triggerCheck(); }); } /** * @hidden \@internal * @return {?} */ navigateLast() { /** @type {?} */ const vContainer = this.verticalScrollContainer; /** @type {?} */ const scrollTarget = this.combo.totalItemCount ? this.combo.totalItemCount - 1 : Math.max(this.combo.data.length - 1, vContainer.igxForOf.length - 1); if (vContainer.igxForOf.length <= vContainer.state.startIndex + vContainer.state.chunkSize) { super.navigateItem(this.items.length - 1); return; } vContainer.scrollTo(scrollTarget); this.subscribeNext(vContainer, () => { this.combo.triggerCheck(); super.navigateItem(this.items.length - 1); this.combo.triggerCheck(); }); } /** * @private * @param {?} direction * @return {?} */ navigateRemoteItem(direction) { /** @type {?} */ const vContainer = this.verticalScrollContainer; vContainer.addScrollTop(direction * this.combo.itemHeight); this.subscribeNext(vContainer, () => { if (direction === Navigate.Up) { super.navigateItem(0); } else { super.navigateItem(this.focusedItem.itemIndex); } }); } /** * @hidden \@internal * @param {?} item * @return {?} */ selectItem(item) { if (item === null || item === undefined) { return; } this.comboAPI.set_selected_item(item.itemID); this._focusedItem = item; } /** * @private * @param {?=} newIndex * @return {?} */ navigateDown(newIndex) { /** @type {?} */ const vContainer = this.verticalScrollContainer; /** @type {?} */ const allData = vContainer.igxForOf; /** @type {?} */ const extraScroll = this.combo.isAddButtonVisible() ? 1 : 0; /** @type {?} */ const focusedItem = this.focusedItem; /** @type {?} */ const items = this.items; /** @type {?} */ const children = this.sortedChildren; if (focusedItem) { if (this.isAddItemFocused()) { return; } if (focusedItem.value === allData[allData.length - 1]) { this.focusAddItemButton(); return; } } /** @type {?} */ let targetDataIndex = newIndex === -1 ? this.itemIndexInData(this.focusedItem.itemIndex) + 1 : this.itemIndexInData(newIndex); /** @type {?} */ const lastLoadedIndex = vContainer.state.startIndex + vContainer.state.chunkSize - 1; if (targetDataIndex < lastLoadedIndex) { // If no scroll is required if (newIndex !== -1 || newIndex === children.length - 1 - extraScroll) { // Use normal nav for visible items super.navigateItem(newIndex); } } else if (this.isScrolledToLast && targetDataIndex === lastLoadedIndex) { // If already at bottom and target is last item super.navigateItem(items.length - 1 - extraScroll); // Focus the last item (excluding Add Button) } else { // If scroll is required // If scroll is required // If item is header, find next non-header index /** @type {?} */ const addedIndex = allData[targetDataIndex].isHeader ? this.findNextFocusableItem(targetDataIndex, Navigate.Down, allData) : 0; targetDataIndex += addedIndex; // Add steps to the target index if (addedIndex === -1) { // If there are no more non-header items & add button is visible this.focusAddItemButton(); } else if (targetDataIndex === allData.length - 1 && !this.isScrolledToLast) { // If target is very last loaded item, but scroll is not at the bottom (item is in DOM but not visible) vContainer.scrollTo(targetDataIndex); // This will not trigger `onChunkLoad` super.navigateItem(items.length - 1 - extraScroll); // Target last item (excluding Add Button) } else { // Perform virtual scroll this.subscribeNext(vContainer, () => { // children = all items in the DD (including addItemButton) // length - 2 instead of -1, because we do not want to focus the last loaded item (in DOM, but not visible) // Focus last item (excluding Add Button) super.navigateItem(!addedIndex ? children[children.length - 1 - extraScroll].itemIndex : this.items.length - 2); }); vContainer.scrollTo(targetDataIndex); // Perform virtual scroll } } } /** * @private * @param {?=} newIndex * @return {?} */ navigateUp(newIndex) { /** @type {?} */ const vContainer = this.verticalScrollContainer; /** @type {?} */ const allData = vContainer.igxForOf; /** @type {?} */ const focusedItem = this.focusedItem; if (focusedItem.value === allData.find(e => !e.isHeader && !e.hidden)) { // If this is the very first non-header item this.focusComboSearch(); // Focus combo search return; } /** @type {?} */ let targetDataIndex = newIndex === -1 ? this.itemIndexInData(focusedItem.itemIndex) - 1 : this.itemIndexInData(newIndex); if (newIndex !== -1) { // If no scroll is required if (this.isScrolledToLast && targetDataIndex === vContainer.state.startIndex) { // If virt scrollbar is @ bottom, first item is in DOM but not visible vContainer.scrollTo(targetDataIndex); // This will not trigger `onChunkLoad` super.navigateItem(0); // Focus first visible item } else { super.navigateItem(newIndex); // Use normal navigation } } else { // Perform virtual scroll // Perform virtual scroll // If item is header, find next non-header index /** @type {?} */ const addedIndex = allData[targetDataIndex].isHeader ? this.findNextFocusableItem(targetDataIndex, Navigate.Up, allData) : 0; targetDataIndex -= addedIndex; // Add steps to targetDataIndex if (addedIndex === -1) { // If there is no non-header vContainer.scrollTo(0); this.focusComboSearch(); // Focus combo search; } else { this.subscribeNext(vContainer, () => { super.navigateItem(0); // Focus the first loaded item }); vContainer.scrollTo(targetDataIndex); // Perform virtual scroll } } } /** * @protected * @param {?} direction * @param {?=} currentIndex * @return {?} */ navigate(direction, currentIndex) { /** @type {?} */ let index = -1; if (this._focusedItem) { index = currentIndex ? currentIndex : this._focusedItem.itemIndex; } /** @type {?} */ const newIndex = this.getNearestSiblingFocusableItemIndex(index, direction); /** @type {?} */ const vContainer = this.verticalScrollContainer; /** @type {?} */ const notVirtual = vContainer.dc.instance.notVirtual; if (notVirtual || !direction) { // If list has no scroll OR no direction is passed super.navigateItem(newIndex); // use default scroll } else if (vContainer && vContainer.totalItemCount && vContainer.totalItemCount !== 0) { // Remote scroll if (newIndex !== -1 && this.items[newIndex].isVisible(direction)) { this.navigateItem(newIndex); } else { this.navigateRemoteItem(direction); } } else { if (direction === Navigate.Up) { // Navigate UP this.navigateUp(newIndex); } else if (direction === Navigate.Down) { // Navigate DOWN this.navigateDown(newIndex); } } } /** * @private * @param {?} index * @return {?} */ itemIndexInData(index) { return this.sortedChildren.findIndex(e => e.itemIndex === index) + this.verticalScrollContainer.state.startIndex; } /** * @private * @param {?} indexInData * @param {?} direction * @param {?} data * @return {?} */ findNextFocusableItem(indexInData, direction, data) { if (direction === Navigate.Up) { return [...data].splice(0, indexInData + 1).reverse().findIndex(e => !e.isHeader); } return [...data].splice(indexInData, data.length - 1).findIndex(e => !e.isHeader); } /** * @private * @return {?} */ focusComboSearch() { this.combo.focusSearchInput(false); if (this.focusedItem) { this.focusedItem.focused = false; } this.focusedItem = null; } /** * @private * @return {?} */ focusAddItemButton() { if (this.combo.isAddButtonVisible()) { super.navigateItem(this.items.length - 1); } } /** * @private * @param {?} virtualContainer * @param {?} callback * @return {?} */ subscribeNext(virtualContainer, callback) { virtualContainer.onChunkLoad.pipe(take(1), takeUntil(this.destroy$)).subscribe({ next: (e) => { callback(e); } }); } /** * @protected * @param {?} newItem * @return {?} */ scrollToHiddenItem(newItem) { } /** * @protected * @return {?} */ get sortedChildren() { if (this.children !== undefined) { return this.children.toArray() .sort((a, b) => { return a.index - b.index; }); } return null; } /** * Get all non-header items * * ```typescript * let myDropDownItems = this.dropdown.items; * ``` * @return {?} */ get items() { /** @type {?} */ const items = []; if (this.children !== undefined) { /** @type {?} */ const sortedChildren = (/** @type {?} */ (this.sortedChildren)); for (const child of sortedChildren) { if (!child.isHeader) { items.push(child); } } } return items; } /** * @protected * @return {?} */ scrollToItem() { } /** * @hidden \@internal * @param {?} e * @return {?} */ onToggleClosing(e) { super.onToggleClosing(e); this._scrollPosition = this.verticalScrollContainer.getVerticalScroll().scrollTop; } /** * @hidden \@internal * @return {?} */ updateScrollPosition() { this.verticalScrollContainer.getVerticalScroll().scrollTop = this._scrollPosition; } /** * @hidden \@internal * @param {?} key * @return {?} */ onItemActionKey(key) { switch (key) { case DropDownActionKey.ENTER: this.handleEnter(); break; case DropDownActionKey.SPACE: this.handleSpace(); break; case DropDownActionKey.ESCAPE: this.close(); } } /** * @private * @return {?} */ handleEnter() { if (this.isAddItemFocused()) { this.combo.addItemToCollection(); } else { this.close(); } } /** * @private * @return {?} */ handleSpace() { if (this.isAddItemFocused()) { return; } else { this.selectItem(this.focusedItem); } } /** * @private * @return {?} */ isAddItemFocused() { return this.focusedItem instanceof IgxComboAddItemComponent; } /** * @return {?} */ ngAfterViewInit() { this.verticalScrollContainer.getVerticalScroll().addEventListener('scroll', this.scrollHandler); } /** * @hidden \@internal * @return {?} */ ngOnDestroy() { this.verticalScrollContainer.getVerticalScroll().removeEventListener('scroll', this.scrollHandler); this.destroy$.next(true); this.destroy$.complete(); } } IgxComboDropDownComponent.decorators = [ { type: Component, args: [{ selector: 'igx-combo-drop-down', template: "<div class=\"igx-drop-down__list\" igxToggle [style.width]=\"width\" [style.height]=\"height\"\n[style.maxHeight]=\"maxHeight\" [attr.id]=\"this.listId\" role=\"listbox\"\n (onOpening)=\"onToggleOpening($event)\" (onOpened)=\"onToggleOpened()\"\n (onClosing)=\"onToggleClosing($event)\" (onClosed)=\"onToggleClosed()\">\n <ng-container *ngIf=\"!collapsed\">\n <ng-content></ng-content>\n </ng-container>\n</div>\n", providers: [{ provide: IGX_DROPDOWN_BASE, useExisting: IgxComboDropDownComponent }] }] } ]; /** @nocollapse */ IgxComboDropDownComponent.ctorParameters = () => [ { type: ElementRef }, { type: ChangeDetectorRef }, { type: IgxSelectionAPIService }, { type: undefined, decorators: [{ type: Inject, args: [IGX_COMBO_COMPONENT,] }] }, { type: IgxComboAPIService } ]; IgxComboDropDownComponent.propDecorators = { children: [{ type: ContentChildren, args: [IgxComboItemComponent, { descendants: true },] }], verticalScrollContainer: [{ type: ContentChild, args: [forwardRef(() => IgxForOfDirective), { read: IgxForOfDirective },] }] }; if (false) { /** * @type {?} * @private */ IgxComboDropDownComponent.prototype._scrollPosition; /** * @hidden * \@internal * @type {?} */ IgxComboDropDownComponent.prototype.children; /** * @hidden \@internal * @type {?} */ IgxComboDropDownComponent.prototype.verticalScrollContainer; /** * @type {?} * @protected */ IgxComboDropDownComponent.prototype.scrollHandler; /** * @type {?} * @protected */ IgxComboDropDownComponent.prototype.elementRef; /** * @type {?} * @protected */ IgxComboDropDownComponent.prototype.cdr; /** * @type {?} * @protected */ IgxComboDropDownComponent.prototype.selection; /** @type {?} */ IgxComboDropDownComponent.prototype.combo; /** * @type {?} * @protected */ IgxComboDropDownComponent.prototype.comboAPI; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm8tZHJvcGRvd24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9jb21iby9jb21iby1kcm9wZG93bi5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDSCxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBNEIsZUFBZSxFQUNuSSxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBRTFFLE9BQU8sRUFBZ0IsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDekQsT0FBTyxFQUFpQixpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVqRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7OztBQVEvRCxNQUFNLE9BQU8seUJBQTBCLFNBQVEsb0JBQW9COzs7Ozs7OztJQUMvRCxZQUNjLFVBQXNCLEVBQ3RCLEdBQXNCLEVBQ3RCLFNBQWlDLEVBQ1AsS0FBbUIsRUFDN0MsUUFBNEI7UUFDdEMsS0FB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QyxFQUFFLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFOzs7Ozs7O0lBWjlFLG9EQUE0Qjs7Ozs7O0lBTTVCLDZDQUN1RDs7Ozs7SUFLdkQsNERBQ3VEOzs7OztJQTZPdkQsa0RBRUM7Ozs7O0lBcFJHLCtDQUFnQzs7Ozs7SUFDaEMsd0NBQWdDOzs7OztJQUNoQyw4Q0FBMkM7O0lBQzNDLDBDQUF1RDs7Ozs7SUFDdkQsNkNBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBDb250ZW50Q2hpbGQsIEVsZW1lbnRSZWYsIGZvcndhcmRSZWYsIEluamVjdCwgUXVlcnlMaXN0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQsIENvbnRlbnRDaGlsZHJlblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbCwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElneEZvck9mRGlyZWN0aXZlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBDYW5jZWxhYmxlQnJvd3NlckV2ZW50QXJncyB9IGZyb20gJy4uL2NvcmUvdXRpbHMnO1xuaW1wb3J0IHsgSWd4Q29tYm9CYXNlLCBJR1hfQ09NQk9fQ09NUE9ORU5UIH0gZnJvbSAnLi9jb21iby5jb21tb24nO1xuaW1wb3J0IHsgTmF2aWdhdGUgfSBmcm9tICcuLi9kcm9wLWRvd24vZHJvcC1kb3duLmNvbW1vbic7XG5pbXBvcnQgeyBJRHJvcERvd25CYXNlLCBJR1hfRFJPUERPV05fQkFTRSB9IGZyb20gJy4uL2Ryb3AtZG93bi9kcm9wLWRvd24uY29tbW9uJztcbmltcG9ydCB7IElneERyb3BEb3duQ29tcG9uZW50IH0gZnJvbSAnLi4vZHJvcC1kb3duL2Ryb3AtZG93bi5jb21wb25lbnQnO1xuaW1wb3J0IHsgRHJvcERvd25BY3Rpb25LZXkgfSBmcm9tICcuLi9kcm9wLWRvd24vZHJvcC1kb3duLmNvbW1vbic7XG5pbXBvcnQgeyBJZ3hDb21ib0FkZEl0ZW1Db21wb25lbnQgfSBmcm9tICcuL2NvbWJvLWFkZC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hDb21ib0FQSVNlcnZpY2UgfSBmcm9tICcuL2NvbWJvLmFwaSc7XG5pbXBvcnQgeyBJZ3hEcm9wRG93bkl0ZW1CYXNlIH0gZnJvbSAnLi4vZHJvcC1kb3duL2Ryb3AtZG93bi1pdGVtLmJhc2UnO1xuaW1wb3J0IHsgSWd4U2VsZWN0aW9uQVBJU2VydmljZSB9IGZyb20gJy4uL2NvcmUvc2VsZWN0aW9uJztcbmltcG9ydCB7IElneENvbWJvSXRlbUNvbXBvbmVudCB9IGZyb20gJy4vY29tYm8taXRlbS5jb21wb25lbnQnO1xuXG4vKiogQGhpZGRlbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdpZ3gtY29tYm8tZHJvcC1kb3duJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4uL2Ryb3AtZG93bi9kcm9wLWRvd24uY29tcG9uZW50Lmh0bWwnLFxuICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogSUdYX0RST1BET1dOX0JBU0UsIHVzZUV4aXN0aW5nOiBJZ3hDb21ib0Ryb3BEb3duQ29tcG9uZW50IH1dXG59KVxuZXhwb3J0IGNsYXNzIElneENvbWJvRHJvcERvd25Db21wb25lbnQgZXh0ZW5kcyBJZ3hEcm9wRG93bkNvbXBvbmVudCBpbXBsZW1lbnRzIElEcm9wRG93bkJhc2UsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdCB7XG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByb3RlY3RlZCBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICBwcm90ZWN0ZWQgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHJvdGVjdGVkIHNlbGVjdGlvbjogSWd4U2VsZWN0aW9uQVBJU2VydmljZSxcbiAgICAgICAgQEluamVjdChJR1hfQ09NQk9fQ09NUE9ORU5UKSBwdWJsaWMgY29tYm86IElneENvbWJvQmFzZSxcbiAgICAgICAgcHJvdGVjdGVkIGNvbWJvQVBJOiBJZ3hDb21ib0FQSVNlcnZpY2UpIHtcbiAgICAgICAgc3VwZXIoZWxlbWVudFJlZiwgY2RyLCBzZWxlY3Rpb24pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgc2Nyb2xsQ29udGFpbmVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5kYy5sb2NhdGlvbi5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgaXNTY3JvbGxlZFRvTGFzdCgpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3Qgc2Nyb2xsVG9wID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5nZXRWZXJ0aWNhbFNjcm9sbCgpLnNjcm9sbFRvcDtcbiAgICAgICAgY29uc3Qgc2Nyb2xsSGVpZ2h0ID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5nZXRWZXJ0aWNhbFNjcm9sbCgpLnNjcm9sbEhlaWdodDtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3Ioc2Nyb2xsVG9wICsgdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5pZ3hGb3JDb250YWluZXJTaXplKSA9PT0gc2Nyb2xsSGVpZ2h0O1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgbGFzdFZpc2libGVJbmRleCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21iby50b3RhbEl0ZW1Db3VudCA/XG4gICAgICAgICAgICBNYXRoLmZsb29yKHRoaXMuY29tYm8uaXRlbXNNYXhIZWlnaHQgLyB0aGlzLmNvbWJvLml0ZW1IZWlnaHQpIDpcbiAgICAgICAgICAgIHRoaXMuaXRlbXMubGVuZ3RoIC0gMTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zY3JvbGxQb3NpdGlvbiA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihJZ3hDb21ib0l0ZW1Db21wb25lbnQsIHsgZGVzY2VuZGFudHM6IHRydWUgfSlcbiAgICBwdWJsaWMgY2hpbGRyZW46IFF1ZXJ5TGlzdDxJZ3hEcm9wRG93bkl0ZW1CYXNlPiA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIEBDb250ZW50Q2hpbGQoZm9yd2FyZFJlZigoKSA9PiBJZ3hGb3JPZkRpcmVjdGl2ZSksIHsgcmVhZDogSWd4Rm9yT2ZEaXJlY3RpdmUgfSlcbiAgICBwdWJsaWMgdmVydGljYWxTY3JvbGxDb250YWluZXI6IElneEZvck9mRGlyZWN0aXZlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBvbkZvY3VzKCkge1xuICAgICAgICB0aGlzLl9mb2N1c2VkSXRlbSA9IHRoaXMuX2ZvY3VzZWRJdGVtIHx8IHRoaXMuaXRlbXNbMF07XG4gICAgICAgIGlmICh0aGlzLl9mb2N1c2VkSXRlbSkge1xuICAgICAgICAgICAgdGhpcy5fZm9jdXNlZEl0ZW0uZm9jdXNlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBvbkJsdXIoZXZ0Pykge1xuICAgICAgICBpZiAodGhpcy5fZm9jdXNlZEl0ZW0pIHtcbiAgICAgICAgICAgIHRoaXMuX2ZvY3VzZWRJdGVtLmZvY3VzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2ZvY3VzZWRJdGVtID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW4gQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIG9uVG9nZ2xlT3BlbmVkKCkge1xuICAgICAgICB0aGlzLm9uT3BlbmVkLmVtaXQoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuYXZpZ2F0ZVByZXYoKSB7XG4gICAgICAgIGlmICh0aGlzLl9mb2N1c2VkSXRlbS5pdGVtSW5kZXggPT09IDAgJiYgdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lci5zdGF0ZS5zdGFydEluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLmZvY3VzU2VhcmNoSW5wdXQoZmFsc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVQcmV2KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHB1YmxpYyBuYXZpZ2F0ZUZpcnN0KCkge1xuICAgICAgICBjb25zdCB2Q29udGFpbmVyID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lcjtcbiAgICAgICAgaWYgKHZDb250YWluZXIuc3RhdGUuc3RhcnRJbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZDb250YWluZXIuc2Nyb2xsVG8oMCk7XG4gICAgICAgIHRoaXMuc3Vic2NyaWJlTmV4dCh2Q29udGFpbmVyLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRyaWdnZXJDaGVjaygpO1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKDApO1xuICAgICAgICAgICAgdGhpcy5jb21iby50cmlnZ2VyQ2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlbiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgbmF2aWdhdGVMYXN0KCkge1xuICAgICAgICBjb25zdCB2Q29udGFpbmVyID0gdGhpcy52ZXJ0aWNhbFNjcm9sbENvbnRhaW5lcjtcbiAgICAgICAgY29uc3Qgc2Nyb2xsVGFyZ2V0ID0gdGhpcy5jb21iby50b3RhbEl0ZW1Db3VudCA/XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRvdGFsSXRlbUNvdW50IC0gMSA6XG4gICAgICAgICAgICBNYXRoLm1heCh0aGlzLmNvbWJvLmRhdGEubGVuZ3RoIC0gMSwgdkNvbnRhaW5lci5pZ3hGb3JPZi5sZW5ndGggLSAxKTtcbiAgICAgICAgaWYgKHZDb250YWluZXIuaWd4Rm9yT2YubGVuZ3RoIDw9IHZDb250YWluZXIuc3RhdGUuc3RhcnRJbmRleCArIHZDb250YWluZXIuc3RhdGUuY2h1bmtTaXplKSB7XG4gICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0odGhpcy5pdGVtcy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Q29udGFpbmVyLnNjcm9sbFRvKHNjcm9sbFRhcmdldCk7XG4gICAgICAgIHRoaXMuc3Vic2NyaWJlTmV4dCh2Q29udGFpbmVyLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRyaWdnZXJDaGVjaygpO1xuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKHRoaXMuaXRlbXMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB0aGlzLmNvbWJvLnRyaWdnZXJDaGVjaygpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG5hdmlnYXRlUmVtb3RlSXRlbShkaXJlY3Rpb246IE5hdmlnYXRlKSB7XG4gICAgICAgIGNvbnN0IHZDb250YWluZXIgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsQ29udGFpbmVyO1xuICAgICAgICB2Q29udGFpbmVyLmFkZFNjcm9sbFRvcChkaXJlY3Rpb24gKiB0aGlzLmNvbWJvLml0ZW1IZWlnaHQpO1xuICAgICAgICB0aGlzLnN1YnNjcmliZU5leHQodkNvbnRhaW5lciwgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gTmF2aWdhdGUuVXApIHtcbiAgICAgICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0oMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbSh0aGlzLmZvY3VzZWRJdGVtLml0ZW1JbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW4gQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIHNlbGVjdEl0ZW0oaXRlbTogSWd4RHJvcERvd25JdGVtQmFzZSkge1xuICAgICAgICBpZiAoaXRlbSA9PT0gbnVsbCB8fCBpdGVtID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbWJvQVBJLnNldF9zZWxlY3RlZF9pdGVtKGl0ZW0uaXRlbUlEKTtcbiAgICAgICAgdGhpcy5fZm9jdXNlZEl0ZW0gPSBpdGVtO1xuICAgIH1cblxuICAgIHByaXZhdGUgbmF2aWdhdGVEb3duKG5ld0luZGV4PzogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IHZDb250YWluZXIgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsQ29udGFpbmVyO1xuICAgICAgICBjb25zdCBhbGxEYXRhID0gdkNvbnRhaW5lci5pZ3hGb3JPZjtcbiAgICAgICAgY29uc3QgZXh0cmFTY3JvbGwgPSB0aGlzLmNvbWJvLmlzQWRkQnV0dG9uVmlzaWJsZSgpID8gMSA6IDA7XG4gICAgICAgIGNvbnN0IGZvY3VzZWRJdGVtID0gdGhpcy5mb2N1c2VkSXRlbTtcbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zO1xuICAgICAgICBjb25zdCBjaGlsZHJlbiA9IHRoaXMuc29ydGVkQ2hpbGRyZW47XG4gICAgICAgIGlmIChmb2N1c2VkSXRlbSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNBZGRJdGVtRm9jdXNlZCgpKSB7IHJldHVybjsgfVxuICAgICAgICAgICAgaWYgKGZvY3VzZWRJdGVtLnZhbHVlID09PSBhbGxEYXRhW2FsbERhdGEubGVuZ3RoIC0gMV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzQWRkSXRlbUJ1dHRvbigpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgdGFyZ2V0RGF0YUluZGV4ID0gbmV3SW5kZXggPT09IC0xID8gdGhpcy5pdGVtSW5kZXhJbkRhdGEodGhpcy5mb2N1c2VkSXRlbS5pdGVtSW5kZXgpICsgMSA6IHRoaXMuaXRlbUluZGV4SW5EYXRhKG5ld0luZGV4KTtcbiAgICAgICAgY29uc3QgbGFzdExvYWRlZEluZGV4ID0gdkNvbnRhaW5lci5zdGF0ZS5zdGFydEluZGV4ICsgdkNvbnRhaW5lci5zdGF0ZS5jaHVua1NpemUgLSAxOyAvLyBMYXN0IGl0ZW0gaXMgbm90IHZpc2libGUsIHNvIHJlcXVpcmUgc2Nyb2xsXG4gICAgICAgIGlmICh0YXJnZXREYXRhSW5kZXggPCBsYXN0TG9hZGVkSW5kZXgpIHsgLy8gSWYgbm8gc2Nyb2xsIGlzIHJlcXVpcmVkXG4gICAgICAgICAgICBpZiAobmV3SW5kZXggIT09IC0xIHx8IG5ld0luZGV4ID09PSBjaGlsZHJlbi5sZW5ndGggLSAxIC0gZXh0cmFTY3JvbGwpIHsgLy8gVXNlIG5vcm1hbCBuYXYgZm9yIHZpc2libGUgaXRlbXNcbiAgICAgICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0obmV3SW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNTY3JvbGxlZFRvTGFzdCAmJiB0YXJnZXREYXRhSW5kZXggPT09IGxhc3RMb2FkZWRJbmRleCkgeyAvLyBJZiBhbHJlYWR5IGF0IGJvdHRvbSBhbmQgdGFyZ2V0IGlzIGxhc3QgaXRlbVxuICAgICAgICAgICAgc3VwZXIubmF2aWdhdGVJdGVtKGl0ZW1zLmxlbmd0aCAtIDEgLSBleHRyYVNjcm9sbCk7IC8vIEZvY3VzIHRoZSBsYXN0IGl0ZW0gKGV4Y2x1ZGluZyBBZGQgQnV0dG9uKVxuICAgICAgICB9IGVsc2UgeyAvLyBJZiBzY3JvbGwgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgIC8vIElmIGl0ZW0gaXMgaGVhZGVyLCBmaW5kIG5leHQgbm9uLWhlYWRlciBpbmRleFxuICAgICAgICAgICAgY29uc3QgYWRkZWRJbmRleCA9IGFsbERhdGFbdGFyZ2V0RGF0YUluZGV4XS5pc0hlYWRlciA/IHRoaXMuZmluZE5leHRGb2N1c2FibGVJdGVtKHRhcmdldERhdGFJbmRleCwgTmF2aWdhdGUuRG93biwgYWxsRGF0YSkgOiAwO1xuICAgICAgICAgICAgdGFyZ2V0RGF0YUluZGV4ICs9IGFkZGVkSW5kZXg7IC8vIEFkZCBzdGVwcyB0byB0aGUgdGFyZ2V0IGluZGV4XG4gICAgICAgICAgICBpZiAoYWRkZWRJbmRleCA9PT0gLTEpIHsgLy8gSWYgdGhlcmUgYXJlIG5vIG1vcmUgbm9uLWhlYWRlciBpdGVtcyAmIGFkZCBidXR0b24gaXMgdmlzaWJsZVxuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNBZGRJdGVtQnV0dG9uKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldERhdGFJbmRleCA9PT0gYWxsRGF0YS5sZW5ndGggLSAxICYmICF0aGlzLmlzU2Nyb2xsZWRUb0xhc3QpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0YXJnZXQgaXMgdmVyeSBsYXN0IGxvYWRlZCBpdGVtLCBidXQgc2Nyb2xsIGlzIG5vdCBhdCB0aGUgYm90dG9tIChpdGVtIGlzIGluIERPTSBidXQgbm90IHZpc2libGUpXG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBUaGlzIHdpbGwgbm90IHRyaWdnZXIgYG9uQ2h1bmtMb2FkYFxuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbShpdGVtcy5sZW5ndGggLSAxIC0gZXh0cmFTY3JvbGwpOyAvLyBUYXJnZXQgbGFzdCBpdGVtIChleGNsdWRpbmcgQWRkIEJ1dHRvbilcbiAgICAgICAgICAgIH0gZWxzZSB7IC8vIFBlcmZvcm0gdmlydHVhbCBzY3JvbGxcbiAgICAgICAgICAgICAgICB0aGlzLnN1YnNjcmliZU5leHQodkNvbnRhaW5lciwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGlsZHJlbiA9IGFsbCBpdGVtcyBpbiB0aGUgREQgKGluY2x1ZGluZyBhZGRJdGVtQnV0dG9uKVxuICAgICAgICAgICAgICAgICAgICAvLyBsZW5ndGggLSAyIGluc3RlYWQgb2YgLTEsIGJlY2F1c2Ugd2UgZG8gbm90IHdhbnQgdG8gZm9jdXMgdGhlIGxhc3QgbG9hZGVkIGl0ZW0gKGluIERPTSwgYnV0IG5vdCB2aXNpYmxlKVxuICAgICAgICAgICAgICAgICAgICAvLyBGb2N1cyBsYXN0IGl0ZW0gKGV4Y2x1ZGluZyBBZGQgQnV0dG9uKVxuICAgICAgICAgICAgICAgICAgICBzdXBlci5uYXZpZ2F0ZUl0ZW0oIWFkZGVkSW5kZXggPyBjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxIC0gZXh0cmFTY3JvbGxdLml0ZW1JbmRleCA6IHRoaXMuaXRlbXMubGVuZ3RoIC0gMik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBQZXJmb3JtIHZpcnR1YWwgc2Nyb2xsXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG5hdmlnYXRlVXAobmV3SW5kZXg/OiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgdkNvbnRhaW5lciA9IHRoaXMudmVydGljYWxTY3JvbGxDb250YWluZXI7XG4gICAgICAgIGNvbnN0IGFsbERhdGEgPSB2Q29udGFpbmVyLmlneEZvck9mO1xuICAgICAgICBjb25zdCBmb2N1c2VkSXRlbSA9IHRoaXMuZm9jdXNlZEl0ZW07XG4gICAgICAgIGlmIChmb2N1c2VkSXRlbS52YWx1ZSA9PT0gYWxsRGF0YS5maW5kKGUgPT4gIWUuaXNIZWFkZXIgJiYgIWUuaGlkZGVuKSkgeyAvLyBJZiB0aGlzIGlzIHRoZSB2ZXJ5IGZpcnN0IG5vbi1oZWFkZXIgaXRlbVxuICAgICAgICAgICAgdGhpcy5mb2N1c0NvbWJvU2VhcmNoKCk7IC8vIEZvY3VzIGNvbWJvIHNlYXJjaFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGxldCB0YXJnZXREYXRhSW5kZXggPSBuZXdJbmRleCA9PT0gLTEgPyB0aGlzLml0ZW1JbmRleEluRGF0YShmb2N1c2VkSXRlbS5pdGVtSW5kZXgpIC0gMSA6IHRoaXMuaXRlbUluZGV4SW5EYXRhKG5ld0luZGV4KTtcbiAgICAgICAgaWYgKG5ld0luZGV4ICE9PSAtMSkgeyAvLyBJZiBubyBzY3JvbGwgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgIGlmICh0aGlzLmlzU2Nyb2xsZWRUb0xhc3QgJiYgdGFyZ2V0RGF0YUluZGV4ID09PSB2Q29udGFpbmVyLnN0YXRlLnN0YXJ0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB2aXJ0IHNjcm9sbGJhciBpcyBAIGJvdHRvbSwgZmlyc3QgaXRlbSBpcyBpbiBET00gYnV0IG5vdCB2aXNpYmxlXG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBUaGlzIHdpbGwgbm90IHRyaWdnZXIgYG9uQ2h1bmtMb2FkYFxuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbSgwKTsgLy8gRm9jdXMgZmlyc3QgdmlzaWJsZSBpdGVtXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbShuZXdJbmRleCk7IC8vIFVzZSBub3JtYWwgbmF2aWdhdGlvblxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgeyAvLyBQZXJmb3JtIHZpcnR1YWwgc2Nyb2xsXG4gICAgICAgICAgICAvLyBJZiBpdGVtIGlzIGhlYWRlciwgZmluZCBuZXh0IG5vbi1oZWFkZXIgaW5kZXhcbiAgICAgICAgICAgIGNvbnN0IGFkZGVkSW5kZXggPSBhbGxEYXRhW3RhcmdldERhdGFJbmRleF0uaXNIZWFkZXIgPyB0aGlzLmZpbmROZXh0Rm9jdXNhYmxlSXRlbSh0YXJnZXREYXRhSW5kZXgsIE5hdmlnYXRlLlVwLCBhbGxEYXRhKSA6IDA7XG4gICAgICAgICAgICB0YXJnZXREYXRhSW5kZXggLT0gYWRkZWRJbmRleDsgLy8gQWRkIHN0ZXBzIHRvIHRhcmdldERhdGFJbmRleFxuICAgICAgICAgICAgaWYgKGFkZGVkSW5kZXggPT09IC0xKSB7IC8vIElmIHRoZXJlIGlzIG5vIG5vbi1oZWFkZXJcbiAgICAgICAgICAgICAgICB2Q29udGFpbmVyLnNjcm9sbFRvKDApO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNDb21ib1NlYXJjaCgpOyAvLyBGb2N1cyBjb21ibyBzZWFyY2g7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3Vic2NyaWJlTmV4dCh2Q29udGFpbmVyLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbSgwKTsgLy8gRm9jdXMgdGhlIGZpcnN0IGxvYWRlZCBpdGVtXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdkNvbnRhaW5lci5zY3JvbGxUbyh0YXJnZXREYXRhSW5kZXgpOyAvLyBQZXJmb3JtIHZpcnR1YWwgc2Nyb2xsXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbmF2aWdhdGUoZGlyZWN0aW9uOiBOYXZpZ2F0ZSwgY3VycmVudEluZGV4PzogbnVtYmVyKSB7XG4gICAgICAgIGxldCBpbmRleCA9IC0xO1xuICAgICAgICBpZiAodGhpcy5fZm9jdXNlZEl0ZW0pIHtcbiAgICAgICAgICAgIGluZGV4ID0gY3VycmVudEluZGV4ID8gY3VycmVudEluZGV4IDogdGhpcy5fZm9jdXNlZEl0ZW0uaXRlbUluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5ld0luZGV4ID0gdGhpcy5nZXROZWFyZXN0U2libGluZ0ZvY3VzYWJsZUl0ZW1JbmRleChpbmRleCwgZGlyZWN0aW9uKTtcbiAgICAgICAgY29uc3QgdkNvbnRhaW5lciA9IHRoaXMudmVydGljYWxTY3JvbGxDb250YWluZXI7XG4gICAgICAgIGNvbnN0IG5vdFZpcnR1YWwgPSB2Q29udGFpbmVyLmRjLmluc3RhbmNlLm5vdFZpcnR1YWw7XG4gICAgICAgIGlmIChub3RWaXJ0dWFsIHx8ICFkaXJlY3Rpb24pIHsgLy8gSWYgbGlzdCBoYXMgbm8gc2Nyb2xsIE9SIG5vIGRpcmVjdGlvbiBpcyBwYXNzZWRcbiAgICAgICAgICAgIHN1cGVyLm5hdmlnYXRlSXRlbShuZXdJbmRleCk7IC8vIHVzZSBkZWZhdWx0IHNjcm9sbFxuICAgICAgICB9IGVsc2UgaWYgKHZDb250YWluZXIgJiYgdkNvbnRhaW5lci50b3RhbEl0ZW1Db3VudCAmJiB2Q29udGFpbmVyLnRvdGFsSXRlbUNvdW50ICE9PSAwKSB7IC8vIFJlbW90ZSBzY3JvbGxcbiAgICAgICAgICAgIGlmIChuZXdJbmRleCAhPT0gLTEgJiZcbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1zW25ld0luZGV4XS5pc1Zpc2libGUoZGlyZWN0aW9uKSkge1xuICAgICAgICAgICAgICAgIHRoaXMubmF2aWdhdGVJdGVtKG5ld0luZGV4KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVJlbW90ZUl0ZW0oZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkaXJlY3Rpb24gPT09IE5hdmlnYXRlLlVwKSB7IC8vIE5hdmlnYXRlIFVQXG4gICAgICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVVwKG5ld0luZGV4KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGlyZWN0aW9uID09PSBOYXZpZ2F0ZS5Eb3duKSB7