@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,520 lines • 214 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, DoCheck, EmbeddedViewRef, EventEmitter, Input, IterableChanges, IterableDiffer, IterableDiffers, NgModule, NgZone, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, TemplateRef, TrackByFunction, ViewContainerRef, ViewRef, AfterViewInit } from '@angular/core';
import { DisplayContainerComponent } from './display.container';
import { HVirtualHelperComponent } from './horizontal.virtual.helper.component';
import { VirtualHelperComponent } from './virtual.helper.component';
import { IgxScrollInertiaModule } from './../scroll-inertia/scroll_inertia.directive';
import { IgxForOfSyncService, IgxForOfScrollSyncService } from './for_of.sync.service';
import { Subject } from 'rxjs';
import { takeUntil, filter, throttleTime, first } from 'rxjs/operators';
import ResizeObserver from 'resize-observer-polyfill';
import { VirtualHelperBaseDirective } from './base.helper.component';
/**
* @publicApi
*/
export class IgxForOfContext {
constructor($implicit, index, count) {
this.$implicit = $implicit;
this.index = index;
this.count = count;
}
/**
* A function that returns whether the element is the first or not
*/
get first() { return this.index === 0; }
/**
* A function that returns whether the element is the last or not
*/
get last() { return this.index === this.count - 1; }
/**
* A function that returns whether the element is even or not
*/
get even() { return this.index % 2 === 0; }
/**
* A function that returns whether the element is odd or not
*/
get odd() { return !this.even; }
}
let IgxForOfDirective = class IgxForOfDirective {
constructor(_viewContainer, _template, _differs, resolver, cdr, _zone, syncScrollService) {
this._viewContainer = _viewContainer;
this._template = _template;
this._differs = _differs;
this.resolver = resolver;
this.cdr = cdr;
this._zone = _zone;
this.syncScrollService = syncScrollService;
/**
* An @Input property that specifies the scroll orientation.
* Scroll orientation can be "vertical" or "horizontal".
* ```html
* <ng-template igxFor let-item [igxForOf]="data" [igxForScrollOrientation]="'horizontal'"></ng-template>
* ```
*/
this.igxForScrollOrientation = 'vertical';
/**
* The current state of the directive. It contains `startIndex` and `chunkSize`.
* state.startIndex - The index of the item at which the current visible chunk begins.
* state.chunkSize - The number of items the current visible chunk holds.
* These options can be used when implementing remote virtualization as they provide the necessary state information.
* ```typescript
* const gridState = this.parentVirtDir.state;
* ```
*/
this.state = {
startIndex: 0,
chunkSize: 0
};
/**
* The total count of the virtual data items, when using remote service.
* ```typescript
* this.parentVirtDir.totalItemCount = data.Count;
* ```
*/
this.totalItemCount = null;
/**
* An event that is emitted after a new chunk has been loaded.
* ```html
* <ng-template igxFor [igxForOf]="data" [igxForScrollOrientation]="'horizontal'" (onChunkLoad)="chunkLoad($event)"></ng-template>
* ```
* ```typescript
* chunkLoad(e){
* alert("chunk loaded!");
* }
* ```
*/
this.onChunkLoad = new EventEmitter();
/**
* @hidden @internal
* An event that is emitted when scrollbar visibility has changed.
*/
this.onScrollbarVisibilityChanged = new EventEmitter();
/**
* An event that is emitted after the rendered content size of the igxForOf has been changed.
*/
this.onContentSizeChange = new EventEmitter();
/**
* An event that is emitted after data has been changed.
* ```html
* <ng-template igxFor [igxForOf]="data" [igxForScrollOrientation]="'horizontal'" (onDataChanged)="dataChanged($event)"></ng-template>
* ```
* ```typescript
* dataChanged(e){
* alert("data changed!");
* }
* ```
*/
this.onDataChanged = new EventEmitter();
this.onBeforeViewDestroyed = new EventEmitter();
/**
* An event that is emitted on chunk loading to emit the current state information - startIndex, endIndex, totalCount.
* Can be used for implementing remote load on demand for the igxFor data.
* ```html
* <ng-template igxFor [igxForOf]="data" [igxForScrollOrientation]="'horizontal'" (onChunkPreload)="chunkPreload($event)"></ng-template>
* ```
* ```typescript
* chunkPreload(e){
* alert("chunk is loading!");
* }
* ```
*/
this.onChunkPreload = new EventEmitter();
this._sizesCache = [];
this._differ = null;
this.heightCache = [];
this.MAX_PERF_SCROLL_DIFF = 4;
/** Height that is being virtualized. */
this._virtHeight = 0;
/**
* Ratio for height that's being virtualizaed and the one visible
* If _virtHeightRatio = 1, the visible height and the virtualized are the same, also _maxHeight > _virtHeight.
*/
this._virtHeightRatio = 1;
/** Internal track for scroll top that is being virtualized */
this._virtScrollTop = 0;
/** If the next onScroll event is triggered due to internal setting of scrollTop */
this._bScrollInternal = false;
// End properties related to virtual height handling
this._embeddedViews = [];
this.contentResizeNotify = new Subject();
/**
* @hidden
*/
this.destroy$ = new Subject();
}
get displayContainer() {
return this.dc.instance._viewContainer.element.nativeElement;
}
get virtualHelper() {
return this.scrollComponent.nativeElement;
}
get sizesCache() {
return this._sizesCache;
}
set sizesCache(value) {
this._sizesCache = value;
}
get _isScrolledToBottom() {
if (!this.getScroll()) {
return true;
}
const scrollHeight = this.getScroll().scrollHeight;
// Use === and not >= because `scrollTop + container size` can't be bigger than `scrollHeight`, unless something isn't updated.
// Also use Math.round because Chrome has some inconsistencies and `scrollTop + container` can be float when zooming the page.
return Math.round(this.getScroll().scrollTop + this.igxForContainerSize) === scrollHeight;
}
get _isAtBottomIndex() {
return this.igxForOf && this.state.startIndex + this.state.chunkSize > this.igxForOf.length;
}
/**
* @hidden
*/
get isRemote() {
return this.totalItemCount !== null;
}
/**
*
* Gets/Sets the scroll position.
* ```typescript
* const position = directive.scrollPosition;
* directive.scrollPosition = value;
* ```
*/
get scrollPosition() {
return this.scrollComponent.scrollAmount;
}
set scrollPosition(val) {
if (val === this.scrollComponent.scrollAmount) {
return;
}
if (this.igxForScrollOrientation === 'horizontal' && this.scrollComponent) {
this.scrollComponent.nativeElement.scrollLeft = val;
}
else if (this.scrollComponent) {
this.scrollComponent.nativeElement.scrollTop = val;
}
}
/**
* @hidden
*/
removeScrollEventListeners() {
if (this.igxForScrollOrientation === 'horizontal') {
this._zone.runOutsideAngular(() => this.scrollComponent.nativeElement.removeEventListener('scroll', this.func));
}
else {
this._zone.runOutsideAngular(() => this.scrollComponent.nativeElement.removeEventListener('scroll', this.verticalScrollHandler));
}
}
verticalScrollHandler(event) {
this.onScroll(event);
}
isScrollable() {
return this.scrollComponent.size > parseInt(this.igxForContainerSize, 10);
}
/**
* @hidden
*/
ngOnInit() {
let totalSize = 0;
const vc = this.igxForScrollContainer ? this.igxForScrollContainer._viewContainer : this._viewContainer;
this.igxForSizePropName = this.igxForSizePropName || 'width';
const dcFactory = this.resolver.resolveComponentFactory(DisplayContainerComponent);
this.dc = this._viewContainer.createComponent(dcFactory, 0);
this.dc.instance.scrollDirection = this.igxForScrollOrientation;
if (typeof MSGesture === 'function') {
// On Edge and IE when scrolling on touch the page scroll instead of the grid.
this.dc.instance._viewContainer.element.nativeElement.style.touchAction = 'none';
}
if (this.igxForOf && this.igxForOf.length) {
totalSize = this.initSizesCache(this.igxForOf);
this.scrollComponent = this.syncScrollService.getScrollMaster(this.igxForScrollOrientation);
this.state.chunkSize = this._calculateChunkSize();
this.dc.instance.notVirtual = !(this.igxForContainerSize && this.state.chunkSize < this.igxForOf.length);
if (this.scrollComponent) {
this.state.startIndex = Math.min(this.getIndexAt(this.scrollPosition, this.sizesCache, 0), this.igxForOf.length - this.state.chunkSize);
}
for (let i = this.state.startIndex; i < this.state.startIndex + this.state.chunkSize &&
this.igxForOf[i] !== undefined; i++) {
const input = this.igxForOf[i];
const embeddedView = this.dc.instance._vcr.createEmbeddedView(this._template, new IgxForOfContext(input, this.getContextIndex(input), this.igxForOf.length));
this._embeddedViews.push(embeddedView);
}
}
if (this.igxForScrollOrientation === 'vertical') {
this.dc.instance._viewContainer.element.nativeElement.style.top = '0px';
const factory = this.resolver.resolveComponentFactory(VirtualHelperComponent);
this.scrollComponent = vc.createComponent(factory).instance;
this._maxHeight = this._calcMaxBrowserHeight();
this.scrollComponent.size = this.igxForOf ? this._calcHeight() : 0;
this.syncScrollService.setScrollMaster(this.igxForScrollOrientation, this.scrollComponent);
this._zone.runOutsideAngular(() => {
this.verticalScrollHandler = this.verticalScrollHandler.bind(this);
this.scrollComponent.nativeElement.addEventListener('scroll', this.verticalScrollHandler);
this.dc.instance.scrollContainer = this.scrollComponent.nativeElement;
});
const destructor = takeUntil(this.destroy$);
this.contentResizeNotify.pipe(destructor, filter(() => this.igxForContainerSize && this.igxForOf && this.igxForOf.length > 0), throttleTime(40))
.subscribe(() => {
this._zone.runTask(() => {
this.updateSizes();
});
});
}
if (this.igxForScrollOrientation === 'horizontal') {
this.func = (evt) => { this.onHScroll(evt); };
this.scrollComponent = this.syncScrollService.getScrollMaster(this.igxForScrollOrientation);
if (!this.scrollComponent) {
const hvFactory = this.resolver.resolveComponentFactory(HVirtualHelperComponent);
this.scrollComponent = vc.createComponent(hvFactory).instance;
this.scrollComponent.size = totalSize;
this.syncScrollService.setScrollMaster(this.igxForScrollOrientation, this.scrollComponent);
this._zone.runOutsideAngular(() => {
this.scrollComponent.nativeElement.addEventListener('scroll', this.func);
this.dc.instance.scrollContainer = this.scrollComponent.nativeElement;
});
}
else {
this._zone.runOutsideAngular(() => {
this.scrollComponent.nativeElement.addEventListener('scroll', this.func);
this.dc.instance.scrollContainer = this.scrollComponent.nativeElement;
});
}
this._updateHScrollOffset();
}
}
ngAfterViewInit() {
if (this.igxForScrollOrientation === 'vertical') {
this._zone.runOutsideAngular(() => {
this.contentObserver = new ResizeObserver(() => this.contentResizeNotify.next());
this.contentObserver.observe(this.dc.instance._viewContainer.element.nativeElement);
});
}
}
/**
* @hidden
*/
ngOnDestroy() {
this.removeScrollEventListeners();
this.destroy$.next(true);
this.destroy$.complete();
if (this.contentObserver) {
this.contentObserver.disconnect();
}
}
/**
* @hidden
*/
ngOnChanges(changes) {
const forOf = 'igxForOf';
if (forOf in changes) {
const value = changes[forOf].currentValue;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this.igxForTrackBy);
}
catch (e) {
throw new Error(`Cannot find a differ supporting object "${value}" of type "${getTypeNameForDebugging(value)}".
NgFor only supports binding to Iterables such as Arrays.`);
}
}
}
const defaultItemSize = 'igxForItemSize';
if (defaultItemSize in changes && !changes[defaultItemSize].firstChange &&
this.igxForScrollOrientation === 'vertical' && this.igxForOf) {
// handle default item size changed.
this.initSizesCache(this.igxForOf);
this._applyChanges();
}
const containerSize = 'igxForContainerSize';
if (containerSize in changes && !changes[containerSize].firstChange && this.igxForOf) {
this._recalcOnContainerChange(changes);
}
}
/**
* @hidden
*/
ngDoCheck() {
if (this._differ) {
const changes = this._differ.diff(this.igxForOf);
if (changes) {
// re-init cache.
if (!this.igxForOf) {
this.igxForOf = [];
}
this._updateSizeCache();
this._zone.run(() => {
this._applyChanges();
this.cdr.markForCheck();
this._updateScrollOffset();
this.onDataChanged.emit();
});
}
}
}
/**
* Shifts the scroll thumb position.
* ```typescript
* this.parentVirtDir.addScrollTop(5);
* ```
* @param addTop negative value to scroll up and positive to scroll down;
*/
addScrollTop(addTop) {
if (addTop === 0 && this.igxForScrollOrientation === 'horizontal') {
return false;
}
const originalVirtScrollTop = this._virtScrollTop;
const containerSize = parseInt(this.igxForContainerSize, 10);
const maxVirtScrollTop = this._virtHeight - containerSize;
this._bScrollInternal = true;
this._virtScrollTop += addTop;
this._virtScrollTop = this._virtScrollTop > 0 ?
(this._virtScrollTop < maxVirtScrollTop ? this._virtScrollTop : maxVirtScrollTop) :
0;
this.scrollPosition += addTop / this._virtHeightRatio;
if (Math.abs(addTop / this._virtHeightRatio) < 1) {
// Actual scroll delta that was added is smaller than 1 and onScroll handler doesn't trigger when scrolling < 1px
const scrollOffset = this.fixedUpdateAllElements(this._virtScrollTop);
// scrollOffset = scrollOffset !== parseInt(this.igxForItemSize, 10) ? scrollOffset : 0;
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
}
const maxRealScrollTop = this.scrollComponent.nativeElement.scrollHeight - containerSize;
if ((this._virtScrollTop > 0 && this.scrollPosition === 0) ||
(this._virtScrollTop < maxVirtScrollTop && this.scrollPosition === maxRealScrollTop)) {
// Actual scroll position is at the top or bottom, but virtual one is not at the top or bottom (there's more to scroll)
// Recalculate actual scroll position based on the virtual scroll.
this.scrollPosition = this._virtScrollTop / this._virtHeightRatio;
}
else if (this._virtScrollTop === 0 && this.scrollPosition > 0) {
// Actual scroll position is not at the top, but virtual scroll is. Just update the actual scroll
this.scrollPosition = 0;
}
else if (this._virtScrollTop === maxVirtScrollTop && this.scrollPosition < maxRealScrollTop) {
// Actual scroll position is not at the bottom, but virtual scroll is. Just update the acual scroll
this.scrollPosition = maxRealScrollTop;
}
return this._virtScrollTop !== originalVirtScrollTop;
}
/**
* Scrolls to the specified index.
* ```typescript
* this.parentVirtDir.scrollTo(5);
* ```
* @param index
*/
scrollTo(index) {
if (index < 0 || index > (this.isRemote ? this.totalItemCount : this.igxForOf.length) - 1) {
return;
}
const containerSize = parseInt(this.igxForContainerSize, 10);
const isPrevItem = index < this.state.startIndex || this.scrollPosition > this.sizesCache[index];
let nextScroll = isPrevItem ? this.sizesCache[index] : this.sizesCache[index + 1] - containerSize;
if (nextScroll < 0) {
return;
}
if (this.igxForScrollOrientation === 'horizontal') {
this.scrollPosition = nextScroll;
}
else {
const maxVirtScrollTop = this._virtHeight - containerSize;
if (nextScroll > maxVirtScrollTop) {
nextScroll = maxVirtScrollTop;
}
this._bScrollInternal = true;
this._virtScrollTop = nextScroll;
this.scrollPosition = this._virtScrollTop / this._virtHeightRatio;
this._adjustToIndex = !isPrevItem ? index : null;
}
}
/**
* Scrolls by one item into the appropriate next direction.
* For "horizontal" orientation that will be the right column and for "vertical" that is the lower row.
* ```typescript
* this.parentVirtDir.scrollNext();
* ```
*/
scrollNext() {
const scr = Math.ceil(this.scrollPosition);
const endIndex = this.getIndexAt(scr + parseInt(this.igxForContainerSize, 10), this.sizesCache, 0);
this.scrollTo(endIndex);
}
/**
* Scrolls by one item into the appropriate previous direction.
* For "horizontal" orientation that will be the left column and for "vertical" that is the upper row.
* ```typescript
* this.parentVirtDir.scrollPrev();
* ```
*/
scrollPrev() {
this.scrollTo(this.state.startIndex - 1);
}
/**
* Scrolls by one page into the appropriate next direction.
* For "horizontal" orientation that will be one view to the right and for "vertical" that is one view to the bottom.
* ```typescript
* this.parentVirtDir.scrollNextPage();
* ```
*/
scrollNextPage() {
if (this.igxForScrollOrientation === 'horizontal') {
this.scrollPosition += parseInt(this.igxForContainerSize, 10);
}
else {
this.addScrollTop(parseInt(this.igxForContainerSize, 10));
}
}
/**
* Scrolls by one page into the appropriate previous direction.
* For "horizontal" orientation that will be one view to the left and for "vertical" that is one view to the top.
* ```typescript
* this.parentVirtDir.scrollPrevPage();
* ```
*/
scrollPrevPage() {
if (this.igxForScrollOrientation === 'horizontal') {
this.scrollPosition -= parseInt(this.igxForContainerSize, 10);
}
else {
const containerSize = (parseInt(this.igxForContainerSize, 10));
this.addScrollTop(-containerSize);
}
}
/**
* @hidden
*/
getColumnScrollLeft(colIndex) {
return this.sizesCache[colIndex];
}
/**
* Returns the total number of items that are fully visible.
* ```typescript
* this.parentVirtDir.getItemCountInView();
* ```
*/
getItemCountInView() {
let startIndex = this.getIndexAt(this.scrollPosition, this.sizesCache, 0);
if (this.scrollPosition - this.sizesCache[startIndex] > 0) {
// fisrt item is not fully in view
startIndex++;
}
const endIndex = this.getIndexAt(this.scrollPosition + parseInt(this.igxForContainerSize, 10), this.sizesCache, 0);
return endIndex - startIndex;
}
/**
* Returns a reference to the scrollbar DOM element.
* This is either a vertical or horizontal scrollbar depending on the specified igxForScrollOrientation.
* ```typescript
* dir.getScroll();
* ```
*/
getScroll() {
return this.scrollComponent.nativeElement;
}
/**
* Returns the size of the element at the specified index.
* ```typescript
* this.parentVirtDir.getSizeAt(1);
* ```
*/
getSizeAt(index) {
return this.sizesCache[index + 1] - this.sizesCache[index];
}
/**
* Returns the scroll offset of the element at the specified index.
* ```typescript
* this.parentVirtDir.getScrollForIndex(1);
* ```
*/
getScrollForIndex(index, bottom) {
const containerSize = parseInt(this.igxForContainerSize, 10);
const scroll = bottom ? Math.max(0, this.sizesCache[index + 1] - containerSize) : this.sizesCache[index];
return scroll;
}
/**
* @hidden
* Function that is called when scrolling vertically
*/
onScroll(event) {
/* in certain situations this may be called when no scrollbar is visible */
if (!parseInt(this.scrollComponent.nativeElement.style.height, 10)) {
return;
}
const containerSize = parseInt(this.igxForContainerSize, 10);
const maxRealScrollTop = event.target.children[0].scrollHeight - containerSize;
const realPercentScrolled = maxRealScrollTop !== 0 ? event.target.scrollTop / maxRealScrollTop : 0;
if (!this._bScrollInternal) {
const maxVirtScrollTop = this._virtHeight - containerSize;
this._virtScrollTop = realPercentScrolled * maxVirtScrollTop;
}
else {
this._bScrollInternal = false;
}
const prevStartIndex = this.state.startIndex;
const scrollOffset = this.fixedUpdateAllElements(this._virtScrollTop);
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
this.dc.changeDetectorRef.detectChanges();
if (prevStartIndex !== this.state.startIndex) {
this.onChunkLoad.emit(this.state);
}
}
updateSizes() {
this.recalcUpdateSizes();
this._applyChanges();
this._updateScrollOffset();
this.onContentSizeChange.emit();
}
/**
* @hidden
* Function that recaculates and updates cache sizes.
*/
recalcUpdateSizes() {
const dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
const diffs = [];
let totalDiff = 0;
const l = this._embeddedViews.length;
const rNodes = this._embeddedViews.map(view => view.rootNodes.find(node => node.nodeType === Node.ELEMENT_NODE) || view.rootNodes[0].nextElementSibling);
for (let i = 0; i < l; i++) {
const rNode = rNodes[i];
if (rNode) {
const h = rNode.offsetHeight || parseInt(this.igxForItemSize, 10);
const index = this.state.startIndex + i;
if (!this.isRemote && !this.igxForOf[index]) {
continue;
}
const oldVal = dimension === 'height' ? this.heightCache[index] : this.igxForOf[index][dimension];
const newVal = dimension === 'height' ? h : rNode.clientWidth;
if (dimension === 'height') {
this.heightCache[index] = newVal;
}
else {
this.igxForOf[index][dimension] = newVal;
}
const currDiff = newVal - oldVal;
diffs.push(currDiff);
totalDiff += currDiff;
this.sizesCache[index + 1] += totalDiff;
}
}
// update cache
if (Math.abs(totalDiff) > 0) {
for (let j = this.state.startIndex + this.state.chunkSize + 1; j < this.sizesCache.length; j++) {
this.sizesCache[j] += totalDiff;
}
// update scrBar heights/widths
if (this.igxForScrollOrientation === 'horizontal') {
const totalWidth = parseInt(this.scrollComponent.nativeElement.children[0].style.width, 10) + totalDiff;
this.scrollComponent.nativeElement.children[0].style.width = totalWidth + 'px';
}
const reducer = (acc, val) => acc + val;
if (this.igxForScrollOrientation === 'vertical') {
const scrToBottom = this._isScrolledToBottom && !this.dc.instance.notVirtual;
const hSum = this.heightCache.reduce(reducer);
if (hSum > this._maxHeight) {
this._virtHeightRatio = hSum / this._maxHeight;
}
this.scrollComponent.size = Math.min(this.scrollComponent.size + totalDiff, this._maxHeight);
this._virtHeight = hSum;
if (!this.scrollComponent.destroyed) {
this.scrollComponent.cdr.detectChanges();
}
if (scrToBottom && !this._isAtBottomIndex) {
const containerSize = parseInt(this.igxForContainerSize, 10);
const maxVirtScrollTop = this._virtHeight - containerSize;
this._bScrollInternal = true;
this._virtScrollTop = maxVirtScrollTop;
this.scrollPosition = maxVirtScrollTop;
return;
}
if (this._adjustToIndex) {
// in case scrolled to specific index where after scroll heights are changed
// need to adjust the offsets so that item is last in view.
const updatesToIndex = this._adjustToIndex - this.state.startIndex + 1;
const sumDiffs = diffs.slice(0, updatesToIndex).reduce(reducer);
const currOffset = parseInt(this.dc.instance._viewContainer.element.nativeElement.style.top, 10);
this.dc.instance._viewContainer.element.nativeElement.style.top = (currOffset - sumDiffs) + 'px';
this._adjustToIndex = null;
}
}
}
}
/**
* @hidden
*/
fixedUpdateAllElements(inScrollTop) {
const count = this.isRemote ? this.totalItemCount : this.igxForOf.length;
let newStart = this.getIndexAt(inScrollTop, this.sizesCache, 0);
if (newStart + this.state.chunkSize > count) {
newStart = count - this.state.chunkSize;
}
const prevStart = this.state.startIndex;
const diff = newStart - this.state.startIndex;
this.state.startIndex = newStart;
if (diff) {
this.onChunkPreload.emit(this.state);
if (!this.isRemote) {
/*recalculate and apply page size.*/
if (diff > 0 && diff <= this.MAX_PERF_SCROLL_DIFF) {
this.moveApplyScrollNext(prevStart);
}
else if (diff < 0 && Math.abs(diff) <= this.MAX_PERF_SCROLL_DIFF) {
this.moveApplyScrollPrev(prevStart);
}
else {
this.fixedApplyScroll();
}
}
}
return inScrollTop - this.sizesCache[this.state.startIndex];
}
/**
* @hidden
* The function applies an optimized state change for scrolling down/right employing context change with view rearrangement
*/
moveApplyScrollNext(prevIndex) {
const start = prevIndex + this.state.chunkSize;
for (let i = start; i < start + this.state.startIndex - prevIndex && this.igxForOf[i] !== undefined; i++) {
const input = this.igxForOf[i];
const embView = this._embeddedViews.shift();
const cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
const view = this.dc.instance._vcr.detach(0);
this.dc.instance._vcr.insert(view);
this._embeddedViews.push(embView);
}
}
/**
* @hidden
* The function applies an optimized state change for scrolling up/left employing context change with view rearrangement
*/
moveApplyScrollPrev(prevIndex) {
for (let i = prevIndex - 1; i >= this.state.startIndex && this.igxForOf[i] !== undefined; i--) {
const input = this.igxForOf[i];
const embView = this._embeddedViews.pop();
const cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
const view = this.dc.instance._vcr.detach(this.dc.instance._vcr.length - 1);
this.dc.instance._vcr.insert(view, 0);
this._embeddedViews.unshift(embView);
}
}
/**
* @hidden
*/
getContextIndex(input) {
return this.isRemote ? this.state.startIndex + this.igxForOf.indexOf(input) : this.igxForOf.indexOf(input);
}
/**
* @hidden
* The function applies an optimized state change through context change for each view
*/
fixedApplyScroll() {
let j = 0;
const endIndex = this.state.startIndex + this.state.chunkSize;
for (let i = this.state.startIndex; i < endIndex && this.igxForOf[i] !== undefined; i++) {
const input = this.igxForOf[i];
const embView = this._embeddedViews[j++];
const cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
}
}
/**
* @hidden
* Function that is called when scrolling horizontally
*/
onHScroll(event) {
/* in certain situations this may be called when no scrollbar is visible */
if (!parseInt(this.scrollComponent.nativeElement.children[0].style.width, 10)) {
return;
}
const prevStartIndex = this.state.startIndex;
// Updating horizontal chunks
const scrollOffset = this.fixedUpdateAllElements(event.target.scrollLeft);
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
this.dc.changeDetectorRef.detectChanges();
if (prevStartIndex !== this.state.startIndex) {
this.onChunkLoad.emit(this.state);
}
}
/**
* Gets the function used to track changes in the items collection.
* By default the object references are compared. However this can be optimized if you have unique identifier
* value that can be used for the comparison instead of the object ref or if you have some other property values
* in the item object that should be tracked for changes.
* This option is similar to ngForTrackBy.
* ```typescript
* const trackFunc = this.parentVirtDir.igxForTrackBy;
* ```
*/
get igxForTrackBy() { return this._trackByFn; }
/**
* Sets the function used to track changes in the items collection.
* This function can be set in scenarios where you want to optimize or
* customize the tracking of changes for the items in the collection.
* The igxForTrackBy function takes the index and the current item as arguments and needs to return the unique identifier for this item.
* ```typescript
* this.parentVirtDir.igxForTrackBy = (index, item) => {
* return item.id + item.width;
* };
* ```
*/
set igxForTrackBy(fn) { this._trackByFn = fn; }
/**
* @hidden
*/
_applyChanges() {
const prevChunkSize = this.state.chunkSize;
this.applyChunkSizeChange();
this._recalcScrollBarSize();
if (this.igxForOf && this.igxForOf.length && this.dc) {
const embeddedViewCopy = Object.assign([], this._embeddedViews);
let startIndex = this.state.startIndex;
let endIndex = this.state.chunkSize + this.state.startIndex;
if (this.isRemote) {
startIndex = 0;
endIndex = this.igxForOf.length;
}
for (let i = startIndex; i < endIndex && this.igxForOf[i] !== undefined; i++) {
const input = this.igxForOf[i];
const embView = embeddedViewCopy.shift();
const cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
}
if (prevChunkSize !== this.state.chunkSize) {
this.onChunkLoad.emit(this.state);
}
}
}
/**
* @hidden
*/
_calcMaxBrowserHeight() {
const div = document.createElement('div');
const style = div.style;
style.position = 'absolute';
style.top = '9999999999999999px';
document.body.appendChild(div);
const size = Math.abs(div.getBoundingClientRect()['top']);
document.body.removeChild(div);
return size;
}
/**
* @hidden
* Recalculates the chunkSize based on current startIndex and returns the new size.
* This should be called after this.state.startIndex is updated, not before.
*/
_calculateChunkSize() {
let chunkSize = 0;
if (this.igxForContainerSize !== null && this.igxForContainerSize !== undefined) {
if (!this.sizesCache) {
this.initSizesCache(this.igxForOf);
}
chunkSize = this._calcMaxChunkSize();
if (this.igxForOf && chunkSize > this.igxForOf.length) {
chunkSize = this.igxForOf.length;
}
}
else {
if (this.igxForOf) {
chunkSize = this.igxForOf.length;
}
}
return chunkSize;
}
/**
* @hidden
*/
getElement(viewref, nodeName) {
const elem = viewref.element.nativeElement.parentNode.getElementsByTagName(nodeName);
return elem.length > 0 ? elem[0] : null;
}
/**
* @hidden
*/
initSizesCache(items) {
let totalSize = 0;
let size = 0;
const dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
let i = 0;
this.sizesCache = [];
this.heightCache = [];
this.sizesCache.push(0);
const count = this.isRemote ? this.totalItemCount : items.length;
for (i; i < count; i++) {
if (dimension === 'height') {
// cols[i][dimension] = parseInt(this.igxForItemSize, 10) || 0;
size = parseInt(this.igxForItemSize, 10) || 0;
this.heightCache.push(size);
}
else {
size = this._getItemSize(items[i], dimension);
}
totalSize += size;
this.sizesCache.push(totalSize);
}
return totalSize;
}
_updateSizeCache() {
if (this.igxForScrollOrientation === 'horizontal') {
this.initSizesCache(this.igxForOf);
return;
}
const oldHeight = this.heightCache.length > 0 ? this.heightCache.reduce((acc, val) => acc + val) : 0;
const newHeight = this.initSizesCache(this.igxForOf);
const diff = oldHeight - newHeight;
// if data has been changed while container is scrolled
// should update scroll top/left according to change so that same startIndex is in view
if (Math.abs(diff) > 0 && this.scrollPosition > 0) {
this.recalcUpdateSizes();
const offset = parseInt(this.dc.instance._viewContainer.element.nativeElement.style.top, 10);
this.scrollPosition = this.sizesCache[this.state.startIndex] - offset;
}
}
/**
* @hidden
*/
_calcMaxChunkSize() {
let i = 0;
let length = 0;
let maxLength = 0;
const arr = [];
let sum = 0;
const availableSize = parseInt(this.igxForContainerSize, 10);
if (!availableSize) {
return 0;
}
const dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
const reducer = (accumulator, currentItem) => accumulator + this._getItemSize(currentItem, dimension);
for (i; i < this.igxForOf.length; i++) {
let item = this.igxForOf[i];
if (dimension === 'height') {
item = { value: this.igxForOf[i], height: this.heightCache[i] };
}
const size = dimension === 'height' ?
this.heightCache[i] :
this._getItemSize(item, dimension);
sum = arr.reduce(reducer, size);
if (sum < availableSize) {
arr.push(item);
length = arr.length;
if (i === this.igxForOf.length - 1) {
// reached end without exceeding
// include prev items until size is filled or first item is reached.
let curItem = dimension === 'height' ? arr[0].value : arr[0];
let prevIndex = this.igxForOf.indexOf(curItem) - 1;
while (prevIndex >= 0 && sum <= availableSize) {
curItem = dimension === 'height' ? arr[0].value : arr[0];
prevIndex = this.igxForOf.indexOf(curItem) - 1;
const prevItem = this.igxForOf[prevIndex];
const prevSize = dimension === 'height' ?
this.heightCache[prevIndex] :
parseInt(prevItem[dimension], 10);
sum = arr.reduce(reducer, prevSize);
arr.unshift(prevItem);
length = arr.length;
}
}
}
else {
arr.push(item);
length = arr.length + 1;
arr.shift();
}
if (length > maxLength) {
maxLength = length;
}
}
return maxLength;
}
/**
* @hidden
*/
getIndexAt(left, set, index) {
let start = 0;
let end = set.length - 1;
if (left === 0) {
return 0;
}
while (start <= end) {
const midIdx = Math.floor((start + end) / 2);
const midLeft = set[midIdx];
const cmp = left - midLeft;
if (cmp > 0) {
start = midIdx + 1;
}
else if (cmp < 0) {
end = midIdx - 1;
}
else {
return midIdx;
}
}
return end;
}
_recalcScrollBarSize() {
const count = this.isRemote ? this.totalItemCount : (this.igxForOf ? this.igxForOf.length : 0);
this.dc.instance.notVirtual = !(this.igxForContainerSize && this.dc && this.state.chunkSize < count);
const scrollable = this.isScrollable();
if (this.igxForScrollOrientation === 'horizontal') {
const totalWidth = this.igxForContainerSize ? this.initSizesCache(this.igxForOf) : 0;
this.scrollComponent.nativeElement.style.width = this.igxForContainerSize + 'px';
this.scrollComponent.size = totalWidth;
if (totalWidth <= parseInt(this.igxForContainerSize, 10)) {
this.scrollPosition = 0;
}
}
if (this.igxForScrollOrientation === 'vertical') {
this.scrollComponent.nativeElement.style.height = parseInt(this.igxForContainerSize, 10) + 'px';
this.scrollComponent.size = this._calcHeight();
if (this.scrollComponent.size <= parseInt(this.igxForContainerSize, 10)) {
this.scrollPosition = 0;
}
}
if (scrollable !== this.isScrollable()) {
// scrollbar visibility has changed
this.onScrollbarVisibilityChanged.emit();
}
}
_calcHeight() {
let height;
if (this.heightCache) {
height = this.heightCache.reduce((acc, val) => acc + val, 0);
}
else {
height = this.initSizesCache(this.igxForOf);
}
this._virtHeight = height;
if (height > this._maxHeight) {
this._virtHeightRatio = height / this._maxHeight;
height = this._maxHeight;
}
return height;
}
_recalcOnContainerChange(changes) {
this.dc.instance._viewContainer.element.nativeElement.style.top = '0px';
this.dc.instance._viewContainer.element.nativeElement.style.left = '0px';
const prevChunkSize = this.state.chunkSize;
this.applyChunkSizeChange();
this._recalcScrollBarSize();
if (prevChunkSize !== this.state.chunkSize) {
this.onChunkLoad.emit(this.state);
}
if (this.sizesCache && this.igxForScrollOrientation === 'horizontal') {
// Updating horizontal chunks and offsets based on the new scrollLeft
const scrollOffset = this.fixedUpdateAllElements(this.scrollPosition);
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
}
}
/**
* @hidden
* Removes an elemenet from the embedded views and updates chunkSize.
*/
removeLastElem() {
const oldElem = this._embeddedViews.pop();
this.onBeforeViewDestroyed.emit(oldElem);
// also detach from ViewContainerRef to make absolutely sure this is removed from the view container.
this.dc.instance._vcr.detach(this.dc.instance._vcr.length - 1);
oldElem.destroy();
this.state.chunkSize--;
}
/**
* @hidden
* If there exists an element that we can create embedded view for creates it, appends it and updates chunkSize
*/
addLastElem() {
let elemIndex = this.state.startIndex + this.state.chunkSize;
if (!this.isRemote && !this.igxForOf) {
return;
}
if (elemIndex >= this.igxForOf.length) {
elemIndex = this.igxForOf.length - this.state.chunkSize;
}
const input = this.igxForOf[elemIndex];
const embeddedView = this.dc.instance._vcr.createEmbeddedView(this._template, new IgxForOfContext(input, this.getContextIndex(input), this.igxForOf.length));
this._embeddedViews.push(embeddedView);
this.state.chunkSize++;
this._zone.run(() => {
this.cdr.markForCheck();
});
}
/**
* Recalculates chunkSize and adds/removes elements if need due to the change.
* this.state.chunkSize is updated in @addLastElem() or @removeLastElem()
*/
applyChunkSizeChange() {
const chunkSize = this.isRemote ? (this.igxForOf ? this.igxForOf.length : 0) : this._calculateChunkSize();
if (chunkSize > this.state.chunkSize) {
const diff = chunkSize - this.state.chunkSize;
for (let i = 0; i < diff; i++) {
this.addLastElem();
}
}
else if (chunkSize < this.state.chunkSize) {
const diff = this.state.chunkSize - chunkSize;
for (let i = 0; i < diff; i++) {
this.removeLastElem();
}
}
}
_updateScrollOffset() {
if (this.igxForScrollOrientation === 'horizontal') {
this._updateHScrollOffset();
}
else {
this._updateVScrollOffset();
}
}
_updateVScrollOffset() {
let scrollOffset = 0;
const vScroll = this.scrollComponent.nativeElement;
scrollOffset = vScroll && this.scrollComponent.size ?
this.scrollPosition - this.sizesCache[this.state.startIndex] : 0;
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
}
_updateHScrollOffset() {
let scrollOffset = 0;
scrollOffset = this.scrollComponent.nativeElement &&
this.scrollComponent.size ?
this.scrollPosition - this.sizesCache[this.state.startIndex] : 0;
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
}
_getItemSize(item, dimension) {
const dim = item[dimension];
return typeof dim === 'number' ? dim : parseInt(this.igxForItemSize, 10) || 0;
}
};
IgxForOfDirective.ctorParameters = () => [
{ type: ViewContainerRef },
{ type: TemplateRef },
{ type: IterableDiffers },
{ type: ComponentFactoryResolver },
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: IgxForOfScrollSyncService }
];
__decorate([
Input(),
__metadata("design:type", Array)
], IgxForOfDirective.prototype, "igxForOf", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForSizePropName", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForScrollOrientation", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForScrollContainer", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForContainerSize", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "igxForItemSize", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onChunkLoad", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onScrollbarVisibilityChanged", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onContentSizeChange", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onDataChanged", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onBeforeViewDestroyed", void 0);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxForOfDirective.prototype, "onChunkPreload", void 0);
__decorate([
Input(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Function])
], IgxForOfDirective.prototype, "igxForTrackBy", null);
IgxForOfDirective = __decorate([
Directive({ selector: '[igxFor][igxForOf]' }),
__metadata("design:paramtypes", [ViewContainerRef,
TemplateRef,
IterableDiffers,
ComponentFactoryResolver,
ChangeDetectorRef,
NgZone,
IgxForOfScrollSyncService])
], IgxForOfDirective);
export { IgxForOfDirective };
export function getTypeNameForDebugging(type) {
const name = 'name';
return type[name] || typeof type;
}
let IgxGridForOfDirective = class IgxGridForOfDirective extends IgxForOfDirective {
constructor(_viewContainer, _template, _differs, resolver, cdr, _zone, syncScrollService, syncService) {
super(_viewContainer, _template, _differs, resolver, cdr, _zone, syncScrollService);
this.syncScrollService = syncScrollService;
this.syncService = syncService;
/**
* @hidden @internal
* An event that is emitted after data has been changed but before the view is refreshed
*/
this.onDataChanging = new EventEmitter();
}
set igxGridForOf(value) {
this.igxForOf = value;
}
get igxGridForOf() {
return this.igxForOf;
}
ngOnInit() {
this.syncService.setMaster(this);
super.ngOnInit();
this.removeScrollEventListeners();
}
ngOnChanges(changes) {
const forOf = 'igxGridForOf';
this.syncService.setMaster(this);
if (forOf in changes) {
const value = changes[forOf].currentValue;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this.igxForTrackBy);
}
catch (e) {
throw new Error(`Cannot find a differ supporting object "${value}" of type "${getTypeNameForDebugging(value)}".
NgFor only supports binding to Iterables such as Arrays.`);
}
}
}
const defaultItemSize = 'igxForItemSize';
if (defaultItemSize in changes && !changes[defaultItemSize].firstChange &&
this.igxForScrollOrientation === 'vertical' && this.igxForOf) {
// handle default item size changed.
this.initSizesCache(this.igxForOf);
}
const containerSize = 'igxForContainerSize';
if (containerSize in changes && !changes[containerSize].firstChange && this.igxForOf) {
this._recalcOnContainerChange(changes);
}
}
/**
* @hidden
* @internal
*/
get sizesCache() {
if (this.syncService.isMaster(this)) {
return this._sizesCache;
}
return this.syncService.sizesCache(this.igxForScrollOrientation);
}
/**
* @hidden
* @internal
*/
set sizesCache(value) {
this._sizesCache = value;
}
get itemsDimension() {
return this.igxForScrollOrientation === 'horizontal' ? this.igxForSizePropName : 'height';
}
getItemSize(item) {
let size = 0;
const dimension = this.igxForScrollOrientation === 'horizontal' ?
this.igxForSizePropName : 'height';
if (dimension === 'height') {
size = parseInt(this.igxForItemSize, 10) || 0;
if (item && item.summaries) {
size = item.max;
}
else if (item && item.groups && item.height) {
size = item.height;
}
}
else {
size = parseInt(item[dimension], 10) || 0;
}
return size;
}
initSizesCache(items) {
if (!this.syncService.isMaster(this)) {
const masterSizesCache = this.syncService.sizesCache(this.igxForScrollOrientation);
return masterSizesCache[masterSizesCache.length - 1];
}
let totalSize = 0;
let size = 0;
let i = 0;
this.sizesCache = [];
this.heightCache = [];
this.sizesCache.push(0);
const count = this.isRemote ? this.totalItemCount : items.length;
for (i; i < count; i++) {
size = this.getItemSize(items[i]);
if (this.itemsDimension === 'height') {
this.heightCache.push(size);
}
totalSize += size;
this.sizesCache.push(totalSize);
}
return totalSize;
}
_updateSizeCache(changes = null) {
if (this.igxForScrollOrientation === 'horizontal') {
this.initSizesCache(this.igxForOf);
return;
}
const oldHeight = this.heightCache.length > 0 ? this.heightCache.reduce((acc, val) => acc + val) : 0;
let newHeight = oldHeight;
if (changes && !this.isRemote) {
newHeight = this.handleCacheChanges(changes);
}
else {
newHeight = this.initSizesCache(this.igxForOf);
}
const diff = oldHeight - newHeight;
// if data has been changed while container is scrolled
// should update scroll top/left according to change so that same startIndex is in view
if (Math.abs(diff) > 0) {
// TODO: This code can be removed. However tests need to be rewritten in a way that they wait for ResizeObserved to complete.
// So leaving as is for the moment.
requestAnimationFrame(() => {
this.recalcUpdateSizes();
const offset = parseInt(this.dc.instance._viewContainer.element.nativeElement.style.top, 10);
if (this.scrollPosition !== 0) {
this.scrollPosition = this.sizesCache[this.state.startIndex] - offset;
}
else {
this._updateScrollOffset();
}
});
}
}
handleCacheChanges(changes) {
const identityChanges = [];
const newHeightCache = [];
const newSizesCache = [];
newSizesCache.push(0);
let newHeight = 0;
// When there are more than one removed items the changes are not reliable so those with identity change should be default size.
let numRemovedItems = 0;
changes.forEachRemovedItem(() => numRemovedItems++);
// Get the identity changes to determine later if those that have changed their indexes should be assigned default item size.
changes.forEachIdentityChange((item) => {
if (item.currentIndex !== item.previousIndex) {
// Filter out ones that have not changed their index.
identityChanges[item.currentIndex] = item;
}
});
// Processing each item that is passed to the igxForOf so far seem to be most reliable. We parse the updated list of items.
changes.forEachItem((item) => {
if (item.previousIndex !== null &&
(numRemovedItems < 2 || !identityChanges.length || identityChanges[item.currentIndex])) {
// Reuse cache on those who have previousIndex.
// When there are more than one removed items currently the changes are not readable so ones with identity change
// should be racalculated.
newHeightCache[item.currentIndex] = this.heightCache[item.previousIndex];
}
else {
// Assign default item size.
newHeightCache[item.currentIndex] = this.getItemSize(item.item);
}
newSizesCache[item.currentIndex + 1] = newSizesCache[item.currentIndex] + newHeightCache[item.currentIndex];
newHeight += newHeightCache[item.currentIndex];
});
this.heightCache = newHeightCache;
this.sizesCache = newSizesCache;
return newHeight;
}
/**
* @hidden
* @internal
*/
assumeMaster() {
this._sizesCache = this.syncService.sizesCache(this.igxForScrollOrientation);
this.syncService.setMaster(this, true);
}
ngDoCheck() {
if (this._differ) {
const changes = this._differ.diff(this.igxForOf);
if (changes) {
const args = {
containerSize: this.igxForContainerSize
};
this.onDataChanging.emit(args);
// re-init cache.
if (!this.igxForOf) {
this.igxForOf = [];
}
/* we need to reset the master dir if all rows are removed
(e.g. because of filtering); if all columns are hidden, rows are
still rendered empty, so we should not reset master */
if (!this.igxForOf.length &&
this.igxForScrollOrientation === 'vertical') {
this.syncService.resetMaster();
}
this.syncService.setMaster(this);
this.igxForContainerSize = args.containerSize;
this._updateSizeCache(changes);
this._applyChanges();
this._updateScrollOffset();
this.onDataChanged.emit();
}
}
}
onScroll(event) {
if (!parseInt(this.scrollComponent.nativeElement.style.height, 10)) {
return;
}
const containerSize = parseInt(this.igxForContainerSize, 10);
const maxRealScrollTop = event.target.children[0].scrollHeight - containerSize;
const realPercentScrolled = maxRealScrollTop !== 0 ? event.target.scrollTop / maxRealScrollTop : 0;
if (!this._bScrollInternal) {
const maxVirtScrollTop = this._virtHeight - containerSize;
this._virtScrollTop = realPercentScrolled * maxVirtScrollTop;
}
else {
this._bScrollInternal = false;
}
const scrollOffset = this.fixedUpdateAllElements(this._virtScrollTop);
this.dc.instance._viewContainer.element.nativeElement.style.top = -(scrollOffset) + 'px';
this._zone.onStable.pipe(first()).subscribe(() => {
this.recalcUpdateSizes();
});
this.cdr.markForCheck();
}
onHScroll(scrollAmount) {
/* in certain situations this may be called when no scrollbar is visible */
if (!this.scrollComponent || !parseInt(this.scrollComponent.nativeElement.children[0].style.width, 10)) {
return;
}
// Updating horizontal chunks
const scrollOffset = this.fixedUpdateAllElements(scrollAmount);
this.dc.instance._viewContainer.element.nativeElement.style.left = -scrollOffset + 'px';
}
addLastElem() {
let elemIndex = this.state.startIndex + this.state.chunkSize;
if (!this.isRemote && !this.igxForOf) {
return;
}
if (elemIndex >= this.igxForOf.length) {
elemIndex = this.igxForOf.length - this.state.chunkSize;
}
const input = this.igxForOf[elemIndex];
const embeddedView = this.dc.instance._vcr.createEmbeddedView(this._template, new IgxForOfContext(input, this.getContextIndex(input), this.igxForOf.length));
this._embeddedViews.push(embeddedView);
this.state.chunkSize++;
}
_updateViews(prevChunkSize) {
if (this.igxForOf && this.igxForOf.length && this.dc) {
const embeddedViewCopy = Object.assign([], this._embeddedViews);
let startIndex;
let endIndex;
if (this.isRemote) {
startIndex = 0;
endIndex = this.igxForOf.length;
}
else {
startIndex = this.getIndexAt(this.scrollPosition, this.sizesCache, 0);
if (startIndex + this.state.chunkSize > this.igxForOf.length) {
startIndex = this.igxForOf.length - this.state.chunkSize;
}
this.state.startIndex = startIndex;
endIndex = this.state.chunkSize + this.state.startIndex;
}
for (let i = startIndex; i < endIndex && this.igxForOf[i] !== undefined; i++) {
const input = this.igxForOf[i];
const embView = embeddedViewCopy.shift();
const cntx = embView.context;
cntx.$implicit = input;
cntx.index = this.getContextIndex(input);
cntx.count = this.igxForOf.length;
}
if (prevChunkSize !== this.state.chunkSize) {
this.onChunkLoad.emit(this.state);
}
}
}
_applyChanges() {
const prevChunkSize = this.state.chunkSize;
this.applyChunkSizeChange();
this._recalcScrollBarSize();
this._updateViews(prevChunkSize);
}
/**
* @hidden
*/
_calcMaxChunkSize() {
if (this.syncService.isMaster(this)) {
return super._calcMaxChunkSize();
}
return this.syncService.chunkSize(this.igxForScrollOrientation);
}
};
IgxGridForOfDirective.ctorParameters = () => [
{ type: ViewContainerRef },
{ type: TemplateRef },
{ type: IterableDiffers },
{ type: ComponentFactoryResolver },
{ type: ChangeDetectorRef },
{ type: NgZone },
{ type: IgxForOfScrollSyncService },
{ type: IgxForOfSyncService }
];
__decorate([
Input(),
__metadata("design:type", Object),
__metadata("design:paramtypes", [Object])
], IgxGridForOfDirective.prototype, "igxGridForOf", null);
__decorate([
Output(),
__metadata("design:type", Object)
], IgxGridForOfDirective.prototype, "onDataChanging", void 0);
IgxGridForOfDirective = __decorate([
Directive({
selector: '[igxGridFor][igxGridForOf]'
}),
__metadata("design:paramtypes", [ViewContainerRef,
TemplateRef,
IterableDiffers,
ComponentFactoryResolver,
ChangeDetectorRef,
NgZone,
IgxForOfScrollSyncService,
IgxForOfSyncService])
], IgxGridForOfDirective);
export { IgxGridForOfDirective };
/**
* @hidden
*/
let IgxForOfModule = class IgxForOfModule {
};
IgxForOfModule = __decorate([
NgModule({
declarations: [IgxForOfDirective, IgxGridForOfDirective, DisplayContainerComponent, VirtualHelperComponent,
HVirtualHelperComponent, VirtualHelperBaseDirective],
entryComponents: [DisplayContainerComponent, VirtualHelperComponent, HVirtualHelperComponent],
exports: [IgxForOfDirective, IgxGridForOfDirective],
imports: [IgxScrollInertiaModule, CommonModule]
})
], IgxForOfModule);
export { IgxForOfModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yX29mLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFlBQVksRUFBa0IsTUFBTSxpQkFBaUIsQ0FBQztBQUMvRCxPQUFPLEVBQ0gsaUJBQWlCLEVBQ2pCLGdCQUFnQixFQUNoQix3QkFBd0IsRUFDeEIsWUFBWSxFQUNaLFNBQVMsRUFDVCxPQUFPLEVBQ1AsZUFBZSxFQUNmLFlBQVksRUFDWixLQUFLLEVBQ0wsZUFBZSxFQUNmLGNBQWMsRUFDZCxlQUFlLEVBQ2YsUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sYUFBYSxFQUNiLFdBQVcsRUFDWCxlQUFlLEVBQ2YsZ0JBQWdCLEVBQ2hCLE9BQU8sRUFDUCxhQUFhLEVBQ2hCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hFLE9BQU8sY0FBYyxNQUFNLDBCQUEwQixDQUFDO0FBRXRELE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxN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QUNwQztRQUNELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFDcEUsQ0FBQztDQUNKLENBQUE7O1lBL1V1QixnQkFBZ0I7WUFDckIsV0FBVztZQUNaLGVBQWU7WUFDZix3QkFBd0I7WUFDN0IsaUJBQWlCO1lBQ2YsTUFBTTtZQUNnQix5QkFBeUI7WUFDL0IsbUJBQW1COztBQUs5QztJQURDLEtBQUssRUFBRTs7O3lEQUdQO0FBV0Q7SUFEQyxNQUFNLEVBQUU7OzZEQUMrRDtBQTVCL0QscUJBQXFCO0lBSGpDLFNBQVMsQ0FBQztRQUNQLFFBQVEsRUFBRSw0QkFBNEI7S0FDekMsQ0FBQztxQ0FJc0IsZ0JBQWdCO1FBQ3JCLFdBQVc7UUFDWixlQUFlO1FBQ2Ysd0JBQXdCO1FBQzdCLGlCQUFpQjtRQUNmLE1BQU07UUFDZ0IseUJBQXlCO1FBQy9CLG1CQUFtQjtHQVZyQyxxQkFBcUIsQ0FrVmpDO1NBbFZZLHFCQUFxQjtBQW9WbEM7O0dBRUc7QUFTSCxJQUFhLGNBQWMsR0FBM0IsTUFBYSxjQUFjO0NBQzFCLENBQUE7QUFEWSxjQUFjO0lBUjFCLFFBQVEsQ0FBQztRQUNOLFlBQVksRUFBRSxDQUFDLGlCQUFpQixFQUFFLHFCQUFxQixFQUFFLHlCQUF5QixFQUFFLHNCQUFzQjtZQUNyRyx1QkFBdUIsRUFBRSwwQkFBMEIsQ0FBQztRQUN6RCxlQUFlLEVBQUUsQ0FBQyx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSx1QkFBdUIsQ0FBQztRQUM3RixPQUFPLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxxQkFBcUIsQ0FBQztRQUNuRCxPQUFPLEVBQUUsQ0FBQyxzQkFBc0IsRUFBRSxZQUFZLENBQUM7S0FDbEQsQ0FBQztHQUVXLGNBQWMsQ0FDMUI7U0FEWSxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBOZ0Zvck9mQ29udGV4dCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICAgIENoYW5nZURldGVjdG9yUmVmLFxuICAgIENvbXBvbmVudEZhY3RvcnksXG4gICAgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgIENvbXBvbmVudFJlZixcbiAgICBEaXJlY3RpdmUsXG4gICAgRG9DaGVjayxcbiAgICBFbWJlZGRlZFZpZXdSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIElucHV0LFxuICAgIEl0ZXJhYmxlQ2hhbmdlcyxcbiAgICBJdGVyYWJsZURpZmZlcixcbiAgICBJdGVyYWJsZURpZmZlcnMsXG4gICAgTmdNb2R1bGUsXG4gICAgTmdab25lLFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT25Jbml0LFxuICAgIE91dHB1dCxcbiAgICBTaW1wbGVDaGFuZ2VzLFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIFRyYWNrQnlGdW5jdGlvbixcbiAgICBWaWV3Q29udGFpbmVyUmVmLFxuICAgIFZpZXdSZWYsXG4gICAgQWZ0ZXJWaWV3SW5pdFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgRGlzcGxheUNvbnRhaW5lckNvbXBvbmVudCB9IGZyb20gJy4vZGlzcGxheS5jb250YWluZXInO1xuaW1wb3J0IHsgSFZpcnR1YWxIZWxwZXJDb21wb25lbnQgfSBmcm9tICcuL2hvcml6b250YWwudmlydHVhbC5oZWxwZXIuY29tcG9uZW50JztcbmltcG9ydCB7IFZpcnR1YWxIZWxwZXJDb21wb25lbnQgfSBmcm9tICcuL3ZpcnR1YWwuaGVscGVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJZ3hTY3JvbGxJbmVydGlhTW9kdWxlIH0gZnJvbSAnLi8uLi9zY3JvbGwtaW5lcnRpYS9zY3JvbGxfaW5lcnRpYS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSWd4Rm9yT2ZTeW5jU2VydmljZSwgSWd4Rm9yT2ZTY3JvbGxTeW5jU2VydmljZSB9IGZyb20gJy4vZm9yX29mLnN5bmMuc2VydmljZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwsIGZpbHRlciwgdGhyb3R0bGVUaW1lLCBmaXJzdCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCBSZXNpemVPYnNlcnZlciBmcm9tICdyZXNpemUtb2JzZXJ2ZXItcG9seWZpbGwnO1xuaW1wb3J0IHsgSUJhc2VFdmVudEFyZ3MgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWxzJztcbmltcG9ydCB7IFZpcnR1YWxIZWxwZXJCYXNlRGlyZWN0aXZlIH0gZnJvbSAnLi9iYXNlLmhlbHBlci5jb21wb25lbnQnO1xuXG4vKipcbiAqICBAcHVibGljQXBpXG4gKi9cbmV4cG9ydCBjbGFzcyBJZ3hGb3JPZkNvbnRleHQ8VD4ge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgIHB1YmxpYyAkaW1wbGljaXQ6IFQsXG4gICAgICAgcHVibGljIGluZGV4OiBudW1iZXIsXG4gICAgICAgcHVibGljIGNvdW50OiBudW1iZXJcbiAgICApIHt9XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIHRoZSBmaXJzdCBvciBub3RcbiAgICAgKi9cbiAgICBnZXQgZmlyc3QoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLmluZGV4ID09PSAwOyB9XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIHRoZSBsYXN0IG9yIG5vdFxuICAgICAqL1xuICAgIGdldCBsYXN0KCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5pbmRleCA9PT0gdGhpcy5jb3VudCAtIDE7IH1cblxuICAgIC8qKlxuICAgICAqIEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZXZlbiBvciBub3RcbiAgICAgKi9cbiAgICBnZXQgZXZlbigpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuaW5kZXggJSAyID09PSAwOyB9XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB3aGV0aGVyIHRoZSBlbGVtZW50IGlzIG9kZCBvciBub3RcbiAgICAgKi9cbiAgICBnZXQgb2RkKCk6IGJvb2xlYW4geyByZXR1cm4gIXRoaXMuZXZlbjsgfVxuXG59XG5cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ1tpZ3hGb3JdW2lneEZvck9mXScgfSlcbmV4cG9ydCBjbGFzcyBJZ3hGb3JPZkRpcmVjdGl2ZTxUPiBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBEb0NoZWNrLCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc2V0cyB0aGUgZGF0YSB0byBiZSByZW5kZXJlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBsZXQtaXRlbSBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGlneEZvck9mOiBhbnlbXTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNldHMgdGhlIHByb3BlcnR5IG5hbWUgZnJvbSB3aGljaCB0byByZWFkIHRoZSBzaXplIGluIHRoZSBkYXRhIG9iamVjdC5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JTaXplUHJvcE5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzcGVjaWZpZXMgdGhlIHNjcm9sbCBvcmllbnRhdGlvbi5cbiAgICAgKiBTY3JvbGwgb3JpZW50YXRpb24gY2FuIGJlIFwidmVydGljYWxcIiBvciBcImhvcml6b250YWxcIi5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBsZXQtaXRlbSBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGlneEZvclNjcm9sbE9yaWVudGF0aW9uID0gJ3ZlcnRpY2FsJztcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbmFsbHkgcGFzcyB0aGUgcGFyZW50IGBpZ3hGb3JgIGluc3RhbmNlIHRvIGNyZWF0ZSBhIHZpcnR1YWwgdGVtcGxhdGUgc2Nyb2xsaW5nIGJvdGggaG9yaXpvbnRhbGx5IGFuZCB2ZXJ0aWNhbGx5LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8bmctdGVtcGxhdGUgI3Njcm9sbENvbnRhaW5lciBpZ3hGb3IgbGV0LXJvd0RhdGEgW2lneEZvck9mXT1cImRhdGFcIlxuICAgICAqICAgICAgIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCIndmVydGljYWwnXCJcbiAgICAgKiAgICAgICBbaWd4Rm9yQ29udGFpbmVyU2l6ZV09XCInNTAwcHgnXCJcbiAgICAgKiAgICAgICBbaWd4Rm9ySXRlbVNpemVdPVwiJzUwcHgnXCJcbiAgICAgKiAgICAgICBsZXQtcm93SW5kZXg9XCJpbmRleFwiPlxuICAgICAqICAgICAgIDxkaXYgW3N0eWxlLmRpc3BsYXldPVwiJ2ZsZXgnXCIgW3N0eWxlLmhlaWdodF09XCInNTBweCdcIj5cbiAgICAgKiAgICAgICAgICAgPG5nLXRlbXBsYXRlICNjaGlsZENvbnRhaW5lciBpZ3hGb3IgbGV0LWl0ZW0gW2lneEZvck9mXT1cImRhdGFcIlxuICAgICAqICAgICAgICAgICAgICAgW2lneEZvclNjcm9sbE9yaWVudGF0aW9uXT1cIidob3Jpem9udGFsJ1wiXG4gICAgICogICAgICAgICAgICAgICBbaWd4Rm9yU2Nyb2xsQ29udGFpbmVyXT1cInBhcmVudFZpcnREaXJcIlxuICAgICAqICAgICAgICAgICAgICAgW2lneEZvckNvbnRhaW5lclNpemVdPVwiJzUwMHB4J1wiPlxuICAgICAqICAgICAgICAgICAgICAgICAgIDxkaXYgW3N0eWxlLm1pbi13aWR0aF09XCInNTBweCdcIj57e3Jvd0luZGV4fX0gOiB7e2l0ZW0udGV4dH19PC9kaXY+XG4gICAgICogICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICogICAgICAgPC9kaXY+XG4gICAgICogPC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JTY3JvbGxDb250YWluZXI6IGFueTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNldHMgdGhlIHB4LWFmZml4ZWQgc2l6ZSBvZiB0aGUgY29udGFpbmVyIGFsb25nIHRoZSBheGlzIG9mIHNjcm9sbGluZy5cbiAgICAgKiBGb3IgXCJob3Jpem9udGFsXCIgb3JpZW50YXRpb24gdGhpcyB2YWx1ZSBpcyB0aGUgd2lkdGggb2YgdGhlIGNvbnRhaW5lciBhbmQgZm9yIFwidmVydGljYWxcIiBpcyB0aGUgaGVpZ2h0LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8bmctdGVtcGxhdGUgaWd4Rm9yIGxldC1pdGVtIFtpZ3hGb3JPZl09XCJkYXRhXCIgW2lneEZvckNvbnRhaW5lclNpemVdPVwiJzUwMHB4J1wiXG4gICAgICogICAgICBbaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb25dPVwiJ2hvcml6b250YWwnXCI+XG4gICAgICogPC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JDb250YWluZXJTaXplOiBhbnk7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzZXRzIHRoZSBweC1hZmZpeGVkIHNpemUgb2YgdGhlIGl0ZW0gYWxvbmcgdGhlIGF4aXMgb2Ygc2Nyb2xsaW5nLlxuICAgICAqIEZvciBcImhvcml6b250YWxcIiBvcmllbnRhdGlvbiB0aGlzIHZhbHVlIGlzIHRoZSB3aWR0aCBvZiB0aGUgY29sdW1uIGFuZCBmb3IgXCJ2ZXJ0aWNhbFwiIGlzIHRoZSBoZWlnaHQgb3IgdGhlIHJvdy5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBsZXQtaXRlbSBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiBbaWd4Rm9ySXRlbVNpemVdPVwiJzUwcHgnXCI+PC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpZ3hGb3JJdGVtU2l6ZTogYW55O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBkYzogQ29tcG9uZW50UmVmPERpc3BsYXlDb250YWluZXJDb21wb25lbnQ+O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGRpcmVjdGl2ZS4gSXQgY29udGFpbnMgYHN0YXJ0SW5kZXhgIGFuZCBgY2h1bmtTaXplYC5cbiAgICAgKiBzdGF0ZS5zdGFydEluZGV4IC0gVGhlIGluZGV4IG9mIHRoZSBpdGVtIGF0IHdoaWNoIHRoZSBjdXJyZW50IHZpc2libGUgY2h1bmsgYmVnaW5zLlxuICAgICAqIHN0YXRlLmNodW5rU2l6ZSAtIFRoZSBudW1iZXIgb2YgaXRlbXMgdGhlIGN1cnJlbnQgdmlzaWJsZSBjaHVuayBob2xkcy5cbiAgICAgKiBUaGVzZSBvcHRpb25zIGNhbiBiZSB1c2VkIHdoZW4gaW1wbGVtZW50aW5nIHJlbW90ZSB2aXJ0dWFsaXphdGlvbiBhcyB0aGV5IHByb3ZpZGUgdGhlIG5lY2Vzc2FyeSBzdGF0ZSBpbmZvcm1hdGlvbi5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY29uc3QgZ3JpZFN0YXRlID0gdGhpcy5wYXJlbnRWaXJ0RGlyLnN0YXRlO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0ZTogSUZvck9mU3RhdGUgPSB7XG4gICAgICAgIHN0YXJ0SW5kZXg6IDAsXG4gICAgICAgIGNodW5rU2l6ZTogMFxuICAgIH07XG4gICAgLyoqXG4gICAgICogVGhlIHRvdGFsIGNvdW50IG9mIHRoZSB2aXJ0dWFsIGRhdGEgaXRlbXMsIHdoZW4gdXNpbmcgcmVtb3RlIHNlcnZpY2UuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci50b3RhbEl0ZW1Db3VudCA9IGRhdGEuQ291bnQ7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHRvdGFsSXRlbUNvdW50OiBudW1iZXIgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIGEgbmV3IGNodW5rIGhhcyBiZWVuIGxvYWRlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiAob25DaHVua0xvYWQpPVwiY2h1bmtMb2FkKCRldmVudClcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjaHVua0xvYWQoZSl7XG4gICAgICogYWxlcnQoXCJjaHVuayBsb2FkZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25DaHVua0xvYWQgPSBuZXcgRXZlbnRFbWl0dGVyPElGb3JPZlN0YXRlPigpO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlbiBAaW50ZXJuYWxcbiAgICAgKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiBzY3JvbGxiYXIgdmlzaWJpbGl0eSBoYXMgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25TY3JvbGxiYXJWaXNpYmlsaXR5Q2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIHRoZSByZW5kZXJlZCBjb250ZW50IHNpemUgb2YgdGhlIGlneEZvck9mIGhhcyBiZWVuIGNoYW5nZWQuXG4gICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Db250ZW50U2l6ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gICAgLyoqXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIGRhdGEgaGFzIGJlZW4gY2hhbmdlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiAob25EYXRhQ2hhbmdlZCk9XCJkYXRhQ2hhbmdlZCgkZXZlbnQpXCI+PC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogZGF0YUNoYW5nZWQoZSl7XG4gICAgICogYWxlcnQoXCJkYXRhIGNoYW5nZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25EYXRhQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uQmVmb3JlVmlld0Rlc3Ryb3llZCA9IG5ldyBFdmVudEVtaXR0ZXI8RW1iZWRkZWRWaWV3UmVmPGFueT4+KCk7XG5cbiAgICAvKipcbiAgICAgKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgb24gY2h1bmsgbG9hZGluZyB0byBlbWl0IHRoZSBjdXJyZW50IHN0YXRlIGluZm9ybWF0aW9uIC0gc3RhcnRJbmRleCwgZW5kSW5kZXgsIHRvdGFsQ291bnQuXG4gICAgICogQ2FuIGJlIHVzZWQgZm9yIGltcGxlbWVudGluZyByZW1vdGUgbG9hZCBvbiBkZW1hbmQgZm9yIHRoZSBpZ3hGb3IgZGF0YS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPG5nLXRlbXBsYXRlIGlneEZvciBbaWd4Rm9yT2ZdPVwiZGF0YVwiIFtpZ3hGb3JTY3JvbGxPcmllbnRhdGlvbl09XCInaG9yaXpvbnRhbCdcIiAob25DaHVua1ByZWxvYWQpPVwiY2h1bmtQcmVsb2FkKCRldmVudClcIj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjaHVua1ByZWxvYWQoZSl7XG4gICAgICogYWxlcnQoXCJjaHVuayBpcyBsb2FkaW5nIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uQ2h1bmtQcmVsb2FkID0gbmV3IEV2ZW50RW1pdHRlcjxJRm9yT2ZTdGF0ZT4oKTtcbiAgICBwcm90ZWN0ZWQgZnVuYztcbiAgICBwcm90ZWN0ZWQgX3NpemVzQ2FjaGU6IG51bWJlcltdID0gW107XG4gICAgcHJvdGVjdGVkIHNjcm9sbENvbXBvbmVudDogVmlydHVhbEhlbHBlckJhc2VEaXJlY3RpdmU7XG4gICAgcHJvdGVjdGVkIF9kaWZmZXI6IEl0ZXJhYmxlRGlmZmVyPFQ+IHwgbnVsbCA9IG51bGw7XG4gICAgcHJvdGVjdGVkIF90cmFja0J5Rm46IFRyYWNrQnlGdW5jdGlvbjxUPjtcbiAgICBwcm90ZWN0ZWQgaGVpZ2h0Q2FjaGUgPSBbXTtcbiAgICBwcml2YXRlIF9hZGp1c3RUb0luZGV4O1xuICAgIHByaXZhdGUgTUFYX1BFUkZfU0NST0xMX0RJRkYgPSA0O1xuXG5cbiAgICBwdWJsaWMgZ2V0IGRpc3BsYXlDb250YWluZXIoKTogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCB2aXJ0dWFsSGVscGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IHNpemVzQ2FjaGUoKTogbnVtYmVyW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2l6ZXNDYWNoZTtcbiAgICB9XG4gICAgcHJvdGVjdGVkIHNldCBzaXplc0NhY2hlKHZhbHVlOiBudW1iZXJbXSkge1xuICAgICAgICB0aGlzLl9zaXplc0NhY2hlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgX2lzU2Nyb2xsZWRUb0JvdHRvbSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdldFNjcm9sbCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzY3JvbGxIZWlnaHQgPSB0aGlzLmdldFNjcm9sbCgpLnNjcm9sbEhlaWdodDtcbiAgICAgICAgLy8gVXNlID09PSBhbmQgbm90ID49IGJlY2F1c2UgYHNjcm9sbFRvcCArIGNvbnRhaW5lciBzaXplYCBjYW4ndCBiZSBiaWdnZXIgdGhhbiBgc2Nyb2xsSGVpZ2h0YCwgdW5sZXNzIHNvbWV0aGluZyBpc24ndCB1cGRhdGVkLlxuICAgICAgICAvLyBBbHNvIHVzZSBNYXRoLnJvdW5kIGJlY2F1c2UgQ2hyb21lIGhhcyBzb21lIGluY29uc2lzdGVuY2llcyBhbmQgYHNjcm9sbFRvcCArIGNvbnRhaW5lcmAgY2FuIGJlIGZsb2F0IHdoZW4gem9vbWluZyB0aGUgcGFnZS5cbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodGhpcy5nZXRTY3JvbGwoKS5zY3JvbGxUb3AgKyB0aGlzLmlneEZvckNvbnRhaW5lclNpemUpID09PSBzY3JvbGxIZWlnaHQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgX2lzQXRCb3R0b21JbmRleCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaWd4Rm9yT2YgJiYgdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5zdGF0ZS5jaHVua1NpemUgPiB0aGlzLmlneEZvck9mLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvLyBTdGFydCBwcm9wZXJ0aWVzIHJlbGF0ZWQgdG8gdmlydHVhbCBoZWlnaHQgaGFuZGxpbmcgZHVlIHRvIGJyb3dzZXIgbGltaXRhdGlvblxuICAgIC8qKiBNYXhpbXVtIGhlaWdodCBmb3IgYW4gZWxlbWVudCBvZiB0aGUgYnJvd3Nlci4gKi9cbiAgICBwcml2YXRlIF9tYXhIZWlnaHQ7XG5cbiAgICAvKiogSGVpZ2h0IHRoYXQgaXMgYmVpbmcgdmlydHVhbGl6ZWQuICovXG4gICAgcHJvdGVjdGVkIF92aXJ0SGVpZ2h0ID0gMDtcblxuICAgIC8qKlxuICAgICAqIFJhdGlvIGZvciBoZWlnaHQgdGhhdCdzIGJlaW5nIHZpcnR1YWxpemFlZCBhbmQgdGhlIG9uZSB2aXNpYmxlXG4gICAgICogSWYgX3ZpcnRIZWlnaHRSYXRpbyA9IDEsIHRoZSB2aXNpYmxlIGhlaWdodCBhbmQgdGhlIHZpcnR1YWxpemVkIGFyZSB0aGUgc2FtZSwgYWxzbyBfbWF4SGVpZ2h0ID4gX3ZpcnRIZWlnaHQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfdmlydEhlaWdodFJhdGlvID0gMTtcblxuICAgIC8qKiBJbnRlcm5hbCB0cmFjayBmb3Igc2Nyb2xsIHRvcCB0aGF0IGlzIGJlaW5nIHZpcnR1YWxpemVkICovXG4gICAgcHJvdGVjdGVkIF92aXJ0U2Nyb2xsVG9wID0gMDtcblxuICAgIC8qKiBJZiB0aGUgbmV4dCBvblNjcm9sbCBldmVudCBpcyB0cmlnZ2VyZWQgZHVlIHRvIGludGVybmFsIHNldHRpbmcgb2Ygc2Nyb2xsVG9wICovXG4gICAgcHJvdGVjdGVkIF9iU2Nyb2xsSW50ZXJuYWwgPSBmYWxzZTtcbiAgICAvLyBFbmQgcHJvcGVydGllcyByZWxhdGVkIHRvIHZpcnR1YWwgaGVpZ2h0IGhhbmRsaW5nXG5cbiAgICBwcm90ZWN0ZWQgX2VtYmVkZGVkVmlld3M6IEFycmF5PEVtYmVkZGVkVmlld1JlZjxhbnk+PiA9IFtdO1xuXG4gICAgcHJvdGVjdGVkIGNvbnRlbnRSZXNpemVOb3RpZnkgPSBuZXcgU3ViamVjdCgpO1xuICAgIHByb3RlY3RlZCBjb250ZW50T2JzZXJ2ZXI6IFJlc2l6ZU9ic2VydmVyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIF92aWV3Q29udGFpbmVyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgICAgICBwcm90ZWN0ZWQgX3RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxOZ0Zvck9mQ29udGV4dDxUPj4sXG4gICAgICAgIHByb3RlY3RlZCBfZGlmZmVyczogSXRlcmFibGVEaWZmZXJzLFxuICAgICAgICBwcml2YXRlIHJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgICAgIHB1YmxpYyBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwcm90ZWN0ZWQgX3pvbmU6IE5nWm9uZSxcbiAgICAgICAgcHJvdGVjdGVkIHN5bmNTY3JvbGxTZXJ2aWNlOiBJZ3hGb3JPZlNjcm9sbFN5bmNTZXJ2aWNlKSB7IH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0IGlzUmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy50b3RhbEl0ZW1Db3VudCAhPT0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEdldHMvU2V0cyB0aGUgc2Nyb2xsIHBvc2l0aW9uLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBjb25zdCBwb3NpdGlvbiA9IGRpcmVjdGl2ZS5zY3JvbGxQb3NpdGlvbjtcbiAgICAgKiBkaXJlY3RpdmUuc2Nyb2xsUG9zaXRpb24gPSB2YWx1ZTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHNjcm9sbFBvc2l0aW9uKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbENvbXBvbmVudC5zY3JvbGxBbW91bnQ7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgc2Nyb2xsUG9zaXRpb24odmFsOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKHZhbCA9PT0gdGhpcy5zY3JvbGxDb21wb25lbnQuc2Nyb2xsQW1vdW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJyAmJiB0aGlzLnNjcm9sbENvbXBvbmVudCkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zY3JvbGxMZWZ0ID0gdmFsO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2Nyb2xsQ29tcG9uZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LnNjcm9sbFRvcCA9IHZhbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVtb3ZlU2Nyb2xsRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuX3pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuZnVuYylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLnZlcnRpY2FsU2Nyb2xsSGFuZGxlcilcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgdmVydGljYWxTY3JvbGxIYW5kbGVyKGV2ZW50KSB7XG4gICAgICAgIHRoaXMub25TY3JvbGwoZXZlbnQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1Njcm9sbGFibGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbENvbXBvbmVudC5zaXplID4gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgbGV0IHRvdGFsU2l6ZSA9IDA7XG4gICAgICAgIGNvbnN0IHZjID0gdGhpcy5pZ3hGb3JTY3JvbGxDb250YWluZXIgPyB0aGlzLmlneEZvclNjcm9sbENvbnRhaW5lci5fdmlld0NvbnRhaW5lciA6IHRoaXMuX3ZpZXdDb250YWluZXI7XG4gICAgICAgIHRoaXMuaWd4Rm9yU2l6ZVByb3BOYW1lID0gdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgfHwgJ3dpZHRoJztcblxuICAgICAgICBjb25zdCBkY0ZhY3Rvcnk6IENvbXBvbmVudEZhY3Rvcnk8RGlzcGxheUNvbnRhaW5lckNvbXBvbmVudD4gPSB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KERpc3BsYXlDb250YWluZXJDb21wb25lbnQpO1xuICAgICAgICB0aGlzLmRjID0gdGhpcy5fdmlld0NvbnRhaW5lci5jcmVhdGVDb21wb25lbnQoZGNGYWN0b3J5LCAwKTtcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5zY3JvbGxEaXJlY3Rpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uO1xuICAgICAgICBpZiAodHlwZW9mIE1TR2VzdHVyZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgLy8gT24gRWRnZSBhbmQgSUUgd2hlbiBzY3JvbGxpbmcgb24gdG91Y2ggdGhlIHBhZ2Ugc2Nyb2xsIGluc3RlYWQgb2YgdGhlIGdyaWQuXG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3VjaEFjdGlvbiA9ICdub25lJztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pZ3hGb3JPZiAmJiB0aGlzLmlneEZvck9mLmxlbmd0aCkge1xuICAgICAgICAgICAgdG90YWxTaXplID0gdGhpcy5pbml0U2l6ZXNDYWNoZSh0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50ID0gdGhpcy5zeW5jU2Nyb2xsU2VydmljZS5nZXRTY3JvbGxNYXN0ZXIodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbik7XG4gICAgICAgICAgICB0aGlzLnN0YXRlLmNodW5rU2l6ZSA9IHRoaXMuX2NhbGN1bGF0ZUNodW5rU2l6ZSgpO1xuICAgICAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5ub3RWaXJ0dWFsID0gISh0aGlzLmlneEZvckNvbnRhaW5lclNpemUgJiYgdGhpcy5zdGF0ZS5jaHVua1NpemUgPCB0aGlzLmlneEZvck9mLmxlbmd0aCk7XG4gICAgICAgICAgICBpZiAodGhpcy5zY3JvbGxDb21wb25lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggPSBNYXRoLm1pbih0aGlzLmdldEluZGV4QXQodGhpcy5zY3JvbGxQb3NpdGlvbiwgdGhpcy5zaXplc0NhY2hlLCAwKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JPZi5sZW5ndGggLSB0aGlzLnN0YXRlLmNodW5rU2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4OyBpIDwgdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5zdGF0ZS5jaHVua1NpemUgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JPZltpXSAhPT0gdW5kZWZpbmVkOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgZW1iZWRkZWRWaWV3ID0gdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmNyZWF0ZUVtYmVkZGVkVmlldyhcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgICAgIG5ldyBJZ3hGb3JPZkNvbnRleHQ8VD4oaW5wdXQsIHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KSwgdGhpcy5pZ3hGb3JPZi5sZW5ndGgpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnB1c2goZW1iZWRkZWRWaWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAnMHB4JztcbiAgICAgICAgICAgIGNvbnN0IGZhY3Rvcnk6IENvbXBvbmVudEZhY3Rvcnk8VmlydHVhbEhlbHBlckNvbXBvbmVudD4gPSB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KFZpcnR1YWxIZWxwZXJDb21wb25lbnQpO1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQgPSB2Yy5jcmVhdGVDb21wb25lbnQoZmFjdG9yeSkuaW5zdGFuY2U7XG4gICAgICAgICAgICB0aGlzLl9tYXhIZWlnaHQgPSB0aGlzLl9jYWxjTWF4QnJvd3NlckhlaWdodCgpO1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQuc2l6ZSA9IHRoaXMuaWd4Rm9yT2YgPyB0aGlzLl9jYWxjSGVpZ2h0KCkgOiAwO1xuICAgICAgICAgICAgdGhpcy5zeW5jU2Nyb2xsU2VydmljZS5zZXRTY3JvbGxNYXN0ZXIodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiwgdGhpcy5zY3JvbGxDb21wb25lbnQpO1xuICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy52ZXJ0aWNhbFNjcm9sbEhhbmRsZXIgPSB0aGlzLnZlcnRpY2FsU2Nyb2xsSGFuZGxlci5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy52ZXJ0aWNhbFNjcm9sbEhhbmRsZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2Uuc2Nyb2xsQ29udGFpbmVyID0gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgZGVzdHJ1Y3RvciA9IHRha2VVbnRpbDxhbnk+KHRoaXMuZGVzdHJveSQpO1xuICAgICAgICAgICAgdGhpcy5jb250ZW50UmVzaXplTm90aWZ5LnBpcGUoZGVzdHJ1Y3RvcixcbiAgICAgICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLmlneEZvckNvbnRhaW5lclNpemUgJiYgdGhpcy5pZ3hGb3JPZiAmJiB0aGlzLmlneEZvck9mLmxlbmd0aCA+IDApLCB0aHJvdHRsZVRpbWUoNDApKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5UYXNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTaXplcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICB0aGlzLmZ1bmMgPSAoZXZ0KSA9PiB7IHRoaXMub25IU2Nyb2xsKGV2dCk7IH07XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudCA9IHRoaXMuc3luY1Njcm9sbFNlcnZpY2UuZ2V0U2Nyb2xsTWFzdGVyKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNjcm9sbENvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh2RmFjdG9yeTogQ29tcG9uZW50RmFjdG9yeTxIVmlydHVhbEhlbHBlckNvbXBvbmVudD4gPVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KEhWaXJ0dWFsSGVscGVyQ29tcG9uZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudCA9IHZjLmNyZWF0ZUNvbXBvbmVudChodkZhY3RvcnkpLmluc3RhbmNlO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgPSB0b3RhbFNpemU7XG4gICAgICAgICAgICAgICAgdGhpcy5zeW5jU2Nyb2xsU2VydmljZS5zZXRTY3JvbGxNYXN0ZXIodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiwgdGhpcy5zY3JvbGxDb21wb25lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuZnVuYyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2Uuc2Nyb2xsQ29udGFpbmVyID0gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5mdW5jKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5zY3JvbGxDb250YWluZXIgPSB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fdXBkYXRlSFNjcm9sbE9mZnNldCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50T2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy5jb250ZW50UmVzaXplTm90aWZ5Lm5leHQoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50T2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlU2Nyb2xsRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgICAgIGlmICh0aGlzLmNvbnRlbnRPYnNlcnZlcikge1xuICAgICAgICAgICAgdGhpcy5jb250ZW50T2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGZvck9mID0gJ2lneEZvck9mJztcbiAgICAgICAgaWYgKGZvck9mIGluIGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY2hhbmdlc1tmb3JPZl0uY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9kaWZmZXIgJiYgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodmFsdWUpLmNyZWF0ZSh0aGlzLmlneEZvclRyYWNrQnkpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYENhbm5vdCBmaW5kIGEgZGlmZmVyIHN1cHBvcnRpbmcgb2JqZWN0IFwiJHt2YWx1ZX1cIiBvZiB0eXBlIFwiJHtnZXRUeXBlTmFtZUZvckRlYnVnZ2luZyh2YWx1ZSl9XCIuXG4gICAgICAgICAgICAgICAgICAgICBOZ0ZvciBvbmx5IHN1cHBvcnRzIGJpbmRpbmcgdG8gSXRlcmFibGVzIHN1Y2ggYXMgQXJyYXlzLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZWZhdWx0SXRlbVNpemUgPSAnaWd4Rm9ySXRlbVNpemUnO1xuICAgICAgICBpZiAoZGVmYXVsdEl0ZW1TaXplIGluIGNoYW5nZXMgJiYgIWNoYW5nZXNbZGVmYXVsdEl0ZW1TaXplXS5maXJzdENoYW5nZSAmJlxuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJyAmJiB0aGlzLmlneEZvck9mKSB7XG4gICAgICAgICAgICAvLyBoYW5kbGUgZGVmYXVsdCBpdGVtIHNpemUgY2hhbmdlZC5cbiAgICAgICAgICAgIHRoaXMuaW5pdFNpemVzQ2FjaGUodGhpcy5pZ3hGb3JPZik7XG4gICAgICAgICAgICB0aGlzLl9hcHBseUNoYW5nZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb250YWluZXJTaXplID0gJ2lneEZvckNvbnRhaW5lclNpemUnO1xuICAgICAgICBpZiAoY29udGFpbmVyU2l6ZSBpbiBjaGFuZ2VzICYmICFjaGFuZ2VzW2NvbnRhaW5lclNpemVdLmZpcnN0Q2hhbmdlICYmIHRoaXMuaWd4Rm9yT2YpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlY2FsY09uQ29udGFpbmVyQ2hhbmdlKGNoYW5nZXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ0RvQ2hlY2soKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl9kaWZmZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLl9kaWZmZXIuZGlmZih0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgLy8gIHJlLWluaXQgY2FjaGUuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlneEZvck9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWd4Rm9yT2YgPSBbXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlU2l6ZUNhY2hlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9hcHBseUNoYW5nZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVNjcm9sbE9mZnNldCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uRGF0YUNoYW5nZWQuZW1pdCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hpZnRzIHRoZSBzY3JvbGwgdGh1bWIgcG9zaXRpb24uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5hZGRTY3JvbGxUb3AoNSk7XG4gICAgICogYGBgXG4gICAgICogQHBhcmFtIGFkZFRvcCBuZWdhdGl2ZSB2YWx1ZSB0byBzY3JvbGwgdXAgYW5kIHBvc2l0aXZlIHRvIHNjcm9sbCBkb3duO1xuICAgICAqL1xuICAgIHB1YmxpYyBhZGRTY3JvbGxUb3AoYWRkVG9wOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKGFkZFRvcCA9PT0gMCAmJiB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcmlnaW5hbFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0U2Nyb2xsVG9wO1xuICAgICAgICBjb25zdCBjb250YWluZXJTaXplID0gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCk7XG4gICAgICAgIGNvbnN0IG1heFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0SGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcblxuICAgICAgICB0aGlzLl9iU2Nyb2xsSW50ZXJuYWwgPSB0cnVlO1xuICAgICAgICB0aGlzLl92aXJ0U2Nyb2xsVG9wICs9IGFkZFRvcDtcbiAgICAgICAgdGhpcy5fdmlydFNjcm9sbFRvcCA9IHRoaXMuX3ZpcnRTY3JvbGxUb3AgPiAwID9cbiAgICAgICAgICAgICh0aGlzLl92aXJ0U2Nyb2xsVG9wIDwgbWF4VmlydFNjcm9sbFRvcCA/IHRoaXMuX3ZpcnRTY3JvbGxUb3AgOiBtYXhWaXJ0U2Nyb2xsVG9wKSA6XG4gICAgICAgICAgICAwO1xuXG4gICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gKz0gYWRkVG9wIC8gdGhpcy5fdmlydEhlaWdodFJhdGlvO1xuICAgICAgICBpZiAoTWF0aC5hYnMoYWRkVG9wIC8gdGhpcy5fdmlydEhlaWdodFJhdGlvKSA8IDEpIHtcbiAgICAgICAgICAgIC8vIEFjdHVhbCBzY3JvbGwgZGVsdGEgdGhhdCB3YXMgYWRkZWQgaXMgc21hbGxlciB0aGFuIDEgYW5kIG9uU2Nyb2xsIGhhbmRsZXIgZG9lc24ndCB0cmlnZ2VyIHdoZW4gc2Nyb2xsaW5nIDwgMXB4XG4gICAgICAgICAgICBjb25zdCBzY3JvbGxPZmZzZXQgPSB0aGlzLmZpeGVkVXBkYXRlQWxsRWxlbWVudHModGhpcy5fdmlydFNjcm9sbFRvcCk7XG4gICAgICAgICAgICAvLyBzY3JvbGxPZmZzZXQgPSBzY3JvbGxPZmZzZXQgIT09IHBhcnNlSW50KHRoaXMuaWd4Rm9ySXRlbVNpemUsIDEwKSA/IHNjcm9sbE9mZnNldCA6IDA7XG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAtKHNjcm9sbE9mZnNldCkgKyAncHgnO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbWF4UmVhbFNjcm9sbFRvcCA9IHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcbiAgICAgICAgaWYgKCh0aGlzLl92aXJ0U2Nyb2xsVG9wID4gMCAmJiB0aGlzLnNjcm9sbFBvc2l0aW9uID09PSAwKSB8fFxuICAgICAgICAgICAgKHRoaXMuX3ZpcnRTY3JvbGxUb3AgPCBtYXhWaXJ0U2Nyb2xsVG9wICYmIHRoaXMuc2Nyb2xsUG9zaXRpb24gPT09IG1heFJlYWxTY3JvbGxUb3ApKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWwgc2Nyb2xsIHBvc2l0aW9uIGlzIGF0IHRoZSB0b3Agb3IgYm90dG9tLCBidXQgdmlydHVhbCBvbmUgaXMgbm90IGF0IHRoZSB0b3Agb3IgYm90dG9tICh0aGVyZSdzIG1vcmUgdG8gc2Nyb2xsKVxuICAgICAgICAgICAgLy8gUmVjYWxjdWxhdGUgYWN0dWFsIHNjcm9sbCBwb3NpdGlvbiBiYXNlZCBvbiB0aGUgdmlydHVhbCBzY3JvbGwuXG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gdGhpcy5fdmlydFNjcm9sbFRvcCAvIHRoaXMuX3ZpcnRIZWlnaHRSYXRpbztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl92aXJ0U2Nyb2xsVG9wID09PSAwICYmIHRoaXMuc2Nyb2xsUG9zaXRpb24gPiAwKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWwgc2Nyb2xsIHBvc2l0aW9uIGlzIG5vdCBhdCB0aGUgdG9wLCBidXQgdmlydHVhbCBzY3JvbGwgaXMuIEp1c3QgdXBkYXRlIHRoZSBhY3R1YWwgc2Nyb2xsXG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gMDtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl92aXJ0U2Nyb2xsVG9wID09PSBtYXhWaXJ0U2Nyb2xsVG9wICYmIHRoaXMuc2Nyb2xsUG9zaXRpb24gPCBtYXhSZWFsU2Nyb2xsVG9wKSB7XG4gICAgICAgICAgICAvLyBBY3R1YWwgc2Nyb2xsIHBvc2l0aW9uIGlzIG5vdCBhdCB0aGUgYm90dG9tLCBidXQgdmlydHVhbCBzY3JvbGwgaXMuIEp1c3QgdXBkYXRlIHRoZSBhY3VhbCBzY3JvbGxcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gPSBtYXhSZWFsU2Nyb2xsVG9wO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl92aXJ0U2Nyb2xsVG9wICE9PSBvcmlnaW5hbFZpcnRTY3JvbGxUb3A7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2Nyb2xscyB0byB0aGUgc3BlY2lmaWVkIGluZGV4LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnBhcmVudFZpcnREaXIuc2Nyb2xsVG8oNSk7XG4gICAgICogYGBgXG4gICAgICogQHBhcmFtIGluZGV4XG4gICAgICovXG4gICAgcHVibGljIHNjcm9sbFRvKGluZGV4KSB7XG4gICAgICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPiAodGhpcy5pc1JlbW90ZSA/IHRoaXMudG90YWxJdGVtQ291bnQgOiB0aGlzLmlneEZvck9mLmxlbmd0aCkgLSAxKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICBjb25zdCBpc1ByZXZJdGVtID0gaW5kZXggPCB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggfHwgdGhpcy5zY3JvbGxQb3NpdGlvbiA+IHRoaXMuc2l6ZXNDYWNoZVtpbmRleF07XG4gICAgICAgIGxldCBuZXh0U2Nyb2xsID0gaXNQcmV2SXRlbSA/IHRoaXMuc2l6ZXNDYWNoZVtpbmRleF0gOiB0aGlzLnNpemVzQ2FjaGVbaW5kZXggKyAxXSAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgIGlmIChuZXh0U2Nyb2xsIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gPSBuZXh0U2Nyb2xsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbWF4VmlydFNjcm9sbFRvcCA9IHRoaXMuX3ZpcnRIZWlnaHQgLSBjb250YWluZXJTaXplO1xuICAgICAgICAgICAgaWYgKG5leHRTY3JvbGwgPiBtYXhWaXJ0U2Nyb2xsVG9wKSB7XG4gICAgICAgICAgICAgICAgbmV4dFNjcm9sbCA9IG1heFZpcnRTY3JvbGxUb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9iU2Nyb2xsSW50ZXJuYWwgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fdmlydFNjcm9sbFRvcCA9IG5leHRTY3JvbGw7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gdGhpcy5fdmlydFNjcm9sbFRvcCAvIHRoaXMuX3ZpcnRIZWlnaHRSYXRpbztcbiAgICAgICAgICAgIHRoaXMuX2FkanVzdFRvSW5kZXggPSAhaXNQcmV2SXRlbSA/IGluZGV4IDogbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjcm9sbHMgYnkgb25lIGl0ZW0gaW50byB0aGUgYXBwcm9wcmlhdGUgbmV4dCBkaXJlY3Rpb24uXG4gICAgICogRm9yIFwiaG9yaXpvbnRhbFwiIG9yaWVudGF0aW9uIHRoYXQgd2lsbCBiZSB0aGUgcmlnaHQgY29sdW1uIGFuZCBmb3IgXCJ2ZXJ0aWNhbFwiIHRoYXQgaXMgdGhlIGxvd2VyIHJvdy5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5wYXJlbnRWaXJ0RGlyLnNjcm9sbE5leHQoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2Nyb2xsTmV4dCgpIHtcbiAgICAgICAgY29uc3Qgc2NyID0gTWF0aC5jZWlsKHRoaXMuc2Nyb2xsUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBlbmRJbmRleCA9IHRoaXMuZ2V0SW5kZXhBdChcbiAgICAgICAgICAgIHNjciArIHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApLFxuICAgICAgICAgICAgdGhpcy5zaXplc0NhY2hlLFxuICAgICAgICAgICAgMFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnNjcm9sbFRvKGVuZEluZGV4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTY3JvbGxzIGJ5IG9uZSBpdGVtIGludG8gdGhlIGFwcHJvcHJpYXRlIHByZXZpb3VzIGRpcmVjdGlvbi5cbiAgICAgKiBGb3IgXCJob3Jpem9udGFsXCIgb3JpZW50YXRpb24gdGhhdCB3aWxsIGJlIHRoZSBsZWZ0IGNvbHVtbiBhbmQgZm9yIFwidmVydGljYWxcIiB0aGF0IGlzIHRoZSB1cHBlciByb3cuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5zY3JvbGxQcmV2KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHNjcm9sbFByZXYoKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG8odGhpcy5zdGF0ZS5zdGFydEluZGV4IC0gMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2Nyb2xscyBieSBvbmUgcGFnZSBpbnRvIHRoZSBhcHByb3ByaWF0ZSBuZXh0IGRpcmVjdGlvbi5cbiAgICAgKiBGb3IgXCJob3Jpem9udGFsXCIgb3JpZW50YXRpb24gdGhhdCB3aWxsIGJlIG9uZSB2aWV3IHRvIHRoZSByaWdodCBhbmQgZm9yIFwidmVydGljYWxcIiB0aGF0IGlzIG9uZSB2aWV3IHRvIHRoZSBib3R0b20uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5zY3JvbGxOZXh0UGFnZSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBzY3JvbGxOZXh0UGFnZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbiArPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYWRkU2Nyb2xsVG9wKHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjcm9sbHMgYnkgb25lIHBhZ2UgaW50byB0aGUgYXBwcm9wcmlhdGUgcHJldmlvdXMgZGlyZWN0aW9uLlxuICAgICAqIEZvciBcImhvcml6b250YWxcIiBvcmllbnRhdGlvbiB0aGF0IHdpbGwgYmUgb25lIHZpZXcgdG8gdGhlIGxlZnQgYW5kIGZvciBcInZlcnRpY2FsXCIgdGhhdCBpcyBvbmUgdmlldyB0byB0aGUgdG9wLlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnBhcmVudFZpcnREaXIuc2Nyb2xsUHJldlBhZ2UoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2Nyb2xsUHJldlBhZ2UoKSB7XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gLT0gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBjb250YWluZXJTaXplID0gKHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApKTtcbiAgICAgICAgICAgIHRoaXMuYWRkU2Nyb2xsVG9wKC1jb250YWluZXJTaXplKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q29sdW1uU2Nyb2xsTGVmdChjb2xJbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zaXplc0NhY2hlW2NvbEluZGV4XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMgdGhhdCBhcmUgZnVsbHkgdmlzaWJsZS5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5wYXJlbnRWaXJ0RGlyLmdldEl0ZW1Db3VudEluVmlldygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRJdGVtQ291bnRJblZpZXcoKSB7XG4gICAgICAgIGxldCBzdGFydEluZGV4ID0gdGhpcy5nZXRJbmRleEF0KFxuICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbixcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZSxcbiAgICAgICAgICAgIDBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHRoaXMuc2Nyb2xsUG9zaXRpb24gLSB0aGlzLnNpemVzQ2FjaGVbc3RhcnRJbmRleF0gPiAwKSB7XG4gICAgICAgICAgICAvLyBmaXNydCBpdGVtIGlzIG5vdCBmdWxseSBpbiB2aWV3XG4gICAgICAgICAgICBzdGFydEluZGV4Kys7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZW5kSW5kZXggPSB0aGlzLmdldEluZGV4QXQoXG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uICsgcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCksXG4gICAgICAgICAgICB0aGlzLnNpemVzQ2FjaGUsXG4gICAgICAgICAgICAwXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBlbmRJbmRleCAtIHN0YXJ0SW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgc2Nyb2xsYmFyIERPTSBlbGVtZW50LlxuICAgICAqIFRoaXMgaXMgZWl0aGVyIGEgdmVydGljYWwgb3IgaG9yaXpvbnRhbCBzY3JvbGxiYXIgZGVwZW5kaW5nIG9uIHRoZSBzcGVjaWZpZWQgaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGRpci5nZXRTY3JvbGwoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U2Nyb2xsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgc2l6ZSBvZiB0aGUgZWxlbWVudCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLnBhcmVudFZpcnREaXIuZ2V0U2l6ZUF0KDEpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTaXplQXQoaW5kZXg6IG51bWJlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zaXplc0NhY2hlW2luZGV4ICsgMV0gLSB0aGlzLnNpemVzQ2FjaGVbaW5kZXhdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNjcm9sbCBvZmZzZXQgb2YgdGhlIGVsZW1lbnQgYXQgdGhlIHNwZWNpZmllZCBpbmRleC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5wYXJlbnRWaXJ0RGlyLmdldFNjcm9sbEZvckluZGV4KDEpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTY3JvbGxGb3JJbmRleChpbmRleDogbnVtYmVyLCBib3R0b20/OiBib29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lclNpemUgPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKTtcbiAgICAgICAgY29uc3Qgc2Nyb2xsID0gYm90dG9tID8gTWF0aC5tYXgoMCwgdGhpcy5zaXplc0NhY2hlW2luZGV4ICsgMV0gLSBjb250YWluZXJTaXplKSA6IHRoaXMuc2l6ZXNDYWNoZVtpbmRleF07XG4gICAgICAgIHJldHVybiBzY3JvbGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIEZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gc2Nyb2xsaW5nIHZlcnRpY2FsbHlcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgb25TY3JvbGwoZXZlbnQpIHtcbiAgICAgICAgLyogaW4gY2VydGFpbiBzaXR1YXRpb25zIHRoaXMgbWF5IGJlIGNhbGxlZCB3aGVuIG5vIHNjcm9sbGJhciBpcyB2aXNpYmxlICovXG4gICAgICAgIGlmICghcGFyc2VJbnQodGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQsIDEwKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICBjb25zdCBtYXhSZWFsU2Nyb2xsVG9wID0gZXZlbnQudGFyZ2V0LmNoaWxkcmVuWzBdLnNjcm9sbEhlaWdodCAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgIGNvbnN0IHJlYWxQZXJjZW50U2Nyb2xsZWQgPSBtYXhSZWFsU2Nyb2xsVG9wICE9PSAwID8gIGV2ZW50LnRhcmdldC5zY3JvbGxUb3AgLyBtYXhSZWFsU2Nyb2xsVG9wIDogMDtcbiAgICAgICAgaWYgKCF0aGlzLl9iU2Nyb2xsSW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0SGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcbiAgICAgICAgICAgIHRoaXMuX3ZpcnRTY3JvbGxUb3AgPSByZWFsUGVyY2VudFNjcm9sbGVkICogbWF4VmlydFNjcm9sbFRvcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2JTY3JvbGxJbnRlcm5hbCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByZXZTdGFydEluZGV4ID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4O1xuICAgICAgICBjb25zdCBzY3JvbGxPZmZzZXQgPSB0aGlzLmZpeGVkVXBkYXRlQWxsRWxlbWVudHModGhpcy5fdmlydFNjcm9sbFRvcCk7XG5cbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudG9wID0gLShzY3JvbGxPZmZzZXQpICsgJ3B4JztcblxuICAgICAgICB0aGlzLmRjLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgaWYgKHByZXZTdGFydEluZGV4ICE9PSB0aGlzLnN0YXRlLnN0YXJ0SW5kZXgpIHtcbiAgICAgICAgICAgIHRoaXMub25DaHVua0xvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCB1cGRhdGVTaXplcygpIHtcbiAgICAgICAgdGhpcy5yZWNhbGNVcGRhdGVTaXplcygpO1xuICAgICAgICB0aGlzLl9hcHBseUNoYW5nZXMoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlU2Nyb2xsT2Zmc2V0KCk7XG4gICAgICAgIHRoaXMub25Db250ZW50U2l6ZUNoYW5nZS5lbWl0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIEZ1bmN0aW9uIHRoYXQgcmVjYWN1bGF0ZXMgYW5kIHVwZGF0ZXMgY2FjaGUgc2l6ZXMuXG4gICAgICovXG4gICAgcHVibGljIHJlY2FsY1VwZGF0ZVNpemVzKCkge1xuICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcgP1xuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICAgICAgY29uc3QgZGlmZnMgPSBbXTtcbiAgICAgICAgbGV0IHRvdGFsRGlmZiA9IDA7XG4gICAgICAgIGNvbnN0IGwgPSB0aGlzLl9lbWJlZGRlZFZpZXdzLmxlbmd0aDtcbiAgICAgICAgY29uc3Qgck5vZGVzID0gdGhpcy5fZW1iZWRkZWRWaWV3cy5tYXAodmlldyA9PlxuICAgICAgICAgICAgdmlldy5yb290Tm9kZXMuZmluZChub2RlID0+IG5vZGUubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFKSB8fCB2aWV3LnJvb3ROb2Rlc1swXS5uZXh0RWxlbWVudFNpYmxpbmcpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgck5vZGUgPSByTm9kZXNbaV07XG4gICAgICAgICAgICBpZiAock5vZGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoID0gck5vZGUub2Zmc2V0SGVpZ2h0IHx8IHBhcnNlSW50KHRoaXMuaWd4Rm9ySXRlbVNpemUsIDEwKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIGk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzUmVtb3RlICYmICF0aGlzLmlneEZvck9mW2luZGV4XSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsID0gZGltZW5zaW9uID09PSAnaGVpZ2h0JyA/IHRoaXMuaGVpZ2h0Q2FjaGVbaW5kZXhdIDogdGhpcy5pZ3hGb3JPZltpbmRleF1bZGltZW5zaW9uXTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdWYWwgPSBkaW1lbnNpb24gPT09ICdoZWlnaHQnID8gaCA6IHJOb2RlLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgICAgIGlmIChkaW1lbnNpb24gPT09ICdoZWlnaHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0Q2FjaGVbaW5kZXhdID0gbmV3VmFsO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWd4Rm9yT2ZbaW5kZXhdW2RpbWVuc2lvbl0gPSBuZXdWYWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJEaWZmID0gbmV3VmFsIC0gb2xkVmFsO1xuICAgICAgICAgICAgICAgIGRpZmZzLnB1c2goY3VyckRpZmYpO1xuICAgICAgICAgICAgICAgIHRvdGFsRGlmZiArPSBjdXJyRGlmZjtcbiAgICAgICAgICAgICAgICB0aGlzLnNpemVzQ2FjaGVbaW5kZXggKyAxXSArPSB0b3RhbERpZmY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gdXBkYXRlIGNhY2hlXG4gICAgICAgIGlmIChNYXRoLmFicyh0b3RhbERpZmYpID4gMCkge1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIHRoaXMuc3RhdGUuY2h1bmtTaXplICsgMTsgaiA8IHRoaXMuc2l6ZXNDYWNoZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZVtqXSArPSB0b3RhbERpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSBzY3JCYXIgaGVpZ2h0cy93aWR0aHNcbiAgICAgICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0b3RhbFdpZHRoID0gcGFyc2VJbnQodGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5jaGlsZHJlblswXS5zdHlsZS53aWR0aCwgMTApICsgdG90YWxEaWZmO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW5bMF0uc3R5bGUud2lkdGggPSB0b3RhbFdpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlZHVjZXIgPSAoYWNjLCB2YWwpID0+IGFjYyArIHZhbDtcbiAgICAgICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NyVG9Cb3R0b20gPSB0aGlzLl9pc1Njcm9sbGVkVG9Cb3R0b20gJiYgIXRoaXMuZGMuaW5zdGFuY2Uubm90VmlydHVhbDtcbiAgICAgICAgICAgICAgICBjb25zdCBoU3VtID0gdGhpcy5oZWlnaHRDYWNoZS5yZWR1Y2UocmVkdWNlcik7XG4gICAgICAgICAgICAgICAgaWYgKGhTdW0gPiB0aGlzLl9tYXhIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmlydEhlaWdodFJhdGlvID0gaFN1bSAvIHRoaXMuX21heEhlaWdodDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQuc2l6ZSA9IE1hdGgubWluKHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgKyB0b3RhbERpZmYsIHRoaXMuX21heEhlaWdodCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmlydEhlaWdodCA9IGhTdW07XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnNjcm9sbENvbXBvbmVudC5kZXN0cm95ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNjclRvQm90dG9tICYmICF0aGlzLl9pc0F0Qm90dG9tSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhWaXJ0U2Nyb2xsVG9wID0gdGhpcy5fdmlydEhlaWdodCAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2JTY3JvbGxJbnRlcm5hbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3ZpcnRTY3JvbGxUb3AgPSBtYXhWaXJ0U2Nyb2xsVG9wO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gbWF4VmlydFNjcm9sbFRvcDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fYWRqdXN0VG9JbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpbiBjYXNlIHNjcm9sbGVkIHRvIHNwZWNpZmljIGluZGV4IHdoZXJlIGFmdGVyIHNjcm9sbCBoZWlnaHRzIGFyZSBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgICAgIC8vIG5lZWQgdG8gYWRqdXN0IHRoZSBvZmZzZXRzIHNvIHRoYXQgaXRlbSBpcyBsYXN0IGluIHZpZXcuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVwZGF0ZXNUb0luZGV4ID0gdGhpcy5fYWRqdXN0VG9JbmRleCAtIHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1bURpZmZzID0gZGlmZnMuc2xpY2UoMCwgdXBkYXRlc1RvSW5kZXgpLnJlZHVjZShyZWR1Y2VyKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3Vyck9mZnNldCA9IHBhcnNlSW50KHRoaXMuZGMuaW5zdGFuY2UuX3ZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRvcCwgMTApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAoY3Vyck9mZnNldCAtIHN1bURpZmZzKSArICdweCc7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkanVzdFRvSW5kZXggPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZml4ZWRVcGRhdGVBbGxFbGVtZW50cyhpblNjcm9sbFRvcDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmlzUmVtb3RlID8gdGhpcy50b3RhbEl0ZW1Db3VudCA6IHRoaXMuaWd4Rm9yT2YubGVuZ3RoO1xuICAgICAgICBsZXQgbmV3U3RhcnQgPSB0aGlzLmdldEluZGV4QXQoXG4gICAgICAgICAgICBpblNjcm9sbFRvcCxcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZSxcbiAgICAgICAgICAgIDBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKG5ld1N0YXJ0ICsgdGhpcy5zdGF0ZS5jaHVua1NpemUgPiBjb3VudCkge1xuICAgICAgICAgICAgbmV3U3RhcnQgPSBjb3VudCAtIHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByZXZTdGFydCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleDtcbiAgICAgICAgY29uc3QgZGlmZiA9IG5ld1N0YXJ0IC0gdGhpcy5zdGF0ZS5zdGFydEluZGV4O1xuICAgICAgICB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggPSBuZXdTdGFydDtcbiAgICAgICAgaWYgKGRpZmYpIHtcbiAgICAgICAgICAgIHRoaXMub25DaHVua1ByZWxvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgICAgIC8qcmVjYWxjdWxhdGUgYW5kIGFwcGx5IHBhZ2Ugc2l6ZS4qL1xuICAgICAgICAgICAgICAgIGlmIChkaWZmID4gMCAmJiBkaWZmIDw9IHRoaXMuTUFYX1BFUkZfU0NST0xMX0RJRkYpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlQXBwbHlTY3JvbGxOZXh0KHByZXZTdGFydCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkaWZmIDwgMCAmJiBNYXRoLmFicyhkaWZmKSA8PSB0aGlzLk1BWF9QRVJGX1NDUk9MTF9ESUZGKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubW92ZUFwcGx5U2Nyb2xsUHJldihwcmV2U3RhcnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZml4ZWRBcHBseVNjcm9sbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW5TY3JvbGxUb3AgLSB0aGlzLnNpemVzQ2FjaGVbdGhpcy5zdGF0ZS5zdGFydEluZGV4XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogVGhlIGZ1bmN0aW9uIGFwcGxpZXMgYW4gb3B0aW1pemVkIHN0YXRlIGNoYW5nZSBmb3Igc2Nyb2xsaW5nIGRvd24vcmlnaHQgZW1wbG95aW5nIGNvbnRleHQgY2hhbmdlIHdpdGggdmlldyByZWFycmFuZ2VtZW50XG4gICAgICovXG4gICAgcHJvdGVjdGVkIG1vdmVBcHBseVNjcm9sbE5leHQocHJldkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc3RhcnQgPSBwcmV2SW5kZXggKyB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgc3RhcnQgKyB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggLSBwcmV2SW5kZXggJiYgdGhpcy5pZ3hGb3JPZltpXSAhPT0gdW5kZWZpbmVkOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGlucHV0ID0gdGhpcy5pZ3hGb3JPZltpXTtcbiAgICAgICAgICAgIGNvbnN0IGVtYlZpZXcgPSB0aGlzLl9lbWJlZGRlZFZpZXdzLnNoaWZ0KCk7XG4gICAgICAgICAgICBjb25zdCBjbnR4ID0gZW1iVmlldy5jb250ZXh0O1xuICAgICAgICAgICAgY250eC4kaW1wbGljaXQgPSBpbnB1dDtcbiAgICAgICAgICAgIGNudHguaW5kZXggPSB0aGlzLmdldENvbnRleHRJbmRleChpbnB1dCk7XG4gICAgICAgICAgICBjbnR4LmNvdW50ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCB2aWV3OiBWaWV3UmVmID0gdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmRldGFjaCgwKTtcbiAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5pbnNlcnQodmlldyk7XG4gICAgICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnB1c2goZW1iVmlldyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogVGhlIGZ1bmN0aW9uIGFwcGxpZXMgYW4gb3B0aW1pemVkIHN0YXRlIGNoYW5nZSBmb3Igc2Nyb2xsaW5nIHVwL2xlZnQgZW1wbG95aW5nIGNvbnRleHQgY2hhbmdlIHdpdGggdmlldyByZWFycmFuZ2VtZW50XG4gICAgICovXG4gICAgcHJvdGVjdGVkIG1vdmVBcHBseVNjcm9sbFByZXYocHJldkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IHByZXZJbmRleCAtIDE7IGkgPj0gdGhpcy5zdGF0ZS5zdGFydEluZGV4ICYmIHRoaXMuaWd4Rm9yT2ZbaV0gIT09IHVuZGVmaW5lZDsgaS0tKSB7XG4gICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICBjb25zdCBlbWJWaWV3ID0gdGhpcy5fZW1iZWRkZWRWaWV3cy5wb3AoKTtcbiAgICAgICAgICAgIGNvbnN0IGNudHggPSBlbWJWaWV3LmNvbnRleHQ7XG4gICAgICAgICAgICBjbnR4LiRpbXBsaWNpdCA9IGlucHV0O1xuICAgICAgICAgICAgY250eC5pbmRleCA9IHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KTtcbiAgICAgICAgICAgIGNvbnN0IHZpZXc6IFZpZXdSZWYgPSB0aGlzLmRjLmluc3RhbmNlLl92Y3IuZGV0YWNoKHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5pbnNlcnQodmlldywgMCk7XG4gICAgICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnVuc2hpZnQoZW1iVmlldyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0Q29udGV4dEluZGV4KGlucHV0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzUmVtb3RlID8gdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5pZ3hGb3JPZi5pbmRleE9mKGlucHV0KSA6IHRoaXMuaWd4Rm9yT2YuaW5kZXhPZihpbnB1dCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIFRoZSBmdW5jdGlvbiBhcHBsaWVzIGFuIG9wdGltaXplZCBzdGF0ZSBjaGFuZ2UgdGhyb3VnaCBjb250ZXh0IGNoYW5nZSBmb3IgZWFjaCB2aWV3XG4gICAgICovXG4gICAgcHJvdGVjdGVkIGZpeGVkQXBwbHlTY3JvbGwoKTogdm9pZCB7XG4gICAgICAgIGxldCBqID0gMDtcbiAgICAgICAgY29uc3QgZW5kSW5kZXggPSB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggKyB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleDsgaSA8IGVuZEluZGV4ICYmIHRoaXMuaWd4Rm9yT2ZbaV0gIT09IHVuZGVmaW5lZDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICBjb25zdCBlbWJWaWV3ID0gdGhpcy5fZW1iZWRkZWRWaWV3c1tqKytdO1xuICAgICAgICAgICAgY29uc3QgY250eCA9IChlbWJWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5jb250ZXh0O1xuICAgICAgICAgICAgY250eC4kaW1wbGljaXQgPSBpbnB1dDtcbiAgICAgICAgICAgIGNudHguaW5kZXggPSB0aGlzLmdldENvbnRleHRJbmRleChpbnB1dCk7XG4gICAgICAgICAgICBjbnR4LmNvdW50ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiBzY3JvbGxpbmcgaG9yaXpvbnRhbGx5XG4gICAgICovXG4gICAgcHJvdGVjdGVkIG9uSFNjcm9sbChldmVudCkge1xuICAgICAgICAvKiBpbiBjZXJ0YWluIHNpdHVhdGlvbnMgdGhpcyBtYXkgYmUgY2FsbGVkIHdoZW4gbm8gc2Nyb2xsYmFyIGlzIHZpc2libGUgKi9cbiAgICAgICAgaWYgKCFwYXJzZUludCh0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LmNoaWxkcmVuWzBdLnN0eWxlLndpZHRoLCAxMCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcmV2U3RhcnRJbmRleCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleDtcbiAgICAgICAgLy8gVXBkYXRpbmcgaG9yaXpvbnRhbCBjaHVua3NcbiAgICAgICAgY29uc3Qgc2Nyb2xsT2Zmc2V0ID0gdGhpcy5maXhlZFVwZGF0ZUFsbEVsZW1lbnRzKGV2ZW50LnRhcmdldC5zY3JvbGxMZWZ0KTtcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9IC1zY3JvbGxPZmZzZXQgKyAncHgnO1xuXG4gICAgICAgIHRoaXMuZGMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICBpZiAocHJldlN0YXJ0SW5kZXggIT09IHRoaXMuc3RhdGUuc3RhcnRJbmRleCkge1xuICAgICAgICAgICAgdGhpcy5vbkNodW5rTG9hZC5lbWl0KHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZnVuY3Rpb24gdXNlZCB0byB0cmFjayBjaGFuZ2VzIGluIHRoZSBpdGVtcyBjb2xsZWN0aW9uLlxuICAgICAqIEJ5IGRlZmF1bHQgdGhlIG9iamVjdCByZWZlcmVuY2VzIGFyZSBjb21wYXJlZC4gSG93ZXZlciB0aGlzIGNhbiBiZSBvcHRpbWl6ZWQgaWYgeW91IGhhdmUgdW5pcXVlIGlkZW50aWZpZXJcbiAgICAgKiB2YWx1ZSB0aGF0IGNhbiBiZSB1c2VkIGZvciB0aGUgY29tcGFyaXNvbiBpbnN0ZWFkIG9mIHRoZSBvYmplY3QgcmVmIG9yIGlmIHlvdSBoYXZlIHNvbWUgb3RoZXIgcHJvcGVydHkgdmFsdWVzXG4gICAgICogaW4gdGhlIGl0ZW0gb2JqZWN0IHRoYXQgc2hvdWxkIGJlIHRyYWNrZWQgZm9yIGNoYW5nZXMuXG4gICAgICogVGhpcyBvcHRpb24gaXMgc2ltaWxhciB0byBuZ0ZvclRyYWNrQnkuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNvbnN0IHRyYWNrRnVuYyA9IHRoaXMucGFyZW50VmlydERpci5pZ3hGb3JUcmFja0J5O1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGlneEZvclRyYWNrQnkoKTogVHJhY2tCeUZ1bmN0aW9uPFQ+IHsgcmV0dXJuIHRoaXMuX3RyYWNrQnlGbjsgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgZnVuY3Rpb24gdXNlZCB0byB0cmFjayBjaGFuZ2VzIGluIHRoZSBpdGVtcyBjb2xsZWN0aW9uLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY2FuIGJlIHNldCBpbiBzY2VuYXJpb3Mgd2hlcmUgeW91IHdhbnQgdG8gb3B0aW1pemUgb3JcbiAgICAgKiBjdXN0b21pemUgdGhlIHRyYWNraW5nIG9mIGNoYW5nZXMgZm9yIHRoZSBpdGVtcyBpbiB0aGUgY29sbGVjdGlvbi5cbiAgICAgKiBUaGUgaWd4Rm9yVHJhY2tCeSBmdW5jdGlvbiB0YWtlcyB0aGUgaW5kZXggYW5kIHRoZSBjdXJyZW50IGl0ZW0gYXMgYXJndW1lbnRzIGFuZCBuZWVkcyB0byByZXR1cm4gdGhlIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGlzIGl0ZW0uXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMucGFyZW50VmlydERpci5pZ3hGb3JUcmFja0J5ID0gKGluZGV4LCBpdGVtKSA9PiB7XG4gICAgICogICAgICByZXR1cm4gaXRlbS5pZCArIGl0ZW0ud2lkdGg7XG4gICAgICogfTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBzZXQgaWd4Rm9yVHJhY2tCeShmbjogVHJhY2tCeUZ1bmN0aW9uPFQ+KSB7IHRoaXMuX3RyYWNrQnlGbiA9IGZuOyB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9hcHBseUNoYW5nZXMoKSB7XG4gICAgICAgIGNvbnN0IHByZXZDaHVua1NpemUgPSB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgdGhpcy5hcHBseUNodW5rU2l6ZUNoYW5nZSgpO1xuICAgICAgICB0aGlzLl9yZWNhbGNTY3JvbGxCYXJTaXplKCk7XG4gICAgICAgIGlmICh0aGlzLmlneEZvck9mICYmIHRoaXMuaWd4Rm9yT2YubGVuZ3RoICYmIHRoaXMuZGMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVtYmVkZGVkVmlld0NvcHkgPSBPYmplY3QuYXNzaWduKFtdLCB0aGlzLl9lbWJlZGRlZFZpZXdzKTtcbiAgICAgICAgICAgIGxldCBzdGFydEluZGV4ID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4O1xuICAgICAgICAgICAgbGV0IGVuZEluZGV4ID0gdGhpcy5zdGF0ZS5jaHVua1NpemUgKyB0aGlzLnN0YXRlLnN0YXJ0SW5kZXg7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGVuZEluZGV4ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleDsgaSA8IGVuZEluZGV4ICYmIHRoaXMuaWd4Rm9yT2ZbaV0gIT09IHVuZGVmaW5lZDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlneEZvck9mW2ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVtYlZpZXcgPSBlbWJlZGRlZFZpZXdDb3B5LnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY250eCA9IChlbWJWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5jb250ZXh0O1xuICAgICAgICAgICAgICAgIGNudHguJGltcGxpY2l0ID0gaW5wdXQ7XG4gICAgICAgICAgICAgICAgY250eC5pbmRleCA9IHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KTtcbiAgICAgICAgICAgICAgICBjbnR4LmNvdW50ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJldkNodW5rU2l6ZSAhPT0gdGhpcy5zdGF0ZS5jaHVua1NpemUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ2h1bmtMb2FkLmVtaXQodGhpcy5zdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9jYWxjTWF4QnJvd3NlckhlaWdodCgpOiBudW1iZXIge1xuICAgICAgICBjb25zdCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBkaXYuc3R5bGU7XG4gICAgICAgIHN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgc3R5bGUudG9wID0gJzk5OTk5OTk5OTk5OTk5OTlweCc7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZGl2KTtcbiAgICAgICAgY29uc3Qgc2l6ZSA9IE1hdGguYWJzKGRpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVsndG9wJ10pO1xuICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGRpdik7XG4gICAgICAgIHJldHVybiBzaXplO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBSZWNhbGN1bGF0ZXMgdGhlIGNodW5rU2l6ZSBiYXNlZCBvbiBjdXJyZW50IHN0YXJ0SW5kZXggYW5kIHJldHVybnMgdGhlIG5ldyBzaXplLlxuICAgICAqIFRoaXMgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggaXMgdXBkYXRlZCwgbm90IGJlZm9yZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgX2NhbGN1bGF0ZUNodW5rU2l6ZSgpOiBudW1iZXIge1xuICAgICAgICBsZXQgY2h1bmtTaXplID0gMDtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSAhPT0gbnVsbCAmJiB0aGlzLmlneEZvckNvbnRhaW5lclNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNpemVzQ2FjaGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2h1bmtTaXplID0gdGhpcy5fY2FsY01heENodW5rU2l6ZSgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaWd4Rm9yT2YgJiYgY2h1bmtTaXplID4gdGhpcy5pZ3hGb3JPZi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjaHVua1NpemUgPSB0aGlzLmlneEZvck9mLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlneEZvck9mKSB7XG4gICAgICAgICAgICAgICAgY2h1bmtTaXplID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNodW5rU2l6ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGdldEVsZW1lbnQodmlld3JlZiwgbm9kZU5hbWUpIHtcbiAgICAgICAgY29uc3QgZWxlbSA9IHZpZXdyZWYuZWxlbWVudC5uYXRpdmVFbGVtZW50LnBhcmVudE5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUobm9kZU5hbWUpO1xuICAgICAgICByZXR1cm4gZWxlbS5sZW5ndGggPiAwID8gZWxlbVswXSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBpbml0U2l6ZXNDYWNoZShpdGVtczogYW55W10pOiBudW1iZXIge1xuICAgICAgICBsZXQgdG90YWxTaXplID0gMDtcbiAgICAgICAgbGV0IHNpemUgPSAwO1xuICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcgP1xuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICB0aGlzLnNpemVzQ2FjaGUgPSBbXTtcbiAgICAgICAgdGhpcy5oZWlnaHRDYWNoZSA9IFtdO1xuICAgICAgICB0aGlzLnNpemVzQ2FjaGUucHVzaCgwKTtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmlzUmVtb3RlID8gdGhpcy50b3RhbEl0ZW1Db3VudCA6IGl0ZW1zLmxlbmd0aDtcbiAgICAgICAgZm9yIChpOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgaWYgKGRpbWVuc2lvbiA9PT0gJ2hlaWdodCcpIHtcbiAgICAgICAgICAgICAgICAvLyBjb2xzW2ldW2RpbWVuc2lvbl0gPSBwYXJzZUludCh0aGlzLmlneEZvckl0ZW1TaXplLCAxMCkgfHwgMDtcbiAgICAgICAgICAgICAgICBzaXplID0gcGFyc2VJbnQodGhpcy5pZ3hGb3JJdGVtU2l6ZSwgMTApIHx8IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWlnaHRDYWNoZS5wdXNoKHNpemUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaXplID0gdGhpcy5fZ2V0SXRlbVNpemUoaXRlbXNbaV0sIGRpbWVuc2lvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b3RhbFNpemUgKz0gc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZS5wdXNoKHRvdGFsU2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvdGFsU2l6ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVNpemVDYWNoZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgdGhpcy5pbml0U2l6ZXNDYWNoZSh0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSB0aGlzLmhlaWdodENhY2hlLmxlbmd0aCA+IDAgPyB0aGlzLmhlaWdodENhY2hlLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCkgOiAwO1xuICAgICAgICBjb25zdCBuZXdIZWlnaHQgPSB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuXG4gICAgICAgIGNvbnN0IGRpZmYgPSBvbGRIZWlnaHQgLSBuZXdIZWlnaHQ7XG5cbiAgICAgICAgLy8gaWYgZGF0YSBoYXMgYmVlbiBjaGFuZ2VkIHdoaWxlIGNvbnRhaW5lciBpcyBzY3JvbGxlZFxuICAgICAgICAvLyBzaG91bGQgdXBkYXRlIHNjcm9sbCB0b3AvbGVmdCBhY2NvcmRpbmcgdG8gY2hhbmdlIHNvIHRoYXQgc2FtZSBzdGFydEluZGV4IGlzIGluIHZpZXdcbiAgICAgICAgaWYgKE1hdGguYWJzKGRpZmYpID4gMCAmJiB0aGlzLnNjcm9sbFBvc2l0aW9uID4gMCkge1xuICAgICAgICAgICAgdGhpcy5yZWNhbGNVcGRhdGVTaXplcygpO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gcGFyc2VJbnQodGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudG9wLCAxMCk7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gdGhpcy5zaXplc0NhY2hlW3RoaXMuc3RhdGUuc3RhcnRJbmRleF0gLSBvZmZzZXQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9jYWxjTWF4Q2h1bmtTaXplKCk6IG51bWJlciB7XG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgbGV0IGxlbmd0aCA9IDA7XG4gICAgICAgIGxldCBtYXhMZW5ndGggPSAwO1xuICAgICAgICBjb25zdCBhcnIgPSBbXTtcbiAgICAgICAgbGV0IHN1bSA9IDA7XG4gICAgICAgIGNvbnN0IGF2YWlsYWJsZVNpemUgPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKTtcbiAgICAgICAgaWYgKCFhdmFpbGFibGVTaXplKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkaW1lbnNpb24gPSB0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcgP1xuICAgICAgICAgICAgdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICAgICAgY29uc3QgcmVkdWNlciA9IChhY2N1bXVsYXRvciwgY3VycmVudEl0ZW0pID0+IGFjY3VtdWxhdG9yICsgdGhpcy5fZ2V0SXRlbVNpemUoY3VycmVudEl0ZW0sIGRpbWVuc2lvbik7XG4gICAgICAgIGZvciAoaTsgaSA8IHRoaXMuaWd4Rm9yT2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBpdGVtID0gdGhpcy5pZ3hGb3JPZltpXTtcbiAgICAgICAgICAgIGlmIChkaW1lbnNpb24gPT09ICdoZWlnaHQnKSB7XG4gICAgICAgICAgICAgICAgaXRlbSA9IHsgdmFsdWU6IHRoaXMuaWd4Rm9yT2ZbaV0sIGhlaWdodDogdGhpcy5oZWlnaHRDYWNoZVtpXSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGRpbWVuc2lvbiA9PT0gJ2hlaWdodCcgP1xuICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0Q2FjaGVbaV0gOlxuICAgICAgICAgICAgICAgIHRoaXMuX2dldEl0ZW1TaXplKGl0ZW0sIGRpbWVuc2lvbik7XG4gICAgICAgICAgICBzdW0gPSBhcnIucmVkdWNlKHJlZHVjZXIsIHNpemUpO1xuICAgICAgICAgICAgaWYgKHN1bSA8IGF2YWlsYWJsZVNpemUpIHtcbiAgICAgICAgICAgICAgICBhcnIucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICBsZW5ndGggPSBhcnIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmIChpID09PSB0aGlzLmlneEZvck9mLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVhY2hlZCBlbmQgd2l0aG91dCBleGNlZWRpbmdcbiAgICAgICAgICAgICAgICAgICAgLy8gaW5jbHVkZSBwcmV2IGl0ZW1zIHVudGlsIHNpemUgaXMgZmlsbGVkIG9yIGZpcnN0IGl0ZW0gaXMgcmVhY2hlZC5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGN1ckl0ZW0gPSBkaW1lbnNpb24gPT09ICdoZWlnaHQnID8gYXJyWzBdLnZhbHVlIDogYXJyWzBdO1xuICAgICAgICAgICAgICAgICAgICBsZXQgcHJldkluZGV4ID0gdGhpcy5pZ3hGb3JPZi5pbmRleE9mKGN1ckl0ZW0pIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHByZXZJbmRleCA+PSAwICYmIHN1bSA8PSBhdmFpbGFibGVTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJJdGVtID0gZGltZW5zaW9uID09PSAnaGVpZ2h0JyA/IGFyclswXS52YWx1ZSA6IGFyclswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZJbmRleCA9IHRoaXMuaWd4Rm9yT2YuaW5kZXhPZihjdXJJdGVtKSAtIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwcmV2SXRlbSA9IHRoaXMuaWd4Rm9yT2ZbcHJldkluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZTaXplID0gZGltZW5zaW9uID09PSAnaGVpZ2h0JyA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oZWlnaHRDYWNoZVtwcmV2SW5kZXhdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJzZUludChwcmV2SXRlbVtkaW1lbnNpb25dLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdW0gPSBhcnIucmVkdWNlKHJlZHVjZXIsIHByZXZTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyci51bnNoaWZ0KHByZXZJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA9IGFyci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFyci5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgICAgIGxlbmd0aCA9IGFyci5sZW5ndGggKyAxO1xuICAgICAgICAgICAgICAgIGFyci5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxlbmd0aCA+IG1heExlbmd0aCkge1xuICAgICAgICAgICAgICAgIG1heExlbmd0aCA9IGxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWF4TGVuZ3RoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0SW5kZXhBdChsZWZ0LCBzZXQsIGluZGV4KSB7XG4gICAgICAgIGxldCBzdGFydCA9IDA7XG4gICAgICAgIGxldCBlbmQgPSBzZXQubGVuZ3RoIC0gMTtcbiAgICAgICAgaWYgKGxlZnQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChzdGFydCA8PSBlbmQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1pZElkeCA9IE1hdGguZmxvb3IoKHN0YXJ0ICsgZW5kKSAvIDIpO1xuICAgICAgICAgICAgY29uc3QgbWlkTGVmdCA9IHNldFttaWRJZHhdO1xuICAgICAgICAgICAgY29uc3QgY21wID0gbGVmdCAtIG1pZExlZnQ7XG4gICAgICAgICAgICBpZiAoY21wID4gMCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gbWlkSWR4ICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY21wIDwgMCkge1xuICAgICAgICAgICAgICAgIGVuZCA9IG1pZElkeCAtIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtaWRJZHg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVuZDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3JlY2FsY1Njcm9sbEJhclNpemUoKSB7XG4gICAgICAgIGNvbnN0IGNvdW50ID0gdGhpcy5pc1JlbW90ZSA/IHRoaXMudG90YWxJdGVtQ291bnQgOiAodGhpcy5pZ3hGb3JPZiA/IHRoaXMuaWd4Rm9yT2YubGVuZ3RoIDogMCk7XG4gICAgICAgIHRoaXMuZGMuaW5zdGFuY2Uubm90VmlydHVhbCA9ICEodGhpcy5pZ3hGb3JDb250YWluZXJTaXplICYmIHRoaXMuZGMgJiYgdGhpcy5zdGF0ZS5jaHVua1NpemUgPCBjb3VudCk7XG4gICAgICAgIGNvbnN0IHNjcm9sbGFibGUgPSB0aGlzLmlzU2Nyb2xsYWJsZSgpO1xuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICBjb25zdCB0b3RhbFdpZHRoID0gdGhpcy5pZ3hGb3JDb250YWluZXJTaXplID8gdGhpcy5pbml0U2l6ZXNDYWNoZSh0aGlzLmlneEZvck9mKSA6IDA7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5uYXRpdmVFbGVtZW50LnN0eWxlLndpZHRoID0gdGhpcy5pZ3hGb3JDb250YWluZXJTaXplICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgPSB0b3RhbFdpZHRoO1xuICAgICAgICAgICAgaWYgKHRvdGFsV2lkdGggPD0gcGFyc2VJbnQodGhpcy5pZ3hGb3JDb250YWluZXJTaXplLCAxMCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBwYXJzZUludCh0aGlzLmlneEZvckNvbnRhaW5lclNpemUsIDEwKSArICdweCc7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbENvbXBvbmVudC5zaXplID0gdGhpcy5fY2FsY0hlaWdodCgpO1xuICAgICAgICAgICAgaWYgKCB0aGlzLnNjcm9sbENvbXBvbmVudC5zaXplIDw9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNjcm9sbGFibGUgIT09IHRoaXMuaXNTY3JvbGxhYmxlKCkpIHtcbiAgICAgICAgICAgIC8vIHNjcm9sbGJhciB2aXNpYmlsaXR5IGhhcyBjaGFuZ2VkXG4gICAgICAgICAgICB0aGlzLm9uU2Nyb2xsYmFyVmlzaWJpbGl0eUNoYW5nZWQuZW1pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIF9jYWxjSGVpZ2h0KCk6IG51bWJlciB7XG4gICAgICAgIGxldCBoZWlnaHQ7XG4gICAgICAgIGlmICh0aGlzLmhlaWdodENhY2hlKSB7XG4gICAgICAgICAgICBoZWlnaHQgPSB0aGlzLmhlaWdodENhY2hlLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoZWlnaHQgPSB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3ZpcnRIZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGlmIChoZWlnaHQgPiB0aGlzLl9tYXhIZWlnaHQpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZpcnRIZWlnaHRSYXRpbyA9IGhlaWdodCAvIHRoaXMuX21heEhlaWdodDtcbiAgICAgICAgICAgIGhlaWdodCA9IHRoaXMuX21heEhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGVpZ2h0O1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBfcmVjYWxjT25Db250YWluZXJDaGFuZ2UoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAnMHB4JztcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9ICcwcHgnO1xuICAgICAgICBjb25zdCBwcmV2Q2h1bmtTaXplID0gdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgIHRoaXMuYXBwbHlDaHVua1NpemVDaGFuZ2UoKTtcbiAgICAgICAgdGhpcy5fcmVjYWxjU2Nyb2xsQmFyU2l6ZSgpO1xuICAgICAgICBpZiAocHJldkNodW5rU2l6ZSAhPT0gdGhpcy5zdGF0ZS5jaHVua1NpemUpIHtcbiAgICAgICAgICAgIHRoaXMub25DaHVua0xvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zaXplc0NhY2hlICYmIHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgLy8gVXBkYXRpbmcgaG9yaXpvbnRhbCBjaHVua3MgYW5kIG9mZnNldHMgYmFzZWQgb24gdGhlIG5ldyBzY3JvbGxMZWZ0XG4gICAgICAgICAgICBjb25zdCBzY3JvbGxPZmZzZXQgPSB0aGlzLmZpeGVkVXBkYXRlQWxsRWxlbWVudHModGhpcy5zY3JvbGxQb3NpdGlvbik7XG4gICAgICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gLXNjcm9sbE9mZnNldCArICdweCc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogUmVtb3ZlcyBhbiBlbGVtZW5ldCBmcm9tIHRoZSBlbWJlZGRlZCB2aWV3cyBhbmQgdXBkYXRlcyBjaHVua1NpemUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlbW92ZUxhc3RFbGVtKCkge1xuICAgICAgICBjb25zdCBvbGRFbGVtID0gdGhpcy5fZW1iZWRkZWRWaWV3cy5wb3AoKTtcbiAgICAgICAgdGhpcy5vbkJlZm9yZVZpZXdEZXN0cm95ZWQuZW1pdChvbGRFbGVtKTtcbiAgICAgICAgLy8gYWxzbyBkZXRhY2ggZnJvbSBWaWV3Q29udGFpbmVyUmVmIHRvIG1ha2UgYWJzb2x1dGVseSBzdXJlIHRoaXMgaXMgcmVtb3ZlZCBmcm9tIHRoZSB2aWV3IGNvbnRhaW5lci5cbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmRldGFjaCh0aGlzLmRjLmluc3RhbmNlLl92Y3IubGVuZ3RoIC0gMSk7XG4gICAgICAgIG9sZEVsZW0uZGVzdHJveSgpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUuY2h1bmtTaXplLS07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIElmIHRoZXJlIGV4aXN0cyBhbiBlbGVtZW50IHRoYXQgd2UgY2FuIGNyZWF0ZSBlbWJlZGRlZCB2aWV3IGZvciBjcmVhdGVzIGl0LCBhcHBlbmRzIGl0IGFuZCB1cGRhdGVzIGNodW5rU2l6ZVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhZGRMYXN0RWxlbSgpIHtcbiAgICAgICAgbGV0IGVsZW1JbmRleCA9IHRoaXMuc3RhdGUuc3RhcnRJbmRleCArIHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICBpZiAoIXRoaXMuaXNSZW1vdGUgJiYgIXRoaXMuaWd4Rm9yT2YpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlbGVtSW5kZXggPj0gdGhpcy5pZ3hGb3JPZi5sZW5ndGgpIHtcbiAgICAgICAgICAgIGVsZW1JbmRleCA9IHRoaXMuaWd4Rm9yT2YubGVuZ3RoIC0gdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlneEZvck9mW2VsZW1JbmRleF07XG4gICAgICAgIGNvbnN0IGVtYmVkZGVkVmlldyA9IHRoaXMuZGMuaW5zdGFuY2UuX3Zjci5jcmVhdGVFbWJlZGRlZFZpZXcoXG4gICAgICAgICAgICB0aGlzLl90ZW1wbGF0ZSxcbiAgICAgICAgICAgIG5ldyBJZ3hGb3JPZkNvbnRleHQ8VD4oaW5wdXQsIHRoaXMuZ2V0Q29udGV4dEluZGV4KGlucHV0KSwgdGhpcy5pZ3hGb3JPZi5sZW5ndGgpXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5fZW1iZWRkZWRWaWV3cy5wdXNoKGVtYmVkZGVkVmlldyk7XG4gICAgICAgIHRoaXMuc3RhdGUuY2h1bmtTaXplKys7XG5cbiAgICAgICAgdGhpcy5fem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY2FsY3VsYXRlcyBjaHVua1NpemUgYW5kIGFkZHMvcmVtb3ZlcyBlbGVtZW50cyBpZiBuZWVkIGR1ZSB0byB0aGUgY2hhbmdlLlxuICAgICAqIHRoaXMuc3RhdGUuY2h1bmtTaXplIGlzIHVwZGF0ZWQgaW4gQGFkZExhc3RFbGVtKCkgb3IgQHJlbW92ZUxhc3RFbGVtKClcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYXBwbHlDaHVua1NpemVDaGFuZ2UoKSB7XG4gICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMuaXNSZW1vdGUgPyAodGhpcy5pZ3hGb3JPZiA/IHRoaXMuaWd4Rm9yT2YubGVuZ3RoIDogMCkgOiB0aGlzLl9jYWxjdWxhdGVDaHVua1NpemUoKTtcbiAgICAgICAgaWYgKGNodW5rU2l6ZSA+IHRoaXMuc3RhdGUuY2h1bmtTaXplKSB7XG4gICAgICAgICAgICBjb25zdCBkaWZmID0gY2h1bmtTaXplIC0gdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpZmY7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkTGFzdEVsZW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjaHVua1NpemUgPCB0aGlzLnN0YXRlLmNodW5rU2l6ZSkge1xuICAgICAgICAgICAgY29uc3QgZGlmZiA9IHRoaXMuc3RhdGUuY2h1bmtTaXplIC0gY2h1bmtTaXplO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaWZmOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxhc3RFbGVtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVNjcm9sbE9mZnNldCgpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlSFNjcm9sbE9mZnNldCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlVlNjcm9sbE9mZnNldCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHByaXZhdGUgX3VwZGF0ZVZTY3JvbGxPZmZzZXQoKSB7XG4gICAgICAgIGxldCBzY3JvbGxPZmZzZXQgPSAwO1xuICAgICAgICBjb25zdCB2U2Nyb2xsID0gIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIHNjcm9sbE9mZnNldCA9IHZTY3JvbGwgJiYgdGhpcy5zY3JvbGxDb21wb25lbnQuc2l6ZSA/XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uIC0gdGhpcy5zaXplc0NhY2hlW3RoaXMuc3RhdGUuc3RhcnRJbmRleF0gOiAwO1xuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAtKHNjcm9sbE9mZnNldCkgKyAncHgnO1xuICAgIH1cbiAgICBwcml2YXRlIF91cGRhdGVIU2Nyb2xsT2Zmc2V0KCkge1xuICAgICAgICBsZXQgc2Nyb2xsT2Zmc2V0ID0gMDtcbiAgICAgICAgc2Nyb2xsT2Zmc2V0ID0gIHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQgJiZcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ29tcG9uZW50LnNpemUgP1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxQb3NpdGlvbiAtIHRoaXMuc2l6ZXNDYWNoZVt0aGlzLnN0YXRlLnN0YXJ0SW5kZXhdIDogMDtcbiAgICAgICAgdGhpcy5kYy5pbnN0YW5jZS5fdmlld0NvbnRhaW5lci5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9IC1zY3JvbGxPZmZzZXQgKyAncHgnO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldEl0ZW1TaXplKGl0ZW0sIGRpbWVuc2lvbjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgZGltID0gaXRlbVtkaW1lbnNpb25dO1xuICAgICAgICByZXR1cm4gdHlwZW9mIGRpbSA9PT0gJ251bWJlcicgPyBkaW0gOiBwYXJzZUludCh0aGlzLmlneEZvckl0ZW1TaXplLCAxMCkgfHwgMDtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUeXBlTmFtZUZvckRlYnVnZ2luZyh0eXBlOiBhbnkpOiBzdHJpbmcge1xuICAgIGNvbnN0IG5hbWUgPSAnbmFtZSc7XG4gICAgcmV0dXJuIHR5cGVbbmFtZV0gfHwgdHlwZW9mIHR5cGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUZvck9mU3RhdGUgZXh0ZW5kcyBJQmFzZUV2ZW50QXJncyB7XG4gICAgc3RhcnRJbmRleD86IG51bWJlcjtcbiAgICBjaHVua1NpemU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUZvck9mRGF0YUNoYW5naW5nRXZlbnRBcmdzIGV4dGVuZHMgSUJhc2VFdmVudEFyZ3Mge1xuICAgIGNvbnRhaW5lclNpemU6IG51bWJlcjtcbn1cblxuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbaWd4R3JpZEZvcl1baWd4R3JpZEZvck9mXSdcbn0pXG5leHBvcnQgY2xhc3MgSWd4R3JpZEZvck9mRGlyZWN0aXZlPFQ+IGV4dGVuZHMgSWd4Rm9yT2ZEaXJlY3RpdmU8VD4gaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgRG9DaGVjayB7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgX3ZpZXdDb250YWluZXI6IFZpZXdDb250YWluZXJSZWYsXG4gICAgICAgIF90ZW1wbGF0ZTogVGVtcGxhdGVSZWY8TmdGb3JPZkNvbnRleHQ8VD4+LFxuICAgICAgICBfZGlmZmVyczogSXRlcmFibGVEaWZmZXJzLFxuICAgICAgICByZXNvbHZlcjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgICAgICBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBfem9uZTogTmdab25lLFxuICAgICAgICBwcm90ZWN0ZWQgc3luY1Njcm9sbFNlcnZpY2U6IElneEZvck9mU2Nyb2xsU3luY1NlcnZpY2UsXG4gICAgICAgIHByb3RlY3RlZCBzeW5jU2VydmljZTogSWd4Rm9yT2ZTeW5jU2VydmljZSkge1xuICAgICAgICBzdXBlcihfdmlld0NvbnRhaW5lciwgX3RlbXBsYXRlLCBfZGlmZmVycywgcmVzb2x2ZXIsIGNkciwgX3pvbmUsIHN5bmNTY3JvbGxTZXJ2aWNlKTtcbiAgICB9XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCBpZ3hHcmlkRm9yT2YodmFsdWUpIHtcbiAgICAgICAgdGhpcy5pZ3hGb3JPZiA9IHZhbHVlO1xuICAgIH1cblxuICAgIGdldCBpZ3hHcmlkRm9yT2YoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlneEZvck9mO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW4gQGludGVybmFsXG4gICAgICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGFmdGVyIGRhdGEgaGFzIGJlZW4gY2hhbmdlZCBidXQgYmVmb3JlIHRoZSB2aWV3IGlzIHJlZnJlc2hlZFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvbkRhdGFDaGFuZ2luZyA9IG5ldyBFdmVudEVtaXR0ZXI8SUZvck9mRGF0YUNoYW5naW5nRXZlbnRBcmdzPigpO1xuXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuc3luY1NlcnZpY2Uuc2V0TWFzdGVyKHRoaXMpO1xuICAgICAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgICAgICB0aGlzLnJlbW92ZVNjcm9sbEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgICAgICBjb25zdCBmb3JPZiA9ICdpZ3hHcmlkRm9yT2YnO1xuICAgICAgICB0aGlzLnN5bmNTZXJ2aWNlLnNldE1hc3Rlcih0aGlzKTtcbiAgICAgICAgaWYgKGZvck9mIGluIGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY2hhbmdlc1tmb3JPZl0uY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9kaWZmZXIgJiYgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodmFsdWUpLmNyZWF0ZSh0aGlzLmlneEZvclRyYWNrQnkpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYENhbm5vdCBmaW5kIGEgZGlmZmVyIHN1cHBvcnRpbmcgb2JqZWN0IFwiJHt2YWx1ZX1cIiBvZiB0eXBlIFwiJHtnZXRUeXBlTmFtZUZvckRlYnVnZ2luZyh2YWx1ZSl9XCIuXG4gICAgICAgICAgICAgICAgICAgICBOZ0ZvciBvbmx5IHN1cHBvcnRzIGJpbmRpbmcgdG8gSXRlcmFibGVzIHN1Y2ggYXMgQXJyYXlzLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZWZhdWx0SXRlbVNpemUgPSAnaWd4Rm9ySXRlbVNpemUnO1xuICAgICAgICBpZiAoZGVmYXVsdEl0ZW1TaXplIGluIGNoYW5nZXMgJiYgIWNoYW5nZXNbZGVmYXVsdEl0ZW1TaXplXS5maXJzdENoYW5nZSAmJlxuICAgICAgICAgICAgIHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICd2ZXJ0aWNhbCcgJiYgdGhpcy5pZ3hGb3JPZikge1xuICAgICAgICAgICAgLy8gaGFuZGxlIGRlZmF1bHQgaXRlbSBzaXplIGNoYW5nZWQuXG4gICAgICAgICAgICB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lclNpemUgPSAnaWd4Rm9yQ29udGFpbmVyU2l6ZSc7XG4gICAgICAgIGlmIChjb250YWluZXJTaXplIGluIGNoYW5nZXMgJiYgIWNoYW5nZXNbY29udGFpbmVyU2l6ZV0uZmlyc3RDaGFuZ2UgJiYgdGhpcy5pZ3hGb3JPZikge1xuICAgICAgICAgICAgdGhpcy5fcmVjYWxjT25Db250YWluZXJDaGFuZ2UoY2hhbmdlcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcHVibGljIGdldCBzaXplc0NhY2hlKCk6IG51bWJlcltdIHtcbiAgICAgICAgaWYgKHRoaXMuc3luY1NlcnZpY2UuaXNNYXN0ZXIodGhpcykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zaXplc0NhY2hlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmNTZXJ2aWNlLnNpemVzQ2FjaGUodGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IHNpemVzQ2FjaGUodmFsdWU6IG51bWJlcltdKSB7XG4gICAgICAgIHRoaXMuX3NpemVzQ2FjaGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGl0ZW1zRGltZW5zaW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnID8gdGhpcy5pZ3hGb3JTaXplUHJvcE5hbWUgOiAnaGVpZ2h0JztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0SXRlbVNpemUoaXRlbSkge1xuICAgICAgICBsZXQgc2l6ZSA9IDA7XG4gICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJyA/XG4gICAgICAgICAgICB0aGlzLmlneEZvclNpemVQcm9wTmFtZSA6ICdoZWlnaHQnO1xuICAgICAgICBpZiAoZGltZW5zaW9uID09PSAnaGVpZ2h0Jykge1xuICAgICAgICAgICAgc2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9ySXRlbVNpemUsIDEwKSB8fCAwO1xuICAgICAgICAgICAgaWYgKGl0ZW0gJiYgaXRlbS5zdW1tYXJpZXMpIHtcbiAgICAgICAgICAgICAgICBzaXplID0gaXRlbS5tYXg7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGl0ZW0gJiYgaXRlbS5ncm91cHMgJiYgaXRlbS5oZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBzaXplID0gaXRlbS5oZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzaXplID0gcGFyc2VJbnQoaXRlbVtkaW1lbnNpb25dLCAxMCkgfHwgMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2l6ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaW5pdFNpemVzQ2FjaGUoaXRlbXM6IGFueVtdKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKCF0aGlzLnN5bmNTZXJ2aWNlLmlzTWFzdGVyKHRoaXMpKSB7XG4gICAgICAgICAgICBjb25zdCBtYXN0ZXJTaXplc0NhY2hlID0gdGhpcy5zeW5jU2VydmljZS5zaXplc0NhY2hlKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIG1hc3RlclNpemVzQ2FjaGVbbWFzdGVyU2l6ZXNDYWNoZS5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgdG90YWxTaXplID0gMDtcbiAgICAgICAgbGV0IHNpemUgPSAwO1xuICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgIHRoaXMuc2l6ZXNDYWNoZSA9IFtdO1xuICAgICAgICB0aGlzLmhlaWdodENhY2hlID0gW107XG4gICAgICAgIHRoaXMuc2l6ZXNDYWNoZS5wdXNoKDApO1xuICAgICAgICBjb25zdCBjb3VudCA9IHRoaXMuaXNSZW1vdGUgPyB0aGlzLnRvdGFsSXRlbUNvdW50IDogaXRlbXMubGVuZ3RoO1xuICAgICAgICBmb3IgKGk7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBzaXplID0gdGhpcy5nZXRJdGVtU2l6ZShpdGVtc1tpXSk7XG4gICAgICAgICAgICBpZiAodGhpcy5pdGVtc0RpbWVuc2lvbiA9PT0gJ2hlaWdodCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhlaWdodENhY2hlLnB1c2goc2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b3RhbFNpemUgKz0gc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZS5wdXNoKHRvdGFsU2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRvdGFsU2l6ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVNpemVDYWNoZShjaGFuZ2VzOiBJdGVyYWJsZUNoYW5nZXM8VD4gPSBudWxsKSB7XG4gICAgICAgIGlmICh0aGlzLmlneEZvclNjcm9sbE9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFNpemVzQ2FjaGUodGhpcy5pZ3hGb3JPZik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSB0aGlzLmhlaWdodENhY2hlLmxlbmd0aCA+IDAgPyB0aGlzLmhlaWdodENhY2hlLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCkgOiAwO1xuICAgICAgICBsZXQgbmV3SGVpZ2h0ID0gb2xkSGVpZ2h0O1xuICAgICAgICBpZiAoY2hhbmdlcyAmJiAhdGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgbmV3SGVpZ2h0ID0gdGhpcy5oYW5kbGVDYWNoZUNoYW5nZXMoY2hhbmdlcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdIZWlnaHQgPSB0aGlzLmluaXRTaXplc0NhY2hlKHRoaXMuaWd4Rm9yT2YpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGlmZiA9IG9sZEhlaWdodCAtIG5ld0hlaWdodDtcblxuICAgICAgICAvLyBpZiBkYXRhIGhhcyBiZWVuIGNoYW5nZWQgd2hpbGUgY29udGFpbmVyIGlzIHNjcm9sbGVkXG4gICAgICAgIC8vIHNob3VsZCB1cGRhdGUgc2Nyb2xsIHRvcC9sZWZ0IGFjY29yZGluZyB0byBjaGFuZ2Ugc28gdGhhdCBzYW1lIHN0YXJ0SW5kZXggaXMgaW4gdmlld1xuICAgICAgICBpZiAoTWF0aC5hYnMoZGlmZikgPiAwKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBUaGlzIGNvZGUgY2FuIGJlIHJlbW92ZWQuIEhvd2V2ZXIgdGVzdHMgbmVlZCB0byBiZSByZXdyaXR0ZW4gaW4gYSB3YXkgdGhhdCB0aGV5IHdhaXQgZm9yIFJlc2l6ZU9ic2VydmVkIHRvIGNvbXBsZXRlLlxuICAgICAgICAgICAgLy8gU28gbGVhdmluZyBhcyBpcyBmb3IgdGhlIG1vbWVudC5cbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWNhbGNVcGRhdGVTaXplcygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHBhcnNlSW50KHRoaXMuZGMuaW5zdGFuY2UuX3ZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRvcCwgMTApO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNjcm9sbFBvc2l0aW9uICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24gPSB0aGlzLnNpemVzQ2FjaGVbdGhpcy5zdGF0ZS5zdGFydEluZGV4XSAtIG9mZnNldDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVTY3JvbGxPZmZzZXQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBoYW5kbGVDYWNoZUNoYW5nZXMoY2hhbmdlczogSXRlcmFibGVDaGFuZ2VzPFQ+KSB7XG4gICAgICAgIGNvbnN0IGlkZW50aXR5Q2hhbmdlcyA9IFtdO1xuICAgICAgICBjb25zdCBuZXdIZWlnaHRDYWNoZSA9IFtdO1xuICAgICAgICBjb25zdCBuZXdTaXplc0NhY2hlID0gW107XG4gICAgICAgIG5ld1NpemVzQ2FjaGUucHVzaCgwKTtcbiAgICAgICAgbGV0IG5ld0hlaWdodCA9IDA7XG5cbiAgICAgICAgLy8gV2hlbiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSByZW1vdmVkIGl0ZW1zIHRoZSBjaGFuZ2VzIGFyZSBub3QgcmVsaWFibGUgc28gdGhvc2Ugd2l0aCBpZGVudGl0eSBjaGFuZ2Ugc2hvdWxkIGJlIGRlZmF1bHQgc2l6ZS5cbiAgICAgICAgbGV0IG51bVJlbW92ZWRJdGVtcyA9IDA7XG4gICAgICAgIGNoYW5nZXMuZm9yRWFjaFJlbW92ZWRJdGVtKCgpID0+IG51bVJlbW92ZWRJdGVtcysrKTtcblxuICAgICAgICAvLyBHZXQgdGhlIGlkZW50aXR5IGNoYW5nZXMgdG8gZGV0ZXJtaW5lIGxhdGVyIGlmIHRob3NlIHRoYXQgaGF2ZSBjaGFuZ2VkIHRoZWlyIGluZGV4ZXMgc2hvdWxkIGJlIGFzc2lnbmVkIGRlZmF1bHQgaXRlbSBzaXplLlxuICAgICAgICBjaGFuZ2VzLmZvckVhY2hJZGVudGl0eUNoYW5nZSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGl0ZW0uY3VycmVudEluZGV4ICE9PSBpdGVtLnByZXZpb3VzSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBGaWx0ZXIgb3V0IG9uZXMgdGhhdCBoYXZlIG5vdCBjaGFuZ2VkIHRoZWlyIGluZGV4LlxuICAgICAgICAgICAgICAgIGlkZW50aXR5Q2hhbmdlc1tpdGVtLmN1cnJlbnRJbmRleF0gPSBpdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBQcm9jZXNzaW5nIGVhY2ggaXRlbSB0aGF0IGlzIHBhc3NlZCB0byB0aGUgaWd4Rm9yT2Ygc28gZmFyIHNlZW0gdG8gYmUgbW9zdCByZWxpYWJsZS4gV2UgcGFyc2UgdGhlIHVwZGF0ZWQgbGlzdCBvZiBpdGVtcy5cbiAgICAgICAgY2hhbmdlcy5mb3JFYWNoSXRlbSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGl0ZW0ucHJldmlvdXNJbmRleCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgIChudW1SZW1vdmVkSXRlbXMgPCAyIHx8ICFpZGVudGl0eUNoYW5nZXMubGVuZ3RoIHx8IGlkZW50aXR5Q2hhbmdlc1tpdGVtLmN1cnJlbnRJbmRleF0pKSB7XG4gICAgICAgICAgICAgICAgLy8gUmV1c2UgY2FjaGUgb24gdGhvc2Ugd2hvIGhhdmUgcHJldmlvdXNJbmRleC5cbiAgICAgICAgICAgICAgICAvLyBXaGVuIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIHJlbW92ZWQgaXRlbXMgY3VycmVudGx5IHRoZSBjaGFuZ2VzIGFyZSBub3QgcmVhZGFibGUgc28gb25lcyB3aXRoIGlkZW50aXR5IGNoYW5nZVxuICAgICAgICAgICAgICAgIC8vIHNob3VsZCBiZSByYWNhbGN1bGF0ZWQuXG4gICAgICAgICAgICAgICAgbmV3SGVpZ2h0Q2FjaGVbaXRlbS5jdXJyZW50SW5kZXhdID0gdGhpcy5oZWlnaHRDYWNoZVtpdGVtLnByZXZpb3VzSW5kZXhdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBBc3NpZ24gZGVmYXVsdCBpdGVtIHNpemUuXG4gICAgICAgICAgICAgICAgbmV3SGVpZ2h0Q2FjaGVbaXRlbS5jdXJyZW50SW5kZXhdID0gdGhpcy5nZXRJdGVtU2l6ZShpdGVtLml0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3U2l6ZXNDYWNoZVtpdGVtLmN1cnJlbnRJbmRleCArIDFdID0gbmV3U2l6ZXNDYWNoZVtpdGVtLmN1cnJlbnRJbmRleF0gKyBuZXdIZWlnaHRDYWNoZVtpdGVtLmN1cnJlbnRJbmRleF07XG4gICAgICAgICAgICBuZXdIZWlnaHQgKz0gbmV3SGVpZ2h0Q2FjaGVbaXRlbS5jdXJyZW50SW5kZXhdO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5oZWlnaHRDYWNoZSA9IG5ld0hlaWdodENhY2hlO1xuICAgICAgICB0aGlzLnNpemVzQ2FjaGUgPSBuZXdTaXplc0NhY2hlO1xuICAgICAgICByZXR1cm4gbmV3SGVpZ2h0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBwdWJsaWMgYXNzdW1lTWFzdGVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9zaXplc0NhY2hlID0gdGhpcy5zeW5jU2VydmljZS5zaXplc0NhY2hlKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgICAgICB0aGlzLnN5bmNTZXJ2aWNlLnNldE1hc3Rlcih0aGlzLCB0cnVlKTtcbiAgICB9XG5cbiAgICBuZ0RvQ2hlY2soKSB7XG4gICAgICAgIGlmICh0aGlzLl9kaWZmZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSB0aGlzLl9kaWZmZXIuZGlmZih0aGlzLmlneEZvck9mKTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXJnczogSUZvck9mRGF0YUNoYW5naW5nRXZlbnRBcmdzID0ge1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXJTaXplOiB0aGlzLmlneEZvckNvbnRhaW5lclNpemVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMub25EYXRhQ2hhbmdpbmcuZW1pdChhcmdzKTtcbiAgICAgICAgICAgICAgICAvLyAgcmUtaW5pdCBjYWNoZS5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaWd4Rm9yT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JPZiA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvKiB3ZSBuZWVkIHRvIHJlc2V0IHRoZSBtYXN0ZXIgZGlyIGlmIGFsbCByb3dzIGFyZSByZW1vdmVkXG4gICAgICAgICAgICAgICAgKGUuZy4gYmVjYXVzZSBvZiBmaWx0ZXJpbmcpOyBpZiBhbGwgY29sdW1ucyBhcmUgaGlkZGVuLCByb3dzIGFyZVxuICAgICAgICAgICAgICAgIHN0aWxsIHJlbmRlcmVkIGVtcHR5LCBzbyB3ZSBzaG91bGQgbm90IHJlc2V0IG1hc3RlciAqL1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pZ3hGb3JPZi5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZ3hGb3JTY3JvbGxPcmllbnRhdGlvbiA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN5bmNTZXJ2aWNlLnJlc2V0TWFzdGVyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3luY1NlcnZpY2Uuc2V0TWFzdGVyKHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSA9IGFyZ3MuY29udGFpbmVyU2l6ZTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVTaXplQ2FjaGUoY2hhbmdlcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5fYXBwbHlDaGFuZ2VzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlU2Nyb2xsT2Zmc2V0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkRhdGFDaGFuZ2VkLmVtaXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uU2Nyb2xsKGV2ZW50KSB7XG4gICAgICAgIGlmICghcGFyc2VJbnQodGhpcy5zY3JvbGxDb21wb25lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQsIDEwKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGFpbmVyU2l6ZSA9IHBhcnNlSW50KHRoaXMuaWd4Rm9yQ29udGFpbmVyU2l6ZSwgMTApO1xuICAgICAgICBjb25zdCBtYXhSZWFsU2Nyb2xsVG9wID0gZXZlbnQudGFyZ2V0LmNoaWxkcmVuWzBdLnNjcm9sbEhlaWdodCAtIGNvbnRhaW5lclNpemU7XG4gICAgICAgIGNvbnN0IHJlYWxQZXJjZW50U2Nyb2xsZWQgPSBtYXhSZWFsU2Nyb2xsVG9wICE9PSAwID8gIGV2ZW50LnRhcmdldC5zY3JvbGxUb3AgLyBtYXhSZWFsU2Nyb2xsVG9wIDogMDtcbiAgICAgICAgaWYgKCF0aGlzLl9iU2Nyb2xsSW50ZXJuYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IG1heFZpcnRTY3JvbGxUb3AgPSB0aGlzLl92aXJ0SGVpZ2h0IC0gY29udGFpbmVyU2l6ZTtcbiAgICAgICAgICAgIHRoaXMuX3ZpcnRTY3JvbGxUb3AgPSByZWFsUGVyY2VudFNjcm9sbGVkICogbWF4VmlydFNjcm9sbFRvcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2JTY3JvbGxJbnRlcm5hbCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNjcm9sbE9mZnNldCA9IHRoaXMuZml4ZWRVcGRhdGVBbGxFbGVtZW50cyh0aGlzLl92aXJ0U2Nyb2xsVG9wKTtcblxuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSAtKHNjcm9sbE9mZnNldCkgKyAncHgnO1xuXG4gICAgICAgIHRoaXMuX3pvbmUub25TdGFibGUucGlwZShmaXJzdCgpKS5zdWJzY3JpYmUoICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVjYWxjVXBkYXRlU2l6ZXMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cblxuICAgIG9uSFNjcm9sbChzY3JvbGxBbW91bnQpIHtcbiAgICAgICAgLyogaW4gY2VydGFpbiBzaXR1YXRpb25zIHRoaXMgbWF5IGJlIGNhbGxlZCB3aGVuIG5vIHNjcm9sbGJhciBpcyB2aXNpYmxlICovXG4gICAgICAgIGlmICghdGhpcy5zY3JvbGxDb21wb25lbnQgfHwgIXBhcnNlSW50KHRoaXMuc2Nyb2xsQ29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW5bMF0uc3R5bGUud2lkdGgsIDEwKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFVwZGF0aW5nIGhvcml6b250YWwgY2h1bmtzXG4gICAgICAgIGNvbnN0IHNjcm9sbE9mZnNldCA9IHRoaXMuZml4ZWRVcGRhdGVBbGxFbGVtZW50cyhzY3JvbGxBbW91bnQpO1xuICAgICAgICB0aGlzLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5sZWZ0ID0gLXNjcm9sbE9mZnNldCArICdweCc7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFkZExhc3RFbGVtKCkge1xuICAgICAgICBsZXQgZWxlbUluZGV4ID0gdGhpcy5zdGF0ZS5zdGFydEluZGV4ICsgdGhpcy5zdGF0ZS5jaHVua1NpemU7XG4gICAgICAgIGlmICghdGhpcy5pc1JlbW90ZSAmJiAhdGhpcy5pZ3hGb3JPZikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVsZW1JbmRleCA+PSB0aGlzLmlneEZvck9mLmxlbmd0aCkge1xuICAgICAgICAgICAgZWxlbUluZGV4ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGggLSB0aGlzLnN0YXRlLmNodW5rU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbZWxlbUluZGV4XTtcbiAgICAgICAgY29uc3QgZW1iZWRkZWRWaWV3ID0gdGhpcy5kYy5pbnN0YW5jZS5fdmNyLmNyZWF0ZUVtYmVkZGVkVmlldyhcbiAgICAgICAgICAgIHRoaXMuX3RlbXBsYXRlLFxuICAgICAgICAgICAgbmV3IElneEZvck9mQ29udGV4dDxUPihpbnB1dCwgdGhpcy5nZXRDb250ZXh0SW5kZXgoaW5wdXQpLCB0aGlzLmlneEZvck9mLmxlbmd0aClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLl9lbWJlZGRlZFZpZXdzLnB1c2goZW1iZWRkZWRWaWV3KTtcbiAgICAgICAgdGhpcy5zdGF0ZS5jaHVua1NpemUrKztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3VwZGF0ZVZpZXdzKHByZXZDaHVua1NpemUpIHtcbiAgICAgICAgaWYgKHRoaXMuaWd4Rm9yT2YgJiYgdGhpcy5pZ3hGb3JPZi5sZW5ndGggJiYgdGhpcy5kYykge1xuICAgICAgICAgICAgY29uc3QgZW1iZWRkZWRWaWV3Q29weSA9IE9iamVjdC5hc3NpZ24oW10sIHRoaXMuX2VtYmVkZGVkVmlld3MpO1xuICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXg7XG4gICAgICAgICAgICBsZXQgZW5kSW5kZXg7XG4gICAgICAgICAgICBpZiAodGhpcy5pc1JlbW90ZSkge1xuICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGVuZEluZGV4ID0gdGhpcy5pZ3hGb3JPZi5sZW5ndGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSB0aGlzLmdldEluZGV4QXQoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2l6ZXNDYWNoZSxcbiAgICAgICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXJ0SW5kZXggKyB0aGlzLnN0YXRlLmNodW5rU2l6ZSA+IHRoaXMuaWd4Rm9yT2YubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSB0aGlzLmlneEZvck9mLmxlbmd0aCAtIHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnN0YXJ0SW5kZXggPSBzdGFydEluZGV4O1xuICAgICAgICAgICAgICAgIGVuZEluZGV4ID0gdGhpcy5zdGF0ZS5jaHVua1NpemUgKyB0aGlzLnN0YXRlLnN0YXJ0SW5kZXg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgZW5kSW5kZXggJiYgdGhpcy5pZ3hGb3JPZltpXSAhPT0gdW5kZWZpbmVkOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuaWd4Rm9yT2ZbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgZW1iVmlldyA9IGVtYmVkZGVkVmlld0NvcHkuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjbnR4ID0gKGVtYlZpZXcgYXMgRW1iZWRkZWRWaWV3UmVmPGFueT4pLmNvbnRleHQ7XG4gICAgICAgICAgICAgICAgY250eC4kaW1wbGljaXQgPSBpbnB1dDtcbiAgICAgICAgICAgICAgICBjbnR4LmluZGV4ID0gdGhpcy5nZXRDb250ZXh0SW5kZXgoaW5wdXQpO1xuICAgICAgICAgICAgICAgIGNudHguY291bnQgPSB0aGlzLmlneEZvck9mLmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwcmV2Q2h1bmtTaXplICE9PSB0aGlzLnN0YXRlLmNodW5rU2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMub25DaHVua0xvYWQuZW1pdCh0aGlzLnN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBwcm90ZWN0ZWQgX2FwcGx5Q2hhbmdlcygpIHtcbiAgICAgICAgY29uc3QgcHJldkNodW5rU2l6ZSA9IHRoaXMuc3RhdGUuY2h1bmtTaXplO1xuICAgICAgICB0aGlzLmFwcGx5Q2h1bmtTaXplQ2hhbmdlKCk7XG4gICAgICAgIHRoaXMuX3JlY2FsY1Njcm9sbEJhclNpemUoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlVmlld3MocHJldkNodW5rU2l6ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBfY2FsY01heENodW5rU2l6ZSgpOiBudW1iZXIge1xuICAgICAgICBpZiAodGhpcy5zeW5jU2VydmljZS5pc01hc3Rlcih0aGlzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHN1cGVyLl9jYWxjTWF4Q2h1bmtTaXplKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc3luY1NlcnZpY2UuY2h1bmtTaXplKHRoaXMuaWd4Rm9yU2Nyb2xsT3JpZW50YXRpb24pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbkBOZ01vZHVsZSh7XG4gICAgZGVjbGFyYXRpb25zOiBbSWd4Rm9yT2ZEaXJlY3RpdmUsIElneEdyaWRGb3JPZkRpcmVjdGl2ZSwgRGlzcGxheUNvbnRhaW5lckNvbXBvbmVudCwgVmlydHVhbEhlbHBlckNvbXBvbmVudCxcbiAgICAgICAgIEhWaXJ0dWFsSGVscGVyQ29tcG9uZW50LCBWaXJ0dWFsSGVscGVyQmFzZURpcmVjdGl2ZV0sXG4gICAgZW50cnlDb21wb25lbnRzOiBbRGlzcGxheUNvbnRhaW5lckNvbXBvbmVudCwgVmlydHVhbEhlbHBlckNvbXBvbmVudCwgSFZpcnR1YWxIZWxwZXJDb21wb25lbnRdLFxuICAgIGV4cG9ydHM6IFtJZ3hGb3JPZkRpcmVjdGl2ZSwgSWd4R3JpZEZvck9mRGlyZWN0aXZlXSxcbiAgICBpbXBvcnRzOiBbSWd4U2Nyb2xsSW5lcnRpYU1vZHVsZSwgQ29tbW9uTW9kdWxlXVxufSlcblxuZXhwb3J0IGNsYXNzIElneEZvck9mTW9kdWxlIHtcbn1cbiJdfQ==