UNPKG

@catull/igniteui-angular

Version:

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

1,582 lines 207 kB
import { __decorate, __metadata } from "tslib";
import { Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, NgModule, NgZone, OnDestroy, OnInit, Output, Renderer2, ChangeDetectorRef, ViewContainerRef, AfterContentInit, TemplateRef, ContentChildren, QueryList } from '@angular/core';
import { animationFrameScheduler, fromEvent, interval, Subject } from 'rxjs';
import { takeUntil, throttle } from 'rxjs/operators';
import { IgxDragHandleDirective } from './drag-handle.directive';
import { DeprecateProperty } from '../../core/deprecateDecorators';
import { IgxDefaultDropStrategy } from './drag-drop.strategy';
export var RestrictDrag;
(function (RestrictDrag) {
    RestrictDrag[RestrictDrag["VERTICALLY"] = 0] = "VERTICALLY";
    RestrictDrag[RestrictDrag["HORIZONTALLY"] = 1] = "HORIZONTALLY";
    RestrictDrag[RestrictDrag["NONE"] = 2] = "NONE";
})(RestrictDrag || (RestrictDrag = {}));
var IgxDragLocation = /** @class */ (function () {
    function IgxDragLocation(_pageX, _pageY) {
        this._pageX = _pageX;
        this._pageY = _pageY;
        this.pageX = parseFloat(_pageX);
        this.pageY = parseFloat(_pageY);
    }
    return IgxDragLocation;
}());
export { IgxDragLocation };
var IgxDragDirective = /** @class */ (function () {
    function IgxDragDirective(cdr, element, viewContainer, zone, renderer) {
        this.cdr = cdr;
        this.element = element;
        this.viewContainer = viewContainer;
        this.zone = zone;
        this.renderer = renderer;
        this.ghostContext = null;
        /**
         * An @Input property that indicates when the drag should start.
         * By default the drag starts after the draggable element is moved by 5px.
         * ```html
         * <div igxDrag [dragTolerance]="100">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        this.dragTolerance = 5;
        /**
         * An @Input property that specifies if the base element should not be moved and a ghost element should be rendered that represents it.
         * By default it is set to `true`.
         * If it is set to `false` when dragging the base element is moved instead and no ghost elements are rendered.
         * ```html
         * <div igxDrag [ghost]="false">
         *      <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        this.ghost = true;
        /**
         * Sets a custom class that will be added to the `ghostElement` element.
         * ```html
         * <div igxDrag [ghostClass]="'ghostElement'">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        this.ghostClass = '';
        /**
         * @deprecated Please use custom base styling instead.
         * An @Input property that hides the draggable element.
         * By default it's set to false.
         * ```html
         * <div igxDrag [dragTolerance]="100" [hideBaseOnDrag]="'true'">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        this.hideBaseOnDrag = false;
        /**
         * @deprecated Please use provided transition functions in future.
         * An @Input property that enables/disables the draggable element animation
         * when the element is released.
         * By default it's set to false.
         * ```html
         * <div igxDrag [animateOnRelease]="'true'">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        this.animateOnRelease = false;
        /**
         * Event triggered when the draggable element drag starts.
         * ```html
         * <div igxDrag (dragStart)="onDragStart()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public onDragStart(){
         *      alert("The drag has stared!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.dragStart = new EventEmitter();
        /**
         * Event triggered when the draggable element has been moved.
         * ```html
         * <div igxDrag  (dragMove)="onDragMove()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public onDragMove(){
         *      alert("The element has moved!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.dragMove = new EventEmitter();
        /**
         * Event triggered when the draggable element is released.
         * ```html
         * <div igxDrag (dragEnd)="onDragEnd()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public onDragEnd(){
         *      alert("The drag has ended!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.dragEnd = new EventEmitter();
        /**
         * Event triggered when the draggable element is clicked.
         * ```html
         * <div igxDrag (dragClick)="onDragClick()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public onDragClick(){
         *      alert("The element has been clicked!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.dragClick = new EventEmitter();
        /**
         * Event triggered when the drag ghost element is created.
         * ```html
         * <div igxDrag (ghostCreate)="ghostCreated()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public ghostCreated(){
         *      alert("The ghost has been created!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.ghostCreate = new EventEmitter();
        /**
         * Event triggered when the drag ghost element is created.
         * ```html
         * <div igxDrag (ghostDestroy)="ghostDestroyed()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public ghostDestroyed(){
         *      alert("The ghost has been destroyed!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.ghostDestroy = new EventEmitter();
        /**
         * Event triggered after the draggable element is released and after its animation has finished.
         * ```html
         * <div igxDrag (transitioned)="onMoveEnd()">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * ```typescript
         * public onMoveEnd(){
         *      alert("The move has ended!");
         * }
         * ```
         * @memberof IgxDragDirective
         */
        this.transitioned = new EventEmitter();
        /**
         * @hidden
         */
        this._visibility = 'visible';
        /**
         * @hidden
         */
        this.baseClass = true;
        /**
         * @hidden
         */
        this.selectDisabled = false;
        /**
         * @hidden
         */
        this.defaultReturnDuration = '0.5s';
        /**
         * @hidden
         */
        this.animInProgress = false;
        this._startX = 0;
        this._startY = 0;
        this._lastX = 0;
        this._lastY = 0;
        this._dragStarted = false;
        this._ghostHostX = 0;
        this._ghostHostY = 0;
        this._pointerDownId = null;
        this._clicked = false;
        this._lastDropArea = null;
        this._destroy = new Subject();
        this._removeOnDestroy = true;
    }
    Object.defineProperty(IgxDragDirective.prototype, "ghostOffsetX", {
        get: function () {
            return this._offsetX !== undefined ? this._offsetX : this._defaultOffsetX;
        },
        /**
         * An @Input property that specifies the offset of the dragged element relative to the mouse in pixels.
         * By default it's taking the relative position to the mouse when the drag started and keeps it the same.
         * ```html
         * <div #hostDiv></div>
         * <div igxDrag [ghostOffsetX]="0">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        set: function (value) {
            this._offsetX = parseInt(value, 10);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "ghostOffsetY", {
        get: function () {
            return this._offsetY !== undefined ? this._offsetY : this._defaultOffsetY;
        },
        /**
         * An @Input property that specifies the offset of the dragged element relative to the mouse in pixels.
         * By default it's taking the relative position to the mouse when the drag started and keeps it the same.
         * ```html
         * <div #hostDiv></div>
         * <div igxDrag [ghostOffsetY]="0">
         *         <span>Drag Me!</span>
         * </div>
         * ```
         * @memberof IgxDragDirective
         */
        set: function (value) {
            this._offsetY = parseInt(value, 10);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "visible", {
        /**
         * Returns the visibility state of the draggable element.
         * ```typescript
         * @ViewChild("myDrag" ,{read: IgxDragDirective})
         * public myDrag: IgxDragDirective;
         * ngAfterViewInit(){
         *     let dragVisibility = this.myDrag.visible;
         * }
         * ```
         */
        get: function () {
            return this._visibility === 'visible';
        },
        /**
         * @deprecated Please use native angular ways of hiding it using custom to the base element styling for future versions.
         * Sets the visibility of the draggable element.
         * ```typescript
         * @ViewChild("myDrag" ,{read: IgxDragDirective})
         * public myDrag: IgxDragDirective;
         * ngAfterViewInit(){
         *     this.myDrag.visible = false;
         * }
         * ```
         */
        set: function (bVisible) {
            this._visibility = bVisible ? 'visible' : 'hidden';
            this.cdr.detectChanges();
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "location", {
        /**
         * Gets the current location of the element relative to the page.
         */
        get: function () {
            return new IgxDragLocation(this.pageX, this.pageY);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "originLocation", {
        /**
         * Gets the original location of the element before dragging started.
         */
        get: function () {
            return new IgxDragLocation(this.baseOriginLeft, this.baseOriginTop);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "pointerEventsEnabled", {
        /**
         * @hidden
         */
        get: function () {
            return typeof PointerEvent !== 'undefined';
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "touchEventsEnabled", {
        /**
         * @hidden
         */
        get: function () {
            return 'ontouchstart' in window;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "pageX", {
        /**
         * @hidden
         */
        get: function () {
            if (this.ghost && this.ghostElement) {
                return this.ghostLeft;
            }
            return this.baseLeft;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "pageY", {
        /**
         * @hidden
         */
        get: function () {
            if (this.ghost && this.ghostElement) {
                return this.ghostTop;
            }
            return this.baseTop;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "baseLeft", {
        get: function () {
            return this.element.nativeElement.getBoundingClientRect().left;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "baseTop", {
        get: function () {
            return this.element.nativeElement.getBoundingClientRect().top;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "baseOriginLeft", {
        get: function () {
            return this.baseLeft - this.getTransformX(this.element.nativeElement);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "baseOriginTop", {
        get: function () {
            return this.baseTop - this.getTransformY(this.element.nativeElement);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "ghostLeft", {
        get: function () {
            return parseInt(this.ghostElement.style.left, 10) + this._ghostHostX;
        },
        set: function (pageX) {
            if (this.ghostElement) {
                // We need to take into account marginLeft, since top style does not include margin, but pageX includes the margin.
                var ghostMarginLeft = parseInt(document.defaultView.getComputedStyle(this.ghostElement)['margin-left'], 10);
                // If ghost host is defined it needs to be taken into account.
                this.ghostElement.style.left = (pageX - ghostMarginLeft - this._ghostHostX) + 'px';
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(IgxDragDirective.prototype, "ghostTop", {
        get: function () {
            return parseInt(this.ghostElement.style.top, 10) + this._ghostHostY;
        },
        set: function (pageY) {
            if (this.ghostElement) {
                // We need to take into account marginTop, since top style does not include margin, but pageY includes the margin.
                var ghostMarginTop = parseInt(document.defaultView.getComputedStyle(this.ghostElement)['margin-top'], 10);
                // If ghost host is defined it needs to be taken into account.
                this.ghostElement.style.top = (pageY - ghostMarginTop - this._ghostHostY) + 'px';
            }
        },
        enumerable: true,
        configurable: true
    });
    /**
     * @hidden
     */
    IgxDragDirective.prototype.ngAfterContentInit = function () {
        var _this = this;
        if (!this.dragHandles || !this.dragHandles.length) {
            // Set user select none to the whole draggable element if no drag handles are defined.
            this.selectDisabled = true;
        }
        // Bind events
        this.zone.runOutsideAngular(function () {
            var targetElements = _this.dragHandles && _this.dragHandles.length ?
                _this.dragHandles.map(function (item) { return item.element.nativeElement; }) : [_this.element.nativeElement];
            targetElements.forEach(function (element) {
                if (_this.pointerEventsEnabled) {
                    fromEvent(element, 'pointerdown').pipe(takeUntil(_this._destroy))
                        .subscribe(function (res) { return _this.onPointerDown(res); });
                    fromEvent(element, 'pointermove').pipe(throttle(function () { return interval(0, animationFrameScheduler); }), takeUntil(_this._destroy)).subscribe(function (res) { return _this.onPointerMove(res); });
                    fromEvent(element, 'pointerup').pipe(takeUntil(_this._destroy))
                        .subscribe(function (res) { return _this.onPointerUp(res); });
                    if (!_this.ghost) {
                        // Do not bind `lostpointercapture` to the target, because we will bind it on the ghost later.
                        fromEvent(element, 'lostpointercapture').pipe(takeUntil(_this._destroy))
                            .subscribe(function (res) { return _this.onPointerLost(res); });
                    }
                }
                else if (_this.touchEventsEnabled) {
                    fromEvent(element, 'touchstart').pipe(takeUntil(_this._destroy))
                        .subscribe(function (res) { return _this.onPointerDown(res); });
                }
                else {
                    // We don't have pointer events and touch events. Use then mouse events.
                    fromEvent(element, 'mousedown').pipe(takeUntil(_this._destroy))
                        .subscribe(function (res) { return _this.onPointerDown(res); });
                }
            });
            // We should bind to document events only once when there are no pointer events.
            if (!_this.pointerEventsEnabled && _this.touchEventsEnabled) {
                fromEvent(document.defaultView, 'touchmove').pipe(throttle(function () { return interval(0, animationFrameScheduler); }), takeUntil(_this._destroy)).subscribe(function (res) { return _this.onPointerMove(res); });
                fromEvent(document.defaultView, 'touchend').pipe(takeUntil(_this._destroy))
                    .subscribe(function (res) { return _this.onPointerUp(res); });
            }
            else if (!_this.pointerEventsEnabled) {
                fromEvent(document.defaultView, 'mousemove').pipe(throttle(function () { return interval(0, animationFrameScheduler); }), takeUntil(_this._destroy)).subscribe(function (res) { return _this.onPointerMove(res); });
                fromEvent(document.defaultView, 'mouseup').pipe(takeUntil(_this._destroy))
                    .subscribe(function (res) { return _this.onPointerUp(res); });
            }
            _this.element.nativeElement.addEventListener('transitionend', function (args) {
                _this.onTransitionEnd(args);
            });
        });
        // Set transition duration to 0s. This also helps with setting `visibility: hidden` to the base to not lag.
        this.element.nativeElement.style.transitionDuration = '0.0s';
    };
    /**
     * @hidden
     */
    IgxDragDirective.prototype.ngOnDestroy = function () {
        this._destroy.next(true);
        this._destroy.complete();
        if (this.ghost && this.ghostElement && this._removeOnDestroy) {
            this.ghostElement.parentNode.removeChild(this.ghostElement);
            this.ghostElement = null;
        }
    };
    /**
     * Sets desired location of the base element or ghost element if rended relative to the document.
     * @param newLocation New location that should be applied. It is advised to get new location using getBoundingClientRects() + scroll.
     */
    IgxDragDirective.prototype.setLocation = function (newLocation) {
        // We do not subtract marginLeft and marginTop here because here we calculate deltas.
        if (this.ghost && this.ghostElement) {
            var offsetHostX = this.ghostHost ? this.ghostHostOffsetLeft(this.ghostHost) : 0;
            var offsetHostY = this.ghostHost ? this.ghostHostOffsetTop(this.ghostHost) : 0;
            this.ghostLeft = newLocation.pageX - offsetHostX + this.getWindowScrollLeft();
            this.ghostTop = newLocation.pageY - offsetHostY + this.getWindowScrollTop();
        }
        else if (!this.ghost) {
            var deltaX = newLocation.pageX - this.pageX;
            var deltaY = newLocation.pageY - this.pageY;
            var transformX = this.getTransformX(this.element.nativeElement);
            var transformY = this.getTransformY(this.element.nativeElement);
            this.setTransformXY(transformX + deltaX, transformY + deltaY);
        }
        this._startX = this.baseLeft;
        this._startY = this.baseTop;
    };
    /**
     * Animates the base or ghost element depending on the `ghost` input to its initial location.
     * If `ghost` is true but there is not ghost rendered, it will be created and animated.
     * If the base element has changed its DOM position its initial location will be changed accordingly.
     * @param customAnimArgs Custom transition properties that will be applied when performing the transition.
     * @param startLocation Start location from where the transition should start.
     */
    IgxDragDirective.prototype.transitionToOrigin = function (customAnimArgs, startLocation) {
        var _this = this;
        if ((!!startLocation && startLocation.pageX === this.baseOriginLeft && startLocation.pageY === this.baseOriginLeft) ||
            (!startLocation && this.ghost && !this.ghostElement)) {
            return;
        }
        if (!!startLocation && startLocation.pageX !== this.pageX && startLocation.pageY !== this.pageY) {
            if (this.ghost && !this.ghostElement) {
                this._startX = startLocation.pageX;
                this._startY = startLocation.pageY;
                this._ghostStartX = this._startX;
                this._ghostStartY = this._startY;
                this.createGhost(this._startX, this._startY);
            }
            this.setLocation(startLocation);
        }
        this.animInProgress = true;
        // Use setTimeout because we need to be sure that the element is positioned first correctly if there is start location.
        setTimeout(function () {
            if (_this.ghost) {
                _this.ghostElement.style.transitionProperty = 'top, left';
                _this.ghostElement.style.transitionDuration =
                    customAnimArgs && customAnimArgs.duration ? customAnimArgs.duration + 's' : _this.defaultReturnDuration;
                _this.ghostElement.style.transitionTimingFunction =
                    customAnimArgs && customAnimArgs.timingFunction ? customAnimArgs.timingFunction : '';
                _this.ghostElement.style.transitionDelay = customAnimArgs && customAnimArgs.delay ? customAnimArgs.delay + 's' : '';
                _this.setLocation(new IgxDragLocation(_this.baseLeft, _this.baseTop));
            }
            else if (!_this.ghost) {
                _this.element.nativeElement.style.transitionProperty = 'transform';
                _this.element.nativeElement.style.transitionDuration =
                    customAnimArgs && customAnimArgs.duration ? customAnimArgs.duration + 's' : _this.defaultReturnDuration;
                _this.element.nativeElement.style.transitionTimingFunction =
                    customAnimArgs && customAnimArgs.timingFunction ? customAnimArgs.timingFunction : '';
                _this.element.nativeElement.style.transitionDelay = customAnimArgs && customAnimArgs.delay ? customAnimArgs.delay + 's' : '';
                _this._startX = _this.baseLeft;
                _this._startY = _this.baseTop;
                _this.setTransformXY(0, 0);
            }
        }, 0);
    };
    /**
     * Animates the base or ghost element to a specific target location or other element using transition.
     * If `ghost` is true but there is not ghost rendered, it will be created and animated.
     * It is recommended to use 'getBoundingClientRects() + pageScroll' when determining desired location.
     * @param target Target that the base or ghost will transition to. It can be either location in the page or another HTML element.
     * @param customAnimArgs Custom transition properties that will be applied when performing the transition.
     * @param startLocation Start location from where the transition should start.
     */
    IgxDragDirective.prototype.transitionTo = function (target, customAnimArgs, startLocation) {
        var _this = this;
        if (!!startLocation && this.ghost && !this.ghostElement) {
            this._startX = startLocation.pageX;
            this._startY = startLocation.pageY;
            this._ghostStartX = this._startX;
            this._ghostStartY = this._startY;
        }
        else if (!!startLocation && (!this.ghost || this.ghostElement)) {
            this.setLocation(startLocation);
        }
        else if (this.ghost && !this.ghostElement) {
            this._startX = this.baseLeft;
            this._startY = this.baseTop;
            this._ghostStartX = this._startX + this.getWindowScrollLeft();
            this._ghostStartY = this._startY + this.getWindowScrollTop();
        }
        if (this.ghost && !this.ghostElement) {
            this.createGhost(this._startX, this._startY);
        }
        this.animInProgress = true;
        // Use setTimeout because we need to be sure that the element is positioned first correctly if there is start location.
        setTimeout(function () {
            var movedElem = _this.ghost ? _this.ghostElement : _this.element.nativeElement;
            movedElem.style.transitionProperty = _this.ghost && _this.ghostElement ? 'left, top' : 'transform';
            movedElem.style.transitionDuration =
                customAnimArgs && customAnimArgs.duration ? customAnimArgs.duration + 's' : _this.defaultReturnDuration;
            movedElem.style.transitionTimingFunction =
                customAnimArgs && customAnimArgs.timingFunction ? customAnimArgs.timingFunction : '';
            movedElem.style.transitionDelay = customAnimArgs && customAnimArgs.delay ? customAnimArgs.delay + 's' : '';
            if (target instanceof IgxDragLocation) {
                _this.setLocation(new IgxDragLocation(target.pageX, target.pageY));
            }
            else {
                var targetRects = target.nativeElement.getBoundingClientRect();
                _this.setLocation(new IgxDragLocation(targetRects.left - _this.getWindowScrollLeft(), targetRects.top - _this.getWindowScrollTop()));
            }
        }, 0);
    };
    /**
     * @hidden
     * Method bound to the PointerDown event of the base element igxDrag is initialized.
     * @param event PointerDown event captured
     */
    IgxDragDirective.prototype.onPointerDown = function (event) {
        this._clicked = true;
        this._pointerDownId = event.pointerId;
        // Set pointer capture so we detect pointermove even if mouse is out of bounds until ghostElement is created.
        var handleFound = this.dragHandles.find(function (handle) { return handle.element.nativeElement === event.currentTarget; });
        var targetElement = handleFound ? handleFound.element.nativeElement : this.element.nativeElement;
        if (this.pointerEventsEnabled) {
            targetElement.setPointerCapture(this._pointerDownId);
        }
        else {
            targetElement.focus();
            event.preventDefault();
        }
        if (this.pointerEventsEnabled || !this.touchEventsEnabled) {
            // Check first for pointer events or non touch, because we can have pointer events and touch events at once.
            this._startX = event.pageX;
            this._startY = event.pageY;
        }
        else if (this.touchEventsEnabled) {
            this._startX = event.touches[0].pageX;
            this._startY = event.touches[0].pageY;
        }
        this._defaultOffsetX = this.baseLeft - this._startX + this.getWindowScrollLeft();
        this._defaultOffsetY = this.baseTop - this._startY + this.getWindowScrollTop();
        this._ghostStartX = this._startX + this.ghostOffsetX;
        this._ghostStartY = this._startY + this.ghostOffsetY;
        this._lastX = this._startX;
        this._lastY = this._startY;
    };
    /**
     * @hidden
     * Perform drag move logic when dragging and dispatching events if there is igxDrop under the pointer.
     * This method is bound at first at the base element.
     * If dragging starts and after the ghostElement is rendered the pointerId is reassigned it. Then this method is bound to it.
     * @param event PointerMove event captured
     */
    IgxDragDirective.prototype.onPointerMove = function (event) {
        var _this = this;
        if (this._clicked) {
            var pageX = void 0, pageY = void 0;
            if (this.pointerEventsEnabled || !this.touchEventsEnabled) {
                // Check first for pointer events or non touch, because we can have pointer events and touch events at once.
                pageX = event.pageX;
                pageY = event.pageY;
            }
            else if (this.touchEventsEnabled) {
                pageX = event.touches[0].pageX;
                pageY = event.touches[0].pageY;
                // Prevent scrolling on touch while dragging
                event.preventDefault();
            }
            var totalMovedX = pageX - this._startX;
            var totalMovedY = pageY - this._startY;
            if (!this._dragStarted &&
                (Math.abs(totalMovedX) > this.dragTolerance || Math.abs(totalMovedY) > this.dragTolerance)) {
                var dragStartArgs_1 = {
                    originalEvent: event,
                    owner: this,
                    startX: pageX - totalMovedX,
                    startY: pageY - totalMovedY,
                    pageX: pageX,
                    pageY: pageY,
                    cancel: false
                };
                this.zone.run(function () {
                    _this.dragStart.emit(dragStartArgs_1);
                });
                if (!dragStartArgs_1.cancel) {
                    this._dragStarted = true;
                    if (this.ghost) {
                        // We moved enough so ghostElement can be rendered and actual dragging to start.
                        // When creating it will take into account any offset set by the user by default.
                        this.createGhost(pageX, pageY);
                    }
                    else if (this._offsetX !== undefined || this._offsetY !== undefined) {
                        // There is no need for ghost, but we will need to position initially the base element to reflect any offset.
                        var transformX = (this._offsetX !== undefined ? this._offsetX - this._defaultOffsetX : 0) +
                            this.getTransformX(this.element.nativeElement);
                        var transformY = (this._offsetY !== undefined ? this._offsetY - this._defaultOffsetY : 0) +
                            this.getTransformY(this.element.nativeElement);
                        this.setTransformXY(transformX, transformY);
                    }
                }
                else {
                    return;
                }
            }
            else if (!this._dragStarted) {
                return;
            }
            var moveArgs = {
                originalEvent: event,
                owner: this,
                startX: this._startX,
                startY: this._startY,
                pageX: this._lastX,
                pageY: this._lastY,
                nextPageX: pageX,
                nextPageY: pageY,
                cancel: false
            };
            this.dragMove.emit(moveArgs);
            var setPageX = moveArgs.nextPageX;
            var setPageY = moveArgs.nextPageY;
            var updatedMovedX = setPageX - this._startX;
            var updatedMovedY = setPageY - this._startY;
            if (!moveArgs.cancel) {
                if (this.ghost) {
                    this.ghostLeft = this._ghostStartX + updatedMovedX;
                    this.ghostTop = this._ghostStartY + updatedMovedY;
                }
                else {
                    var lastMovedX = setPageX - this._lastX;
                    var lastMovedY = setPageY - this._lastY;
                    var translateX = this.getTransformX(this.element.nativeElement) + lastMovedX;
                    var translateY = this.getTransformY(this.element.nativeElement) + lastMovedY;
                    this.setTransformXY(translateX, translateY);
                }
                this.dispatchDragEvents(pageX, pageY, event);
            }
            this._lastX = setPageX;
            this._lastY = setPageY;
        }
    };
    /**
     * @hidden
     * Perform drag end logic when releasing the ghostElement and dispatching drop event if igxDrop is under the pointer.
     * This method is bound at first at the base element.
     * If dragging starts and after the ghostElement is rendered the pointerId is reassigned to it. Then this method is bound to it.
     * @param event PointerUp event captured
     */
    IgxDragDirective.prototype.onPointerUp = function (event) {
        var _this = this;
        if (!this._clicked) {
            return;
        }
        var pageX, pageY;
        if (this.pointerEventsEnabled || !this.touchEventsEnabled) {
            // Check first for pointer events or non touch, because we can have pointer events and touch events at once.
            pageX = event.pageX;
            pageY = event.pageY;
        }
        else if (this.touchEventsEnabled) {
            pageX = event.touches[0].pageX;
            pageY = event.touches[0].pageY;
            // Prevent scrolling on touch while dragging
            event.preventDefault();
        }
        var eventArgs = {
            originalEvent: event,
            owner: this,
            startX: this._startX,
            startY: this._startY,
            pageX: pageX,
            pageY: pageY
        };
        this._pointerDownId = null;
        this._clicked = false;
        if (this._dragStarted) {
            if (this._lastDropArea && this._lastDropArea !== this.element.nativeElement) {
                this.dispatchDropEvent(event.pageX, event.pageY, event);
            }
            else if (this.animateOnRelease) {
                this.transitionToOrigin();
            }
            this.zone.run(function () {
                _this.dragEnd.emit(eventArgs);
            });
            if (!this.animInProgress) {
                this.onTransitionEnd(null);
            }
        }
        else {
            // Trigger our own click event because when there is no ghost, native click cannot be prevented when dragging.
            this.zone.run(function () {
                _this.dragClick.emit(eventArgs);
            });
        }
    };
    /**
     * @hidden
     * Execute this method whe the pointer capture has been lost.
     * This means that during dragging the user has performed other action like right clicking and then clicking somewhere else.
     * This method will ensure that the drag state is being reset in this case as if the user released the dragged element.
     * @param event Event captured
     */
    IgxDragDirective.prototype.onPointerLost = function (event) {
        var _this = this;
        if (!this._clicked) {
            return;
        }
        var eventArgs = {
            originalEvent: event,
            owner: this,
            startX: this._startX,
            startY: this._startY,
            pageX: event.pageX,
            pageY: event.pageY
        };
        this._pointerDownId = null;
        this._clicked = false;
        if (this._dragStarted) {
            this.zone.run(function () {
                _this.dragEnd.emit(eventArgs);
            });
            if (this.animateOnRelease) {
                this.transitionToOrigin();
            }
            else if (!this.animInProgress) {
                this.onTransitionEnd(null);
            }
        }
    };
    /**
     * @hidden
     * Create ghost element - if a Node object is provided it creates a clone of that node,
     * otherwise it clones the host element.
     * Bind all needed events.
     * @param pageX Latest pointer position on the X axis relative to the page.
     * @param pageY Latest pointer position on the Y axis relative to the page.
     * @param node The Node object to be cloned.
     */
    IgxDragDirective.prototype.createGhost = function (pageX, pageY, node) {
        var _this = this;
        if (node === void 0) { node = null; }
        if (!this.ghost) {
            return;
        }
        var dynamicGhostRef;
        if (this.ghostTemplate) {
            dynamicGhostRef = this.viewContainer.createEmbeddedView(this.ghostTemplate, this.ghostContext);
            this.ghostElement = dynamicGhostRef.rootNodes[0];
        }
        else {
            this.ghostElement = node ? node.cloneNode(true) : this.element.nativeElement.cloneNode(true);
        }
        var totalMovedX = pageX - this._startX;
        var totalMovedY = pageY - this._startY;
        this._ghostHostX = this.ghostHost ? this.ghostHostOffsetLeft(this.ghostHost) : 0;
        this._ghostHostY = this.ghostHost ? this.ghostHostOffsetTop(this.ghostHost) : 0;
        this.ghostElement.style.transitionDuration = '0.0s';
        this.ghostElement.style.position = 'absolute';
        if (this.ghostClass) {
            this.renderer.addClass(this.ghostElement, this.ghostClass);
        }
        var createEventArgs = {
            owner: this,
            ghostElement: this.ghostElement,
            cancel: false
        };
        this.ghostCreate.emit(createEventArgs);
        if (createEventArgs.cancel) {
            this.ghostElement = null;
            if (this.ghostTemplate && dynamicGhostRef) {
                dynamicGhostRef.destroy();
            }
            return;
        }
        if (this.ghostHost) {
            this.ghostHost.appendChild(this.ghostElement);
        }
        else {
            document.body.appendChild(this.ghostElement);
        }
        var ghostMarginLeft = parseInt(document.defaultView.getComputedStyle(this.ghostElement)['margin-left'], 10);
        var ghostMarginTop = parseInt(document.defaultView.getComputedStyle(this.ghostElement)['margin-top'], 10);
        this.ghostElement.style.left = (this._ghostStartX - ghostMarginLeft + totalMovedX - this._ghostHostX) + 'px';
        this.ghostElement.style.top = (this._ghostStartY - ghostMarginTop + totalMovedY - this._ghostHostX) + 'px';
        if (this.pointerEventsEnabled) {
            // The ghostElement takes control for moving and dragging after it has been rendered.
            if (this._pointerDownId !== null) {
                this.ghostElement.setPointerCapture(this._pointerDownId);
            }
            this.ghostElement.addEventListener('pointermove', function (args) {
                _this.onPointerMove(args);
            });
            this.ghostElement.addEventListener('pointerup', function (args) {
                _this.onPointerUp(args);
            });
            this.ghostElement.addEventListener('lostpointercapture', function (args) {
                _this.onPointerLost(args);
            });
        }
        // Transition animation when the ghostElement is released and it returns to it's original position.
        this.ghostElement.addEventListener('transitionend', function (args) {
            _this.onTransitionEnd(args);
        });
        // Hide the base after the ghostElement is created, because otherwise the ghostElement will be not visible.
        if (this.hideBaseOnDrag) {
            this.visible = false;
        }
        this.cdr.detectChanges();
    };
    /**
     * @hidden
     * Dispatch custom igxDragEnter/igxDragLeave events based on current pointer position and if drop area is under.
     */
    IgxDragDirective.prototype.dispatchDragEvents = function (pageX, pageY, originalEvent) {
        var topDropArea;
        var customEventArgs = {
            startX: this._startX,
            startY: this._startY,
            pageX: pageX,
            pageY: pageY,
            owner: this,
            originalEvent: originalEvent
        };
        var elementsFromPoint = this.getElementsAtPoint(pageX, pageY);
        for (var i = 0; i < elementsFromPoint.length; i++) {
            if (elementsFromPoint[i].getAttribute('droppable') === 'true' &&
                elementsFromPoint[i] !== this.ghostElement && elementsFromPoint[i] !== this.element.nativeElement) {
                topDropArea = elementsFromPoint[i];
                break;
            }
        }
        if (topDropArea &&
            (!this._lastDropArea || (this._lastDropArea && this._lastDropArea !== topDropArea))) {
            if (this._lastDropArea) {
                this.dispatchEvent(this._lastDropArea, 'igxDragLeave', customEventArgs);
            }
            this._lastDropArea = topDropArea;
            this.dispatchEvent(this._lastDropArea, 'igxDragEnter', customEventArgs);
        }
        else if (!topDropArea && this._lastDropArea) {
            this.dispatchEvent(this._lastDropArea, 'igxDragLeave', customEventArgs);
            this._lastDropArea = null;
            return;
        }
        if (topDropArea) {
            this.dispatchEvent(topDropArea, 'igxDragOver', customEventArgs);
        }
    };
    /**
     * @hidden
     * Dispatch custom igxDrop event based on current pointer position if there is last recorder drop area under the pointer.
     * Last recorder drop area is updated in @dispatchDragEvents method.
     */
    IgxDragDirective.prototype.dispatchDropEvent = function (pageX, pageY, originalEvent) {
        var eventArgs = {
            startX: this._startX,
            startY: this._startY,
            pageX: pageX,
            pageY: pageY,
            owner: this,
            originalEvent: originalEvent
        };
        this.dispatchEvent(this._lastDropArea, 'igxDrop', eventArgs);
        this.dispatchEvent(this._lastDropArea, 'igxDragLeave', eventArgs);
        this._lastDropArea = null;
    };
    /**
     * @hidden
     */
    IgxDragDirective.prototype.onTransitionEnd = function (event) {
        var _this = this;
        if ((!this._dragStarted && !this.animInProgress) || this._clicked) {
            // Return if no dragging started and there is no animation in progress.
            return;
        }
        if (this.ghost && this.ghostElement) {
            this._ghostStartX = this.baseLeft + this.getWindowScrollLeft();
            this._ghostStartY = this.baseTop + this.getWindowScrollTop();
            var ghostDestroyArgs = {
                owner: this,
                ghostElement: this.ghostElement,
                cancel: false
            };
            this.ghostDestroy.emit(ghostDestroyArgs);
            if (ghostDestroyArgs.cancel) {
                return;
            }
            if (this.hideBaseOnDrag) {
                this.visible = true;
            }
            this.ghostElement.parentNode.removeChild(this.ghostElement);
            this.ghostElement = null;
        }
        else if (!this.ghost) {
            this.element.nativeElement.style.transitionProperty = '';
            this.element.nativeElement.style.transitionDuration = '0.0s';
            this.element.nativeElement.style.transitionTimingFunction = '';
            this.element.nativeElement.style.transitionDelay = '';
        }
        this.animInProgress = false;
        this._dragStarted = false;
        // Execute transitioned after everything is reset so if the user sets new location on the base now it would work as expected.
        this.zone.run(function () {
            _this.transitioned.emit({
                originalEvent: event,
                owner: _this,
                startX: _this._startX,
                startY: _this._startY,
                pageX: _this._startX,
                pageY: _this._startY
            });
        });
    };
    /**
     * @hidden
     */
    IgxDragDirective.prototype.getElementsAtPoint = function (pageX, pageY) {
        // correct the coordinates with the current scroll position, because
        // document.elementsFromPoint consider position within the current viewport
        // window.pageXOffset == window.scrollX; // always true
        // using window.pageXOffset for IE9 compatibility
        var viewPortX = pageX - window.pageXOffset;
        var viewPortY = pageY - window.pageYOffset;
        if (document['msElementsFromPoint']) {
            // Edge and IE special snowflakes
            var elements = document['msElementsFromPoint'](viewPortX, viewPortY);
            return elements === null ? [] : elements;
        }
        else {
            // Other browsers like Chrome, Firefox, Opera
            return document.elementsFromPoint(viewPortX, viewPortY);
        }
    };
    /**
     * @hidden
     */
    IgxDragDirective.prototype.dispatchEvent = function (target, eventName, eventArgs) {
        // This way is IE11 compatible.
        var dragLeaveEvent = document.createEvent('CustomEvent');
        dragLeaveEvent.initCustomEvent(eventName, false, false, eventArgs);
        target.dispatchEvent(dragLeaveEvent);
        // Otherwise can be used `target.dispatchEvent(new CustomEvent(eventName, eventArgs));`
    };
    IgxDragDirective.prototype.getTransformX = function (elem) {
        var posX = 0;
        if (elem.style.transform) {
            var matrix = elem.style.transform;
            var values = matrix ? matrix.match(/-?[\d\.]+/g) : undefined;
            posX = values ? Number(values[1]) : 0;
        }
        return posX;
    };
    IgxDragDirective.prototype.getTransformY = function (elem) {
        var posY = 0;
        if (elem.style.transform) {
            var matrix = elem.style.transform;
            var values = matrix ? matrix.match(/-?[\d\.]+/g) : undefined;
            posY = values ? Number(values[2]) : 0;
        }
        return posY;
    };
    /** Method setting transformation to the base draggable element. */
    IgxDragDirective.prototype.setTransformXY = function (x, y) {
        this.element.nativeElement.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0px)';
    };
    IgxDragDirective.prototype.getWindowScrollTop = function () {
        return window.scrollY ? window.scrollY : (window.pageYOffset ? window.pageYOffset : 0);
    };
    IgxDragDirective.prototype.getWindowScrollLeft = function () {
        return window.scrollX ? window.scrollX : (window.pageXOffset ? window.pageXOffset : 0);
    };
    IgxDragDirective.prototype.ghostHostOffsetLeft = function (ghostHost) {
        var ghostPosition = document.defaultView.getComputedStyle(ghostHost).getPropertyValue('position');
        if (ghostPosition === 'static' && ghostHost.offsetParent && ghostHost.offsetParent === document.body) {
            return 0;
        }
        else if (ghostPosition === 'static' && ghostHost.offsetParent) {
            return ghostHost.offsetParent.getBoundingClientRect().left - this.getWindowScrollLeft();
        }
        return ghostHost.getBoundingClientRect().left - this.getWindowScrollLeft();
    };
    IgxDragDirective.prototype.ghostHostOffsetTop = function (ghostHost) {
        var ghostPosition = document.defaultView.getComputedStyle(ghostHost).getPropertyValue('position');
        if (ghostPosition === 'static' && ghostHost.offsetParent && ghostHost.offsetParent === document.body) {
            return 0;
        }
        else if (ghostPosition === 'static' && ghostHost.offsetParent) {
            return ghostHost.offsetParent.getBoundingClientRect().top - this.getWindowScrollTop();
        }
        return ghostHost.getBoundingClientRect().top - this.getWindowScrollTop();
    };
    IgxDragDirective.ctorParameters = function () { return [
        { type: ChangeDetectorRef },
        { type: ElementRef },
        { type: ViewContainerRef },
        { type: NgZone },
        { type: Renderer2 }
    ]; };
    __decorate([
        Input('igxDrag'),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "data", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "dragTolerance", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "dragChannel", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "ghost", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "ghostClass", void 0);
    __decorate([
        DeprecateProperty("'hideBaseOnDrag' @Input property is deprecated and will be removed in future major versions.\n        Alternatives to it are using the new no ghost dragging and custom base styling."),
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "hideBaseOnDrag", void 0);
    __decorate([
        DeprecateProperty("'animateOnRelease' @Input property is deprecated and will be removed in future major versions.\n        Please use 'transitionToOrigin' or 'transitionTo' methods instead."),
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "animateOnRelease", void 0);
    __decorate([
        Input(),
        __metadata("design:type", TemplateRef)
    ], IgxDragDirective.prototype, "ghostTemplate", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "ghostHost", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [Object])
    ], IgxDragDirective.prototype, "ghostOffsetX", null);
    __decorate([
        Input(),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [Object])
    ], IgxDragDirective.prototype, "ghostOffsetY", null);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "dragStart", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "dragMove", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "dragEnd", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "dragClick", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "ghostCreate", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "ghostDestroy", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "transitioned", void 0);
    __decorate([
        ContentChildren(IgxDragHandleDirective),
        __metadata("design:type", QueryList)
    ], IgxDragDirective.prototype, "dragHandles", void 0);
    __decorate([
        HostBinding('style.visibility'),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "_visibility", void 0);
    __decorate([
        HostBinding('class.igx-drag'),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "baseClass", void 0);
    __decorate([
        HostBinding('class.igx-drag--select-disabled'),
        __metadata("design:type", Object)
    ], IgxDragDirective.prototype, "selectDisabled", void 0);
    __decorate([
        DeprecateProperty("'visible' @Input property is deprecated and will be removed in future major versions.\n        Please use native angular ways of hiding the base element using styling."),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [Object])
    ], IgxDragDirective.prototype, "visible", null);
    IgxDragDirective = __decorate([
        Directive({
            exportAs: 'drag',
            selector: '[igxDrag]'
        }),
        __metadata("design:paramtypes", [ChangeDetectorRef,
            ElementRef,
            ViewContainerRef,
            NgZone,
            Renderer2])
    ], IgxDragDirective);
    return IgxDragDirective;
}());
export { IgxDragDirective };
var IgxDropDirective = /** @class */ (function () {
    function IgxDropDirective(element, _renderer, _zone) {
        this.element = element;
        this._renderer = _renderer;
        this._zone = _zone;
        /** Event triggered when dragged element enters the area of the element.
         * ```html
         * <div class="cageArea" igxDrop (enter)="dragEnter()" (igxDragEnter)="onDragCageEnter()" (igxDragLeave)="onDragCageLeave()">
         * </div>
         * ```
         * ```typescript
         * public dragEnter(){
         *     alert("A draggable element has entered the chip area!");
         * }
         * ```
         * @memberof IgxDropDirective
         */
        this.enter = new EventEmitter();
        /** Event triggered when dragged element enters the area of the element.
     * ```html
     * <div class="cageArea" igxDrop (enter)="dragEnter()" (igxDragEnter)="onDragCageEnter()" (igxDragLeave)="onDragCageLeave()">
     * </div>
     * ```
     * ```typescript
     * public dragEnter(){
     *     alert("A draggable element has entered the chip area!");
     * }
     * ```
     * @memberof IgxDropDirective
     */
        this.over = new EventEmitter();
        /** Event triggered when dragged element leaves the area of the element.
         * ```html
         * <div class="cageArea" igxDrop (leave)="dragLeave()" (igxDragEnter)="onDragCageEnter()" (igxDragLeave)="onDragCageLeave()">
         * </div>
         * ```
         * ```typescript
         * public dragLeave(){
         *     alert("A draggable element has left the chip area!");
         * }
         * ```
         * @memberof IgxDropDirective
         */
        this.leave = new EventEmitter();
        /** Event triggered when dragged element is dropped in the area of the element.
         * Since the `igxDrop` has default logic that appends the dropped element as a child, it can be canceled here.
         * To cancel the default logic the `cancel` property of the event needs to be set to true.
         * ```html
         * <div class="cageArea" igxDrop (dropped)="dragDrop()" (igxDragEnter)="onDragCageEnter()" (igxDragLeave)="onDragCageLeave()">
         * </div>
         * ```
         * ```typescript
         * public dragDrop(){
         *     alert("A draggable element has been dropped in the chip area!");
         * }
         * ```
         * @memberof IgxDropDirective
         */
        this.dropped = new EventEmitter();
        /**
         * @hidden
         */
        this.droppable = true;
        /**
         * @hidden
         */
        this.dragover = false;
        /**
         * @hidden
         */
        this._destroy = new Subject();
        this._dropStrategy = new IgxDefaultDropStrategy();
    }
    Object.defineProperty(IgxDropDirective.prototype, "dropStrategy", {
        get: function () {
            return this._dropStrategy;
        },
        /**
         * An @Input property that specifies a drop strategy type that will be executed when an `IgxDrag` element is released inside
         *  the current drop area. The provided strategies are:
         *  - IgxDefaultDropStrategy - This is the default base strategy and it doesn't perform any actions.
         *  - IgxAppendDropStrategy - Appends the dropped element to last position as a direct child to the `igxDrop`.
         *  - IgxPrependDropStrategy - Prepends the dropped element to first position as a direct child to the `igxDrop`.
         *  - IgxInsertDropStrategy - If the dropped element is released above a child element of the `igxDrop`, it will be inserted
         *      at that position. Otherwise the dropped element will be appended if released outside any child of the `igxDrop`.
         * ```html
         * <div igxDrag>
         *      <span>DragMe</span>
         * </div>
         * <div igxDrop [dropStrategy]="myDropStrategy">
         *         <span>Numbers drop area!</span>
         * </div>
         * ```
         * ```typescript
         * import { IgxAppendDropStrategy } from 'igniteui-angular';
         *
         * export class App {
         *      public myDropStrategy = IgxAppendDropStrategy;
         * }
         * ```
         * @memberof IgxDropDirective
         */
        set: function (classRef) {
            this._dropStrategy = new classRef(this._renderer);
        },
        enumerable: true,
        configurable: true
    });
    /**
     * @hidden
     */
    IgxDropDirective.prototype.ngOnInit = function () {
        var _this = this;
        this._zone.runOutsideAngular(function () {
            fromEvent(_this.element.nativeElement, 'igxDragEnter').pipe(takeUntil(_this._destroy))
                .subscribe(function (res) { return _this.onDragEnter(res); });
            fromEvent(_this.element.nativeElement, 'igxDragLeave').pipe(takeUntil(_this._destroy)).subscribe(function (res) { return _this.onDragLeave(res); });
            fromEvent(_this.element.nativeElement, 'igxDragOver').pipe(takeUntil(_this._destroy)).subscribe(function (res) { return _this.onDragOver(res); });
        });
    };
    /**
     * @hidden
     */
    IgxDropDirective.prototype.ngOnDestroy = function () {
        this._destroy.next(true);
        this._destroy.complete();
    };
    /**
     * @hidden
     */
    IgxDropDirective.prototype.onDragOver = function (event) {
        var elementPosX = this.element.nativeElement.getBoundingClientRect().left + this.getWindowScrollLeft();
        var elementPosY = this.element.nativeElement.getBoundingClientRect().top + this.getWindowScrollTop();
        var offsetX = event.detail.pageX - elementPosX;
        var offsetY = event.detail.pageY - elementPosY;
        var eventArgs = {
            originalEvent: event.detail.originalEvent,
            owner: this,
            drag: event.detail.owner,
            dragData: event.detail.owner.data,
            startX: event.detail.startX,
            startY: event.detail.startY,
            pageX: event.detail.pageX,
            pageY: event.detail.pageY,
            offsetX: offsetX,
            offsetY: offsetY
        };
        this.over.emit(eventArgs);
    };
    /**
     * @hidden
     */
    IgxDropDirective.prototype.onDragEnter = function (event) {
        var _this = this;
        if (!this.isDragLinked(event.detail.owner)) {
            return;
        }
        this.dragover = true;
        var elementPosX = this.element.nativeElement.getBoundingClientRect().left + this.getWindowScrollLeft();
        var elementPosY = this.element.nativeElement.getBoundingClientRect().top + this.getWindowScrollTop();
        var offsetX = event.detail.pageX - elementPosX;
        var offsetY = event.detail.pageY - elementPosY;
        var eventArgs = {
            originalEvent: event.detail.originalEvent,
            owner: this,
            drag: event.detail.owner,
            dragData: event.detail.owner.data,
            startX: event.detail.startX,
            startY: event.detail.startY,
            pageX: event.detail.pageX,
            pageY: event.detail.pageY,
            offsetX: offsetX,
            offsetY: offsetY
        };
        this._zone.run(function () {
            _this.enter.emit(eventArgs);
        });
    };
    /**
     * @hidden
     */
    IgxDropDirective.prototype.onDragLeave = function (event) {
        var _this = this;
        if (!this.isDragLinked(event.detail.owner)) {
            return;
        }
        this.dragover = false;
        var elementPosX = this.element.nativeElement.getBoundingClientRect().left + this.getWindowScrollLeft();
        var elementPosY = this.element.nativeElement.getBoundingClientRect().top + this.getWindowScrollTop();
        var offsetX = event.detail.pageX - elementPosX;
        var offsetY = event.detail.pageY - elementPosY;
        var eventArgs = {
            originalEvent: event.detail.originalEvent,
            owner: this,
            drag: event.detail.owner,
            dragData: event.detail.owner.data,
            startX: event.detail.startX,
            startY: event.detail.startY,
            pageX: event.detail.pageX,
            pageY: event.detail.pageY,
            offsetX: offsetX,
            offsetY: offsetY
        };
        this._zone.run(function () {
            _this.leave.emit(eventArgs);
        });
    };
    /**
     * @hidden
     */
    IgxDropDirective.prototype.onDragDrop = function (event) {
        var _this = this;
        if (!this.isDragLinked(event.detail.owner)) {
            return;
        }
        var elementPosX = this.element.nativeElement.getBoundingClientRect().left + this.getWindowScrollLeft();
        var elementPosY = this.element.nativeElement.getBoundingClientRect().top + this.getWindowScrollTop();
        var offsetX = event.detail.pageX - elementPosX;
        var offsetY = event.detail.pageY - elementPosY;
        var args = {
            owner: this,
            originalEvent: event.detail.originalEvent,
            drag: event.detail.owner,
            dragData: event.detail.owner.data,
            startX: event.detail.startX,
            startY: event.detail.startY,
            pageX: event.detail.pageX,
            pageY: event.detail.pageY,
            offsetX: offsetX,
            offsetY: offsetY,
            cancel: false
        };
        this._zone.run(function () {
            _this.dropped.emit(args);
        });
        if (this._dropStrategy && !args.cancel) {
            var elementsAtPoint = event.detail.owner.getElementsAtPoint(event.detail.pageX, event.detail.pageY);
            var insertIndex = this.getInsertIndexAt(event.detail.owner, elementsAtPoint);
            this._dropStrategy.dropAction(event.detail.owner, this, insertIndex);
        }
    };
    IgxDropDirective.prototype.getWindowScrollTop = function () {
        return window.scrollY ? window.scrollY : (window.pageYOffset ? window.pageYOffset : 0);
    };
    IgxDropDirective.prototype.getWindowScrollLeft = function () {
        return window.scrollX ? window.scrollX : (window.pageXOffset ? window.pageXOffset : 0);
    };
    IgxDropDirective.prototype.isDragLinked = function (drag) {
        var dragLinkArray = drag.dragChannel instanceof Array;
        var dropLinkArray = this.dropChannel instanceof Array;
        if (!dragLinkArray && !dropLinkArray) {
            return this.dropChannel === drag.dragChannel;
        }
        else if (!dragLinkArray && dropLinkArray) {
            var dropLinks = this.dropChannel;
            for (var i = 0; i < dropLinks.length; i++) {
                if (dropLinks[i] === drag.dragChannel) {
                    return true;
                }
            }
        }
        else if (dragLinkArray && !dropLinkArray) {
            var dragLinks = drag.dragChannel;
            for (var i = 0; i < dragLinks.length; i++) {
                if (dragLinks[i] === this.dropChannel) {
                    return true;
                }
            }
        }
        else {
            var dragLinks = drag.dragChannel;
            var dropLinks = this.dropChannel;
            for (var i = 0; i < dragLinks.length; i++) {
                for (var j = 0; j < dropLinks.length; j++) {
                    if (dragLinks[i] === dropLinks[j]) {
                        return true;
                    }
                }
            }
        }
        return false;
    };
    IgxDropDirective.prototype.getInsertIndexAt = function (draggedDir, elementsAtPoint) {
        var insertIndex = -1;
        var dropChildren = Array.prototype.slice.call(this.element.nativeElement.children);
        if (!dropChildren.length) {
            return insertIndex;
        }
        var i = 0;
        var childUnder = null;
        while (!childUnder && i < elementsAtPoint.length) {
            if (elementsAtPoint[i].parentElement === this.element.nativeElement) {
                childUnder = elementsAtPoint[i];
            }
            i++;
        }
        var draggedElemIndex = dropChildren.indexOf(draggedDir.element.nativeElement);
        insertIndex = dropChildren.indexOf(childUnder);
        if (draggedElemIndex !== -1 && draggedElemIndex < insertIndex) {
            insertIndex++;
        }
        return insertIndex;
    };
    IgxDropDirective.ctorParameters = function () { return [
        { type: ElementRef },
        { type: Renderer2 },
        { type: NgZone }
    ]; };
    __decorate([
        Input('igxDrop'),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "data", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "dropChannel", void 0);
    __decorate([
        Input(),
        __metadata("design:type", Object),
        __metadata("design:paramtypes", [Object])
    ], IgxDropDirective.prototype, "dropStrategy", null);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "enter", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "over", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "leave", void 0);
    __decorate([
        Output(),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "dropped", void 0);
    __decorate([
        HostBinding('attr.droppable'),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "droppable", void 0);
    __decorate([
        HostBinding('class.dragOver'),
        __metadata("design:type", Object)
    ], IgxDropDirective.prototype, "dragover", void 0);
    __decorate([
        HostListener('igxDrop', ['$event']),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", void 0)
    ], IgxDropDirective.prototype, "onDragDrop", null);
    IgxDropDirective = __decorate([
        Directive({
            exportAs: 'drop',
            selector: '[igxDrop]'
        }),
        __metadata("design:paramtypes", [ElementRef, Renderer2, NgZone])
    ], IgxDropDirective);
    return IgxDropDirective;
}());
export { IgxDropDirective };
/**
 * @hidden
 */
var IgxDragDropModule = /** @class */ (function () {
    function IgxDragDropModule() {
    }
    IgxDragDropModule = __decorate([
        NgModule({
            declarations: [IgxDragDirective, IgxDropDirective, IgxDragHandleDirective],
            exports: [IgxDragDirective, IgxDropDirective, IgxDragHandleDirective]
        })
    ], IgxDragDropModule);
    return IgxDragDropModule;
}());
export { IgxDragDropModule };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZy1kcm9wLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZGlyZWN0aXZlcy9kcmFnLWRyb3AvZHJhZy1kcm9wLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFdBQVcsRUFDWCxZQUFZLEVBQ1osS0FBSyxFQUNMLFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sU0FBUyxFQUNULGlCQUFpQixFQUNqQixnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLFdBQVcsRUFDWCxlQUFlLEVBQ2YsU0FBUyxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3RSxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRW5FLE9BQU8sRUFBaUIsc0JBQXNCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUU3RSxNQUFNLENBQU4sSUFBWSxZQUlYO0FBSkQsV0FBWSxZQUFZO0lBQ3BCLDJEQUFVLENBQUE7SUFDViwrREFBWSxDQUFBO0lBQ1osK0NBQUksQ0FBQTtBQUNSLENBQUMsRUFKVyxZQUFZLEtBQVosWUFBWSxRQUl2QjtBQTBHRDtJQUlJLHlCQUFvQixNQUFNLEVBQVUsTUFBTTtRQUF0QixXQUFNLEdBQU4sTUFBTSxDQUFBO1FBQVUsV0FBTSxHQUFOLE1BQU0sQ0FBQTtRQUN0QyxJQUFJLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxNQUFN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LGdCQUFnQjtRQUo1QixTQUFTLENBQUM7WUFDUCxRQUFRLEVBQUUsTUFBTTtZQUNoQixRQUFRLEVBQUUsV0FBVztTQUN4QixDQUFDO3lDQStJOEIsVUFBVSxFQUFxQixTQUFTLEVBQWlCLE1BQU07T0E5SWxGLGdCQUFnQixDQW1XNUI7SUFBRCx1QkFBQztDQUFBLEFBbldELElBbVdDO1NBbldZLGdCQUFnQjtBQXNXN0I7O0dBRUc7QUFLSDtJQUFBO0lBQWlDLENBQUM7SUFBckIsaUJBQWlCO1FBSjdCLFFBQVEsQ0FBQztZQUNOLFlBQVksRUFBRSxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLHNCQUFzQixDQUFDO1lBQzFFLE9BQU8sRUFBRSxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLHNCQUFzQixDQUFDO1NBQ3hFLENBQUM7T0FDVyxpQkFBaUIsQ0FBSTtJQUFELHdCQUFDO0NBQUEsQUFBbEMsSUFBa0M7U0FBckIsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBEaXJlY3RpdmUsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgSG9zdEJpbmRpbmcsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIElucHV0LFxuICAgIE5nTW9kdWxlLFxuICAgIE5nWm9uZSxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT25Jbml0LFxuICAgIE91dHB1dCxcbiAgICBSZW5kZXJlcjIsXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgVmlld0NvbnRhaW5lclJlZixcbiAgICBBZnRlckNvbnRlbnRJbml0LFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIENvbnRlbnRDaGlsZHJlbixcbiAgICBRdWVyeUxpc3Rcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBhbmltYXRpb25GcmFtZVNjaGVkdWxlciwgZnJvbUV2ZW50LCBpbnRlcnZhbCwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsLCB0aHJvdHRsZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElneERyYWdIYW5kbGVEaXJlY3RpdmUgfSBmcm9tICcuL2RyYWctaGFuZGxlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBEZXByZWNhdGVQcm9wZXJ0eSB9IGZyb20gJy4uLy4uL2NvcmUvZGVwcmVjYXRlRGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBJQmFzZUV2ZW50QXJncyB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbHMnO1xuaW1wb3J0IHsgSURyb3BTdHJhdGVneSwgSWd4RGVmYXVsdERyb3BTdHJhdGVneSB9IGZyb20gJy4vZHJhZy1kcm9wLnN0cmF0ZWd5JztcblxuZXhwb3J0IGVudW0gUmVzdHJpY3REcmFnIHtcbiAgICBWRVJUSUNBTExZLFxuICAgIEhPUklaT05UQUxMWSxcbiAgICBOT05FXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSWd4RHJhZ0N1c3RvbUV2ZW50RGV0YWlscyB7XG4gICAgc3RhcnRYOiBudW1iZXI7XG4gICAgc3RhcnRZOiBudW1iZXI7XG4gICAgcGFnZVg6IG51bWJlcjtcbiAgICBwYWdlWTogbnVtYmVyO1xuICAgIG93bmVyOiBJZ3hEcmFnRGlyZWN0aXZlO1xuICAgIG9yaWdpbmFsRXZlbnQ6IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRHJvcEJhc2VFdmVudEFyZ3MgZXh0ZW5kcyBJQmFzZUV2ZW50QXJncyB7XG4gICAgICAgIC8qKlxuICAgICAqIFJlZmVyZW5jZSB0byB0aGUgb3JpZ2luYWwgZXZlbnQgdGhhdCBjYXVzZWQgdGhlIGRyYWdnYWJsZSBlbGVtZW50IHRvIGVudGVyIHRoZSBpZ3hEcm9wIGVsZW1lbnQuXG4gICAgICogQ2FuIGJlIFBvaW50ZXJFdmVudCwgVG91Y2hFdmVudCBvciBNb3VzZUV2ZW50LlxuICAgICAqL1xuICAgIG9yaWdpbmFsRXZlbnQ6IGFueTtcbiAgICAvKiogVGhlIG93bmVyIGlneERyb3AgZGlyZWN0aXZlIHRoYXQgdHJpZ2dlcmVkIHRoaXMgZXZlbnQuICovXG4gICAgb3duZXI6IElneERyb3BEaXJlY3RpdmU7XG4gICAgLyoqIFRoZSBpZ3hEcmFnIGRpcmVjdGl2ZSBpbnN0YW5jZWQgb24gYW4gZWxlbWVudCB0aGF0IGVudGVyZWQgdGhlIGFyZWEgb2YgdGhlIGlneERyb3AgZWxlbWVudCAqL1xuICAgIGRyYWc6IElneERyYWdEaXJlY3RpdmU7XG4gICAgLyoqIFRoZSBkYXRhIGNvbnRhaW5lZCBmb3IgdGhlIGRyYWdnYWJsZSBlbGVtZW50IGluIGlneERyYWcgZGlyZWN0aXZlLiAqL1xuICAgIGRyYWdEYXRhOiBhbnk7XG4gICAgLyoqIFRoZSBpbml0aWFsIHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIG9uIFggYXhpcyB3aGVuIHRoZSBkcmFnZ2VkIGVsZW1lbnQgYmVnYW4gbW92aW5nICovXG4gICAgc3RhcnRYOiBudW1iZXI7XG4gICAgLyoqIFRoZSBpbml0aWFsIHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIG9uIFkgYXhpcyB3aGVuIHRoZSBkcmFnZ2VkIGVsZW1lbnQgYmVnYW4gbW92aW5nICovXG4gICAgc3RhcnRZOiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgcG9zaXRpb24gb2YgdGhlIHBvaW50ZXIgb24gWCBheGlzIHdoZW4gdGhlIGV2ZW50IHdhcyB0cmlnZ2VyZWQuXG4gICAgICogTm90ZTogVGhlIGJyb3dzZXIgbWlnaHQgdHJpZ2dlciB0aGUgZXZlbnQgd2l0aCBzb21lIGRlbGF5IGFuZCBwb2ludGVyIHdvdWxkIGJlIGFscmVhZHkgaW5zaWRlIHRoZSBpZ3hEcm9wLlxuICAgICAqL1xuICAgIHBhZ2VYOiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgcG9zaXRpb24gb2YgdGhlIHBvaW50ZXIgb24gWSBheGlzIHdoZW4gdGhlIGV2ZW50IHdhcyB0cmlnZ2VyZWQuXG4gICAgICogTm90ZTogVGhlIGJyb3dzZXIgbWlnaHQgdHJpZ2dlciB0aGUgZXZlbnQgd2l0aCBzb21lIGRlbGF5IGFuZCBwb2ludGVyIHdvdWxkIGJlIGFscmVhZHkgaW5zaWRlIHRoZSBpZ3hEcm9wLlxuICAgICAqL1xuICAgIHBhZ2VZOiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgcG9zaXRpb24gb2YgdGhlIHBvaW50ZXIgb24gWCBheGlzIHJlbGF0aXZlIHRvIHRoZSBjb250YWluZXIgdGhhdCBpbml0aWFsaXplcyB0aGUgaWd4RHJvcC5cbiAgICAgKiBOb3RlOiBUaGUgYnJvd3NlciBtaWdodCB0cmlnZ2VyIHRoZSBldmVudCB3aXRoIHNvbWUgZGVsYXkgYW5kIHBvaW50ZXIgd291bGQgYmUgYWxyZWFkeSBpbnNpZGUgdGhlIGlneERyb3AuXG4gICAgICovXG4gICAgb2Zmc2V0WDogbnVtYmVyO1xuICAgIC8qKlxuICAgICAqIFRoZSBjdXJyZW50IHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIG9uIFkgYXhpcyByZWxhdGl2ZSB0byB0aGUgY29udGFpbmVyIHRoYXQgaW5pdGlhbGl6ZXMgdGhlIGlneERyb3AuXG4gICAgICogTm90ZTogVGhlIGJyb3dzZXIgbWlnaHQgdHJpZ2dlciB0aGUgZXZlbnQgd2l0aCBzb21lIGRlbGF5IGFuZCBwb2ludGVyIHdvdWxkIGJlIGFscmVhZHkgaW5zaWRlIHRoZSBpZ3hEcm9wLlxuICAgICAqL1xuICAgIG9mZnNldFk6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRHJvcERyb3BwZWRFdmVudEFyZ3MgZXh0ZW5kcyBJRHJvcEJhc2VFdmVudEFyZ3Mge1xuICAgIC8qKiBTcGVjaWZpZXMgaWYgdGhlIGRlZmF1bHQgZHJvcCBsb2dpYyByZWxhdGVkIHRvIHRoZSBldmVudCBzaG91bGQgYmUgY2FuY2VsZWQuICovXG4gICAgY2FuY2VsOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElEcmFnQmFzZUV2ZW50QXJncyBleHRlbmRzIElCYXNlRXZlbnRBcmdzIHtcbiAgICAvKipcbiAgICAgKiBSZWZlcmVuY2UgdG8gdGhlIG9yaWdpbmFsIGV2ZW50IHRoYXQgY2F1c2VkIHRoZSBpbnRlcmFjdGlvbiB3aXRoIHRoZSBlbGVtZW50LlxuICAgICAqIENhbiBiZSBQb2ludGVyRXZlbnQsIFRvdWNoRXZlbnQgb3IgTW91c2VFdmVudC5cbiAgICAgKi9cbiAgICBvcmlnaW5hbEV2ZW50OiBQb2ludGVyRXZlbnQgfCBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudDtcbiAgICAvKiogVGhlIG93bmVyIGlneERyYWcgZGlyZWN0aXZlIHRoYXQgdHJpZ2dlcmVkIHRoaXMgZXZlbnQuICovXG4gICAgb3duZXI6IElneERyYWdEaXJlY3RpdmU7XG4gICAgLyoqIFRoZSBpbml0aWFsIHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIG9uIFggYXhpcyB3aGVuIHRoZSBkcmFnZ2VkIGVsZW1lbnQgYmVnYW4gbW92aW5nICovXG4gICAgc3RhcnRYOiBudW1iZXI7XG4gICAgLyoqIFRoZSBpbml0aWFsIHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIG9uIFkgYXhpcyB3aGVuIHRoZSBkcmFnZ2VkIGVsZW1lbnQgYmVnYW4gbW92aW5nICovXG4gICAgc3RhcnRZOiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogVGhlIGN1cnJlbnQgcG9zaXRpb24gb2YgdGhlIHBvaW50ZXIgb24gWCBheGlzIHdoZW4gdGhlIGV2ZW50IHdhcyB0cmlnZ2VyZWQuXG4gICAgICogTm90ZTogVGhlIGJyb3dzZXIgbWlnaHQgdHJpZ2dlciB0aGUgZXZlbnQgd2l0aCBzb21lIGRlbGF5IGFuZCBwb2ludGVyIHdvdWxkIGJlIGFscmVhZHkgaW5zaWRlIHRoZSBpZ3hEcm9wLlxuICAgICAqL1xuICAgIHBhZ2VYOiBudW1iZXI7XG4gICAgICAgIC8qKlxuICAgICAqIFRoZSBjdXJyZW50IHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIG9uIFkgYXhpcyB3aGVuIHRoZSBldmVudCB3YXMgdHJpZ2dlcmVkLlxuICAgICAqIE5vdGU6IFRoZSBicm93c2VyIG1pZ2h0IHRyaWdnZXIgdGhlIGV2ZW50IHdpdGggc29tZSBkZWxheSBhbmQgcG9pbnRlciB3b3VsZCBiZSBhbHJlYWR5IGluc2lkZSB0aGUgaWd4RHJvcC5cbiAgICAgKi9cbiAgICBwYWdlWTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElEcmFnU3RhcnRFdmVudEFyZ3MgZXh0ZW5kcyBJRHJhZ0Jhc2VFdmVudEFyZ3Mge1xuICAgIC8qKiBTZXQgaWYgdGhlIHRoZSBkcmFnZ2luZyBzaG91bGQgYmUgY2FuY2VsZWQuICovXG4gICAgY2FuY2VsOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElEcmFnTW92ZUV2ZW50QXJncyBleHRlbmRzIElEcmFnU3RhcnRFdmVudEFyZ3Mge1xuICAgIC8qKiBUaGUgbmV3IHBhZ2VYIHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIHRoYXQgdGhlIGlneERyYWcgd2lsbCB1c2UuIEl0IGNhbiBiZSBvdmVycmlkZGVuIHRvIGxpbWl0IGRyYWdnZWQgZWxlbWVudCBYIG1vdmVtZW50LiAqL1xuICAgIG5leHRQYWdlWDogbnVtYmVyO1xuICAgIC8qKiBUaGUgbmV3IHBhZ2VYIHBvc2l0aW9uIG9mIHRoZSBwb2ludGVyIHRoYXQgdGhlIGlneERyYWcgd2lsbCB1c2UuIEl0IGNhbiBiZSBvdmVycmlkZGVuIHRvIGxpbWl0IGRyYWdnZWQgZWxlbWVudCBZIG1vdmVtZW50LiAqL1xuICAgIG5leHRQYWdlWTogbnVtYmVyO1xufVxuXG5cbmV4cG9ydCBpbnRlcmZhY2UgSURyYWdHaG9zdEJhc2VFdmVudEFyZ3MgZXh0ZW5kcyBJQmFzZUV2ZW50QXJncyB7XG4gICAgLyoqIFRoZSBvd25lciBpZ3hEcmFnIGRpcmVjdGl2ZSB0aGF0IHRyaWdnZXJlZCB0aGlzIGV2ZW50LiAqL1xuICAgIG93bmVyOiBJZ3hEcmFnRGlyZWN0aXZlO1xuICAgIC8qKiBJbnN0YW5jZSB0byB0aGUgZ2hvc3QgZWxlbWVudCB0aGF0IGlzIGNyZWF0ZWQgd2hlbiBkcmFnZ2luZyBzdGFydHMuICovXG4gICAgZ2hvc3RFbGVtZW50OiBhbnk7XG4gICAgLyoqIFNldCBpZiB0aGUgZ2hvc3QgY3JlYXRpb24vZGVzdHJ1Y3Rpb24gc2hvdWxkIGJlIGNhbmNlbGVkLiAqL1xuICAgIGNhbmNlbDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRHJhZ0N1c3RvbVRyYW5zaXRpb25BcmdzIHtcbiAgICBkdXJhdGlvbj86IG51bWJlcjtcbiAgICB0aW1pbmdGdW5jdGlvbj86IHN0cmluZztcbiAgICBkZWxheT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIElneERyYWdMb2NhdGlvbiB7XG4gICAgcHVibGljIHBhZ2VYOiBudW1iZXI7XG4gICAgcHVibGljIHBhZ2VZOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9wYWdlWCwgcHJpdmF0ZSBfcGFnZVkpIHtcbiAgICAgICAgdGhpcy5wYWdlWCA9IHBhcnNlRmxvYXQoX3BhZ2VYKTtcbiAgICAgICAgdGhpcy5wYWdlWSA9IHBhcnNlRmxvYXQoX3BhZ2VZKTtcbiAgICB9XG59XG5cbkBEaXJlY3RpdmUoe1xuICAgIGV4cG9ydEFzOiAnZHJhZycsXG4gICAgc2VsZWN0b3I6ICdbaWd4RHJhZ10nXG59KVxuZXhwb3J0IGNsYXNzIElneERyYWdEaXJlY3RpdmUgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkRlc3Ryb3kge1xuXG4gICAgcHJvdGVjdGVkIGdob3N0Q29udGV4dDogYW55ID0gbnVsbDtcblxuICAgIC8qKlxuICAgICAqIC0gU2F2ZSBkYXRhIGluc2lkZSB0aGUgYGlneERyYWdgIGRpcmVjdGl2ZS4gVGhpcyBjYW4gYmUgc2V0IHdoZW4gaW5zdGFuY2luZyBgaWd4RHJhZ2Agb24gYW4gZWxlbWVudC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBbaWd4RHJhZ109XCJ7IHNvdXJjZTogbXlFbGVtZW50IH1cIj48L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBJbnB1dCgnaWd4RHJhZycpXG4gICAgcHVibGljIGRhdGE6IGFueTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IGluZGljYXRlcyB3aGVuIHRoZSBkcmFnIHNob3VsZCBzdGFydC5cbiAgICAgKiBCeSBkZWZhdWx0IHRoZSBkcmFnIHN0YXJ0cyBhZnRlciB0aGUgZHJhZ2dhYmxlIGVsZW1lbnQgaXMgbW92ZWQgYnkgNXB4LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2IGlneERyYWcgW2RyYWdUb2xlcmFuY2VdPVwiMTAwXCI+XG4gICAgICogICAgICAgICA8c3Bhbj5EcmFnIE1lITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGRyYWdUb2xlcmFuY2UgPSA1O1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgcHJvdmlkZSBhIHdheSBmb3IgaWd4RHJhZyBhbmQgaWd4RHJvcCB0byBiZSBsaW5rZWQgdGhyb3VnaCBjaGFubmVscy5cbiAgICAgKiBJdCBhY2NlcHRzIHNpbmdsZSB2YWx1ZSBvciBhbiBhcnJheSBvZiB2YWx1ZXMgYW5kIGV2YWx1YXRlcyB0aGVuIHVzaW5nIHN0cmljdCBlcXVhbGl0eS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBpZ3hEcmFnIFtkcmFnQ2hhbm5lbF09XCInb2RkJ1wiPlxuICAgICAqICAgICAgICAgPHNwYW4+OTU8L3NwYW4+XG4gICAgICogPC9kaXY+XG4gICAgICogPGRpdiBpZ3hEcm9wIFtkcm9wQ2hhbm5lbF09XCJbJ29kZCcsICdpcnJhdGlvbmFsJ11cIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPk51bWJlcnMgZHJvcCBhcmVhITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGRyYWdDaGFubmVsOiBudW1iZXIgfCBzdHJpbmcgfCBudW1iZXJbXSB8IHN0cmluZ1tdO1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc3BlY2lmaWVzIGlmIHRoZSBiYXNlIGVsZW1lbnQgc2hvdWxkIG5vdCBiZSBtb3ZlZCBhbmQgYSBnaG9zdCBlbGVtZW50IHNob3VsZCBiZSByZW5kZXJlZCB0aGF0IHJlcHJlc2VudHMgaXQuXG4gICAgICogQnkgZGVmYXVsdCBpdCBpcyBzZXQgdG8gYHRydWVgLlxuICAgICAqIElmIGl0IGlzIHNldCB0byBgZmFsc2VgIHdoZW4gZHJhZ2dpbmcgdGhlIGJhc2UgZWxlbWVudCBpcyBtb3ZlZCBpbnN0ZWFkIGFuZCBubyBnaG9zdCBlbGVtZW50cyBhcmUgcmVuZGVyZWQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgaWd4RHJhZyBbZ2hvc3RdPVwiZmFsc2VcIj5cbiAgICAgKiAgICAgIDxzcGFuPkRyYWcgTWUhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcmFnRGlyZWN0aXZlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2hvc3QgPSB0cnVlO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIGN1c3RvbSBjbGFzcyB0aGF0IHdpbGwgYmUgYWRkZWQgdG8gdGhlIGBnaG9zdEVsZW1lbnRgIGVsZW1lbnQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgaWd4RHJhZyBbZ2hvc3RDbGFzc109XCInZ2hvc3RFbGVtZW50J1wiPlxuICAgICAqICAgICAgICAgPHNwYW4+RHJhZyBNZSE8L3NwYW4+XG4gICAgICogPC9kaXY+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyYWdEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBnaG9zdENsYXNzID0gJyc7XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlIGN1c3RvbSBiYXNlIHN0eWxpbmcgaW5zdGVhZC5cbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBoaWRlcyB0aGUgZHJhZ2dhYmxlIGVsZW1lbnQuXG4gICAgICogQnkgZGVmYXVsdCBpdCdzIHNldCB0byBmYWxzZS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBpZ3hEcmFnIFtkcmFnVG9sZXJhbmNlXT1cIjEwMFwiIFtoaWRlQmFzZU9uRHJhZ109XCIndHJ1ZSdcIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPkRyYWcgTWUhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcmFnRGlyZWN0aXZlXG4gICAgICovXG4gICAgQERlcHJlY2F0ZVByb3BlcnR5KGAnaGlkZUJhc2VPbkRyYWcnIEBJbnB1dCBwcm9wZXJ0eSBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIG1ham9yIHZlcnNpb25zLlxuICAgICAgICBBbHRlcm5hdGl2ZXMgdG8gaXQgYXJlIHVzaW5nIHRoZSBuZXcgbm8gZ2hvc3QgZHJhZ2dpbmcgYW5kIGN1c3RvbSBiYXNlIHN0eWxpbmcuYClcbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBoaWRlQmFzZU9uRHJhZyA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBwcm92aWRlZCB0cmFuc2l0aW9uIGZ1bmN0aW9ucyBpbiBmdXR1cmUuXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgZW5hYmxlcy9kaXNhYmxlcyB0aGUgZHJhZ2dhYmxlIGVsZW1lbnQgYW5pbWF0aW9uXG4gICAgICogd2hlbiB0aGUgZWxlbWVudCBpcyByZWxlYXNlZC5cbiAgICAgKiBCeSBkZWZhdWx0IGl0J3Mgc2V0IHRvIGZhbHNlLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2IGlneERyYWcgW2FuaW1hdGVPblJlbGVhc2VdPVwiJ3RydWUnXCI+XG4gICAgICogICAgICAgICA8c3Bhbj5EcmFnIE1lITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBEZXByZWNhdGVQcm9wZXJ0eShgJ2FuaW1hdGVPblJlbGVhc2UnIEBJbnB1dCBwcm9wZXJ0eSBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIG1ham9yIHZlcnNpb25zLlxuICAgICAgICBQbGVhc2UgdXNlICd0cmFuc2l0aW9uVG9PcmlnaW4nIG9yICd0cmFuc2l0aW9uVG8nIG1ldGhvZHMgaW5zdGVhZC5gKVxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGFuaW1hdGVPblJlbGVhc2UgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNwZWNpZmllcyBhIHRlbXBsYXRlIGZvciB0aGUgZ2hvc3QgZWxlbWVudCBjcmVhdGVkIHdoZW4gZHJhZ2dpbmcgc3RhcnRzIGFuZCBgZ2hvc3RgIGlzIHRydWUuXG4gICAgICogQnkgZGVmYXVsdCBhIGNsb25lIG9mIHRoZSBiYXNlIGVsZW1lbnQgdGhlIGlneERyYWcgaXMgaW5zdGFuY2VkIGlzIGNyZWF0ZWQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgaWd4RHJhZyBbZ2hvc3RUZW1wbGF0ZV09XCJjdXN0b21HaG9zdFwiPlxuICAgICAqICAgICAgICAgPHNwYW4+RHJhZyBNZSE8L3NwYW4+XG4gICAgICogPC9kaXY+XG4gICAgICogPG5nLXRlbXBsYXRlICNjdXN0b21HaG9zdD5cbiAgICAgKiAgICAgIDxkaXYgY2xhc3M9XCJjdXN0b21HaG9zdFN0eWxlXCI+XG4gICAgICogICAgICAgICAgPHNwYW4+SSBhbSBiZWluZyBkcmFnZ2VkITwvc3Bhbj5cbiAgICAgKiAgICAgIDwvZGl2PlxuICAgICAqIDwvbmctdGVtcGxhdGU+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyYWdEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBnaG9zdFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc2V0cyB0aGUgZWxlbWVudCB0byB3aGljaCB0aGUgZHJhZ2dlZCBlbGVtZW50IHdpbGwgYmUgYXBwZW5kZWQuXG4gICAgICogQnkgZGVmYXVsdCBpdCdzIHNldCB0byBudWxsIGFuZCB0aGUgZHJhZ2dlZCBlbGVtZW50IGlzIGFwcGVuZGVkIHRvIHRoZSBib2R5LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2ICNob3N0RGl2PjwvZGl2PlxuICAgICAqIDxkaXYgaWd4RHJhZyBbZ2hvc3RIb3N0XT1cImhvc3REaXZcIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPkRyYWcgTWUhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcmFnRGlyZWN0aXZlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZ2hvc3RIb3N0O1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgc3BlY2lmaWVzIHRoZSBvZmZzZXQgb2YgdGhlIGRyYWdnZWQgZWxlbWVudCByZWxhdGl2ZSB0byB0aGUgbW91c2UgaW4gcGl4ZWxzLlxuICAgICAqIEJ5IGRlZmF1bHQgaXQncyB0YWtpbmcgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIHRvIHRoZSBtb3VzZSB3aGVuIHRoZSBkcmFnIHN0YXJ0ZWQgYW5kIGtlZXBzIGl0IHRoZSBzYW1lLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2ICNob3N0RGl2PjwvZGl2PlxuICAgICAqIDxkaXYgaWd4RHJhZyBbZ2hvc3RPZmZzZXRYXT1cIjBcIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPkRyYWcgTWUhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcmFnRGlyZWN0aXZlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgc2V0IGdob3N0T2Zmc2V0WCh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9vZmZzZXRYID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGdob3N0T2Zmc2V0WCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29mZnNldFggIT09IHVuZGVmaW5lZCA/IHRoaXMuX29mZnNldFggOiB0aGlzLl9kZWZhdWx0T2Zmc2V0WDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzcGVjaWZpZXMgdGhlIG9mZnNldCBvZiB0aGUgZHJhZ2dlZCBlbGVtZW50IHJlbGF0aXZlIHRvIHRoZSBtb3VzZSBpbiBwaXhlbHMuXG4gICAgICogQnkgZGVmYXVsdCBpdCdzIHRha2luZyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gdG8gdGhlIG1vdXNlIHdoZW4gdGhlIGRyYWcgc3RhcnRlZCBhbmQga2VlcHMgaXQgdGhlIHNhbWUuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgI2hvc3REaXY+PC9kaXY+XG4gICAgICogPGRpdiBpZ3hEcmFnIFtnaG9zdE9mZnNldFldPVwiMFwiPlxuICAgICAqICAgICAgICAgPHNwYW4+RHJhZyBNZSE8L3NwYW4+XG4gICAgICogPC9kaXY+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyYWdEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZXQgZ2hvc3RPZmZzZXRZKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29mZnNldFkgPSBwYXJzZUludCh2YWx1ZSwgMTApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZ2hvc3RPZmZzZXRZKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb2Zmc2V0WSAhPT0gdW5kZWZpbmVkID8gdGhpcy5fb2Zmc2V0WSA6IHRoaXMuX2RlZmF1bHRPZmZzZXRZIDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCB0cmlnZ2VyZWQgd2hlbiB0aGUgZHJhZ2dhYmxlIGVsZW1lbnQgZHJhZyBzdGFydHMuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgaWd4RHJhZyAoZHJhZ1N0YXJ0KT1cIm9uRHJhZ1N0YXJ0KClcIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPkRyYWcgTWUhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBwdWJsaWMgb25EcmFnU3RhcnQoKXtcbiAgICAgKiAgICAgIGFsZXJ0KFwiVGhlIGRyYWcgaGFzIHN0YXJlZCFcIik7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcmFnRGlyZWN0aXZlXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIGRyYWdTdGFydCA9IG5ldyBFdmVudEVtaXR0ZXI8SURyYWdTdGFydEV2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEV2ZW50IHRyaWdnZXJlZCB3aGVuIHRoZSBkcmFnZ2FibGUgZWxlbWVudCBoYXMgYmVlbiBtb3ZlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBpZ3hEcmFnICAoZHJhZ01vdmUpPVwib25EcmFnTW92ZSgpXCI+XG4gICAgICogICAgICAgICA8c3Bhbj5EcmFnIE1lITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcHVibGljIG9uRHJhZ01vdmUoKXtcbiAgICAgKiAgICAgIGFsZXJ0KFwiVGhlIGVsZW1lbnQgaGFzIG1vdmVkIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyYWdEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgZHJhZ01vdmUgPSBuZXcgRXZlbnRFbWl0dGVyPElEcmFnTW92ZUV2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEV2ZW50IHRyaWdnZXJlZCB3aGVuIHRoZSBkcmFnZ2FibGUgZWxlbWVudCBpcyByZWxlYXNlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBpZ3hEcmFnIChkcmFnRW5kKT1cIm9uRHJhZ0VuZCgpXCI+XG4gICAgICogICAgICAgICA8c3Bhbj5EcmFnIE1lITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcHVibGljIG9uRHJhZ0VuZCgpe1xuICAgICAqICAgICAgYWxlcnQoXCJUaGUgZHJhZyBoYXMgZW5kZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBkcmFnRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxJRHJhZ0Jhc2VFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCB0cmlnZ2VyZWQgd2hlbiB0aGUgZHJhZ2dhYmxlIGVsZW1lbnQgaXMgY2xpY2tlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBpZ3hEcmFnIChkcmFnQ2xpY2spPVwib25EcmFnQ2xpY2soKVwiPlxuICAgICAqICAgICAgICAgPHNwYW4+RHJhZyBNZSE8L3NwYW4+XG4gICAgICogPC9kaXY+XG4gICAgICogYGBgXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHB1YmxpYyBvbkRyYWdDbGljaygpe1xuICAgICAqICAgICAgYWxlcnQoXCJUaGUgZWxlbWVudCBoYXMgYmVlbiBjbGlja2VkIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyYWdEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgZHJhZ0NsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxJRHJhZ0Jhc2VFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCB0cmlnZ2VyZWQgd2hlbiB0aGUgZHJhZyBnaG9zdCBlbGVtZW50IGlzIGNyZWF0ZWQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgaWd4RHJhZyAoZ2hvc3RDcmVhdGUpPVwiZ2hvc3RDcmVhdGVkKClcIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPkRyYWcgTWUhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBwdWJsaWMgZ2hvc3RDcmVhdGVkKCl7XG4gICAgICogICAgICBhbGVydChcIlRoZSBnaG9zdCBoYXMgYmVlbiBjcmVhdGVkIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyYWdEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgZ2hvc3RDcmVhdGUgPSBuZXcgRXZlbnRFbWl0dGVyPElEcmFnR2hvc3RCYXNlRXZlbnRBcmdzPigpO1xuXG4gICAgLyoqXG4gICAgICogRXZlbnQgdHJpZ2dlcmVkIHdoZW4gdGhlIGRyYWcgZ2hvc3QgZWxlbWVudCBpcyBjcmVhdGVkLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2IGlneERyYWcgKGdob3N0RGVzdHJveSk9XCJnaG9zdERlc3Ryb3llZCgpXCI+XG4gICAgICogICAgICAgICA8c3Bhbj5EcmFnIE1lITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcHVibGljIGdob3N0RGVzdHJveWVkKCl7XG4gICAgICogICAgICBhbGVydChcIlRoZSBnaG9zdCBoYXMgYmVlbiBkZXN0cm95ZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBnaG9zdERlc3Ryb3kgPSBuZXcgRXZlbnRFbWl0dGVyPElEcmFnR2hvc3RCYXNlRXZlbnRBcmdzPigpO1xuXG4gICAgLyoqXG4gICAgICogRXZlbnQgdHJpZ2dlcmVkIGFmdGVyIHRoZSBkcmFnZ2FibGUgZWxlbWVudCBpcyByZWxlYXNlZCBhbmQgYWZ0ZXIgaXRzIGFuaW1hdGlvbiBoYXMgZmluaXNoZWQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgaWd4RHJhZyAodHJhbnNpdGlvbmVkKT1cIm9uTW92ZUVuZCgpXCI+XG4gICAgICogICAgICAgICA8c3Bhbj5EcmFnIE1lITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcHVibGljIG9uTW92ZUVuZCgpe1xuICAgICAqICAgICAgYWxlcnQoXCJUaGUgbW92ZSBoYXMgZW5kZWQhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJhZ0RpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyB0cmFuc2l0aW9uZWQgPSBuZXcgRXZlbnRFbWl0dGVyPElEcmFnQmFzZUV2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBAQ29udGVudENoaWxkcmVuKElneERyYWdIYW5kbGVEaXJlY3RpdmUpXG4gICAgcHVibGljIGRyYWdIYW5kbGVzOiBRdWVyeUxpc3Q8SWd4RHJhZ0hhbmRsZURpcmVjdGl2ZT47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS52aXNpYmlsaXR5JylcbiAgICBwdWJsaWMgX3Zpc2liaWxpdHkgPSAndmlzaWJsZSc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5pZ3gtZHJhZycpXG4gICAgcHVibGljIGJhc2VDbGFzcyA9IHRydWU7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5pZ3gtZHJhZy0tc2VsZWN0LWRpc2FibGVkJylcbiAgICBwdWJsaWMgc2VsZWN0RGlzYWJsZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2UgbmF0aXZlIGFuZ3VsYXIgd2F5cyBvZiBoaWRpbmcgaXQgdXNpbmcgY3VzdG9tIHRvIHRoZSBiYXNlIGVsZW1lbnQgc3R5bGluZyBmb3IgZnV0dXJlIHZlcnNpb25zLlxuICAgICAqIFNldHMgdGhlIHZpc2liaWxpdHkgb2YgdGhlIGRyYWdnYWJsZSBlbGVtZW50LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBAVmlld0NoaWxkKFwibXlEcmFnXCIgLHtyZWFkOiBJZ3hEcmFnRGlyZWN0aXZlfSlcbiAgICAgKiBwdWJsaWMgbXlEcmFnOiBJZ3hEcmFnRGlyZWN0aXZlO1xuICAgICAqIG5nQWZ0ZXJWaWV3SW5pdCgpe1xuICAgICAqICAgICB0aGlzLm15RHJhZy52aXNpYmxlID0gZmFsc2U7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBEZXByZWNhdGVQcm9wZXJ0eShgJ3Zpc2libGUnIEBJbnB1dCBwcm9wZXJ0eSBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIG1ham9yIHZlcnNpb25zLlxuICAgICAgICBQbGVhc2UgdXNlIG5hdGl2ZSBhbmd1bGFyIHdheXMgb2YgaGlkaW5nIHRoZSBiYXNlIGVsZW1lbnQgdXNpbmcgc3R5bGluZy5gKVxuICAgIHB1YmxpYyBzZXQgdmlzaWJsZShiVmlzaWJsZSkge1xuICAgICAgICB0aGlzLl92aXNpYmlsaXR5ID0gYlZpc2libGUgPyAndmlzaWJsZScgOiAnaGlkZGVuJztcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHZpc2liaWxpdHkgc3RhdGUgb2YgdGhlIGRyYWdnYWJsZSBlbGVtZW50LlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBAVmlld0NoaWxkKFwibXlEcmFnXCIgLHtyZWFkOiBJZ3hEcmFnRGlyZWN0aXZlfSlcbiAgICAgKiBwdWJsaWMgbXlEcmFnOiBJZ3hEcmFnRGlyZWN0aXZlO1xuICAgICAqIG5nQWZ0ZXJWaWV3SW5pdCgpe1xuICAgICAqICAgICBsZXQgZHJhZ1Zpc2liaWxpdHkgPSB0aGlzLm15RHJhZy52aXNpYmxlO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHZpc2libGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92aXNpYmlsaXR5ID09PSAndmlzaWJsZSc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgY3VycmVudCBsb2NhdGlvbiBvZiB0aGUgZWxlbWVudCByZWxhdGl2ZSB0byB0aGUgcGFnZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGxvY2F0aW9uKCk6IElneERyYWdMb2NhdGlvbiB7XG4gICAgICAgIHJldHVybiBuZXcgSWd4RHJhZ0xvY2F0aW9uKHRoaXMucGFnZVgsIHRoaXMucGFnZVkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG9yaWdpbmFsIGxvY2F0aW9uIG9mIHRoZSBlbGVtZW50IGJlZm9yZSBkcmFnZ2luZyBzdGFydGVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgb3JpZ2luTG9jYXRpb24oKTogSWd4RHJhZ0xvY2F0aW9uIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJZ3hEcmFnTG9jYXRpb24odGhpcy5iYXNlT3JpZ2luTGVmdCwgdGhpcy5iYXNlT3JpZ2luVG9wKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBwb2ludGVyRXZlbnRzRW5hYmxlZCgpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBQb2ludGVyRXZlbnQgIT09ICd1bmRlZmluZWQnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHRvdWNoRXZlbnRzRW5hYmxlZCgpIHtcbiAgICAgICAgcmV0dXJuICdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBwYWdlWCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZ2hvc3QgJiYgdGhpcy5naG9zdEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdob3N0TGVmdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5iYXNlTGVmdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBwYWdlWSgpIHtcbiAgICAgICAgaWYgKHRoaXMuZ2hvc3QgJiYgdGhpcy5naG9zdEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdob3N0VG9wO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmJhc2VUb3A7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdldCBiYXNlTGVmdCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGJhc2VUb3AoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGJhc2VPcmlnaW5MZWZ0KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmJhc2VMZWZ0IC0gdGhpcy5nZXRUcmFuc2Zvcm1YKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50KTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ2V0IGJhc2VPcmlnaW5Ub3AoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmFzZVRvcCAtIHRoaXMuZ2V0VHJhbnNmb3JtWSh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNldCBnaG9zdExlZnQocGFnZVg6IG51bWJlcikge1xuICAgICAgICBpZiAodGhpcy5naG9zdEVsZW1lbnQpIHtcbiAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gdGFrZSBpbnRvIGFjY291bnQgbWFyZ2luTGVmdCwgc2luY2UgdG9wIHN0eWxlIGRvZXMgbm90IGluY2x1ZGUgbWFyZ2luLCBidXQgcGFnZVggaW5jbHVkZXMgdGhlIG1hcmdpbi5cbiAgICAgICAgICAgIGNvbnN0IGdob3N0TWFyZ2luTGVmdCA9IHBhcnNlSW50KGRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUodGhpcy5naG9zdEVsZW1lbnQpWydtYXJnaW4tbGVmdCddLCAxMCk7XG4gICAgICAgICAgICAvLyBJZiBnaG9zdCBob3N0IGlzIGRlZmluZWQgaXQgbmVlZHMgdG8gYmUgdGFrZW4gaW50byBhY2NvdW50LlxuICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQuc3R5bGUubGVmdCA9IChwYWdlWCAtIGdob3N0TWFyZ2luTGVmdCAtIHRoaXMuX2dob3N0SG9zdFgpICsgJ3B4JztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXQgZ2hvc3RMZWZ0KCkge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5naG9zdEVsZW1lbnQuc3R5bGUubGVmdCwgMTApICsgdGhpcy5fZ2hvc3RIb3N0WDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2V0IGdob3N0VG9wKHBhZ2VZOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuZ2hvc3RFbGVtZW50KSB7XG4gICAgICAgICAgICAvLyBXZSBuZWVkIHRvIHRha2UgaW50byBhY2NvdW50IG1hcmdpblRvcCwgc2luY2UgdG9wIHN0eWxlIGRvZXMgbm90IGluY2x1ZGUgbWFyZ2luLCBidXQgcGFnZVkgaW5jbHVkZXMgdGhlIG1hcmdpbi5cbiAgICAgICAgICAgIGNvbnN0IGdob3N0TWFyZ2luVG9wID0gcGFyc2VJbnQoZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLmdob3N0RWxlbWVudClbJ21hcmdpbi10b3AnXSwgMTApO1xuICAgICAgICAgICAgLy8gSWYgZ2hvc3QgaG9zdCBpcyBkZWZpbmVkIGl0IG5lZWRzIHRvIGJlIHRha2VuIGludG8gYWNjb3VudC5cbiAgICAgICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LnN0eWxlLnRvcCA9IChwYWdlWSAtIGdob3N0TWFyZ2luVG9wIC0gdGhpcy5fZ2hvc3RIb3N0WSkgKyAncHgnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdldCBnaG9zdFRvcCgpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2hvc3RFbGVtZW50LnN0eWxlLnRvcCwgMTApICsgdGhpcy5fZ2hvc3RIb3N0WTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGRlZmF1bHRSZXR1cm5EdXJhdGlvbiA9ICcwLjVzJztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2hvc3RFbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBhbmltSW5Qcm9ncmVzcyA9IGZhbHNlO1xuXG4gICAgcHJvdGVjdGVkIF9zdGFydFggPSAwO1xuICAgIHByb3RlY3RlZCBfc3RhcnRZID0gMDtcbiAgICBwcm90ZWN0ZWQgX2xhc3RYID0gMDtcbiAgICBwcm90ZWN0ZWQgX2xhc3RZID0gMDtcbiAgICBwcm90ZWN0ZWQgX2RyYWdTdGFydGVkID0gZmFsc2U7XG5cbiAgICAvKiogRHJhZyBnaG9zdCByZWxhdGVkIHByb3BlcnRpZXMgKi9cbiAgICBwcm90ZWN0ZWQgX2RlZmF1bHRPZmZzZXRYO1xuICAgIHByb3RlY3RlZCBfZGVmYXVsdE9mZnNldFk7XG4gICAgcHJvdGVjdGVkIF9vZmZzZXRYO1xuICAgIHByb3RlY3RlZCBfb2Zmc2V0WTtcbiAgICBwcm90ZWN0ZWQgX2dob3N0U3RhcnRYO1xuICAgIHByb3RlY3RlZCBfZ2hvc3RTdGFydFk7XG4gICAgcHJvdGVjdGVkIF9naG9zdEhvc3RYID0gMDtcbiAgICBwcm90ZWN0ZWQgX2dob3N0SG9zdFkgPSAwO1xuXG4gICAgcHJvdGVjdGVkIF9wb2ludGVyRG93bklkID0gbnVsbDtcbiAgICBwcm90ZWN0ZWQgX2NsaWNrZWQgPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgX2xhc3REcm9wQXJlYSA9IG51bGw7XG5cbiAgICBwcm90ZWN0ZWQgX2Rlc3Ryb3kgPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xuICAgIHByb3RlY3RlZCBfcmVtb3ZlT25EZXN0cm95ID0gdHJ1ZTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwdWJsaWMgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHVibGljIGVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgICAgIHB1YmxpYyB2aWV3Q29udGFpbmVyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgICAgICBwdWJsaWMgem9uZTogTmdab25lLFxuICAgICAgICBwdWJsaWMgcmVuZGVyZXI6IFJlbmRlcmVyMlxuICAgICkge1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgICAgICBpZiAoIXRoaXMuZHJhZ0hhbmRsZXMgfHwgIXRoaXMuZHJhZ0hhbmRsZXMubGVuZ3RoICkge1xuICAgICAgICAgICAgLy8gU2V0IHVzZXIgc2VsZWN0IG5vbmUgdG8gdGhlIHdob2xlIGRyYWdnYWJsZSBlbGVtZW50IGlmIG5vIGRyYWcgaGFuZGxlcyBhcmUgZGVmaW5lZC5cbiAgICAgICAgICAgIHRoaXMuc2VsZWN0RGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmluZCBldmVudHNcbiAgICAgICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnRzID0gdGhpcy5kcmFnSGFuZGxlcyAmJiB0aGlzLmRyYWdIYW5kbGVzLmxlbmd0aCA/XG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnSGFuZGxlcy5tYXAoKGl0ZW0pID0+IGl0ZW0uZWxlbWVudC5uYXRpdmVFbGVtZW50KSA6IFt0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudF07XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50cy5mb3JFYWNoKChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucG9pbnRlckV2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbUV2ZW50KGVsZW1lbnQsICdwb2ludGVyZG93bicpLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpKVxuICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChyZXMpID0+IHRoaXMub25Qb2ludGVyRG93bihyZXMpKTtcblxuICAgICAgICAgICAgICAgICAgICBmcm9tRXZlbnQoZWxlbWVudCwgJ3BvaW50ZXJtb3ZlJykucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm90dGxlKCgpID0+IGludGVydmFsKDAsIGFuaW1hdGlvbkZyYW1lU2NoZWR1bGVyKSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSlcbiAgICAgICAgICAgICAgICAgICAgKS5zdWJzY3JpYmUoKHJlcykgPT4gdGhpcy5vblBvaW50ZXJNb3ZlKHJlcykpO1xuXG4gICAgICAgICAgICAgICAgICAgIGZyb21FdmVudChlbGVtZW50LCAncG9pbnRlcnVwJykucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveSkpXG4gICAgICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChyZXMpID0+IHRoaXMub25Qb2ludGVyVXAocmVzKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmdob3N0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEbyBub3QgYmluZCBgbG9zdHBvaW50ZXJjYXB0dXJlYCB0byB0aGUgdGFyZ2V0LCBiZWNhdXNlIHdlIHdpbGwgYmluZCBpdCBvbiB0aGUgZ2hvc3QgbGF0ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICBmcm9tRXZlbnQoZWxlbWVudCwgJ2xvc3Rwb2ludGVyY2FwdHVyZScpLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnN1YnNjcmliZSgocmVzKSA9PiB0aGlzLm9uUG9pbnRlckxvc3QocmVzKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudG91Y2hFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb21FdmVudChlbGVtZW50LCAndG91Y2hzdGFydCcpLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpKVxuICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChyZXMpID0+IHRoaXMub25Qb2ludGVyRG93bihyZXMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBkb24ndCBoYXZlIHBvaW50ZXIgZXZlbnRzIGFuZCB0b3VjaCBldmVudHMuIFVzZSB0aGVuIG1vdXNlIGV2ZW50cy5cbiAgICAgICAgICAgICAgICAgICAgZnJvbUV2ZW50KGVsZW1lbnQsICdtb3VzZWRvd24nKS5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95KSlcbiAgICAgICAgICAgICAgICAgICAgLnN1YnNjcmliZSgocmVzKSA9PiB0aGlzLm9uUG9pbnRlckRvd24ocmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFdlIHNob3VsZCBiaW5kIHRvIGRvY3VtZW50IGV2ZW50cyBvbmx5IG9uY2Ugd2hlbiB0aGVyZSBhcmUgbm8gcG9pbnRlciBldmVudHMuXG4gICAgICAgICAgICBpZiAoIXRoaXMucG9pbnRlckV2ZW50c0VuYWJsZWQgJiYgdGhpcy50b3VjaEV2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBmcm9tRXZlbnQoZG9jdW1lbnQuZGVmYXVsdFZpZXcsICd0b3VjaG1vdmUnKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICB0aHJvdHRsZSgoKSA9PiBpbnRlcnZhbCgwLCBhbmltYXRpb25GcmFtZVNjaGVkdWxlcikpLFxuICAgICAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSlcbiAgICAgICAgICAgICAgICApLnN1YnNjcmliZSgocmVzKSA9PiB0aGlzLm9uUG9pbnRlck1vdmUocmVzKSk7XG5cbiAgICAgICAgICAgICAgICBmcm9tRXZlbnQoZG9jdW1lbnQuZGVmYXVsdFZpZXcsICd0b3VjaGVuZCcpLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpKVxuICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChyZXMpID0+IHRoaXMub25Qb2ludGVyVXAocmVzKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLnBvaW50ZXJFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgZnJvbUV2ZW50KGRvY3VtZW50LmRlZmF1bHRWaWV3LCAnbW91c2Vtb3ZlJykucGlwZShcbiAgICAgICAgICAgICAgICAgICAgdGhyb3R0bGUoKCkgPT4gaW50ZXJ2YWwoMCwgYW5pbWF0aW9uRnJhbWVTY2hlZHVsZXIpKSxcbiAgICAgICAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpXG4gICAgICAgICAgICAgICAgKS5zdWJzY3JpYmUoKHJlcykgPT4gdGhpcy5vblBvaW50ZXJNb3ZlKHJlcykpO1xuXG4gICAgICAgICAgICAgICAgZnJvbUV2ZW50KGRvY3VtZW50LmRlZmF1bHRWaWV3LCAnbW91c2V1cCcpLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpKVxuICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChyZXMpID0+IHRoaXMub25Qb2ludGVyVXAocmVzKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RyYW5zaXRpb25lbmQnLCAoYXJncykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25UcmFuc2l0aW9uRW5kKGFyZ3MpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFNldCB0cmFuc2l0aW9uIGR1cmF0aW9uIHRvIDBzLiBUaGlzIGFsc28gaGVscHMgd2l0aCBzZXR0aW5nIGB2aXNpYmlsaXR5OiBoaWRkZW5gIHRvIHRoZSBiYXNlIHRvIG5vdCBsYWcuXG4gICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbiA9ICcwLjBzJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLl9kZXN0cm95Lm5leHQodHJ1ZSk7XG4gICAgICAgIHRoaXMuX2Rlc3Ryb3kuY29tcGxldGUoKTtcblxuICAgICAgICBpZiAodGhpcy5naG9zdCAmJiB0aGlzLmdob3N0RWxlbWVudCAmJiB0aGlzLl9yZW1vdmVPbkRlc3Ryb3kpIHtcbiAgICAgICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5naG9zdEVsZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBkZXNpcmVkIGxvY2F0aW9uIG9mIHRoZSBiYXNlIGVsZW1lbnQgb3IgZ2hvc3QgZWxlbWVudCBpZiByZW5kZWQgcmVsYXRpdmUgdG8gdGhlIGRvY3VtZW50LlxuICAgICAqIEBwYXJhbSBuZXdMb2NhdGlvbiBOZXcgbG9jYXRpb24gdGhhdCBzaG91bGQgYmUgYXBwbGllZC4gSXQgaXMgYWR2aXNlZCB0byBnZXQgbmV3IGxvY2F0aW9uIHVzaW5nIGdldEJvdW5kaW5nQ2xpZW50UmVjdHMoKSArIHNjcm9sbC5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0TG9jYXRpb24obmV3TG9jYXRpb246IElneERyYWdMb2NhdGlvbikge1xuICAgICAgICAvLyBXZSBkbyBub3Qgc3VidHJhY3QgbWFyZ2luTGVmdCBhbmQgbWFyZ2luVG9wIGhlcmUgYmVjYXVzZSBoZXJlIHdlIGNhbGN1bGF0ZSBkZWx0YXMuXG4gICAgICAgIGlmICh0aGlzLmdob3N0ICYmIHRoaXMuZ2hvc3RFbGVtZW50KSB7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXRIb3N0WCA9IHRoaXMuZ2hvc3RIb3N0ID8gdGhpcy5naG9zdEhvc3RPZmZzZXRMZWZ0KHRoaXMuZ2hvc3RIb3N0KSA6IDA7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXRIb3N0WSA9IHRoaXMuZ2hvc3RIb3N0ID8gdGhpcy5naG9zdEhvc3RPZmZzZXRUb3AodGhpcy5naG9zdEhvc3QpIDogMDtcbiAgICAgICAgICAgIHRoaXMuZ2hvc3RMZWZ0ID0gbmV3TG9jYXRpb24ucGFnZVggLSBvZmZzZXRIb3N0WCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgdGhpcy5naG9zdFRvcCA9IG5ld0xvY2F0aW9uLnBhZ2VZIC0gb2Zmc2V0SG9zdFkgKyB0aGlzLmdldFdpbmRvd1Njcm9sbFRvcCgpO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmdob3N0KSB7XG4gICAgICAgICAgICBjb25zdCBkZWx0YVggPSBuZXdMb2NhdGlvbi5wYWdlWCAtIHRoaXMucGFnZVg7XG4gICAgICAgICAgICBjb25zdCBkZWx0YVkgPSBuZXdMb2NhdGlvbi5wYWdlWSAtIHRoaXMucGFnZVk7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1YID0gdGhpcy5nZXRUcmFuc2Zvcm1YKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50KTtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybVkgPSB0aGlzLmdldFRyYW5zZm9ybVkodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5zZXRUcmFuc2Zvcm1YWSh0cmFuc2Zvcm1YICsgZGVsdGFYLCB0cmFuc2Zvcm1ZICsgZGVsdGFZKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3N0YXJ0WCA9IHRoaXMuYmFzZUxlZnQ7XG4gICAgICAgIHRoaXMuX3N0YXJ0WSA9IHRoaXMuYmFzZVRvcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmltYXRlcyB0aGUgYmFzZSBvciBnaG9zdCBlbGVtZW50IGRlcGVuZGluZyBvbiB0aGUgYGdob3N0YCBpbnB1dCB0byBpdHMgaW5pdGlhbCBsb2NhdGlvbi5cbiAgICAgKiBJZiBgZ2hvc3RgIGlzIHRydWUgYnV0IHRoZXJlIGlzIG5vdCBnaG9zdCByZW5kZXJlZCwgaXQgd2lsbCBiZSBjcmVhdGVkIGFuZCBhbmltYXRlZC5cbiAgICAgKiBJZiB0aGUgYmFzZSBlbGVtZW50IGhhcyBjaGFuZ2VkIGl0cyBET00gcG9zaXRpb24gaXRzIGluaXRpYWwgbG9jYXRpb24gd2lsbCBiZSBjaGFuZ2VkIGFjY29yZGluZ2x5LlxuICAgICAqIEBwYXJhbSBjdXN0b21BbmltQXJncyBDdXN0b20gdHJhbnNpdGlvbiBwcm9wZXJ0aWVzIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHdoZW4gcGVyZm9ybWluZyB0aGUgdHJhbnNpdGlvbi5cbiAgICAgKiBAcGFyYW0gc3RhcnRMb2NhdGlvbiBTdGFydCBsb2NhdGlvbiBmcm9tIHdoZXJlIHRoZSB0cmFuc2l0aW9uIHNob3VsZCBzdGFydC5cbiAgICAgKi9cbiAgICBwdWJsaWMgdHJhbnNpdGlvblRvT3JpZ2luKGN1c3RvbUFuaW1BcmdzPzogSURyYWdDdXN0b21UcmFuc2l0aW9uQXJncywgc3RhcnRMb2NhdGlvbj86IElneERyYWdMb2NhdGlvbikge1xuICAgICAgICBpZiAoKCEhc3RhcnRMb2NhdGlvbiAmJiBzdGFydExvY2F0aW9uLnBhZ2VYID09PSB0aGlzLmJhc2VPcmlnaW5MZWZ0ICYmIHN0YXJ0TG9jYXRpb24ucGFnZVkgPT09IHRoaXMuYmFzZU9yaWdpbkxlZnQpIHx8XG4gICAgICAgICAgICAoIXN0YXJ0TG9jYXRpb24gJiYgdGhpcy5naG9zdCAmJiAhdGhpcy5naG9zdEVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFzdGFydExvY2F0aW9uICYmIHN0YXJ0TG9jYXRpb24ucGFnZVggIT09IHRoaXMucGFnZVggJiYgc3RhcnRMb2NhdGlvbi5wYWdlWSAhPT0gdGhpcy5wYWdlWSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2hvc3QgJiYgIXRoaXMuZ2hvc3RFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3RhcnRYID0gc3RhcnRMb2NhdGlvbi5wYWdlWDtcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGFydFkgPSBzdGFydExvY2F0aW9uLnBhZ2VZO1xuICAgICAgICAgICAgICAgIHRoaXMuX2dob3N0U3RhcnRYID0gdGhpcy5fc3RhcnRYO1xuICAgICAgICAgICAgICAgIHRoaXMuX2dob3N0U3RhcnRZID0gdGhpcy5fc3RhcnRZO1xuICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlR2hvc3QodGhpcy5fc3RhcnRYLCB0aGlzLl9zdGFydFkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnNldExvY2F0aW9uKHN0YXJ0TG9jYXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hbmltSW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgICAgIC8vIFVzZSBzZXRUaW1lb3V0IGJlY2F1c2Ugd2UgbmVlZCB0byBiZSBzdXJlIHRoYXQgdGhlIGVsZW1lbnQgaXMgcG9zaXRpb25lZCBmaXJzdCBjb3JyZWN0bHkgaWYgdGhlcmUgaXMgc3RhcnQgbG9jYXRpb24uXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2hvc3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5zdHlsZS50cmFuc2l0aW9uUHJvcGVydHkgPSAndG9wLCBsZWZ0JztcbiAgICAgICAgICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPVxuICAgICAgICAgICAgICAgICAgICBjdXN0b21BbmltQXJncyAmJiBjdXN0b21BbmltQXJncy5kdXJhdGlvbiA/IGN1c3RvbUFuaW1BcmdzLmR1cmF0aW9uICsgJ3MnIDogdGhpcy5kZWZhdWx0UmV0dXJuRHVyYXRpb24gO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25UaW1pbmdGdW5jdGlvbiA9XG4gICAgICAgICAgICAgICAgICAgIGN1c3RvbUFuaW1BcmdzICYmIGN1c3RvbUFuaW1BcmdzLnRpbWluZ0Z1bmN0aW9uID8gY3VzdG9tQW5pbUFyZ3MudGltaW5nRnVuY3Rpb24gOiAnJztcbiAgICAgICAgICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5zdHlsZS50cmFuc2l0aW9uRGVsYXkgPSBjdXN0b21BbmltQXJncyAmJiBjdXN0b21BbmltQXJncy5kZWxheSA/IGN1c3RvbUFuaW1BcmdzLmRlbGF5ICsgJ3MnIDogJyc7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRMb2NhdGlvbihuZXcgSWd4RHJhZ0xvY2F0aW9uKHRoaXMuYmFzZUxlZnQsIHRoaXMuYmFzZVRvcCkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5naG9zdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25Qcm9wZXJ0eSA9ICd0cmFuc2Zvcm0nO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbiA9XG4gICAgICAgICAgICAgICAgICAgIGN1c3RvbUFuaW1BcmdzICYmIGN1c3RvbUFuaW1BcmdzLmR1cmF0aW9uID8gY3VzdG9tQW5pbUFyZ3MuZHVyYXRpb24gKyAncycgOiB0aGlzLmRlZmF1bHRSZXR1cm5EdXJhdGlvbiA7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudHJhbnNpdGlvblRpbWluZ0Z1bmN0aW9uID1cbiAgICAgICAgICAgICAgICAgICAgY3VzdG9tQW5pbUFyZ3MgJiYgY3VzdG9tQW5pbUFyZ3MudGltaW5nRnVuY3Rpb24gPyBjdXN0b21BbmltQXJncy50aW1pbmdGdW5jdGlvbiA6ICcnO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25EZWxheSA9IGN1c3RvbUFuaW1BcmdzICYmIGN1c3RvbUFuaW1BcmdzLmRlbGF5ID8gY3VzdG9tQW5pbUFyZ3MuZGVsYXkgKyAncycgOiAnJztcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGFydFggPSB0aGlzLmJhc2VMZWZ0O1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXJ0WSA9IHRoaXMuYmFzZVRvcDtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFRyYW5zZm9ybVhZKDAsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmltYXRlcyB0aGUgYmFzZSBvciBnaG9zdCBlbGVtZW50IHRvIGEgc3BlY2lmaWMgdGFyZ2V0IGxvY2F0aW9uIG9yIG90aGVyIGVsZW1lbnQgdXNpbmcgdHJhbnNpdGlvbi5cbiAgICAgKiBJZiBgZ2hvc3RgIGlzIHRydWUgYnV0IHRoZXJlIGlzIG5vdCBnaG9zdCByZW5kZXJlZCwgaXQgd2lsbCBiZSBjcmVhdGVkIGFuZCBhbmltYXRlZC5cbiAgICAgKiBJdCBpcyByZWNvbW1lbmRlZCB0byB1c2UgJ2dldEJvdW5kaW5nQ2xpZW50UmVjdHMoKSArIHBhZ2VTY3JvbGwnIHdoZW4gZGV0ZXJtaW5pbmcgZGVzaXJlZCBsb2NhdGlvbi5cbiAgICAgKiBAcGFyYW0gdGFyZ2V0IFRhcmdldCB0aGF0IHRoZSBiYXNlIG9yIGdob3N0IHdpbGwgdHJhbnNpdGlvbiB0by4gSXQgY2FuIGJlIGVpdGhlciBsb2NhdGlvbiBpbiB0aGUgcGFnZSBvciBhbm90aGVyIEhUTUwgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0gY3VzdG9tQW5pbUFyZ3MgQ3VzdG9tIHRyYW5zaXRpb24gcHJvcGVydGllcyB0aGF0IHdpbGwgYmUgYXBwbGllZCB3aGVuIHBlcmZvcm1pbmcgdGhlIHRyYW5zaXRpb24uXG4gICAgICogQHBhcmFtIHN0YXJ0TG9jYXRpb24gU3RhcnQgbG9jYXRpb24gZnJvbSB3aGVyZSB0aGUgdHJhbnNpdGlvbiBzaG91bGQgc3RhcnQuXG4gICAgICovXG4gICAgcHVibGljIHRyYW5zaXRpb25Ubyh0YXJnZXQ6IElneERyYWdMb2NhdGlvbiB8IEVsZW1lbnRSZWYsIGN1c3RvbUFuaW1BcmdzPzogSURyYWdDdXN0b21UcmFuc2l0aW9uQXJncywgc3RhcnRMb2NhdGlvbj86IElneERyYWdMb2NhdGlvbikge1xuICAgICAgICBpZiAoISFzdGFydExvY2F0aW9uICYmIHRoaXMuZ2hvc3QgJiYgIXRoaXMuZ2hvc3RFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9zdGFydFggPSBzdGFydExvY2F0aW9uLnBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5fc3RhcnRZID0gc3RhcnRMb2NhdGlvbi5wYWdlWTtcbiAgICAgICAgICAgIHRoaXMuX2dob3N0U3RhcnRYID0gdGhpcy5fc3RhcnRYO1xuICAgICAgICAgICAgdGhpcy5fZ2hvc3RTdGFydFkgPSB0aGlzLl9zdGFydFk7XG4gICAgICAgIH0gZWxzZSBpZiAoISFzdGFydExvY2F0aW9uICYmICghdGhpcy5naG9zdCB8fCB0aGlzLmdob3N0RWxlbWVudCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0TG9jYXRpb24oc3RhcnRMb2NhdGlvbik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5naG9zdCAmJiAhdGhpcy5naG9zdEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0WCA9IHRoaXMuYmFzZUxlZnQ7XG4gICAgICAgICAgICB0aGlzLl9zdGFydFkgPSB0aGlzLmJhc2VUb3A7XG4gICAgICAgICAgICB0aGlzLl9naG9zdFN0YXJ0WCA9IHRoaXMuX3N0YXJ0WCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgICAgICAgICAgdGhpcy5fZ2hvc3RTdGFydFkgPSB0aGlzLl9zdGFydFkgKyB0aGlzLmdldFdpbmRvd1Njcm9sbFRvcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZ2hvc3QgJiYgIXRoaXMuZ2hvc3RFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZUdob3N0KHRoaXMuX3N0YXJ0WCwgdGhpcy5fc3RhcnRZKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYW5pbUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAvLyBVc2Ugc2V0VGltZW91dCBiZWNhdXNlIHdlIG5lZWQgdG8gYmUgc3VyZSB0aGF0IHRoZSBlbGVtZW50IGlzIHBvc2l0aW9uZWQgZmlyc3QgY29ycmVjdGx5IGlmIHRoZXJlIGlzIHN0YXJ0IGxvY2F0aW9uLlxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG1vdmVkRWxlbSA9IHRoaXMuZ2hvc3QgPyB0aGlzLmdob3N0RWxlbWVudCA6IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgICAgICAgICAgbW92ZWRFbGVtLnN0eWxlLnRyYW5zaXRpb25Qcm9wZXJ0eSA9IHRoaXMuZ2hvc3QgJiYgdGhpcy5naG9zdEVsZW1lbnQgPyAnbGVmdCwgdG9wJyA6ICd0cmFuc2Zvcm0nO1xuICAgICAgICAgICAgbW92ZWRFbGVtLnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbiA9XG4gICAgICAgICAgICAgICAgY3VzdG9tQW5pbUFyZ3MgJiYgY3VzdG9tQW5pbUFyZ3MuZHVyYXRpb24gPyBjdXN0b21BbmltQXJncy5kdXJhdGlvbiArICdzJyA6IHRoaXMuZGVmYXVsdFJldHVybkR1cmF0aW9uIDtcbiAgICAgICAgICAgIG1vdmVkRWxlbS5zdHlsZS50cmFuc2l0aW9uVGltaW5nRnVuY3Rpb24gPVxuICAgICAgICAgICAgICAgIGN1c3RvbUFuaW1BcmdzICYmIGN1c3RvbUFuaW1BcmdzLnRpbWluZ0Z1bmN0aW9uID8gY3VzdG9tQW5pbUFyZ3MudGltaW5nRnVuY3Rpb24gOiAnJztcbiAgICAgICAgICAgIG1vdmVkRWxlbS5zdHlsZS50cmFuc2l0aW9uRGVsYXkgPSBjdXN0b21BbmltQXJncyAmJiBjdXN0b21BbmltQXJncy5kZWxheSA/IGN1c3RvbUFuaW1BcmdzLmRlbGF5ICsgJ3MnIDogJyc7XG5cbiAgICAgICAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBJZ3hEcmFnTG9jYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldExvY2F0aW9uKG5ldyBJZ3hEcmFnTG9jYXRpb24gKHRhcmdldC5wYWdlWCwgdGFyZ2V0LnBhZ2VZKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldFJlY3RzID0gdGFyZ2V0Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRMb2NhdGlvbihuZXcgSWd4RHJhZ0xvY2F0aW9uKFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRSZWN0cy5sZWZ0IC0gIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpLFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRSZWN0cy50b3AgLSB0aGlzLmdldFdpbmRvd1Njcm9sbFRvcCgpXG4gICAgICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBNZXRob2QgYm91bmQgdG8gdGhlIFBvaW50ZXJEb3duIGV2ZW50IG9mIHRoZSBiYXNlIGVsZW1lbnQgaWd4RHJhZyBpcyBpbml0aWFsaXplZC5cbiAgICAgKiBAcGFyYW0gZXZlbnQgUG9pbnRlckRvd24gZXZlbnQgY2FwdHVyZWRcbiAgICAgKi9cbiAgICBwdWJsaWMgb25Qb2ludGVyRG93bihldmVudCkge1xuICAgICAgICB0aGlzLl9jbGlja2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fcG9pbnRlckRvd25JZCA9IGV2ZW50LnBvaW50ZXJJZDtcblxuICAgICAgICAvLyBTZXQgcG9pbnRlciBjYXB0dXJlIHNvIHdlIGRldGVjdCBwb2ludGVybW92ZSBldmVuIGlmIG1vdXNlIGlzIG91dCBvZiBib3VuZHMgdW50aWwgZ2hvc3RFbGVtZW50IGlzIGNyZWF0ZWQuXG4gICAgICAgIGNvbnN0IGhhbmRsZUZvdW5kID0gdGhpcy5kcmFnSGFuZGxlcy5maW5kKGhhbmRsZSA9PiBoYW5kbGUuZWxlbWVudC5uYXRpdmVFbGVtZW50ID09PSBldmVudC5jdXJyZW50VGFyZ2V0KTtcbiAgICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IGhhbmRsZUZvdW5kID8gaGFuZGxlRm91bmQuZWxlbWVudC5uYXRpdmVFbGVtZW50IDogdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIGlmICh0aGlzLnBvaW50ZXJFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50LnNldFBvaW50ZXJDYXB0dXJlKHRoaXMuX3BvaW50ZXJEb3duSWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudC5mb2N1cygpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBvaW50ZXJFdmVudHNFbmFibGVkIHx8ICF0aGlzLnRvdWNoRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgLy8gQ2hlY2sgZmlyc3QgZm9yIHBvaW50ZXIgZXZlbnRzIG9yIG5vbiB0b3VjaCwgYmVjYXVzZSB3ZSBjYW4gaGF2ZSBwb2ludGVyIGV2ZW50cyBhbmQgdG91Y2ggZXZlbnRzIGF0IG9uY2UuXG4gICAgICAgICAgICB0aGlzLl9zdGFydFggPSBldmVudC5wYWdlWDtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0WSA9IGV2ZW50LnBhZ2VZO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMudG91Y2hFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9zdGFydFggPSBldmVudC50b3VjaGVzWzBdLnBhZ2VYO1xuICAgICAgICAgICAgdGhpcy5fc3RhcnRZID0gZXZlbnQudG91Y2hlc1swXS5wYWdlWTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2RlZmF1bHRPZmZzZXRYID0gdGhpcy5iYXNlTGVmdCAtIHRoaXMuX3N0YXJ0WCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgICAgICB0aGlzLl9kZWZhdWx0T2Zmc2V0WSA9IHRoaXMuYmFzZVRvcCAtIHRoaXMuX3N0YXJ0WSArIHRoaXMuZ2V0V2luZG93U2Nyb2xsVG9wKCk7XG4gICAgICAgIHRoaXMuX2dob3N0U3RhcnRYID0gdGhpcy5fc3RhcnRYICsgdGhpcy5naG9zdE9mZnNldFg7XG4gICAgICAgIHRoaXMuX2dob3N0U3RhcnRZID0gdGhpcy5fc3RhcnRZICsgdGhpcy5naG9zdE9mZnNldFk7XG4gICAgICAgIHRoaXMuX2xhc3RYID0gdGhpcy5fc3RhcnRYO1xuICAgICAgICB0aGlzLl9sYXN0WSA9IHRoaXMuX3N0YXJ0WTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogUGVyZm9ybSBkcmFnIG1vdmUgbG9naWMgd2hlbiBkcmFnZ2luZyBhbmQgZGlzcGF0Y2hpbmcgZXZlbnRzIGlmIHRoZXJlIGlzIGlneERyb3AgdW5kZXIgdGhlIHBvaW50ZXIuXG4gICAgICogVGhpcyBtZXRob2QgaXMgYm91bmQgYXQgZmlyc3QgYXQgdGhlIGJhc2UgZWxlbWVudC5cbiAgICAgKiBJZiBkcmFnZ2luZyBzdGFydHMgYW5kIGFmdGVyIHRoZSBnaG9zdEVsZW1lbnQgaXMgcmVuZGVyZWQgdGhlIHBvaW50ZXJJZCBpcyByZWFzc2lnbmVkIGl0LiBUaGVuIHRoaXMgbWV0aG9kIGlzIGJvdW5kIHRvIGl0LlxuICAgICAqIEBwYXJhbSBldmVudCBQb2ludGVyTW92ZSBldmVudCBjYXB0dXJlZFxuICAgICAqL1xuICAgIHB1YmxpYyBvblBvaW50ZXJNb3ZlKGV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLl9jbGlja2VkKSB7XG4gICAgICAgICAgICBsZXQgcGFnZVgsIHBhZ2VZO1xuICAgICAgICAgICAgaWYgKHRoaXMucG9pbnRlckV2ZW50c0VuYWJsZWQgfHwgIXRoaXMudG91Y2hFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgZmlyc3QgZm9yIHBvaW50ZXIgZXZlbnRzIG9yIG5vbiB0b3VjaCwgYmVjYXVzZSB3ZSBjYW4gaGF2ZSBwb2ludGVyIGV2ZW50cyBhbmQgdG91Y2ggZXZlbnRzIGF0IG9uY2UuXG4gICAgICAgICAgICAgICAgcGFnZVggPSBldmVudC5wYWdlWDtcbiAgICAgICAgICAgICAgICBwYWdlWSA9IGV2ZW50LnBhZ2VZO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnRvdWNoRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHBhZ2VYID0gZXZlbnQudG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgICAgICAgICBwYWdlWSA9IGV2ZW50LnRvdWNoZXNbMF0ucGFnZVk7XG5cbiAgICAgICAgICAgICAgICAvLyBQcmV2ZW50IHNjcm9sbGluZyBvbiB0b3VjaCB3aGlsZSBkcmFnZ2luZ1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHRvdGFsTW92ZWRYID0gcGFnZVggLSB0aGlzLl9zdGFydFg7XG4gICAgICAgICAgICBjb25zdCB0b3RhbE1vdmVkWSA9IHBhZ2VZIC0gdGhpcy5fc3RhcnRZO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9kcmFnU3RhcnRlZCAmJlxuICAgICAgICAgICAgICAgIChNYXRoLmFicyh0b3RhbE1vdmVkWCkgPiB0aGlzLmRyYWdUb2xlcmFuY2UgfHwgTWF0aC5hYnModG90YWxNb3ZlZFkpID4gdGhpcy5kcmFnVG9sZXJhbmNlKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRyYWdTdGFydEFyZ3M6IElEcmFnU3RhcnRFdmVudEFyZ3MgPSB7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2ZW50LFxuICAgICAgICAgICAgICAgICAgICBvd25lcjogdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRYOiBwYWdlWCAtIHRvdGFsTW92ZWRYLFxuICAgICAgICAgICAgICAgICAgICBzdGFydFk6IHBhZ2VZIC0gdG90YWxNb3ZlZFksXG4gICAgICAgICAgICAgICAgICAgIHBhZ2VYOiBwYWdlWCxcbiAgICAgICAgICAgICAgICAgICAgcGFnZVk6IHBhZ2VZLFxuICAgICAgICAgICAgICAgICAgICBjYW5jZWw6IGZhbHNlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcmFnU3RhcnQuZW1pdChkcmFnU3RhcnRBcmdzKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICghZHJhZ1N0YXJ0QXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZHJhZ1N0YXJ0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5naG9zdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgbW92ZWQgZW5vdWdoIHNvIGdob3N0RWxlbWVudCBjYW4gYmUgcmVuZGVyZWQgYW5kIGFjdHVhbCBkcmFnZ2luZyB0byBzdGFydC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gY3JlYXRpbmcgaXQgd2lsbCB0YWtlIGludG8gYWNjb3VudCBhbnkgb2Zmc2V0IHNldCBieSB0aGUgdXNlciBieSBkZWZhdWx0LlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVHaG9zdChwYWdlWCwgcGFnZVkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX29mZnNldFggIT09IHVuZGVmaW5lZCB8fCB0aGlzLl9vZmZzZXRZICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIG5lZWQgZm9yIGdob3N0LCBidXQgd2Ugd2lsbCBuZWVkIHRvIHBvc2l0aW9uIGluaXRpYWxseSB0aGUgYmFzZSBlbGVtZW50IHRvIHJlZmxlY3QgYW55IG9mZnNldC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybVggPSAodGhpcy5fb2Zmc2V0WCAhPT0gdW5kZWZpbmVkID8gdGhpcy5fb2Zmc2V0WCAtIHRoaXMuX2RlZmF1bHRPZmZzZXRYIDogMCkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0VHJhbnNmb3JtWCh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1ZID0gKHRoaXMuX29mZnNldFkgIT09IHVuZGVmaW5lZCA/IHRoaXMuX29mZnNldFkgLSB0aGlzLl9kZWZhdWx0T2Zmc2V0WSA6IDApICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFRyYW5zZm9ybVkodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRUcmFuc2Zvcm1YWSh0cmFuc2Zvcm1YLCB0cmFuc2Zvcm1ZKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLl9kcmFnU3RhcnRlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbW92ZUFyZ3M6IElEcmFnTW92ZUV2ZW50QXJncyA9IHtcbiAgICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBldmVudCxcbiAgICAgICAgICAgICAgICBvd25lcjogdGhpcyxcbiAgICAgICAgICAgICAgICBzdGFydFg6IHRoaXMuX3N0YXJ0WCxcbiAgICAgICAgICAgICAgICBzdGFydFk6IHRoaXMuX3N0YXJ0WSxcbiAgICAgICAgICAgICAgICBwYWdlWDogdGhpcy5fbGFzdFgsXG4gICAgICAgICAgICAgICAgcGFnZVk6IHRoaXMuX2xhc3RZLFxuICAgICAgICAgICAgICAgIG5leHRQYWdlWDogcGFnZVgsXG4gICAgICAgICAgICAgICAgbmV4dFBhZ2VZOiBwYWdlWSxcbiAgICAgICAgICAgICAgICBjYW5jZWw6IGZhbHNlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5kcmFnTW92ZS5lbWl0KG1vdmVBcmdzKTtcblxuICAgICAgICAgICAgY29uc3Qgc2V0UGFnZVggPSBtb3ZlQXJncy5uZXh0UGFnZVg7XG4gICAgICAgICAgICBjb25zdCBzZXRQYWdlWSA9IG1vdmVBcmdzLm5leHRQYWdlWTtcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRNb3ZlZFggPSBzZXRQYWdlWCAtIHRoaXMuX3N0YXJ0WDtcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRNb3ZlZFkgPSBzZXRQYWdlWSAtIHRoaXMuX3N0YXJ0WTtcblxuICAgICAgICAgICAgaWYgKCFtb3ZlQXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5naG9zdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdob3N0TGVmdCA9IHRoaXMuX2dob3N0U3RhcnRYICsgdXBkYXRlZE1vdmVkWDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5naG9zdFRvcCA9IHRoaXMuX2dob3N0U3RhcnRZICsgdXBkYXRlZE1vdmVkWTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXN0TW92ZWRYID0gc2V0UGFnZVggLSB0aGlzLl9sYXN0WDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFzdE1vdmVkWSA9IHNldFBhZ2VZIC0gdGhpcy5fbGFzdFk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zbGF0ZVggPSB0aGlzLmdldFRyYW5zZm9ybVgodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpICsgbGFzdE1vdmVkWDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhbnNsYXRlWSA9IHRoaXMuZ2V0VHJhbnNmb3JtWSh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCkgKyBsYXN0TW92ZWRZO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFRyYW5zZm9ybVhZKHRyYW5zbGF0ZVgsIHRyYW5zbGF0ZVkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRHJhZ0V2ZW50cyhwYWdlWCwgcGFnZVksIGV2ZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fbGFzdFggPSBzZXRQYWdlWDtcbiAgICAgICAgICAgIHRoaXMuX2xhc3RZID0gc2V0UGFnZVk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogUGVyZm9ybSBkcmFnIGVuZCBsb2dpYyB3aGVuIHJlbGVhc2luZyB0aGUgZ2hvc3RFbGVtZW50IGFuZCBkaXNwYXRjaGluZyBkcm9wIGV2ZW50IGlmIGlneERyb3AgaXMgdW5kZXIgdGhlIHBvaW50ZXIuXG4gICAgICogVGhpcyBtZXRob2QgaXMgYm91bmQgYXQgZmlyc3QgYXQgdGhlIGJhc2UgZWxlbWVudC5cbiAgICAgKiBJZiBkcmFnZ2luZyBzdGFydHMgYW5kIGFmdGVyIHRoZSBnaG9zdEVsZW1lbnQgaXMgcmVuZGVyZWQgdGhlIHBvaW50ZXJJZCBpcyByZWFzc2lnbmVkIHRvIGl0LiBUaGVuIHRoaXMgbWV0aG9kIGlzIGJvdW5kIHRvIGl0LlxuICAgICAqIEBwYXJhbSBldmVudCBQb2ludGVyVXAgZXZlbnQgY2FwdHVyZWRcbiAgICAgKi9cbiAgICBwdWJsaWMgb25Qb2ludGVyVXAoZXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9jbGlja2VkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcGFnZVgsIHBhZ2VZO1xuICAgICAgICBpZiAodGhpcy5wb2ludGVyRXZlbnRzRW5hYmxlZCB8fCAhdGhpcy50b3VjaEV2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGZpcnN0IGZvciBwb2ludGVyIGV2ZW50cyBvciBub24gdG91Y2gsIGJlY2F1c2Ugd2UgY2FuIGhhdmUgcG9pbnRlciBldmVudHMgYW5kIHRvdWNoIGV2ZW50cyBhdCBvbmNlLlxuICAgICAgICAgICAgcGFnZVggPSBldmVudC5wYWdlWDtcbiAgICAgICAgICAgIHBhZ2VZID0gZXZlbnQucGFnZVk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy50b3VjaEV2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgIHBhZ2VYID0gZXZlbnQudG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgICAgIHBhZ2VZID0gZXZlbnQudG91Y2hlc1swXS5wYWdlWTtcblxuICAgICAgICAgICAgLy8gUHJldmVudCBzY3JvbGxpbmcgb24gdG91Y2ggd2hpbGUgZHJhZ2dpbmdcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBldmVudEFyZ3M6IElEcmFnQmFzZUV2ZW50QXJncyA9IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2ZW50LFxuICAgICAgICAgICAgb3duZXI6IHRoaXMsXG4gICAgICAgICAgICBzdGFydFg6IHRoaXMuX3N0YXJ0WCxcbiAgICAgICAgICAgIHN0YXJ0WTogdGhpcy5fc3RhcnRZLFxuICAgICAgICAgICAgcGFnZVg6IHBhZ2VYLFxuICAgICAgICAgICAgcGFnZVk6IHBhZ2VZXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuX3BvaW50ZXJEb3duSWQgPSBudWxsO1xuICAgICAgICB0aGlzLl9jbGlja2VkID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLl9kcmFnU3RhcnRlZCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2xhc3REcm9wQXJlYSAmJiB0aGlzLl9sYXN0RHJvcEFyZWEgIT09IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50ICkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hEcm9wRXZlbnQoZXZlbnQucGFnZVgsIGV2ZW50LnBhZ2VZLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuYW5pbWF0ZU9uUmVsZWFzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudHJhbnNpdGlvblRvT3JpZ2luKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhZ0VuZC5lbWl0KGV2ZW50QXJncyk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLmFuaW1JblByb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblRyYW5zaXRpb25FbmQobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBUcmlnZ2VyIG91ciBvd24gY2xpY2sgZXZlbnQgYmVjYXVzZSB3aGVuIHRoZXJlIGlzIG5vIGdob3N0LCBuYXRpdmUgY2xpY2sgY2Fubm90IGJlIHByZXZlbnRlZCB3aGVuIGRyYWdnaW5nLlxuICAgICAgICAgICAgdGhpcy56b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmFnQ2xpY2suZW1pdChldmVudEFyZ3MpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogRXhlY3V0ZSB0aGlzIG1ldGhvZCB3aGUgdGhlIHBvaW50ZXIgY2FwdHVyZSBoYXMgYmVlbiBsb3N0LlxuICAgICAqIFRoaXMgbWVhbnMgdGhhdCBkdXJpbmcgZHJhZ2dpbmcgdGhlIHVzZXIgaGFzIHBlcmZvcm1lZCBvdGhlciBhY3Rpb24gbGlrZSByaWdodCBjbGlja2luZyBhbmQgdGhlbiBjbGlja2luZyBzb21ld2hlcmUgZWxzZS5cbiAgICAgKiBUaGlzIG1ldGhvZCB3aWxsIGVuc3VyZSB0aGF0IHRoZSBkcmFnIHN0YXRlIGlzIGJlaW5nIHJlc2V0IGluIHRoaXMgY2FzZSBhcyBpZiB0aGUgdXNlciByZWxlYXNlZCB0aGUgZHJhZ2dlZCBlbGVtZW50LlxuICAgICAqIEBwYXJhbSBldmVudCBFdmVudCBjYXB0dXJlZFxuICAgICAqL1xuICAgIHB1YmxpYyBvblBvaW50ZXJMb3N0KGV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5fY2xpY2tlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXZlbnRBcmdzID0ge1xuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZlbnQsXG4gICAgICAgICAgICBvd25lcjogdGhpcyxcbiAgICAgICAgICAgIHN0YXJ0WDogdGhpcy5fc3RhcnRYLFxuICAgICAgICAgICAgc3RhcnRZOiB0aGlzLl9zdGFydFksXG4gICAgICAgICAgICBwYWdlWDogZXZlbnQucGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogZXZlbnQucGFnZVlcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5fcG9pbnRlckRvd25JZCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2NsaWNrZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMuX2RyYWdTdGFydGVkKSB7XG4gICAgICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWdFbmQuZW1pdChldmVudEFyZ3MpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy5hbmltYXRlT25SZWxlYXNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG9PcmlnaW4oKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuYW5pbUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uVHJhbnNpdGlvbkVuZChudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBDcmVhdGUgZ2hvc3QgZWxlbWVudCAtIGlmIGEgTm9kZSBvYmplY3QgaXMgcHJvdmlkZWQgaXQgY3JlYXRlcyBhIGNsb25lIG9mIHRoYXQgbm9kZSxcbiAgICAgKiBvdGhlcndpc2UgaXQgY2xvbmVzIHRoZSBob3N0IGVsZW1lbnQuXG4gICAgICogQmluZCBhbGwgbmVlZGVkIGV2ZW50cy5cbiAgICAgKiBAcGFyYW0gcGFnZVggTGF0ZXN0IHBvaW50ZXIgcG9zaXRpb24gb24gdGhlIFggYXhpcyByZWxhdGl2ZSB0byB0aGUgcGFnZS5cbiAgICAgKiBAcGFyYW0gcGFnZVkgTGF0ZXN0IHBvaW50ZXIgcG9zaXRpb24gb24gdGhlIFkgYXhpcyByZWxhdGl2ZSB0byB0aGUgcGFnZS5cbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgTm9kZSBvYmplY3QgdG8gYmUgY2xvbmVkLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVHaG9zdChwYWdlWCwgcGFnZVksIG5vZGU6IGFueSA9IG51bGwpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdob3N0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZHluYW1pY0dob3N0UmVmO1xuICAgICAgICBpZiAodGhpcy5naG9zdFRlbXBsYXRlKSB7XG4gICAgICAgICAgICBkeW5hbWljR2hvc3RSZWYgPSB0aGlzLnZpZXdDb250YWluZXIuY3JlYXRlRW1iZWRkZWRWaWV3KHRoaXMuZ2hvc3RUZW1wbGF0ZSwgdGhpcy5naG9zdENvbnRleHQpO1xuICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQgPSBkeW5hbWljR2hvc3RSZWYucm9vdE5vZGVzWzBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQgPSBub2RlID8gbm9kZS5jbG9uZU5vZGUodHJ1ZSkgOiB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0b3RhbE1vdmVkWCA9IHBhZ2VYIC0gdGhpcy5fc3RhcnRYO1xuICAgICAgICBjb25zdCB0b3RhbE1vdmVkWSA9IHBhZ2VZIC0gdGhpcy5fc3RhcnRZO1xuICAgICAgICB0aGlzLl9naG9zdEhvc3RYID0gdGhpcy5naG9zdEhvc3QgPyB0aGlzLmdob3N0SG9zdE9mZnNldExlZnQodGhpcy5naG9zdEhvc3QpIDogMDtcbiAgICAgICAgdGhpcy5fZ2hvc3RIb3N0WSA9IHRoaXMuZ2hvc3RIb3N0ID8gdGhpcy5naG9zdEhvc3RPZmZzZXRUb3AodGhpcy5naG9zdEhvc3QpIDogMDtcblxuICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSAnMC4wcyc7XG4gICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcblxuXG4gICAgICAgIGlmICh0aGlzLmdob3N0Q2xhc3MpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5naG9zdEVsZW1lbnQsIHRoaXMuZ2hvc3RDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjcmVhdGVFdmVudEFyZ3MgPSB7XG4gICAgICAgICAgICBvd25lcjogdGhpcyxcbiAgICAgICAgICAgIGdob3N0RWxlbWVudDogdGhpcy5naG9zdEVsZW1lbnQsXG4gICAgICAgICAgICBjYW5jZWw6IGZhbHNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2hvc3RDcmVhdGUuZW1pdChjcmVhdGVFdmVudEFyZ3MpO1xuICAgICAgICBpZiAoY3JlYXRlRXZlbnRBcmdzLmNhbmNlbCkge1xuICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2hvc3RUZW1wbGF0ZSAmJiBkeW5hbWljR2hvc3RSZWYpIHtcbiAgICAgICAgICAgICAgICBkeW5hbWljR2hvc3RSZWYuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZ2hvc3RIb3N0KSB7XG4gICAgICAgICAgICB0aGlzLmdob3N0SG9zdC5hcHBlbmRDaGlsZCh0aGlzLmdob3N0RWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuZ2hvc3RFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGdob3N0TWFyZ2luTGVmdCA9IHBhcnNlSW50KGRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUodGhpcy5naG9zdEVsZW1lbnQpWydtYXJnaW4tbGVmdCddLCAxMCk7XG4gICAgICAgIGNvbnN0IGdob3N0TWFyZ2luVG9wID0gcGFyc2VJbnQoZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLmdob3N0RWxlbWVudClbJ21hcmdpbi10b3AnXSwgMTApO1xuICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5zdHlsZS5sZWZ0ID0gKHRoaXMuX2dob3N0U3RhcnRYIC0gZ2hvc3RNYXJnaW5MZWZ0ICsgdG90YWxNb3ZlZFggLSB0aGlzLl9naG9zdEhvc3RYKSArICdweCc7XG4gICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LnN0eWxlLnRvcCA9ICh0aGlzLl9naG9zdFN0YXJ0WSAtIGdob3N0TWFyZ2luVG9wICsgdG90YWxNb3ZlZFkgLSB0aGlzLl9naG9zdEhvc3RYKSArICdweCc7XG5cbiAgICAgICAgaWYgKHRoaXMucG9pbnRlckV2ZW50c0VuYWJsZWQpIHtcbiAgICAgICAgICAgIC8vIFRoZSBnaG9zdEVsZW1lbnQgdGFrZXMgY29udHJvbCBmb3IgbW92aW5nIGFuZCBkcmFnZ2luZyBhZnRlciBpdCBoYXMgYmVlbiByZW5kZXJlZC5cbiAgICAgICAgICAgIGlmICh0aGlzLl9wb2ludGVyRG93bklkICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQuc2V0UG9pbnRlckNhcHR1cmUodGhpcy5fcG9pbnRlckRvd25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVybW92ZScsIChhcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblBvaW50ZXJNb3ZlKGFyZ3MpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmdob3N0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVydXAnLCAoYXJncykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25Qb2ludGVyVXAoYXJncyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2xvc3Rwb2ludGVyY2FwdHVyZScsIChhcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblBvaW50ZXJMb3N0KGFyZ3MpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmFuc2l0aW9uIGFuaW1hdGlvbiB3aGVuIHRoZSBnaG9zdEVsZW1lbnQgaXMgcmVsZWFzZWQgYW5kIGl0IHJldHVybnMgdG8gaXQncyBvcmlnaW5hbCBwb3NpdGlvbi5cbiAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndHJhbnNpdGlvbmVuZCcsIChhcmdzKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9uVHJhbnNpdGlvbkVuZChhcmdzKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gSGlkZSB0aGUgYmFzZSBhZnRlciB0aGUgZ2hvc3RFbGVtZW50IGlzIGNyZWF0ZWQsIGJlY2F1c2Ugb3RoZXJ3aXNlIHRoZSBnaG9zdEVsZW1lbnQgd2lsbCBiZSBub3QgdmlzaWJsZS5cbiAgICAgICAgaWYgKHRoaXMuaGlkZUJhc2VPbkRyYWcpIHtcbiAgICAgICAgICAgIHRoaXMudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBEaXNwYXRjaCBjdXN0b20gaWd4RHJhZ0VudGVyL2lneERyYWdMZWF2ZSBldmVudHMgYmFzZWQgb24gY3VycmVudCBwb2ludGVyIHBvc2l0aW9uIGFuZCBpZiBkcm9wIGFyZWEgaXMgdW5kZXIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGRpc3BhdGNoRHJhZ0V2ZW50cyhwYWdlWDogbnVtYmVyLCBwYWdlWTogbnVtYmVyLCBvcmlnaW5hbEV2ZW50KSB7XG4gICAgICAgIGxldCB0b3BEcm9wQXJlYTtcbiAgICAgICAgY29uc3QgY3VzdG9tRXZlbnRBcmdzOiBJZ3hEcmFnQ3VzdG9tRXZlbnREZXRhaWxzID0ge1xuICAgICAgICAgICAgc3RhcnRYOiB0aGlzLl9zdGFydFgsXG4gICAgICAgICAgICBzdGFydFk6IHRoaXMuX3N0YXJ0WSxcbiAgICAgICAgICAgIHBhZ2VYOiBwYWdlWCxcbiAgICAgICAgICAgIHBhZ2VZOiBwYWdlWSxcbiAgICAgICAgICAgIG93bmVyOiB0aGlzLFxuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogb3JpZ2luYWxFdmVudFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGVsZW1lbnRzRnJvbVBvaW50ID0gdGhpcy5nZXRFbGVtZW50c0F0UG9pbnQocGFnZVgsIHBhZ2VZKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50c0Zyb21Qb2ludC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGVsZW1lbnRzRnJvbVBvaW50W2ldLmdldEF0dHJpYnV0ZSgnZHJvcHBhYmxlJykgPT09ICd0cnVlJyAmJlxuICAgICAgICAgICAgICAgIGVsZW1lbnRzRnJvbVBvaW50W2ldICE9PSB0aGlzLmdob3N0RWxlbWVudCAmJiBlbGVtZW50c0Zyb21Qb2ludFtpXSAhPT0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0b3BEcm9wQXJlYSA9IGVsZW1lbnRzRnJvbVBvaW50W2ldO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRvcERyb3BBcmVhICYmXG4gICAgICAgICAgICAoIXRoaXMuX2xhc3REcm9wQXJlYSB8fCAodGhpcy5fbGFzdERyb3BBcmVhICYmIHRoaXMuX2xhc3REcm9wQXJlYSAhPT0gdG9wRHJvcEFyZWEpKSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9sYXN0RHJvcEFyZWEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHRoaXMuX2xhc3REcm9wQXJlYSwgJ2lneERyYWdMZWF2ZScsIGN1c3RvbUV2ZW50QXJncyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5fbGFzdERyb3BBcmVhID0gdG9wRHJvcEFyZWE7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHRoaXMuX2xhc3REcm9wQXJlYSwgJ2lneERyYWdFbnRlcicsIGN1c3RvbUV2ZW50QXJncyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0b3BEcm9wQXJlYSAmJiB0aGlzLl9sYXN0RHJvcEFyZWEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQodGhpcy5fbGFzdERyb3BBcmVhLCAnaWd4RHJhZ0xlYXZlJywgY3VzdG9tRXZlbnRBcmdzKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9sYXN0RHJvcEFyZWEgPSBudWxsO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICBpZiAodG9wRHJvcEFyZWEpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudCh0b3BEcm9wQXJlYSwgJ2lneERyYWdPdmVyJywgY3VzdG9tRXZlbnRBcmdzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKiBEaXNwYXRjaCBjdXN0b20gaWd4RHJvcCBldmVudCBiYXNlZCBvbiBjdXJyZW50IHBvaW50ZXIgcG9zaXRpb24gaWYgdGhlcmUgaXMgbGFzdCByZWNvcmRlciBkcm9wIGFyZWEgdW5kZXIgdGhlIHBvaW50ZXIuXG4gICAgICogTGFzdCByZWNvcmRlciBkcm9wIGFyZWEgaXMgdXBkYXRlZCBpbiBAZGlzcGF0Y2hEcmFnRXZlbnRzIG1ldGhvZC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZGlzcGF0Y2hEcm9wRXZlbnQocGFnZVg6IG51bWJlciwgcGFnZVk6IG51bWJlciwgb3JpZ2luYWxFdmVudCkge1xuICAgICAgICBjb25zdCBldmVudEFyZ3M6IElneERyYWdDdXN0b21FdmVudERldGFpbHMgPSB7XG4gICAgICAgICAgICBzdGFydFg6IHRoaXMuX3N0YXJ0WCxcbiAgICAgICAgICAgIHN0YXJ0WTogdGhpcy5fc3RhcnRZLFxuICAgICAgICAgICAgcGFnZVg6IHBhZ2VYLFxuICAgICAgICAgICAgcGFnZVk6IHBhZ2VZLFxuICAgICAgICAgICAgb3duZXI6IHRoaXMsXG4gICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBvcmlnaW5hbEV2ZW50XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHRoaXMuX2xhc3REcm9wQXJlYSwgJ2lneERyb3AnLCBldmVudEFyZ3MpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQodGhpcy5fbGFzdERyb3BBcmVhLCAnaWd4RHJhZ0xlYXZlJywgZXZlbnRBcmdzKTtcbiAgICAgICAgdGhpcy5fbGFzdERyb3BBcmVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG9uVHJhbnNpdGlvbkVuZChldmVudCkge1xuICAgICAgICBpZiAoKCF0aGlzLl9kcmFnU3RhcnRlZCAmJiAhdGhpcy5hbmltSW5Qcm9ncmVzcykgfHwgdGhpcy5fY2xpY2tlZCkge1xuICAgICAgICAgICAgLy8gUmV0dXJuIGlmIG5vIGRyYWdnaW5nIHN0YXJ0ZWQgYW5kIHRoZXJlIGlzIG5vIGFuaW1hdGlvbiBpbiBwcm9ncmVzcy5cbiAgICAgICAgICAgIHJldHVybiA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5naG9zdCAmJiB0aGlzLmdob3N0RWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5fZ2hvc3RTdGFydFggPSB0aGlzLmJhc2VMZWZ0ICsgdGhpcy5nZXRXaW5kb3dTY3JvbGxMZWZ0KCk7XG4gICAgICAgICAgICB0aGlzLl9naG9zdFN0YXJ0WSA9IHRoaXMuYmFzZVRvcCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsVG9wKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGdob3N0RGVzdHJveUFyZ3M6IElEcmFnR2hvc3RCYXNlRXZlbnRBcmdzID0ge1xuICAgICAgICAgICAgICAgIG93bmVyOiB0aGlzLFxuICAgICAgICAgICAgICAgIGdob3N0RWxlbWVudDogdGhpcy5naG9zdEVsZW1lbnQsXG4gICAgICAgICAgICAgICAgY2FuY2VsOiBmYWxzZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZ2hvc3REZXN0cm95LmVtaXQoZ2hvc3REZXN0cm95QXJncyk7XG4gICAgICAgICAgICBpZiAoZ2hvc3REZXN0cm95QXJncy5jYW5jZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmhpZGVCYXNlT25EcmFnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZ2hvc3RFbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5naG9zdEVsZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5naG9zdEVsZW1lbnQgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmdob3N0KSB7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50cmFuc2l0aW9uUHJvcGVydHkgPSAnJztcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbiA9ICcwLjBzJztcbiAgICAgICAgICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zaXRpb25UaW1pbmdGdW5jdGlvbiA9ICcnO1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudHJhbnNpdGlvbkRlbGF5ID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hbmltSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9kcmFnU3RhcnRlZCA9IGZhbHNlO1xuXG4gICAgICAgIC8vIEV4ZWN1dGUgdHJhbnNpdGlvbmVkIGFmdGVyIGV2ZXJ5dGhpbmcgaXMgcmVzZXQgc28gaWYgdGhlIHVzZXIgc2V0cyBuZXcgbG9jYXRpb24gb24gdGhlIGJhc2Ugbm93IGl0IHdvdWxkIHdvcmsgYXMgZXhwZWN0ZWQuXG4gICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uZWQuZW1pdCh7XG4gICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZlbnQsXG4gICAgICAgICAgICAgICAgb3duZXI6IHRoaXMsXG4gICAgICAgICAgICAgICAgc3RhcnRYOiB0aGlzLl9zdGFydFgsXG4gICAgICAgICAgICAgICAgc3RhcnRZOiB0aGlzLl9zdGFydFksXG4gICAgICAgICAgICAgICAgcGFnZVg6IHRoaXMuX3N0YXJ0WCxcbiAgICAgICAgICAgICAgICBwYWdlWTogdGhpcy5fc3RhcnRZXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBnZXRFbGVtZW50c0F0UG9pbnQocGFnZVg6IG51bWJlciwgcGFnZVk6IG51bWJlcikge1xuICAgICAgICAvLyBjb3JyZWN0IHRoZSBjb29yZGluYXRlcyB3aXRoIHRoZSBjdXJyZW50IHNjcm9sbCBwb3NpdGlvbiwgYmVjYXVzZVxuICAgICAgICAvLyBkb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludCBjb25zaWRlciBwb3NpdGlvbiB3aXRoaW4gdGhlIGN1cnJlbnQgdmlld3BvcnRcbiAgICAgICAgLy8gd2luZG93LnBhZ2VYT2Zmc2V0ID09IHdpbmRvdy5zY3JvbGxYOyAvLyBhbHdheXMgdHJ1ZVxuICAgICAgICAvLyB1c2luZyB3aW5kb3cucGFnZVhPZmZzZXQgZm9yIElFOSBjb21wYXRpYmlsaXR5XG4gICAgICAgIGNvbnN0IHZpZXdQb3J0WCA9IHBhZ2VYIC0gd2luZG93LnBhZ2VYT2Zmc2V0O1xuICAgICAgICBjb25zdCB2aWV3UG9ydFkgPSBwYWdlWSAtIHdpbmRvdy5wYWdlWU9mZnNldDtcbiAgICAgICAgaWYgKGRvY3VtZW50Wydtc0VsZW1lbnRzRnJvbVBvaW50J10pIHtcbiAgICAgICAgICAgIC8vIEVkZ2UgYW5kIElFIHNwZWNpYWwgc25vd2ZsYWtlc1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudFsnbXNFbGVtZW50c0Zyb21Qb2ludCddKHZpZXdQb3J0WCwgdmlld1BvcnRZKTtcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50cyA9PT0gbnVsbCA/IFtdIDogZWxlbWVudHM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlciBicm93c2VycyBsaWtlIENocm9tZSwgRmlyZWZveCwgT3BlcmFcbiAgICAgICAgICAgIHJldHVybiBkb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludCh2aWV3UG9ydFgsIHZpZXdQb3J0WSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGRpc3BhdGNoRXZlbnQodGFyZ2V0LCBldmVudE5hbWU6IHN0cmluZywgZXZlbnRBcmdzOiBJZ3hEcmFnQ3VzdG9tRXZlbnREZXRhaWxzKSB7XG4gICAgICAgIC8vIFRoaXMgd2F5IGlzIElFMTEgY29tcGF0aWJsZS5cbiAgICAgICAgY29uc3QgZHJhZ0xlYXZlRXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnQ3VzdG9tRXZlbnQnKTtcbiAgICAgICAgZHJhZ0xlYXZlRXZlbnQuaW5pdEN1c3RvbUV2ZW50KGV2ZW50TmFtZSwgZmFsc2UsIGZhbHNlLCBldmVudEFyZ3MpO1xuICAgICAgICB0YXJnZXQuZGlzcGF0Y2hFdmVudChkcmFnTGVhdmVFdmVudCk7XG4gICAgICAgIC8vIE90aGVyd2lzZSBjYW4gYmUgdXNlZCBgdGFyZ2V0LmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KGV2ZW50TmFtZSwgZXZlbnRBcmdzKSk7YFxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRUcmFuc2Zvcm1YKGVsZW0pIHtcbiAgICAgICAgbGV0IHBvc1ggPSAwO1xuICAgICAgICBpZiAoZWxlbS5zdHlsZS50cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IGVsZW0uc3R5bGUudHJhbnNmb3JtO1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gbWF0cml4ID8gbWF0cml4Lm1hdGNoKC8tP1tcXGRcXC5dKy9nKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHBvc1ggPSB2YWx1ZXMgPyBOdW1iZXIodmFsdWVzWyAxIF0pIDogMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb3NYO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRUcmFuc2Zvcm1ZKGVsZW0pIHtcbiAgICAgICAgbGV0IHBvc1kgPSAwO1xuICAgICAgICBpZiAoZWxlbS5zdHlsZS50cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IGVsZW0uc3R5bGUudHJhbnNmb3JtO1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gbWF0cml4ID8gbWF0cml4Lm1hdGNoKC8tP1tcXGRcXC5dKy9nKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHBvc1kgPSB2YWx1ZXMgPyBOdW1iZXIodmFsdWVzWyAyIF0pIDogMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb3NZO1xuICAgIH1cblxuICAgIC8qKiBNZXRob2Qgc2V0dGluZyB0cmFuc2Zvcm1hdGlvbiB0byB0aGUgYmFzZSBkcmFnZ2FibGUgZWxlbWVudC4gKi9cbiAgICBwcm90ZWN0ZWQgc2V0VHJhbnNmb3JtWFkoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUudHJhbnNmb3JtID0gJ3RyYW5zbGF0ZTNkKCcgKyB4ICsgJ3B4LCAnICsgeSArICdweCwgMHB4KSc7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdldFdpbmRvd1Njcm9sbFRvcCgpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5zY3JvbGxZID8gd2luZG93LnNjcm9sbFkgOiAod2luZG93LnBhZ2VZT2Zmc2V0ID8gd2luZG93LnBhZ2VZT2Zmc2V0IDogMCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdldFdpbmRvd1Njcm9sbExlZnQoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuc2Nyb2xsWCA/IHdpbmRvdy5zY3JvbGxYIDogKHdpbmRvdy5wYWdlWE9mZnNldCA/IHdpbmRvdy5wYWdlWE9mZnNldCA6IDApO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnaG9zdEhvc3RPZmZzZXRMZWZ0KGdob3N0SG9zdDogYW55KSB7XG4gICAgICAgIGNvbnN0IGdob3N0UG9zaXRpb24gPSBkb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKGdob3N0SG9zdCkuZ2V0UHJvcGVydHlWYWx1ZSgncG9zaXRpb24nKTtcbiAgICAgICAgaWYgKGdob3N0UG9zaXRpb24gPT09ICdzdGF0aWMnICYmIGdob3N0SG9zdC5vZmZzZXRQYXJlbnQgJiYgZ2hvc3RIb3N0Lm9mZnNldFBhcmVudCA9PT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0gZWxzZSBpZiAoZ2hvc3RQb3NpdGlvbiA9PT0gJ3N0YXRpYycgJiYgZ2hvc3RIb3N0Lm9mZnNldFBhcmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGdob3N0SG9zdC5vZmZzZXRQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCAtIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnaG9zdEhvc3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCAtIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnaG9zdEhvc3RPZmZzZXRUb3AoZ2hvc3RIb3N0OiBhbnkpIHtcbiAgICAgICAgY29uc3QgZ2hvc3RQb3NpdGlvbiA9IGRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUoZ2hvc3RIb3N0KS5nZXRQcm9wZXJ0eVZhbHVlKCdwb3NpdGlvbicpO1xuICAgICAgICBpZiAoZ2hvc3RQb3NpdGlvbiA9PT0gJ3N0YXRpYycgJiYgZ2hvc3RIb3N0Lm9mZnNldFBhcmVudCAmJiBnaG9zdEhvc3Qub2Zmc2V0UGFyZW50ID09PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSBlbHNlIGlmIChnaG9zdFBvc2l0aW9uID09PSAnc3RhdGljJyAmJiBnaG9zdEhvc3Qub2Zmc2V0UGFyZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gZ2hvc3RIb3N0Lm9mZnNldFBhcmVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgLSB0aGlzLmdldFdpbmRvd1Njcm9sbFRvcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnaG9zdEhvc3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gdGhpcy5nZXRXaW5kb3dTY3JvbGxUb3AoKTtcbiAgICB9XG59XG5cbkBEaXJlY3RpdmUoe1xuICAgIGV4cG9ydEFzOiAnZHJvcCcsXG4gICAgc2VsZWN0b3I6ICdbaWd4RHJvcF0nXG59KVxuZXhwb3J0IGNsYXNzIElneERyb3BEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG5cbiAgICAvKipcbiAgICAgKiAtIFNhdmUgZGF0YSBpbnNpZGUgdGhlIGBpZ3hEcm9wYCBkaXJlY3RpdmUuIFRoaXMgY2FuIGJlIHNldCB3aGVuIGluc3RhbmNpbmcgYGlneERyb3BgIG9uIGFuIGVsZW1lbnQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgW2lneERyb3BdPVwieyBzb3VyY2U6IG15RWxlbWVudCB9XCI+PC9kaXY+XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyb3BEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBASW5wdXQoJ2lneERyb3AnKVxuICAgIHB1YmxpYyBkYXRhOiBhbnk7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBwcm92aWRlIGEgd2F5IGZvciBpZ3hEcmFnIGFuZCBpZ3hEcm9wIHRvIGJlIGxpbmtlZCB0aHJvdWdoIGNoYW5uZWxzLlxuICAgICAqIEl0IGFjY2VwdHMgc2luZ2xlIHZhbHVlIG9yIGFuIGFycmF5IG9mIHZhbHVlcyBhbmQgZXZhbHVhdGVzIHRoZW4gdXNpbmcgc3RyaWN0IGVxdWFsaXR5LlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2IGlneERyYWcgW2RyYWdDaGFubmVsXT1cIidvZGQnXCI+XG4gICAgICogICAgICAgICA8c3Bhbj45NTwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiA8ZGl2IGlneERyb3AgW2Ryb3BDaGFubmVsXT1cIlsnb2RkJywgJ2lycmF0aW9uYWwnXVwiPlxuICAgICAqICAgICAgICAgPHNwYW4+TnVtYmVycyBkcm9wIGFyZWEhPC9zcGFuPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcm9wRGlyZWN0aXZlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZHJvcENoYW5uZWw6IG51bWJlciB8IHN0cmluZyB8IG51bWJlcltdIHwgc3RyaW5nW107XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBzcGVjaWZpZXMgYSBkcm9wIHN0cmF0ZWd5IHR5cGUgdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIHdoZW4gYW4gYElneERyYWdgIGVsZW1lbnQgaXMgcmVsZWFzZWQgaW5zaWRlXG4gICAgICogIHRoZSBjdXJyZW50IGRyb3AgYXJlYS4gVGhlIHByb3ZpZGVkIHN0cmF0ZWdpZXMgYXJlOlxuICAgICAqICAtIElneERlZmF1bHREcm9wU3RyYXRlZ3kgLSBUaGlzIGlzIHRoZSBkZWZhdWx0IGJhc2Ugc3RyYXRlZ3kgYW5kIGl0IGRvZXNuJ3QgcGVyZm9ybSBhbnkgYWN0aW9ucy5cbiAgICAgKiAgLSBJZ3hBcHBlbmREcm9wU3RyYXRlZ3kgLSBBcHBlbmRzIHRoZSBkcm9wcGVkIGVsZW1lbnQgdG8gbGFzdCBwb3NpdGlvbiBhcyBhIGRpcmVjdCBjaGlsZCB0byB0aGUgYGlneERyb3BgLlxuICAgICAqICAtIElneFByZXBlbmREcm9wU3RyYXRlZ3kgLSBQcmVwZW5kcyB0aGUgZHJvcHBlZCBlbGVtZW50IHRvIGZpcnN0IHBvc2l0aW9uIGFzIGEgZGlyZWN0IGNoaWxkIHRvIHRoZSBgaWd4RHJvcGAuXG4gICAgICogIC0gSWd4SW5zZXJ0RHJvcFN0cmF0ZWd5IC0gSWYgdGhlIGRyb3BwZWQgZWxlbWVudCBpcyByZWxlYXNlZCBhYm92ZSBhIGNoaWxkIGVsZW1lbnQgb2YgdGhlIGBpZ3hEcm9wYCwgaXQgd2lsbCBiZSBpbnNlcnRlZFxuICAgICAqICAgICAgYXQgdGhhdCBwb3NpdGlvbi4gT3RoZXJ3aXNlIHRoZSBkcm9wcGVkIGVsZW1lbnQgd2lsbCBiZSBhcHBlbmRlZCBpZiByZWxlYXNlZCBvdXRzaWRlIGFueSBjaGlsZCBvZiB0aGUgYGlneERyb3BgLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8ZGl2IGlneERyYWc+XG4gICAgICogICAgICA8c3Bhbj5EcmFnTWU8L3NwYW4+XG4gICAgICogPC9kaXY+XG4gICAgICogPGRpdiBpZ3hEcm9wIFtkcm9wU3RyYXRlZ3ldPVwibXlEcm9wU3RyYXRlZ3lcIj5cbiAgICAgKiAgICAgICAgIDxzcGFuPk51bWJlcnMgZHJvcCBhcmVhITwvc3Bhbj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogaW1wb3J0IHsgSWd4QXBwZW5kRHJvcFN0cmF0ZWd5IH0gZnJvbSAnaWduaXRldWktYW5ndWxhcic7XG4gICAgICpcbiAgICAgKiBleHBvcnQgY2xhc3MgQXBwIHtcbiAgICAgKiAgICAgIHB1YmxpYyBteURyb3BTdHJhdGVneSA9IElneEFwcGVuZERyb3BTdHJhdGVneTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyb3BEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZXQgZHJvcFN0cmF0ZWd5KGNsYXNzUmVmOiBhbnkpIHtcbiAgICAgICAgdGhpcy5fZHJvcFN0cmF0ZWd5ID0gbmV3IGNsYXNzUmVmKHRoaXMuX3JlbmRlcmVyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGRyb3BTdHJhdGVneSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Ryb3BTdHJhdGVneTtcbiAgICB9XG5cbiAgICAvKiogRXZlbnQgdHJpZ2dlcmVkIHdoZW4gZHJhZ2dlZCBlbGVtZW50IGVudGVycyB0aGUgYXJlYSBvZiB0aGUgZWxlbWVudC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBjbGFzcz1cImNhZ2VBcmVhXCIgaWd4RHJvcCAoZW50ZXIpPVwiZHJhZ0VudGVyKClcIiAoaWd4RHJhZ0VudGVyKT1cIm9uRHJhZ0NhZ2VFbnRlcigpXCIgKGlneERyYWdMZWF2ZSk9XCJvbkRyYWdDYWdlTGVhdmUoKVwiPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBwdWJsaWMgZHJhZ0VudGVyKCl7XG4gICAgICogICAgIGFsZXJ0KFwiQSBkcmFnZ2FibGUgZWxlbWVudCBoYXMgZW50ZXJlZCB0aGUgY2hpcCBhcmVhIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyb3BEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgZW50ZXIgPSBuZXcgRXZlbnRFbWl0dGVyPElEcm9wQmFzZUV2ZW50QXJncz4oKTtcblxuICAgICAgICAvKiogRXZlbnQgdHJpZ2dlcmVkIHdoZW4gZHJhZ2dlZCBlbGVtZW50IGVudGVycyB0aGUgYXJlYSBvZiB0aGUgZWxlbWVudC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBjbGFzcz1cImNhZ2VBcmVhXCIgaWd4RHJvcCAoZW50ZXIpPVwiZHJhZ0VudGVyKClcIiAoaWd4RHJhZ0VudGVyKT1cIm9uRHJhZ0NhZ2VFbnRlcigpXCIgKGlneERyYWdMZWF2ZSk9XCJvbkRyYWdDYWdlTGVhdmUoKVwiPlxuICAgICAqIDwvZGl2PlxuICAgICAqIGBgYFxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiBwdWJsaWMgZHJhZ0VudGVyKCl7XG4gICAgICogICAgIGFsZXJ0KFwiQSBkcmFnZ2FibGUgZWxlbWVudCBoYXMgZW50ZXJlZCB0aGUgY2hpcCBhcmVhIVwiKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQG1lbWJlcm9mIElneERyb3BEaXJlY3RpdmVcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb3ZlciA9IG5ldyBFdmVudEVtaXR0ZXI8SURyb3BCYXNlRXZlbnRBcmdzPigpO1xuXG4gICAgLyoqIEV2ZW50IHRyaWdnZXJlZCB3aGVuIGRyYWdnZWQgZWxlbWVudCBsZWF2ZXMgdGhlIGFyZWEgb2YgdGhlIGVsZW1lbnQuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxkaXYgY2xhc3M9XCJjYWdlQXJlYVwiIGlneERyb3AgKGxlYXZlKT1cImRyYWdMZWF2ZSgpXCIgKGlneERyYWdFbnRlcik9XCJvbkRyYWdDYWdlRW50ZXIoKVwiIChpZ3hEcmFnTGVhdmUpPVwib25EcmFnQ2FnZUxlYXZlKClcIj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcHVibGljIGRyYWdMZWF2ZSgpe1xuICAgICAqICAgICBhbGVydChcIkEgZHJhZ2dhYmxlIGVsZW1lbnQgaGFzIGxlZnQgdGhlIGNoaXAgYXJlYSFcIik7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEBtZW1iZXJvZiBJZ3hEcm9wRGlyZWN0aXZlXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIGxlYXZlID0gbmV3IEV2ZW50RW1pdHRlcjxJRHJvcEJhc2VFdmVudEFyZ3M+KCk7XG5cbiAgICAvKiogRXZlbnQgdHJpZ2dlcmVkIHdoZW4gZHJhZ2dlZCBlbGVtZW50IGlzIGRyb3BwZWQgaW4gdGhlIGFyZWEgb2YgdGhlIGVsZW1lbnQuXG4gICAgICogU2luY2UgdGhlIGBpZ3hEcm9wYCBoYXMgZGVmYXVsdCBsb2dpYyB0aGF0IGFwcGVuZHMgdGhlIGRyb3BwZWQgZWxlbWVudCBhcyBhIGNoaWxkLCBpdCBjYW4gYmUgY2FuY2VsZWQgaGVyZS5cbiAgICAgKiBUbyBjYW5jZWwgdGhlIGRlZmF1bHQgbG9naWMgdGhlIGBjYW5jZWxgIHByb3BlcnR5IG9mIHRoZSBldmVudCBuZWVkcyB0byBiZSBzZXQgdG8gdHJ1ZS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGRpdiBjbGFzcz1cImNhZ2VBcmVhXCIgaWd4RHJvcCAoZHJvcHBlZCk9XCJkcmFnRHJvcCgpXCIgKGlneERyYWdFbnRlcik9XCJvbkRyYWdDYWdlRW50ZXIoKVwiIChpZ3hEcmFnTGVhdmUpPVwib25EcmFnQ2FnZUxlYXZlKClcIj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKiBgYGBcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcHVibGljIGRyYWdEcm9wKCl7XG4gICAgICogICAgIGFsZXJ0KFwiQSBkcmFnZ2FibGUgZWxlbWVudCBoYXMgYmVlbiBkcm9wcGVkIGluIHRoZSBjaGlwIGFyZWEhXCIpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAbWVtYmVyb2YgSWd4RHJvcERpcmVjdGl2ZVxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBkcm9wcGVkID0gbmV3IEV2ZW50RW1pdHRlcjxJRHJvcERyb3BwZWRFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmRyb3BwYWJsZScpXG4gICAgcHVibGljIGRyb3BwYWJsZSA9IHRydWU7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5kcmFnT3ZlcicpXG4gICAgcHVibGljIGRyYWdvdmVyID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIF9kZXN0cm95ID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcbiAgICBwcm90ZWN0ZWQgX2Ryb3BTdHJhdGVneTogSURyb3BTdHJhdGVneTtcblxuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBlbGVtZW50OiBFbGVtZW50UmVmLCBwcml2YXRlIF9yZW5kZXJlcjogUmVuZGVyZXIyLCBwcml2YXRlIF96b25lOiBOZ1pvbmUpIHtcbiAgICAgICAgdGhpcy5fZHJvcFN0cmF0ZWd5ID0gbmV3IElneERlZmF1bHREcm9wU3RyYXRlZ3koKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIGZyb21FdmVudCh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCwgJ2lneERyYWdFbnRlcicpLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kpKVxuICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKHJlcykgPT4gdGhpcy5vbkRyYWdFbnRlcihyZXMgYXMgQ3VzdG9tRXZlbnQ8SWd4RHJhZ0N1c3RvbUV2ZW50RGV0YWlscz4pKTtcblxuICAgICAgICAgICAgZnJvbUV2ZW50KHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAnaWd4RHJhZ0xlYXZlJykucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveSkpLnN1YnNjcmliZSgocmVzKSA9PiB0aGlzLm9uRHJhZ0xlYXZlKHJlcykpO1xuICAgICAgICAgICAgZnJvbUV2ZW50KHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAnaWd4RHJhZ092ZXInKS5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95KSkuc3Vic2NyaWJlKChyZXMpID0+IHRoaXMub25EcmFnT3ZlcihyZXMpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5fZGVzdHJveS5uZXh0KHRydWUpO1xuICAgICAgICB0aGlzLl9kZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBvbkRyYWdPdmVyKGV2ZW50KSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRQb3NYID0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgICAgICBjb25zdCBlbGVtZW50UG9zWSA9IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsVG9wKCk7XG4gICAgICAgIGNvbnN0IG9mZnNldFggPSBldmVudC5kZXRhaWwucGFnZVggLSBlbGVtZW50UG9zWDtcbiAgICAgICAgY29uc3Qgb2Zmc2V0WSA9IGV2ZW50LmRldGFpbC5wYWdlWSAtIGVsZW1lbnRQb3NZO1xuICAgICAgICBjb25zdCBldmVudEFyZ3M6IElEcm9wQmFzZUV2ZW50QXJncyA9IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2ZW50LmRldGFpbC5vcmlnaW5hbEV2ZW50LFxuICAgICAgICAgICAgb3duZXI6IHRoaXMsXG4gICAgICAgICAgICBkcmFnOiBldmVudC5kZXRhaWwub3duZXIsXG4gICAgICAgICAgICBkcmFnRGF0YTogZXZlbnQuZGV0YWlsLm93bmVyLmRhdGEsXG4gICAgICAgICAgICBzdGFydFg6IGV2ZW50LmRldGFpbC5zdGFydFgsXG4gICAgICAgICAgICBzdGFydFk6IGV2ZW50LmRldGFpbC5zdGFydFksXG4gICAgICAgICAgICBwYWdlWDogZXZlbnQuZGV0YWlsLnBhZ2VYLFxuICAgICAgICAgICAgcGFnZVk6IGV2ZW50LmRldGFpbC5wYWdlWSxcbiAgICAgICAgICAgIG9mZnNldFg6IG9mZnNldFgsXG4gICAgICAgICAgICBvZmZzZXRZOiBvZmZzZXRZXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5vdmVyLmVtaXQoZXZlbnRBcmdzKTtcbiAgICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBvbkRyYWdFbnRlcihldmVudDogQ3VzdG9tRXZlbnQ8SWd4RHJhZ0N1c3RvbUV2ZW50RGV0YWlscz4pIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRHJhZ0xpbmtlZChldmVudC5kZXRhaWwub3duZXIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRyYWdvdmVyID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgZWxlbWVudFBvc1ggPSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ICsgdGhpcy5nZXRXaW5kb3dTY3JvbGxMZWZ0KCk7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRQb3NZID0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wICsgdGhpcy5nZXRXaW5kb3dTY3JvbGxUb3AoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0WCA9IGV2ZW50LmRldGFpbC5wYWdlWCAtIGVsZW1lbnRQb3NYO1xuICAgICAgICBjb25zdCBvZmZzZXRZID0gZXZlbnQuZGV0YWlsLnBhZ2VZIC0gZWxlbWVudFBvc1k7XG4gICAgICAgIGNvbnN0IGV2ZW50QXJnczogSURyb3BCYXNlRXZlbnRBcmdzID0ge1xuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZlbnQuZGV0YWlsLm9yaWdpbmFsRXZlbnQsXG4gICAgICAgICAgICBvd25lcjogdGhpcyxcbiAgICAgICAgICAgIGRyYWc6IGV2ZW50LmRldGFpbC5vd25lcixcbiAgICAgICAgICAgIGRyYWdEYXRhOiBldmVudC5kZXRhaWwub3duZXIuZGF0YSxcbiAgICAgICAgICAgIHN0YXJ0WDogZXZlbnQuZGV0YWlsLnN0YXJ0WCxcbiAgICAgICAgICAgIHN0YXJ0WTogZXZlbnQuZGV0YWlsLnN0YXJ0WSxcbiAgICAgICAgICAgIHBhZ2VYOiBldmVudC5kZXRhaWwucGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogZXZlbnQuZGV0YWlsLnBhZ2VZLFxuICAgICAgICAgICAgb2Zmc2V0WDogb2Zmc2V0WCxcbiAgICAgICAgICAgIG9mZnNldFk6IG9mZnNldFlcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5fem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbnRlci5lbWl0KGV2ZW50QXJncyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgb25EcmFnTGVhdmUoZXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRHJhZ0xpbmtlZChldmVudC5kZXRhaWwub3duZXIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRyYWdvdmVyID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRQb3NYID0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsTGVmdCgpO1xuICAgICAgICBjb25zdCBlbGVtZW50UG9zWSA9IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCArIHRoaXMuZ2V0V2luZG93U2Nyb2xsVG9wKCk7XG4gICAgICAgIGNvbnN0IG9mZnNldFggPSBldmVudC5kZXRhaWwucGFnZVggLSBlbGVtZW50UG9zWDtcbiAgICAgICAgY29uc3Qgb2Zmc2V0WSA9IGV2ZW50LmRldGFpbC5wYWdlWSAtIGVsZW1lbnRQb3NZO1xuICAgICAgICBjb25zdCBldmVudEFyZ3M6IElEcm9wQmFzZUV2ZW50QXJncyA9IHtcbiAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2ZW50LmRldGFpbC5vcmlnaW5hbEV2ZW50LFxuICAgICAgICAgICAgb3duZXI6IHRoaXMsXG4gICAgICAgICAgICBkcmFnOiBldmVudC5kZXRhaWwub3duZXIsXG4gICAgICAgICAgICBkcmFnRGF0YTogZXZlbnQuZGV0YWlsLm93bmVyLmRhdGEsXG4gICAgICAgICAgICBzdGFydFg6IGV2ZW50LmRldGFpbC5zdGFydFgsXG4gICAgICAgICAgICBzdGFydFk6IGV2ZW50LmRldGFpbC5zdGFydFksXG4gICAgICAgICAgICBwYWdlWDogZXZlbnQuZGV0YWlsLnBhZ2VYLFxuICAgICAgICAgICAgcGFnZVk6IGV2ZW50LmRldGFpbC5wYWdlWSxcbiAgICAgICAgICAgIG9mZnNldFg6IG9mZnNldFgsXG4gICAgICAgICAgICBvZmZzZXRZOiBvZmZzZXRZXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuX3pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUuZW1pdChldmVudEFyZ3MpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RMaXN0ZW5lcignaWd4RHJvcCcsIFsnJGV2ZW50J10pXG4gICAgcHVibGljIG9uRHJhZ0Ryb3AoZXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRHJhZ0xpbmtlZChldmVudC5kZXRhaWwub3duZXIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlbGVtZW50UG9zWCA9IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgKyB0aGlzLmdldFdpbmRvd1Njcm9sbExlZnQoKTtcbiAgICAgICAgY29uc3QgZWxlbWVudFBvc1kgPSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS50b3AgKyB0aGlzLmdldFdpbmRvd1Njcm9sbFRvcCgpO1xuICAgICAgICBjb25zdCBvZmZzZXRYID0gZXZlbnQuZGV0YWlsLnBhZ2VYIC0gZWxlbWVudFBvc1g7XG4gICAgICAgIGNvbnN0IG9mZnNldFkgPSBldmVudC5kZXRhaWwucGFnZVkgLSBlbGVtZW50UG9zWTtcbiAgICAgICAgY29uc3QgYXJnczogSURyb3BEcm9wcGVkRXZlbnRBcmdzID0ge1xuICAgICAgICAgICAgb3duZXI6IHRoaXMsXG4gICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBldmVudC5kZXRhaWwub3JpZ2luYWxFdmVudCxcbiAgICAgICAgICAgIGRyYWc6IGV2ZW50LmRldGFpbC5vd25lcixcbiAgICAgICAgICAgIGRyYWdEYXRhOiBldmVudC5kZXRhaWwub3duZXIuZGF0YSxcbiAgICAgICAgICAgIHN0YXJ0WDogZXZlbnQuZGV0YWlsLnN0YXJ0WCxcbiAgICAgICAgICAgIHN0YXJ0WTogZXZlbnQuZGV0YWlsLnN0YXJ0WSxcbiAgICAgICAgICAgIHBhZ2VYOiBldmVudC5kZXRhaWwucGFnZVgsXG4gICAgICAgICAgICBwYWdlWTogZXZlbnQuZGV0YWlsLnBhZ2VZLFxuICAgICAgICAgICAgb2Zmc2V0WDogb2Zmc2V0WCxcbiAgICAgICAgICAgIG9mZnNldFk6IG9mZnNldFksXG4gICAgICAgICAgICBjYW5jZWw6IGZhbHNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuX3pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZHJvcHBlZC5lbWl0KGFyZ3MpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5fZHJvcFN0cmF0ZWd5ICYmICFhcmdzLmNhbmNlbCkge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHNBdFBvaW50ID0gZXZlbnQuZGV0YWlsLm93bmVyLmdldEVsZW1lbnRzQXRQb2ludChldmVudC5kZXRhaWwucGFnZVgsIGV2ZW50LmRldGFpbC5wYWdlWSk7XG4gICAgICAgICAgICBjb25zdCBpbnNlcnRJbmRleCA9IHRoaXMuZ2V0SW5zZXJ0SW5kZXhBdChldmVudC5kZXRhaWwub3duZXIsIGVsZW1lbnRzQXRQb2ludCk7XG4gICAgICAgICAgICB0aGlzLl9kcm9wU3RyYXRlZ3kuZHJvcEFjdGlvbihldmVudC5kZXRhaWwub3duZXIsIHRoaXMsIGluc2VydEluZGV4KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRXaW5kb3dTY3JvbGxUb3AoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuc2Nyb2xsWSA/IHdpbmRvdy5zY3JvbGxZIDogKHdpbmRvdy5wYWdlWU9mZnNldCA/IHdpbmRvdy5wYWdlWU9mZnNldCA6IDApO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRXaW5kb3dTY3JvbGxMZWZ0KCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnNjcm9sbFggPyB3aW5kb3cuc2Nyb2xsWCA6ICh3aW5kb3cucGFnZVhPZmZzZXQgPyB3aW5kb3cucGFnZVhPZmZzZXQgOiAwKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaXNEcmFnTGlua2VkKGRyYWc6IElneERyYWdEaXJlY3RpdmUpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgZHJhZ0xpbmtBcnJheSA9IGRyYWcuZHJhZ0NoYW5uZWwgaW5zdGFuY2VvZiBBcnJheTtcbiAgICAgICAgY29uc3QgZHJvcExpbmtBcnJheSA9IHRoaXMuZHJvcENoYW5uZWwgaW5zdGFuY2VvZiBBcnJheTtcblxuICAgICAgICBpZiAoIWRyYWdMaW5rQXJyYXkgJiYgIWRyb3BMaW5rQXJyYXkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRyb3BDaGFubmVsID09PSBkcmFnLmRyYWdDaGFubmVsO1xuICAgICAgICB9IGVsc2UgaWYgKCFkcmFnTGlua0FycmF5ICYmIGRyb3BMaW5rQXJyYXkpIHtcbiAgICAgICAgICAgIGNvbnN0IGRyb3BMaW5rcyA9IDxBcnJheTxhbnk+PnRoaXMuZHJvcENoYW5uZWw7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRyb3BMaW5rcy5sZW5ndGg7IGkgKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZHJvcExpbmtzW2ldID09PSBkcmFnLmRyYWdDaGFubmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChkcmFnTGlua0FycmF5ICYmICFkcm9wTGlua0FycmF5KSB7XG4gICAgICAgICAgICBjb25zdCBkcmFnTGlua3MgPSA8QXJyYXk8YW55Pj5kcmFnLmRyYWdDaGFubmVsO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkcmFnTGlua3MubGVuZ3RoOyBpICsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRyYWdMaW5rc1tpXSA9PT0gdGhpcy5kcm9wQ2hhbm5lbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBkcmFnTGlua3MgPSA8QXJyYXk8YW55Pj5kcmFnLmRyYWdDaGFubmVsO1xuICAgICAgICAgICAgY29uc3QgZHJvcExpbmtzID0gPEFycmF5PGFueT4+dGhpcy5kcm9wQ2hhbm5lbDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZHJhZ0xpbmtzLmxlbmd0aDsgaSArKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZHJvcExpbmtzLmxlbmd0aDsgaiArKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZHJhZ0xpbmtzW2ldID09PSBkcm9wTGlua3Nbal0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRJbnNlcnRJbmRleEF0KGRyYWdnZWREaXI6IElneERyYWdEaXJlY3RpdmUsIGVsZW1lbnRzQXRQb2ludDogYW55W10pOiBudW1iZXIge1xuICAgICAgICBsZXQgaW5zZXJ0SW5kZXggPSAtMTtcbiAgICAgICAgY29uc3QgZHJvcENoaWxkcmVuID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY2hpbGRyZW4pO1xuICAgICAgICBpZiAoIWRyb3BDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnNlcnRJbmRleDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgbGV0IGNoaWxkVW5kZXIgPSBudWxsO1xuICAgICAgICB3aGlsZSAoIWNoaWxkVW5kZXIgJiYgaSA8IGVsZW1lbnRzQXRQb2ludC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50c0F0UG9pbnRbaV0ucGFyZW50RWxlbWVudCA9PT0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBjaGlsZFVuZGVyID0gZWxlbWVudHNBdFBvaW50W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZHJhZ2dlZEVsZW1JbmRleCA9IGRyb3BDaGlsZHJlbi5pbmRleE9mKGRyYWdnZWREaXIuZWxlbWVudC5uYXRpdmVFbGVtZW50KTtcbiAgICAgICAgaW5zZXJ0SW5kZXggPSBkcm9wQ2hpbGRyZW4uaW5kZXhPZihjaGlsZFVuZGVyKTtcbiAgICAgICAgaWYgKGRyYWdnZWRFbGVtSW5kZXggIT09IC0xICYmIGRyYWdnZWRFbGVtSW5kZXggPCBpbnNlcnRJbmRleCkge1xuICAgICAgICAgICAgaW5zZXJ0SW5kZXgrKztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpbnNlcnRJbmRleDtcbiAgICB9XG59XG5cblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbkBOZ01vZHVsZSh7XG4gICAgZGVjbGFyYXRpb25zOiBbSWd4RHJhZ0RpcmVjdGl2ZSwgSWd4RHJvcERpcmVjdGl2ZSwgSWd4RHJhZ0hhbmRsZURpcmVjdGl2ZV0sXG4gICAgZXhwb3J0czogW0lneERyYWdEaXJlY3RpdmUsIElneERyb3BEaXJlY3RpdmUsIElneERyYWdIYW5kbGVEaXJlY3RpdmVdXG59KVxuZXhwb3J0IGNsYXNzIElneERyYWdEcm9wTW9kdWxlIHsgfVxuIl19