UNPKG

@catull/igniteui-angular

Version:

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

855 lines 87.3 kB
import { __decorate, __metadata, __param } from "tslib";
import { AfterContentInit, Component, ContentChild, ElementRef, EventEmitter, HostBinding, Inject, Input, OnChanges, OnDestroy, OnInit, Optional, Output, SimpleChange, ViewChild, Renderer2 } from '@angular/core';
import { fromEvent, interval } from 'rxjs';
import { debounce } from 'rxjs/operators';
import { IgxNavigationService, IToggleView } from '../core/navigation';
import { HammerGesturesManager } from '../core/touch';
import { IgxNavDrawerMiniTemplateDirective, IgxNavDrawerTemplateDirective } from './navigation-drawer.directives';
import { PlatformUtil } from '../core/utils';
let NEXT_ID = 0;
/**
 * **Ignite UI for Angular Navigation Drawer** -
 * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/navdrawer.html)
 *
 * The Ignite UI Navigation Drawer is a collapsible side navigation container commonly used in combination with the Navbar.
 *
 * Example:
 * ```html
 * <igx-nav-drawer id="navigation" [isOpen]="true">
 *   <ng-template igxDrawer>
 *     <nav>
 *       <span igxDrawerItem [isHeader]="true">Email</span>
 *       <span igxDrawerItem igxRipple>Inbox</span>
 *       <span igxDrawerItem igxRipple>Deleted</span>
 *       <span igxDrawerItem igxRipple>Sent</span>
 *     </nav>
 *   </ng-template>
 * </igx-nav-drawer>
 * ```
 */
let IgxNavigationDrawerComponent = class IgxNavigationDrawerComponent {
    constructor(elementRef, _state, renderer, _touchManager, platformUtil) {
        this.elementRef = elementRef;
        this._state = _state;
        this.renderer = renderer;
        this._touchManager = _touchManager;
        this.platformUtil = platformUtil;
        this._isOpen = false;
        this.cssClass = 'igx-nav-drawer';
        /**
         * ID of the component
         *
         * ```typescript
         * // get
         * let myNavDrawerId = this.navdrawer.id;
         * ```
         *
         * ```html
         * <!--set-->
         *  <igx-nav-drawer id='navdrawer'></igx-nav-drawer>
         * ```
         */
        this.id = `igx-nav-drawer-${NEXT_ID++}`;
        /**
         * Position of the Navigation Drawer. Can be "left"(default) or "right".
         *
         * ```typescript
         * // get
         * let myNavDrawerPosition = this.navdrawer.position;
         * ```
         *
         * ```html
         * <!--set-->
         * <igx-nav-drawer [position]="'left'"></igx-nav-drawer>
         * ```
         */
        this.position = 'left';
        /**
         * Enables the use of touch gestures to manipulate the drawer:
         * - swipe/pan from edge to open, swipe-toggle and pan-drag.
         *
         * ```typescript
         * // get
         * let gesturesEnabled = this.navdrawer.enableGestures;
         * ```
         *
         * ```html
         * <!--set-->
         * <igx-nav-drawer [enableGestures]='true'></igx-nav-drawer>
         * ```
         */
        this.enableGestures = true;
        /**
         *@hidden
         */
        this.isOpenChange = new EventEmitter();
        /**
         * When pinned the drawer is relatively positioned instead of sitting above content.
         * May require additional layout styling.
         *
         * ```typescript
         * // get
         * let navDrawerIsPinned = this.navdrawer.pin;
         * ```
         *
         * ```html
         * <!--set-->
         * <igx-nav-drawer [pin]='false'></igx-nav-drawer>
         * ```
         */
        this.pin = false;
        /**
         * Minimum device width required for automatic pin to be toggled.
         * Default is 1024, can be set to a falsy value to disable this behavior.
         *
         * ```typescript
         * // get
         * let navDrawerPinTreshold = this.navdrawer.pinThreshold;
         * ```
         *
         * ```html
         * <!--set-->
         * <igx-nav-drawer [pinTreshold]='1024'></igx-nav-drawer>
         * ```
         */
        this.pinThreshold = 1024;
        /**
         * Width of the drawer in its open state. Defaults to "280px".
         *
         * ```typescript
         * // get
         * let navDrawerWidth = this.navdrawer.width;
         * ```
         *
         * ```html
         * <!--set-->
         * <igx-nav-drawer [width]="'228px'"></igx-nav-drawer>
         * ```
         */
        this.width = '280px';
        /**
         * Width of the drawer in its mini state. Defaults to 68px.
         *
         * ```typescript
         * // get
         * let navDrawerMiniWidth = this.navdrawer.miniWidth;
         * ```
         *
         * ```html
         * <!--set-->
         * <igx-nav-drawer [miniWidth]="'34px'"></igx-nav-drawer>
         * ```
         */
        this.miniWidth = '68px';
        /**
         * Pinned state change output for two-way binding.
         *
         * ```html
         * <igx-nav-drawer [(pin)]='isPinned'></igx-nav-drawer>
         * ```
         */
        this.pinChange = new EventEmitter(true);
        /**
         * Event fired as the Navigation Drawer is about to open.
         *
         * ```html
         *  <igx-nav-drawer (opening)='onOpening()'></igx-nav-drawer>
         * ```
         */
        this.opening = new EventEmitter();
        /**
         * Event fired when the Navigation Drawer has opened.
         *
         * ```html
         * <igx-nav-drawer (opened)='onOpened()'></igx-nav-drawer>
         * ```
         */
        this.opened = new EventEmitter();
        /**
         * Event fired as the Navigation Drawer is about to close.
         *
         * ```html
         * <igx-nav-drawer (closing)='onClosing()'></igx-nav-drawer>
         * ```
         */
        this.closing = new EventEmitter();
        /**
         * Event fired when the Navigation Drawer has closed.
         *
         * ```html
         * <igx-nav-drawer (closed)='onClosed()'></igx-nav-drawer>
         * ```
         */
        this.closed = new EventEmitter();
        this._gesturesAttached = false;
        this._widthCache = { width: null, miniWidth: null, windowWidth: null };
        this.css = {
            drawer: 'igx-nav-drawer__aside',
            mini: 'igx-nav-drawer__aside--mini',
            overlay: 'igx-nav-drawer__overlay',
            styleDummy: 'igx-nav-drawer__style-dummy'
        };
        /** Pan animation properties */
        this._panning = false;
        this._maxEdgeZone = 50;
        this.checkPinThreshold = (evt) => {
            if (!this.platformUtil.isBrowser) {
                return;
            }
            let windowWidth;
            if (this.pinThreshold) {
                windowWidth = this.getWindowWidth();
                if (evt && this._widthCache.windowWidth === windowWidth) {
                    return;
                }
                this._widthCache.windowWidth = windowWidth;
                if (!this.pin && windowWidth >= this.pinThreshold) {
                    this.pin = true;
                    this.pinChange.emit(true);
                }
                else if (this.pin && windowWidth < this.pinThreshold) {
                    this.pin = false;
                    this.pinChange.emit(false);
                }
            }
        };
        this.swipe = (evt) => {
            // TODO: Could also force input type: http://stackoverflow.com/a/27108052
            if (!this.enableGestures || evt.pointerType !== 'touch') {
                return;
            }
            // HammerJS swipe is horizontal-only by default, don't check deltaY
            let deltaX;
            let startPosition;
            if (this.position === 'right') {
                // when on the right use inverse of deltaX
                deltaX = -evt.deltaX;
                startPosition = this.getWindowWidth() - (evt.center.x + evt.distance);
            }
            else {
                deltaX = evt.deltaX;
                startPosition = evt.center.x - evt.distance;
            }
            // only accept closing swipe (ignoring minEdgeZone) when the drawer is expanded:
            if ((this.isOpen && deltaX < 0) ||
                // positive deltaX from the edge:
                (deltaX > 0 && startPosition < this.maxEdgeZone)) {
                this.toggle();
            }
        };
        this.panstart = (evt) => {
            if (!this.enableGestures || this.pin || evt.pointerType !== 'touch') {
                return;
            }
            const startPosition = this.position === 'right' ? this.getWindowWidth() - (evt.center.x + evt.distance)
                : evt.center.x - evt.distance;
            // cache width during animation, flag to allow further handling
            if (this.isOpen || (startPosition < this.maxEdgeZone)) {
                this._panning = true;
                this._panStartWidth = this.getExpectedWidth(!this.isOpen);
                this._panLimit = this.getExpectedWidth(this.isOpen);
                this.renderer.addClass(this.overlay, 'panning');
                this.renderer.addClass(this.drawer, 'panning');
            }
        };
        this.pan = (evt) => {
            // TODO: input.deltaX = prevDelta.x + (center.x - offset.x);
            // get actual delta (not total session one) from event?
            // pan WILL also fire after a full swipe, only resize on flag
            if (!this._panning) {
                return;
            }
            const right = this.position === 'right';
            // when on the right use inverse of deltaX
            const deltaX = right ? -evt.deltaX : evt.deltaX;
            let visibleWidth;
            let newX;
            let percent;
            visibleWidth = this._panStartWidth + deltaX;
            if (this.isOpen && deltaX < 0) {
                // when visibleWidth hits limit - stop animating
                if (visibleWidth <= this._panLimit) {
                    return;
                }
                if (this.hasAnimateWidth) {
                    percent = (visibleWidth - this._panLimit) / (this._panStartWidth - this._panLimit);
                    newX = visibleWidth;
                }
                else {
                    percent = visibleWidth / this._panStartWidth;
                    newX = evt.deltaX;
                }
                this.setXSize(newX, percent.toPrecision(2));
            }
            else if (!this.isOpen && deltaX > 0) {
                // when visibleWidth hits limit - stop animating
                if (visibleWidth >= this._panLimit) {
                    return;
                }
                if (this.hasAnimateWidth) {
                    percent = (visibleWidth - this._panStartWidth) / (this._panLimit - this._panStartWidth);
                    newX = visibleWidth;
                }
                else {
                    percent = visibleWidth / this._panLimit;
                    newX = (this._panLimit - visibleWidth) * (right ? 1 : -1);
                }
                this.setXSize(newX, percent.toPrecision(2));
            }
        };
        this.panEnd = (evt) => {
            if (this._panning) {
                const deltaX = this.position === 'right' ? -evt.deltaX : evt.deltaX;
                const visibleWidth = this._panStartWidth + deltaX;
                this.resetPan();
                // check if pan brought the drawer to 50%
                if (this.isOpen && visibleWidth <= this._panStartWidth / 2) {
                    this.close();
                }
                else if (!this.isOpen && visibleWidth >= this._panLimit / 2) {
                    this.open();
                }
                this._panStartWidth = null;
            }
        };
        this.toggleOpenedEvent = (evt) => {
            this.elementRef.nativeElement.removeEventListener('transitionend', this.toggleOpenedEvent, false);
            this.opened.emit();
        };
        this.toggleClosedEvent = (evt) => {
            this.elementRef.nativeElement.removeEventListener('transitionend', this.toggleClosedEvent, false);
            this.closed.emit();
        };
    }
    /**
     * State of the drawer.
     *
     * ```typescript
     * // get
     * let navDrawerIsOpen = this.navdrawer.isOpen;
     * ```
     *
     * ```html
     * <!--set-->
     * <igx-nav-drawer [isOpen]='false'></igx-nav-drawer>
     * ```
     *
     * Two-way data binding.
     * ```html
     * <!--set-->
     * <igx-nav-drawer [(isOpen)]='model.isOpen'></igx-nav-drawer>
     * ```
     */
    get isOpen() {
        return this._isOpen;
    }
    set isOpen(value) {
        this._isOpen = value;
        this.isOpenChange.emit(this._isOpen);
    }
    /**
     * Returns nativeElement of the component.
     *
     * @hidden
     */
    get element() {
        return this.elementRef.nativeElement;
    }
    /**
     * @hidden
     */
    get template() {
        if (this.miniTemplate && !this.isOpen) {
            return this.miniTemplate.template;
        }
        else if (this.contentTemplate) {
            return this.contentTemplate.template;
        }
    }
    /**
     * @hidden
     */
    get miniTemplate() {
        return this._miniTemplate;
    }
    /**
     * @hidden
     */
    set miniTemplate(v) {
        if (!this.isOpen) {
            this.setDrawerWidth(v ? this.miniWidth : '');
        }
        this._miniTemplate = v;
    }
    /**
     * @hidden
     */
    get flexWidth() {
        if (!this.pin) {
            return '0px';
        }
        if (this.isOpen) {
            return this.width;
        }
        if (this.miniTemplate && this.miniWidth) {
            return this.miniWidth;
        }
        return '0px';
    }
    /** @hidden */
    get isPinnedRight() {
        return this.pin && this.position === 'right' ? '1' : '0';
    }
    /**
      * @hidden
      */
    get drawer() {
        return this._drawer.nativeElement;
    }
    /**
     * @hidden
     */
    get overlay() {
        return this._overlay.nativeElement;
    }
    /**
     * @hidden
     */
    get styleDummy() {
        return this._styleDummy.nativeElement;
    }
    /**
     * Property to decide whether to change width or translate the drawer from pan gesture.
     *
     * @hidden
     */
    get hasAnimateWidth() {
        return this.pin || !!this.miniTemplate;
    }
    /**
     * Used for touch gestures (swipe and pan).
     * Defaults to 50 (in px) and is extended to at least 110% of the mini template width if available.
     *
     * @hidden
     */
    get maxEdgeZone() {
        return this._maxEdgeZone;
    }
    /**
     * Gets the Drawer width for specific state.
     * Will attempt to evaluate requested state and cache.
     *
     *
     * @hidden
     */
    get expectedWidth() {
        return this.getExpectedWidth(false);
    }
    /**
     * Get the Drawer mini width for specific state.
     * Will attempt to evaluate requested state and cache.
     *
     * @hidden
     */
    get expectedMiniWidth() {
        return this.getExpectedWidth(true);
    }
    /**
     * @hidden
     */
    get touchManager() {
        return this._touchManager;
    }
    /**
     * Exposes optional navigation service
     *
     * @hidden
     */
    get state() {
        return this._state;
    }
    /**
     * @hidden
     */
    ngOnInit() {
        // DOM and @Input()-s initialized
        if (this._state) {
            this._state.add(this.id, this);
        }
        if (this.isOpen) {
            this.setDrawerWidth(this.width);
        }
    }
    /**
     * @hidden
     */
    ngAfterContentInit() {
        // wait for template and ng-content to be ready
        this.updateEdgeZone();
        this.checkPinThreshold();
        this.ensureEvents();
        // TODO: apply platform-safe Ruler from http://plnkr.co/edit/81nWDyreYMzkunihfRgX?p=preview
        // (https://github.com/angular/angular/issues/6515), blocked by https://github.com/angular/angular/issues/6904
    }
    /**
     * @hidden
     */
    ngOnDestroy() {
        this._touchManager.destroy();
        if (this._state) {
            this._state.remove(this.id);
        }
        if (this._resizeObserver) {
            this._resizeObserver.unsubscribe();
        }
    }
    /**
     * @hidden
     */
    ngOnChanges(changes) {
        // simple settings can come from attribute set (rather than binding), make sure boolean props are converted
        if (changes.enableGestures && changes.enableGestures.currentValue !== undefined) {
            this.enableGestures = !!(this.enableGestures && this.enableGestures.toString() === 'true');
            this.ensureEvents();
        }
        if (changes.pin && changes.pin.currentValue !== undefined) {
            this.pin = !!(this.pin && this.pin.toString() === 'true');
            if (this.pin) {
                this._touchManager.destroy();
                this._gesturesAttached = false;
            }
            else {
                this.ensureEvents();
            }
        }
        if (changes.pinThreshold) {
            if (this.pinThreshold) {
                this.ensureEvents();
                this.checkPinThreshold();
            }
        }
        if (changes.width && this.isOpen) {
            this.setDrawerWidth(changes.width.currentValue);
        }
        if (changes.miniWidth) {
            if (!this.isOpen) {
                this.setDrawerWidth(changes.miniWidth.currentValue);
            }
            this.updateEdgeZone();
        }
    }
    /**
     * Toggle the open state of the Navigation Drawer.
     *
     * ```typescript
     * this.navdrawer.toggle();
     * ```
     */
    toggle() {
        if (this.isOpen) {
            this.close();
        }
        else {
            this.open();
        }
    }
    /**
     * Open the Navigation Drawer. Has no effect if already opened.
     *
     * ```typescript
     * this.navdrawer.open();
     * ```
     */
    open() {
        if (this._panning) {
            this.resetPan();
        }
        if (this.isOpen) {
            return;
        }
        this.opening.emit();
        this.isOpen = true;
        // TODO: Switch to animate API when available
        // var animationCss = this.animate.css();
        //     animationCss
        //         .setStyles({'width':'50px'}, {'width':'400px'})
        //         .start(this.elementRef.nativeElement)
        //         .onComplete(() => animationCss.setToStyles({'width':'auto'}).start(this.elementRef.nativeElement));
        this.elementRef.nativeElement.addEventListener('transitionend', this.toggleOpenedEvent, false);
        this.setDrawerWidth(this.width);
    }
    /**
     * Close the Navigation Drawer. Has no effect if already closed.
     *
     * ```typescript
     * this.navdrawer.close();
     * ```
     */
    close() {
        if (this._panning) {
            this.resetPan();
        }
        if (!this.isOpen) {
            return;
        }
        this.closing.emit();
        this.isOpen = false;
        this.setDrawerWidth(this.miniTemplate ? this.miniWidth : '');
        this.elementRef.nativeElement.addEventListener('transitionend', this.toggleClosedEvent, false);
    }
    /**
     * @hidden
     */
    set_maxEdgeZone(value) {
        this._maxEdgeZone = value;
    }
    /**
     * Get the Drawer width for specific state. Will attempt to evaluate requested state and cache.
     *
     * @hidden
     * @param [mini] - Request mini width instead
     */
    getExpectedWidth(mini) {
        if (mini) {
            if (!this.miniTemplate) {
                return 0;
            }
            if (this.miniWidth) {
                return parseFloat(this.miniWidth);
            }
            else {
                // if (!this.isOpen) { // This WON'T work due to transition timings...
                //     return this.elementRef.nativeElement.children[1].offsetWidth;
                // } else {
                if (this._widthCache.miniWidth === null) {
                    // force class for width calc. TODO?
                    // force class for width calc. TODO?
                    this.renderer.addClass(this.styleDummy, this.css.drawer);
                    this.renderer.addClass(this.styleDummy, this.css.mini);
                    this._widthCache.miniWidth = this.styleDummy.offsetWidth;
                    this.renderer.removeClass(this.styleDummy, this.css.drawer);
                    this.renderer.removeClass(this.styleDummy, this.css.mini);
                }
                return this._widthCache.miniWidth;
            }
        }
        else {
            if (this.width) {
                return parseFloat(this.width);
            }
            else {
                if (this._widthCache.width === null) {
                    // force class for width calc. TODO?
                    // force class for width calc. TODO?
                    this.renderer.addClass(this.styleDummy, this.css.drawer);
                    this._widthCache.width = this.styleDummy.offsetWidth;
                    this.renderer.removeClass(this.styleDummy, this.css.drawer);
                }
                return this._widthCache.width;
            }
        }
    }
    getWindowWidth() {
        return (window.innerWidth > 0) ? window.innerWidth : screen.width;
    }
    /**
     * Sets the drawer width.
     */
    setDrawerWidth(width) {
        if (this.platformUtil.isBrowser) {
            requestAnimationFrame(() => {
                if (this.drawer) {
                    this.renderer.setStyle(this.drawer, 'width', width);
                }
            });
        }
        else {
            this.renderer.setStyle(this.drawer, 'width', width);
        }
    }
    /**
     * Get current Drawer width.
     */
    getDrawerWidth() {
        return this.drawer.offsetWidth;
    }
    ensureEvents() {
        // set listeners for swipe/pan only if needed, but just once
        if (this.enableGestures && !this.pin && !this._gesturesAttached) {
            // Built-in manager handler(L20887) causes endless loop and max stack exception.
            // https://github.com/angular/angular/issues/6993
            // Use ours for now (until beta.10):
            // this.renderer.listen(document, "swipe", this.swipe);
            this._touchManager.addGlobalEventListener('document', 'swipe', this.swipe);
            this._gesturesAttached = true;
            // this.renderer.listen(document, "panstart", this.panstart);
            // this.renderer.listen(document, "pan", this.pan);
            this._touchManager.addGlobalEventListener('document', 'panstart', this.panstart);
            this._touchManager.addGlobalEventListener('document', 'panmove', this.pan);
            this._touchManager.addGlobalEventListener('document', 'panend', this.panEnd);
        }
        if (!this._resizeObserver && this.platformUtil.isBrowser) {
            this._resizeObserver = fromEvent(window, 'resize').pipe(debounce(() => interval(150)))
                .subscribe((value) => {
                this.checkPinThreshold(value);
            });
        }
    }
    updateEdgeZone() {
        let maxValue;
        if (this.miniTemplate) {
            maxValue = Math.max(this._maxEdgeZone, this.getExpectedWidth(true) * 1.1);
            this.set_maxEdgeZone(maxValue);
        }
    }
    resetPan() {
        this._panning = false;
        /* styles fail to apply when set on parent due to extra attributes, prob ng bug */
        /* styles fail to apply when set on parent due to extra attributes, prob ng bug */
        this.renderer.removeClass(this.overlay, 'panning');
        this.renderer.removeClass(this.drawer, 'panning');
        this.setXSize(0, '');
    }
    /**
     * Sets the absolute position or width in case the drawer doesn't change position.
     * @param x the number pixels to translate on the X axis or the width to set. 0 width will clear the style instead.
     * @param opacity optional value to apply to the overlay
     */
    setXSize(x, opacity) {
        // Angular polyfills patches window.requestAnimationFrame, but switch to DomAdapter API (TODO)
        window.requestAnimationFrame(() => {
            if (this.hasAnimateWidth) {
                this.renderer.setStyle(this.drawer, 'width', x ? Math.abs(x) + 'px' : '');
            }
            else {
                this.renderer.setStyle(this.drawer, 'transform', x ? 'translate3d(' + x + 'px,0,0)' : '');
                this.renderer.setStyle(this.drawer, '-webkit-transform', x ? 'translate3d(' + x + 'px,0,0)' : '');
            }
            if (opacity !== undefined) {
                this.renderer.setStyle(this.overlay, 'opacity', opacity);
            }
        });
    }
};
IgxNavigationDrawerComponent.ctorParameters = () => [
    { type: ElementRef, decorators: [{ type: Inject, args: [ElementRef,] }] },
    { type: IgxNavigationService, decorators: [{ type: Optional }] },
    { type: Renderer2 },
    { type: HammerGesturesManager },
    { type: PlatformUtil }
];
__decorate([
    HostBinding('class'),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "cssClass", void 0);
__decorate([
    HostBinding('attr.id'),
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "id", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "position", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "enableGestures", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], IgxNavigationDrawerComponent.prototype, "isOpen", null);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "isOpenChange", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "pin", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "pinThreshold", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "width", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "miniWidth", void 0);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "pinChange", void 0);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "opening", void 0);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "opened", void 0);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "closing", void 0);
__decorate([
    Output(),
    __metadata("design:type", Object)
], IgxNavigationDrawerComponent.prototype, "closed", void 0);
__decorate([
    ContentChild(IgxNavDrawerMiniTemplateDirective, { read: IgxNavDrawerMiniTemplateDirective }),
    __metadata("design:type", IgxNavDrawerMiniTemplateDirective),
    __metadata("design:paramtypes", [IgxNavDrawerMiniTemplateDirective])
], IgxNavigationDrawerComponent.prototype, "miniTemplate", null);
__decorate([
    ContentChild(IgxNavDrawerTemplateDirective, { read: IgxNavDrawerTemplateDirective }),
    __metadata("design:type", IgxNavDrawerTemplateDirective)
], IgxNavigationDrawerComponent.prototype, "contentTemplate", void 0);
__decorate([
    HostBinding('style.flexBasis'),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], IgxNavigationDrawerComponent.prototype, "flexWidth", null);
__decorate([
    HostBinding('style.order'),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], IgxNavigationDrawerComponent.prototype, "isPinnedRight", null);
__decorate([
    ViewChild('aside', { static: true }),
    __metadata("design:type", ElementRef)
], IgxNavigationDrawerComponent.prototype, "_drawer", void 0);
__decorate([
    ViewChild('overlay', { static: true }),
    __metadata("design:type", ElementRef)
], IgxNavigationDrawerComponent.prototype, "_overlay", void 0);
__decorate([
    ViewChild('dummy', { static: true }),
    __metadata("design:type", ElementRef)
], IgxNavigationDrawerComponent.prototype, "_styleDummy", void 0);
IgxNavigationDrawerComponent = __decorate([
    Component({
        providers: [HammerGesturesManager],
        selector: 'igx-nav-drawer',
        template: "<ng-template #defaultItemsTemplate>\n    <div igxDrawerItem [isHeader]=\"true\">Navigation Drawer</div>\n    <div igxDrawerItem> Start by adding</div>\n    <div igxDrawerItem> <code>&lt;ng-template igxDrawer&gt;</code> </div>\n    <div igxDrawerItem> And some items inside </div>\n    <div igxDrawerItem> Style with igxDrawerItem </div>\n    <div igxDrawerItem> and igxRipple directives</div>\n</ng-template>\n\n<div [hidden]=\"pin\"\n    class=\"igx-nav-drawer__overlay\"\n    [class.igx-nav-drawer__overlay--hidden]=\"!isOpen\"\n    (click)=\"close()\" #overlay>\n</div>\n<aside role=\"navigation\"\n    class=\"igx-nav-drawer__aside\"\n    [class.igx-nav-drawer__aside--collapsed]=\"!miniTemplate && !isOpen\"\n    [class.igx-nav-drawer__aside--mini]=\"miniTemplate && !isOpen\"\n    [class.igx-nav-drawer__aside--normal]=\"!miniTemplate || isOpen\"\n    [class.igx-nav-drawer__aside--pinned]=\"pin\"\n    [class.igx-nav-drawer__aside--right]=\"position == 'right'\" #aside>\n\n    <ng-container *ngTemplateOutlet=\"template || defaultItemsTemplate\"></ng-container>\n</aside>\n<div class=\"igx-nav-drawer__style-dummy\" #dummy></div>\n",
        styles: [`
        :host {
            display: block;
            height: 100%;
        }
    `]
    }),
    __param(0, Inject(ElementRef)),
    __param(1, Optional()),
    __metadata("design:paramtypes", [ElementRef,
        IgxNavigationService,
        Renderer2,
        HammerGesturesManager,
        PlatformUtil])
], IgxNavigationDrawerComponent);
export { IgxNavigationDrawerComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2aWdhdGlvbi1kcmF3ZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9uYXZpZ2F0aW9uLWRyYXdlci9uYXZpZ2F0aW9uLWRyYXdlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFDSCxnQkFBZ0IsRUFDaEIsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsWUFBWSxFQUNaLFdBQVcsRUFDWCxNQUFNLEVBQ04sS0FBSyxFQUNMLFNBQVMsRUFDVCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEVBQ04sWUFBWSxFQUNaLFNBQVMsRUFDVCxTQUFTLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdkUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2xILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFN0MsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0FBQ2hCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBWUgsSUFBYSw0QkFBNEIsR0FBekMsTUFBYSw0QkFBNEI7SUFzV3JDLFlBQ2dDLFVBQXNCLEVBQzlCLE1BQTRCLEVBQ3RDLFFBQW1CLEVBQ3JCLGFBQW9DLEVBQ3BDLFlBQTBCO1FBSk4sZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUM5QixXQUFNLEdBQU4sTUFBTSxDQUFzQjtRQUN0QyxhQUFRLEdBQVIsUUFB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OzhCQUFtQixVQUFVOzhEQUFDO0FBQy9CO0lBQXJDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7OEJBQXNCLFVBQVU7aUVBQUM7QUFqUjdELDRCQUE0QjtJQVh4QyxTQUFTLENBQUM7UUFDUCxTQUFTLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztRQUNsQyxRQUFRLEVBQUUsZ0JBQWdCO1FBQzFCLCtuQ0FBK0M7aUJBQ3RDOzs7OztLQUtSO0tBQ0osQ0FBQztJQXdXTyxXQUFBLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUNsQixXQUFBLFFBQVEsRUFBRSxDQUFBO3FDQUQ2QixVQUFVO1FBQ3RCLG9CQUFvQjtRQUM1QixTQUFTO1FBQ04scUJBQXFCO1FBQ3RCLFlBQVk7R0EzVzdCLDRCQUE0QixDQWd4QnhDO1NBaHhCWSw0QkFBNEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIEFmdGVyQ29udGVudEluaXQsXG4gICAgQ29tcG9uZW50LFxuICAgIENvbnRlbnRDaGlsZCxcbiAgICBFbGVtZW50UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBIb3N0QmluZGluZyxcbiAgICBJbmplY3QsXG4gICAgSW5wdXQsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3B0aW9uYWwsXG4gICAgT3V0cHV0LFxuICAgIFNpbXBsZUNoYW5nZSxcbiAgICBWaWV3Q2hpbGQsXG4gICAgUmVuZGVyZXIyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBpbnRlcnZhbCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWJvdW5jZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElneE5hdmlnYXRpb25TZXJ2aWNlLCBJVG9nZ2xlVmlldyB9IGZyb20gJy4uL2NvcmUvbmF2aWdhdGlvbic7XG5pbXBvcnQgeyBIYW1tZXJHZXN0dXJlc01hbmFnZXIgfSBmcm9tICcuLi9jb3JlL3RvdWNoJztcbmltcG9ydCB7IElneE5hdkRyYXdlck1pbmlUZW1wbGF0ZURpcmVjdGl2ZSwgSWd4TmF2RHJhd2VyVGVtcGxhdGVEaXJlY3RpdmUgfSBmcm9tICcuL25hdmlnYXRpb24tZHJhd2VyLmRpcmVjdGl2ZXMnO1xuaW1wb3J0IHsgUGxhdGZvcm1VdGlsIH0gZnJvbSAnLi4vY29yZS91dGlscyc7XG5cbmxldCBORVhUX0lEID0gMDtcbi8qKlxuICogKipJZ25pdGUgVUkgZm9yIEFuZ3VsYXIgTmF2aWdhdGlvbiBEcmF3ZXIqKiAtXG4gKiBbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuaW5mcmFnaXN0aWNzLmNvbS9wcm9kdWN0cy9pZ25pdGUtdWktYW5ndWxhci9hbmd1bGFyL2NvbXBvbmVudHMvbmF2ZHJhd2VyLmh0bWwpXG4gKlxuICogVGhlIElnbml0ZSBVSSBOYXZpZ2F0aW9uIERyYXdlciBpcyBhIGNvbGxhcHNpYmxlIHNpZGUgbmF2aWdhdGlvbiBjb250YWluZXIgY29tbW9ubHkgdXNlZCBpbiBjb21iaW5hdGlvbiB3aXRoIHRoZSBOYXZiYXIuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYGh0bWxcbiAqIDxpZ3gtbmF2LWRyYXdlciBpZD1cIm5hdmlnYXRpb25cIiBbaXNPcGVuXT1cInRydWVcIj5cbiAqICAgPG5nLXRlbXBsYXRlIGlneERyYXdlcj5cbiAqICAgICA8bmF2PlxuICogICAgICAgPHNwYW4gaWd4RHJhd2VySXRlbSBbaXNIZWFkZXJdPVwidHJ1ZVwiPkVtYWlsPC9zcGFuPlxuICogICAgICAgPHNwYW4gaWd4RHJhd2VySXRlbSBpZ3hSaXBwbGU+SW5ib3g8L3NwYW4+XG4gKiAgICAgICA8c3BhbiBpZ3hEcmF3ZXJJdGVtIGlneFJpcHBsZT5EZWxldGVkPC9zcGFuPlxuICogICAgICAgPHNwYW4gaWd4RHJhd2VySXRlbSBpZ3hSaXBwbGU+U2VudDwvc3Bhbj5cbiAqICAgICA8L25hdj5cbiAqICAgPC9uZy10ZW1wbGF0ZT5cbiAqIDwvaWd4LW5hdi1kcmF3ZXI+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgcHJvdmlkZXJzOiBbSGFtbWVyR2VzdHVyZXNNYW5hZ2VyXSxcbiAgICBzZWxlY3RvcjogJ2lneC1uYXYtZHJhd2VyJyxcbiAgICB0ZW1wbGF0ZVVybDogJ25hdmlnYXRpb24tZHJhd2VyLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZXM6IFtgXG4gICAgICAgIDpob3N0IHtcbiAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgICAgICAgaGVpZ2h0OiAxMDAlO1xuICAgICAgICB9XG4gICAgYF1cbn0pXG5leHBvcnQgY2xhc3MgSWd4TmF2aWdhdGlvbkRyYXdlckNvbXBvbmVudCBpbXBsZW1lbnRzXG4gICAgSVRvZ2dsZVZpZXcsXG4gICAgT25Jbml0LFxuICAgIEFmdGVyQ29udGVudEluaXQsXG4gICAgT25EZXN0cm95LFxuICAgIE9uQ2hhbmdlcyB7XG4gICAgcHJpdmF0ZSBfaXNPcGVuID0gZmFsc2U7XG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcycpIHB1YmxpYyBjc3NDbGFzcyA9ICdpZ3gtbmF2LWRyYXdlcic7XG5cbiAgICAvKipcbiAgICAgKiBJRCBvZiB0aGUgY29tcG9uZW50XG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogLy8gZ2V0XG4gICAgICogbGV0IG15TmF2RHJhd2VySWQgPSB0aGlzLm5hdmRyYXdlci5pZDtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogIDxpZ3gtbmF2LWRyYXdlciBpZD0nbmF2ZHJhd2VyJz48L2lneC1uYXYtZHJhd2VyPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBIb3N0QmluZGluZygnYXR0ci5pZCcpXG4gICAgQElucHV0KCkgcHVibGljIGlkID0gYGlneC1uYXYtZHJhd2VyLSR7TkVYVF9JRCsrfWA7XG5cbiAgICAvKipcbiAgICAgKiBQb3NpdGlvbiBvZiB0aGUgTmF2aWdhdGlvbiBEcmF3ZXIuIENhbiBiZSBcImxlZnRcIihkZWZhdWx0KSBvciBcInJpZ2h0XCIuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogLy8gZ2V0XG4gICAgICogbGV0IG15TmF2RHJhd2VyUG9zaXRpb24gPSB0aGlzLm5hdmRyYXdlci5wb3NpdGlvbjtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogPGlneC1uYXYtZHJhd2VyIFtwb3NpdGlvbl09XCInbGVmdCdcIj48L2lneC1uYXYtZHJhd2VyPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBwb3NpdGlvbiA9ICdsZWZ0JztcblxuICAgIC8qKlxuICAgICAqIEVuYWJsZXMgdGhlIHVzZSBvZiB0b3VjaCBnZXN0dXJlcyB0byBtYW5pcHVsYXRlIHRoZSBkcmF3ZXI6XG4gICAgICogLSBzd2lwZS9wYW4gZnJvbSBlZGdlIHRvIG9wZW4sIHN3aXBlLXRvZ2dsZSBhbmQgcGFuLWRyYWcuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogLy8gZ2V0XG4gICAgICogbGV0IGdlc3R1cmVzRW5hYmxlZCA9IHRoaXMubmF2ZHJhd2VyLmVuYWJsZUdlc3R1cmVzO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDwhLS1zZXQtLT5cbiAgICAgKiA8aWd4LW5hdi1kcmF3ZXIgW2VuYWJsZUdlc3R1cmVzXT0ndHJ1ZSc+PC9pZ3gtbmF2LWRyYXdlcj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgZW5hYmxlR2VzdHVyZXMgPSB0cnVlO1xuXG4gICAgLyoqXG4gICAgICogU3RhdGUgb2YgdGhlIGRyYXdlci5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgbmF2RHJhd2VySXNPcGVuID0gdGhpcy5uYXZkcmF3ZXIuaXNPcGVuO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDwhLS1zZXQtLT5cbiAgICAgKiA8aWd4LW5hdi1kcmF3ZXIgW2lzT3Blbl09J2ZhbHNlJz48L2lneC1uYXYtZHJhd2VyPlxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogVHdvLXdheSBkYXRhIGJpbmRpbmcuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDwhLS1zZXQtLT5cbiAgICAgKiA8aWd4LW5hdi1kcmF3ZXIgWyhpc09wZW4pXT0nbW9kZWwuaXNPcGVuJz48L2lneC1uYXYtZHJhd2VyPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGdldCBpc09wZW4oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc09wZW47XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgaXNPcGVuKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2lzT3BlbiA9IHZhbHVlO1xuICAgICAgICB0aGlzLmlzT3BlbkNoYW5nZS5lbWl0KHRoaXMuX2lzT3Blbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICpAaGlkZGVuXG4gICAgICovXG4gICAgQE91dHB1dCgpIHB1YmxpYyBpc09wZW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIHBpbm5lZCB0aGUgZHJhd2VyIGlzIHJlbGF0aXZlbHkgcG9zaXRpb25lZCBpbnN0ZWFkIG9mIHNpdHRpbmcgYWJvdmUgY29udGVudC5cbiAgICAgKiBNYXkgcmVxdWlyZSBhZGRpdGlvbmFsIGxheW91dCBzdHlsaW5nLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIC8vIGdldFxuICAgICAqIGxldCBuYXZEcmF3ZXJJc1Bpbm5lZCA9IHRoaXMubmF2ZHJhd2VyLnBpbjtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogPGlneC1uYXYtZHJhd2VyIFtwaW5dPSdmYWxzZSc+PC9pZ3gtbmF2LWRyYXdlcj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgcGluID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBNaW5pbXVtIGRldmljZSB3aWR0aCByZXF1aXJlZCBmb3IgYXV0b21hdGljIHBpbiB0byBiZSB0b2dnbGVkLlxuICAgICAqIERlZmF1bHQgaXMgMTAyNCwgY2FuIGJlIHNldCB0byBhIGZhbHN5IHZhbHVlIHRvIGRpc2FibGUgdGhpcyBiZWhhdmlvci5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiAvLyBnZXRcbiAgICAgKiBsZXQgbmF2RHJhd2VyUGluVHJlc2hvbGQgPSB0aGlzLm5hdmRyYXdlci5waW5UaHJlc2hvbGQ7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPCEtLXNldC0tPlxuICAgICAqIDxpZ3gtbmF2LWRyYXdlciBbcGluVHJlc2hvbGRdPScxMDI0Jz48L2lneC1uYXYtZHJhd2VyPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBwaW5UaHJlc2hvbGQgPSAxMDI0O1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBuYXRpdmVFbGVtZW50IG9mIHRoZSBjb21wb25lbnQuXG4gICAgICpcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0IGVsZW1lbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBvZiB0aGUgZHJhd2VyIGluIGl0cyBvcGVuIHN0YXRlLiBEZWZhdWx0cyB0byBcIjI4MHB4XCIuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogLy8gZ2V0XG4gICAgICogbGV0IG5hdkRyYXdlcldpZHRoID0gdGhpcy5uYXZkcmF3ZXIud2lkdGg7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPCEtLXNldC0tPlxuICAgICAqIDxpZ3gtbmF2LWRyYXdlciBbd2lkdGhdPVwiJzIyOHB4J1wiPjwvaWd4LW5hdi1kcmF3ZXI+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIHdpZHRoID0gJzI4MHB4JztcblxuICAgIC8qKlxuICAgICAqIFdpZHRoIG9mIHRoZSBkcmF3ZXIgaW4gaXRzIG1pbmkgc3RhdGUuIERlZmF1bHRzIHRvIDY4cHguXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogLy8gZ2V0XG4gICAgICogbGV0IG5hdkRyYXdlck1pbmlXaWR0aCA9IHRoaXMubmF2ZHJhd2VyLm1pbmlXaWR0aDtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8IS0tc2V0LS0+XG4gICAgICogPGlneC1uYXYtZHJhd2VyIFttaW5pV2lkdGhdPVwiJzM0cHgnXCI+PC9pZ3gtbmF2LWRyYXdlcj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKSBwdWJsaWMgbWluaVdpZHRoID0gJzY4cHgnO1xuXG4gICAgLyoqXG4gICAgICogUGlubmVkIHN0YXRlIGNoYW5nZSBvdXRwdXQgZm9yIHR3by13YXkgYmluZGluZy5cbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LW5hdi1kcmF3ZXIgWyhwaW4pXT0naXNQaW5uZWQnPjwvaWd4LW5hdi1kcmF3ZXI+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpIHB1YmxpYyBwaW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KHRydWUpO1xuICAgIC8qKlxuICAgICAqIEV2ZW50IGZpcmVkIGFzIHRoZSBOYXZpZ2F0aW9uIERyYXdlciBpcyBhYm91dCB0byBvcGVuLlxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqICA8aWd4LW5hdi1kcmF3ZXIgKG9wZW5pbmcpPSdvbk9wZW5pbmcoKSc+PC9pZ3gtbmF2LWRyYXdlcj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcHVibGljIG9wZW5pbmcgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogRXZlbnQgZmlyZWQgd2hlbiB0aGUgTmF2aWdhdGlvbiBEcmF3ZXIgaGFzIG9wZW5lZC5cbiAgICAgKlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LW5hdi1kcmF3ZXIgKG9wZW5lZCk9J29uT3BlbmVkKCknPjwvaWd4LW5hdi1kcmF3ZXI+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpIHB1YmxpYyBvcGVuZWQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogRXZlbnQgZmlyZWQgYXMgdGhlIE5hdmlnYXRpb24gRHJhd2VyIGlzIGFib3V0IHRvIGNsb3NlLlxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtbmF2LWRyYXdlciAoY2xvc2luZyk9J29uQ2xvc2luZygpJz48L2lneC1uYXYtZHJhd2VyPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBPdXRwdXQoKSBwdWJsaWMgY2xvc2luZyA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBFdmVudCBmaXJlZCB3aGVuIHRoZSBOYXZpZ2F0aW9uIERyYXdlciBoYXMgY2xvc2VkLlxuICAgICAqXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtbmF2LWRyYXdlciAoY2xvc2VkKT0nb25DbG9zZWQoKSc+PC9pZ3gtbmF2LWRyYXdlcj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcHVibGljIGNsb3NlZCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXQgdGVtcGxhdGUoKSB7XG4gICAgICAgIGlmICh0aGlzLm1pbmlUZW1wbGF0ZSAmJiAhdGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1pbmlUZW1wbGF0ZS50ZW1wbGF0ZTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbnRlbnRUZW1wbGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGVudFRlbXBsYXRlLnRlbXBsYXRlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfbWluaVRlbXBsYXRlOiBJZ3hOYXZEcmF3ZXJNaW5pVGVtcGxhdGVEaXJlY3RpdmU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgbWluaVRlbXBsYXRlKCk6IElneE5hdkRyYXdlck1pbmlUZW1wbGF0ZURpcmVjdGl2ZSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9taW5pVGVtcGxhdGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBDb250ZW50Q2hpbGQoSWd4TmF2RHJhd2VyTWluaVRlbXBsYXRlRGlyZWN0aXZlLCB7IHJlYWQ6IElneE5hdkRyYXdlck1pbmlUZW1wbGF0ZURpcmVjdGl2ZSB9KVxuICAgIHB1YmxpYyBzZXQgbWluaVRlbXBsYXRlKHY6IElneE5hdkRyYXdlck1pbmlUZW1wbGF0ZURpcmVjdGl2ZSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLnNldERyYXdlcldpZHRoKHYgPyB0aGlzLm1pbmlXaWR0aCA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9taW5pVGVtcGxhdGUgPSB2O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBAQ29udGVudENoaWxkKElneE5hdkRyYXdlclRlbXBsYXRlRGlyZWN0aXZlLCB7IHJlYWQ6IElneE5hdkRyYXdlclRlbXBsYXRlRGlyZWN0aXZlIH0pXG4gICAgcHJvdGVjdGVkIGNvbnRlbnRUZW1wbGF0ZTogSWd4TmF2RHJhd2VyVGVtcGxhdGVEaXJlY3RpdmU7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS5mbGV4QmFzaXMnKVxuICAgIGdldCBmbGV4V2lkdGgoKSB7XG4gICAgICAgIGlmICghdGhpcy5waW4pIHtcbiAgICAgICAgICAgIHJldHVybiAnMHB4JztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpZHRoO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1pbmlUZW1wbGF0ZSAmJiB0aGlzLm1pbmlXaWR0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWluaVdpZHRoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICcwcHgnO1xuICAgIH1cblxuICAgIC8qKiBAaGlkZGVuICovXG4gICAgQEhvc3RCaW5kaW5nKCdzdHlsZS5vcmRlcicpXG4gICAgZ2V0IGlzUGlubmVkUmlnaHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbiAmJiB0aGlzLnBvc2l0aW9uID09PSAncmlnaHQnID8gJzEnIDogJzAnO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dlc3R1cmVzQXR0YWNoZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIF93aWR0aENhY2hlOiB7IHdpZHRoOiBudW1iZXIsIG1pbmlXaWR0aDogbnVtYmVyLCB3aW5kb3dXaWR0aDogbnVtYmVyIH0gPSB7IHdpZHRoOiBudWxsLCBtaW5pV2lkdGg6IG51bGwsIHdpbmRvd1dpZHRoOiBudWxsIH07XG4gICAgcHJpdmF0ZSBfcmVzaXplT2JzZXJ2ZXI6IFN1YnNjcmlwdGlvbjtcbiAgICBwcml2YXRlIGNzczogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nOyB9ID0ge1xuICAgICAgICBkcmF3ZXI6ICdpZ3gtbmF2LWRyYXdlcl9fYXNpZGUnLFxuICAgICAgICBtaW5pOiAnaWd4LW5hdi1kcmF3ZXJfX2FzaWRlLS1taW5pJyxcbiAgICAgICAgb3ZlcmxheTogJ2lneC1uYXYtZHJhd2VyX19vdmVybGF5JyxcbiAgICAgICAgc3R5bGVEdW1teTogJ2lneC1uYXYtZHJhd2VyX19zdHlsZS1kdW1teSdcbiAgICB9O1xuXG4gICAgQFZpZXdDaGlsZCgnYXNpZGUnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIF9kcmF3ZXI6IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgnb3ZlcmxheScsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgX292ZXJsYXk6IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgnZHVtbXknLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIF9zdHlsZUR1bW15OiBFbGVtZW50UmVmO1xuXG4gICAgLyoqXG4gICAgICAqIEBoaWRkZW5cbiAgICAgICovXG4gICAgZ2V0IGRyYXdlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RyYXdlci5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXQgb3ZlcmxheSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX292ZXJsYXkubmF0aXZlRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0IHN0eWxlRHVtbXkoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zdHlsZUR1bW15Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqIFBhbiBhbmltYXRpb24gcHJvcGVydGllcyAqL1xuICAgIHByaXZhdGUgX3Bhbm5pbmcgPSBmYWxzZTtcbiAgICBwcml2YXRlIF9wYW5TdGFydFdpZHRoOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfcGFuTGltaXQ6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFByb3BlcnR5IHRvIGRlY2lkZSB3aGV0aGVyIHRvIGNoYW5nZSB3aWR0aCBvciB0cmFuc2xhdGUgdGhlIGRyYXdlciBmcm9tIHBhbiBnZXN0dXJlLlxuICAgICAqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgaGFzQW5pbWF0ZVdpZHRoKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5waW4gfHwgISF0aGlzLm1pbmlUZW1wbGF0ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9tYXhFZGdlWm9uZSA9IDUwO1xuICAgIC8qKlxuICAgICAqIFVzZWQgZm9yIHRvdWNoIGdlc3R1cmVzIChzd2lwZSBhbmQgcGFuKS5cbiAgICAgKiBEZWZhdWx0cyB0byA1MCAoaW4gcHgpIGFuZCBpcyBleHRlbmRlZCB0byBhdCBsZWFzdCAxMTAlIG9mIHRoZSBtaW5pIHRlbXBsYXRlIHdpZHRoIGlmIGF2YWlsYWJsZS5cbiAgICAgKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IG1heEVkZ2Vab25lKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWF4RWRnZVpvbmU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgRHJhd2VyIHdpZHRoIGZvciBzcGVjaWZpYyBzdGF0ZS5cbiAgICAgKiBXaWxsIGF0dGVtcHQgdG8gZXZhbHVhdGUgcmVxdWVzdGVkIHN0YXRlIGFuZCBjYWNoZS5cbiAgICAgKlxuICAgICAqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgZXhwZWN0ZWRXaWR0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RXhwZWN0ZWRXaWR0aChmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBEcmF3ZXIgbWluaSB3aWR0aCBmb3Igc3BlY2lmaWMgc3RhdGUuXG4gICAgICogV2lsbCBhdHRlbXB0IHRvIGV2YWx1YXRlIHJlcXVlc3RlZCBzdGF0ZSBhbmQgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBleHBlY3RlZE1pbmlXaWR0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RXhwZWN0ZWRXaWR0aCh0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCB0b3VjaE1hbmFnZXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90b3VjaE1hbmFnZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhwb3NlcyBvcHRpb25hbCBuYXZpZ2F0aW9uIHNlcnZpY2VcbiAgICAgKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHN0YXRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc3RhdGU7XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIEBJbmplY3QoRWxlbWVudFJlZikgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICBAT3B0aW9uYWwoKSBwcml2YXRlIF9zdGF0ZTogSWd4TmF2aWdhdGlvblNlcnZpY2UsXG4gICAgICAgIHByb3RlY3RlZCByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgICAgICBwcml2YXRlIF90b3VjaE1hbmFnZXI6IEhhbW1lckdlc3R1cmVzTWFuYWdlcixcbiAgICAgICAgcHJpdmF0ZSBwbGF0Zm9ybVV0aWw6IFBsYXRmb3JtVXRpbCkge1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgICAgIC8vIERPTSBhbmQgQElucHV0KCktcyBpbml0aWFsaXplZFxuICAgICAgICBpZiAodGhpcy5fc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlLmFkZCh0aGlzLmlkLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHRoaXMuc2V0RHJhd2VyV2lkdGgodGhpcy53aWR0aCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcbiAgICAgICAgLy8gd2FpdCBmb3IgdGVtcGxhdGUgYW5kIG5nLWNvbnRlbnQgdG8gYmUgcmVhZHlcbiAgICAgICAgdGhpcy51cGRhdGVFZGdlWm9uZSgpO1xuICAgICAgICB0aGlzLmNoZWNrUGluVGhyZXNob2xkKCk7XG5cbiAgICAgICAgdGhpcy5lbnN1cmVFdmVudHMoKTtcblxuICAgICAgICAvLyBUT0RPOiBhcHBseSBwbGF0Zm9ybS1zYWZlIFJ1bGVyIGZyb20gaHR0cDovL3BsbmtyLmNvL2VkaXQvODFuV0R5cmVZTXprdW5paGZSZ1g/cD1wcmV2aWV3XG4gICAgICAgIC8vIChodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2lzc3Vlcy82NTE1KSwgYmxvY2tlZCBieSBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2lzc3Vlcy82OTA0XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5fdG91Y2hNYW5hZ2VyLmRlc3Ryb3koKTtcbiAgICAgICAgaWYgKHRoaXMuX3N0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZS5yZW1vdmUodGhpcy5pZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3Jlc2l6ZU9ic2VydmVyKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXNpemVPYnNlcnZlci51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiB7IFtwcm9wTmFtZTogc3RyaW5nXTogU2ltcGxlQ2hhbmdlIH0pIHtcbiAgICAgICAgLy8gc2ltcGxlIHNldHRpbmdzIGNhbiBjb21lIGZyb20gYXR0cmlidXRlIHNldCAocmF0aGVyIHRoYW4gYmluZGluZyksIG1ha2Ugc3VyZSBib29sZWFuIHByb3BzIGFyZSBjb252ZXJ0ZWRcbiAgICAgICAgaWYgKGNoYW5nZXMuZW5hYmxlR2VzdHVyZXMgJiYgY2hhbmdlcy5lbmFibGVHZXN0dXJlcy5jdXJyZW50VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5lbmFibGVHZXN0dXJlcyA9ICEhKHRoaXMuZW5hYmxlR2VzdHVyZXMgJiYgdGhpcy5lbmFibGVHZXN0dXJlcy50b1N0cmluZygpID09PSAndHJ1ZScpO1xuICAgICAgICAgICAgdGhpcy5lbnN1cmVFdmVudHMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlcy5waW4gJiYgY2hhbmdlcy5waW4uY3VycmVudFZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMucGluID0gISEodGhpcy5waW4gJiYgdGhpcy5waW4udG9TdHJpbmcoKSA9PT0gJ3RydWUnKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnBpbikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3RvdWNoTWFuYWdlci5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZ2VzdHVyZXNBdHRhY2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuc3VyZUV2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNoYW5nZXMucGluVGhyZXNob2xkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5waW5UaHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuc3VyZUV2ZW50cygpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tQaW5UaHJlc2hvbGQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGFuZ2VzLndpZHRoICYmIHRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLnNldERyYXdlcldpZHRoKGNoYW5nZXMud2lkdGguY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGFuZ2VzLm1pbmlXaWR0aCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzT3Blbikge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0RHJhd2VyV2lkdGgoY2hhbmdlcy5taW5pV2lkdGguY3VycmVudFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXBkYXRlRWRnZVpvbmUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRvZ2dsZSB0aGUgb3BlbiBzdGF0ZSBvZiB0aGUgTmF2aWdhdGlvbiBEcmF3ZXIuXG4gICAgICpcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogdGhpcy5uYXZkcmF3ZXIudG9nZ2xlKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIHRvZ2dsZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm9wZW4oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9wZW4gdGhlIE5hdmlnYXRpb24gRHJhd2VyLiBIYXMgbm8gZWZmZWN0IGlmIGFscmVhZHkgb3BlbmVkLlxuICAgICAqXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIHRoaXMubmF2ZHJhd2VyLm9wZW4oKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBwdWJsaWMgb3BlbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX3Bhbm5pbmcpIHtcbiAgICAgICAgICAgIHRoaXMucmVzZXRQYW4oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc09wZW4pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wZW5pbmcuZW1pdCgpO1xuICAgICAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG5cbiAgICAgICAgLy8gVE9ETzogU3dpdGNoIHRvIGFuaW1hdGUgQVBJIHdoZW4gYXZhaWxhYmxlXG4gICAgICAgIC8vIHZhciBhbmltYXRpb25Dc3MgPSB0aGlzLmFuaW1hdGUuY3NzKCk7XG4gICAgICAgIC8vICAgICBhbmltYXRpb25Dc3NcbiAgICAgICAgLy8gICAgICAgICAuc2V0U3R5bGVzKHsnd2lkdGgnOic1MHB4J30sIHsnd2lkdGgnOic0MDBweCd9KVxuICAgICAgICAvLyAgICAgICAgIC5zdGFydCh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudClcbiAgICAgICAgLy8gICAgICAgICAub25Db21wbGV0ZSgoKSA9PiBhbmltYXRpb25Dc3Muc2V0VG9TdHlsZXMoeyd3aWR0aCc6J2F1dG8nfSkuc3RhcnQodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpKTtcblxuICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0cmFuc2l0aW9uZW5kJywgdGhpcy50b2dnbGVPcGVuZWRFdmVudCwgZmFsc2UpO1xuICAgICAgICB0aGlzLnNldERyYXdlcldpZHRoKHRoaXMud2lkdGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlIHRoZSBOYXZpZ2F0aW9uIERyYXdlci4gSGFzIG5vIGVmZmVjdCBpZiBhbHJlYWR5IGNsb3NlZC5cbiAgICAgKlxuICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgKiB0aGlzLm5hdmRyYXdlci5jbG9zZSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1YmxpYyBjbG9zZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3Bhbm5pbmcpIHtcbiAgICAgICAgICAgIHRoaXMucmVzZXRQYW4oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbG9zaW5nLmVtaXQoKTtcblxuICAgICAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLnNldERyYXdlcldpZHRoKHRoaXMubWluaVRlbXBsYXRlID8gdGhpcy5taW5pV2lkdGggOiAnJyk7XG4gICAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RyYW5zaXRpb25lbmQnLCB0aGlzLnRvZ2dsZUNsb3NlZEV2ZW50LCBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzZXRfbWF4RWRnZVpvbmUodmFsdWU6IG51bWJlcikge1xuICAgICAgICB0aGlzLl9tYXhFZGdlWm9uZSA9IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgRHJhd2VyIHdpZHRoIGZvciBzcGVjaWZpYyBzdGF0ZS4gV2lsbCBhdHRlbXB0IHRvIGV2YWx1YXRlIHJlcXVlc3RlZCBzdGF0ZSBhbmQgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAaGlkZGVuXG4gICAgICogQHBhcmFtIFttaW5pXSAtIFJlcXVlc3QgbWluaSB3aWR0aCBpbnN0ZWFkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGdldEV4cGVjdGVkV2lkdGgobWluaT86IGJvb2xlYW4pOiBudW1iZXIge1xuICAgICAgICBpZiAobWluaSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLm1pbmlUZW1wbGF0ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubWluaVdpZHRoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXQodGhpcy5taW5pV2lkdGgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBpZiAoIXRoaXMuaXNPcGVuKSB7IC8vIFRoaXMgV09OJ1Qgd29yayBkdWUgdG8gdHJhbnNpdGlvbiB0aW1pbmdzLi4uXG4gICAgICAgICAgICAgICAgLy8gICAgIHJldHVybiB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jaGlsZHJlblsxXS5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgICAgICAvLyB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl93aWR0aENhY2hlLm1pbmlXaWR0aCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBmb3JjZSBjbGFzcyBmb3Igd2lkdGggY2FsYy4gVE9ETz9cbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yY2UgY2xhc3MgZm9yIHdpZHRoIGNhbGMuIFRPRE8/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5zdHlsZUR1bW15LCB0aGlzLmNzcy5kcmF3ZXIpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuc3R5bGVEdW1teSwgdGhpcy5jc3MubWluaSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3dpZHRoQ2FjaGUubWluaVdpZHRoID0gdGhpcy5zdHlsZUR1bW15Lm9mZnNldFdpZHRoO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuc3R5bGVEdW1teSwgdGhpcy5jc3MuZHJhd2VyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLnN0eWxlRHVtbXksIHRoaXMuY3NzLm1pbmkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fd2lkdGhDYWNoZS5taW5pV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy53aWR0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHRoaXMud2lkdGgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fd2lkdGhDYWNoZS53aWR0aCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBmb3JjZSBjbGFzcyBmb3Igd2lkdGggY2FsYy4gVE9ETz9cbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yY2UgY2xhc3MgZm9yIHdpZHRoIGNhbGMuIFRPRE8/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5zdHlsZUR1bW15LCB0aGlzLmNzcy5kcmF3ZXIpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl93aWR0aENhY2hlLndpZHRoID0gdGhpcy5zdHlsZUR1bW15Lm9mZnNldFdpZHRoO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMuc3R5bGVEdW1teSwgdGhpcy5jc3MuZHJhd2VyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dpZHRoQ2FjaGUud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFdpbmRvd1dpZHRoKCkge1xuICAgICAgICByZXR1cm4gKHdpbmRvdy5pbm5lcldpZHRoID4gMCkgPyB3aW5kb3cuaW5uZXJXaWR0aCA6IHNjcmVlbi53aWR0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBkcmF3ZXIgd2lkdGguXG4gICAgICovXG4gICAgcHJpdmF0ZSBzZXREcmF3ZXJXaWR0aCh3aWR0aDogc3RyaW5nKSB7XG4gICAgICAgIGlmICh0aGlzLnBsYXRmb3JtVXRpbC5pc0Jyb3dzZXIpIHtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZHJhd2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5kcmF3ZXIsICd3aWR0aCcsIHdpZHRoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5kcmF3ZXIsICd3aWR0aCcsIHdpZHRoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBjdXJyZW50IERyYXdlciB3aWR0aC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGdldERyYXdlcldpZHRoKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmRyYXdlci5vZmZzZXRXaWR0aDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGVuc3VyZUV2ZW50cygpIHtcbiAgICAgICAgLy8gc2V0IGxpc3RlbmVycyBmb3Igc3dpcGUvcGFuIG9ubHkgaWYgbmVlZGVkLCBidXQganVzdCBvbmNlXG4gICAgICAgIGlmICh0aGlzLmVuYWJsZUdlc3R1cmVzICYmICF0aGlzLnBpbiAmJiAhdGhpcy5fZ2VzdHVyZXNBdHRhY2hlZCkge1xuICAgICAgICAgICAgLy8gQnVpbHQtaW4gbWFuYWdlciBoYW5kbGVyKEwyMDg4NykgY2F1c2VzIGVuZGxlc3MgbG9vcCBhbmQgbWF4IHN0YWNrIGV4Y2VwdGlvbi5cbiAgICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvaXNzdWVzLzY5OTNcbiAgICAgICAgICAgIC8vIFVzZSBvdXJzIGZvciBub3cgKHVudGlsIGJldGEuMTApOlxuICAgICAgICAgICAgLy8gdGhpcy5yZW5kZXJlci5saXN0ZW4oZG9jdW1lbnQsIFwic3dpcGVcIiwgdGhpcy5zd2lwZSk7XG4gICAgICAgICAgICB0aGlzLl90b3VjaE1hbmFnZXIuYWRkR2xvYmFsRXZlbnRMaXN0ZW5lcignZG9jdW1lbnQnLCAnc3dpcGUnLCB0aGlzLnN3aXBlKTtcbiAgICAgICAgICAgIHRoaXMuX2dlc3R1cmVzQXR0YWNoZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyB0aGlzLnJlbmRlcmVyLmxpc3Rlbihkb2N1bWVudCwgXCJwYW5zdGFydFwiLCB0aGlzLnBhbnN0YXJ0KTtcbiAgICAgICAgICAgIC8vIHRoaXMucmVuZGVyZXIubGlzdGVuKGRvY3VtZW50LCBcInBhblwiLCB0aGlzLnBhbik7XG4gICAgICAgICAgICB0aGlzLl90b3VjaE1hbmFnZXIuYWRkR2xvYmFsRXZlbnRMaXN0ZW5lcignZG9jdW1lbnQnLCAncGFuc3RhcnQnLCB0aGlzLnBhbnN0YXJ0KTtcbiAgICAgICAgICAgIHRoaXMuX3RvdWNoTWFuYWdlci5hZGRHbG9iYWxFdmVudExpc3RlbmVyKCdkb2N1bWVudCcsICdwYW5tb3ZlJywgdGhpcy5wYW4pO1xuICAgICAgICAgICAgdGhpcy5fdG91Y2hNYW5hZ2VyLmFkZEdsb2JhbEV2ZW50TGlzdGVuZXIoJ2RvY3VtZW50JywgJ3BhbmVuZCcsIHRoaXMucGFuRW5kKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuX3Jlc2l6ZU9ic2VydmVyICYmIHRoaXMucGxhdGZvcm1VdGlsLmlzQnJvd3Nlcikge1xuICAgICAgICAgICAgdGhpcy5fcmVzaXplT2JzZXJ2ZXIgPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJykucGlwZShkZWJvdW5jZSgoKSA9PiBpbnRlcnZhbCgxNTApKSlcbiAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNoZWNrUGluVGhyZXNob2xkKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlRWRnZVpvbmUoKSB7XG4gICAgICAgIGxldCBtYXhWYWx1ZTtcblxuICAgICAgICBpZiAodGhpcy5taW5pVGVtcGxhdGUpIHtcbiAgICAgICAgICAgIG1heFZhbHVlID0gTWF0aC5tYXgodGhpcy5fbWF4RWRnZVpvbmUsIHRoaXMuZ2V0RXhwZWN0ZWRXaWR0aCh0cnVlKSAqIDEuMSk7XG4gICAgICAgICAgICB0aGlzLnNldF9tYXhFZGdlWm9uZShtYXhWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrUGluVGhyZXNob2xkID0gKGV2dD86IEV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5wbGF0Zm9ybVV0aWwuaXNCcm93c2VyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHdpbmRvd1dpZHRoO1xuICAgICAgICBpZiAodGhpcy5waW5UaHJlc2hvbGQpIHtcbiAgICAgICAgICAgIHdpbmRvd1dpZHRoID0gdGhpcy5nZXRXaW5kb3dXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKGV2dCAmJiB0aGlzLl93aWR0aENhY2hlLndpbmRvd1dpZHRoID09PSB3aW5kb3dXaWR0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3dpZHRoQ2FjaGUud2luZG93V2lkdGggPSB3aW5kb3dXaWR0aDtcbiAgICAgICAgICAgIGlmICghdGhpcy5waW4gJiYgd2luZG93V2lkdGggPj0gdGhpcy5waW5UaHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBpbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5waW5DaGFuZ2UuZW1pdCh0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5waW4gJiYgd2luZG93V2lkdGggPCB0aGlzLnBpblRocmVzaG9sZCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGluID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5waW5DaGFuZ2UuZW1pdChmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN3aXBlID0gKGV2dDogSGFtbWVySW5wdXQpID0+IHtcbiAgICAgICAgLy8gVE9ETzogQ291bGQgYWxzbyBmb3JjZSBpbnB1dCB0eXBlOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yNzEwODA1MlxuICAgICAgICBpZiAoIXRoaXMuZW5hYmxlR2VzdHVyZXMgfHwgZXZ0LnBvaW50ZXJUeXBlICE9PSAndG91Y2gnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW1tZXJKUyBzd2lwZSBpcyBob3Jpem9udGFsLW9ubHkgYnkgZGVmYXVsdCwgZG9uJ3QgY2hlY2sgZGVsdGFZXG4gICAgICAgIGxldCBkZWx0YVg7XG4gICAgICAgIGxldCBzdGFydFBvc2l0aW9uO1xuICAgICAgICBpZiAodGhpcy5wb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgLy8gd2hlbiBvbiB0aGUgcmlnaHQgdXNlIGludmVyc2Ugb2YgZGVsdGFYXG4gICAgICAgICAgICBkZWx0YVggPSAtZXZ0LmRlbHRhWDtcbiAgICAgICAgICAgIHN0YXJ0UG9zaXRpb24gPSB0aGlzLmdldFdpbmRvd1dpZHRoKCkgLSAoZXZ0LmNlbnRlci54ICsgZXZ0LmRpc3RhbmNlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbHRhWCA9IGV2dC5kZWx0YVg7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gZXZ0LmNlbnRlci54IC0gZXZ0LmRpc3RhbmNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIG9ubHkgYWNjZXB0IGNsb3Npbmcgc3dpcGUgKGlnbm9yaW5nIG1pbkVkZ2Vab25lKSB3aGVuIHRoZSBkcmF3ZXIgaXMgZXhwYW5kZWQ6XG4gICAgICAgIGlmICgodGhpcy5pc09wZW4gJiYgZGVsdGFYIDwgMCkgfHxcbiAgICAgICAgICAgIC8vIHBvc2l0aXZlIGRlbHRhWCBmcm9tIHRoZSBlZGdlOlxuICAgICAgICAgICAgKGRlbHRhWCA+IDAgJiYgc3RhcnRQb3NpdGlvbiA8IHRoaXMubWF4RWRnZVpvbmUpKSB7XG4gICAgICAgICAgICB0aGlzLnRvZ2dsZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwYW5zdGFydCA9IChldnQ6IEhhbW1lcklucHV0KSA9PiB7IC8vIFRPRE86IHRlc3QgY29kZVxuICAgICAgICBpZiAoIXRoaXMuZW5hYmxlR2VzdHVyZXMgfHwgdGhpcy5waW4gfHwgZXZ0LnBvaW50ZXJUeXBlICE9PSAndG91Y2gnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RhcnRQb3NpdGlvbiA9IHRoaXMucG9zaXRpb24gPT09ICdyaWdodCcgPyB0aGlzLmdldFdpbmRvd1dpZHRoKCkgLSAoZXZ0LmNlbnRlci54ICsgZXZ0LmRpc3RhbmNlKVxuICAgICAgICAgICAgOiBldnQuY2VudGVyLnggLSBldnQuZGlzdGFuY2U7XG5cbiAgICAgICAgLy8gY2FjaGUgd2lkdGggZHVyaW5nIGFuaW1hdGlvbiwgZmxhZyB0byBhbGxvdyBmdXJ0aGVyIGhhbmRsaW5nXG4gICAgICAgIGlmICh0aGlzLmlzT3BlbiB8fCAoc3RhcnRQb3NpdGlvbiA8IHRoaXMubWF4RWRnZVpvbmUpKSB7XG4gICAgICAgICAgICB0aGlzLl9wYW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX3BhblN0YXJ0V2lkdGggPSB0aGlzLmdldEV4cGVjdGVkV2lkdGgoIXRoaXMuaXNPcGVuKTtcbiAgICAgICAgICAgIHRoaXMuX3BhbkxpbWl0ID0gdGhpcy5nZXRFeHBlY3RlZFdpZHRoKHRoaXMuaXNPcGVuKTtcblxuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLm92ZXJsYXksICdwYW5uaW5nJyk7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuZHJhd2VyLCAncGFubmluZycpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwYW4gPSAoZXZ0OiBIYW1tZXJJbnB1dCkgPT4ge1xuICAgICAgICAvLyBUT0RPOiBpbnB1dC5kZWx0YVggPSBwcmV2RGVsdGEueCArIChjZW50ZXIueCAtIG9mZnNldC54KTtcbiAgICAgICAgLy8gZ2V0IGFjdHVhbCBkZWx0YSAobm90IHRvdGFsIHNlc3Npb24gb25lKSBmcm9tIGV2ZW50P1xuICAgICAgICAvLyBwYW4gV0lMTCBhbHNvIGZpcmUgYWZ0ZXIgYSBmdWxsIHN3aXBlLCBvbmx5IHJlc2l6ZSBvbiBmbGFnXG4gICAgICAgIGlmICghdGhpcy5fcGFubmluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJpZ2h0OiBib29sZWFuID0gdGhpcy5wb3NpdGlvbiA9PT0gJ3JpZ2h0JztcbiAgICAgICAgLy8gd2hlbiBvbiB0aGUgcmlnaHQgdXNlIGludmVyc2Ugb2YgZGVsdGFYXG4gICAgICAgIGNvbnN0IGRlbHRhWCA9IHJpZ2h0ID8gLWV2dC5kZWx0YVggOiBldnQuZGVsdGFYO1xuICAgICAgICBsZXQgdmlzaWJsZVdpZHRoO1xuICAgICAgICBsZXQgbmV3WDtcbiAgICAgICAgbGV0IHBlcmNlbnQ7XG5cbiAgICAgICAgdmlzaWJsZVdpZHRoID0gdGhpcy5fcGFuU3RhcnRXaWR0aCArIGRlbHRhWDtcblxuICAgICAgICBpZiAodGhpcy5pc09wZW4gJiYgZGVsdGFYIDwgMCkge1xuICAgICAgICAgICAgLy8gd2hlbiB2aXNpYmxlV2lkdGggaGl0cyBsaW1pdCAtIHN0b3AgYW5pbWF0aW5nXG4gICAgICAgICAgICBpZiAodmlzaWJsZVdpZHRoIDw9IHRoaXMuX3BhbkxpbWl0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBbmltYXRlV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBwZXJjZW50ID0gKHZpc2libGVXaWR0aCAtIHRoaXMuX3BhbkxpbWl0KSAvICh0aGlzLl9wYW5TdGFydFdpZHRoIC0gdGhpcy5fcGFuTGltaXQpO1xuICAgICAgICAgICAgICAgIG5ld1ggPSB2aXNpYmxlV2lkdGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlcmNlbnQgPSB2aXNpYmxlV2lkdGggLyB0aGlzLl9wYW5TdGFydFdpZHRoO1xuICAgICAgICAgICAgICAgIG5ld1ggPSBldnQuZGVsdGFYO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRYU2l6ZShuZXdYLCBwZXJjZW50LnRvUHJlY2lzaW9uKDIpKTtcblxuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmlzT3BlbiAmJiBkZWx0YVggPiAwKSB7XG4gICAgICAgICAgICAvLyB3aGVuIHZpc2libGVXaWR0aCBoaXRzIGxpbWl0IC0gc3RvcCBhbmltYXRpbmdcbiAgICAgICAgICAgIGlmICh2aXNpYmxlV2lkdGggPj0gdGhpcy5fcGFuTGltaXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0FuaW1hdGVXaWR0aCkge1xuICAgICAgICAgICAgICAgIHBlcmNlbnQgPSAodmlzaWJsZVdpZHRoIC0gdGhpcy5fcGFuU3RhcnRXaWR0aCkgLyAodGhpcy5fcGFuTGltaXQgLSB0aGlzLl9wYW5TdGFydFdpZHRoKTtcbiAgICAgICAgICAgICAgICBuZXdYID0gdmlzaWJsZVdpZHRoO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZXJjZW50ID0gdmlzaWJsZVdpZHRoIC8gdGhpcy5fcGFuTGltaXQ7XG4gICAgICAgICAgICAgICAgbmV3WCA9ICh0aGlzLl9wYW5MaW1pdCAtIHZpc2libGVXaWR0aCkgKiAocmlnaHQgPyAxIDogLTEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRYU2l6ZShuZXdYLCBwZXJjZW50LnRvUHJlY2lzaW9uKDIpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcGFuRW5kID0gKGV2dDogSGFtbWVySW5wdXQpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX3Bhbm5pbmcpIHtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhWCA9IHRoaXMucG9zaXRpb24gPT09ICdyaWdodCcgPyAtZXZ0LmRlbHRhWCA6IGV2dC5kZWx0YVg7XG4gICAgICAgICAgICBjb25zdCB2aXNpYmxlV2lkdGg6IG51bWJlciA9IHRoaXMuX3BhblN0YXJ0V2lkdGggKyBkZWx0YVg7XG4gICAgICAgICAgICB0aGlzLnJlc2V0UGFuKCk7XG5cbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHBhbiBicm91Z2h0IHRoZSBkcmF3ZXIgdG8gNTAlXG4gICAgICAgICAgICBpZiAodGhpcy5pc09wZW4gJiYgdmlzaWJsZVdpZHRoIDw9IHRoaXMuX3BhblN0YXJ0V2lkdGggLyAyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5pc09wZW4gJiYgdmlzaWJsZVdpZHRoID49IHRoaXMuX3BhbkxpbWl0IC8gMikge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcGFuU3RhcnRXaWR0aCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJlc2V0UGFuKCkge1xuICAgICAgICB0aGlzLl9wYW5uaW5nID0gZmFsc2U7XG4gICAgICAgIC8qIHN0eWxlcyBmYWlsIHRvIGFwcGx5IHdoZW4gc2V0IG9uIHBhcmVudCBkdWUgdG8gZXh0cmEgYXR0cmlidXRlcywgcHJvYiBuZyBidWcgKi9cbiAgICAgICAgLyogc3R5bGVzIGZhaWwgdG8gYXBwbHkgd2hlbiBzZXQgb24gcGFyZW50IGR1ZSB0byBleHRyYSBhdHRyaWJ1dGVzLCBwcm9iIG5nIGJ1ZyAqL1xuICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKHRoaXMub3ZlcmxheSwgJ3Bhbm5pbmcnKTtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLmRyYXdlciwgJ3Bhbm5pbmcnKTtcbiAgICAgICAgdGhpcy5zZXRYU2l6ZSgwLCAnJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYWJzb2x1dGUgcG9zaXRpb24gb3Igd2lkdGggaW4gY2FzZSB0aGUgZHJhd2VyIGRvZXNuJ3QgY2hhbmdlIHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB4IHRoZSBudW1iZXIgcGl4ZWxzIHRvIHRyYW5zbGF0ZSBvbiB0aGUgWCBheGlzIG9yIHRoZSB3aWR0aCB0byBzZXQuIDAgd2lkdGggd2lsbCBjbGVhciB0aGUgc3R5bGUgaW5zdGVhZC5cbiAgICAgKiBAcGFyYW0gb3BhY2l0eSBvcHRpb25hbCB2YWx1ZSB0byBhcHBseSB0byB0aGUgb3ZlcmxheVxuICAgICAqL1xuICAgIHByaXZhdGUgc2V0WFNpemUoeDogbnVtYmVyLCBvcGFjaXR5Pzogc3RyaW5nKSB7XG4gICAgICAgIC8vIEFuZ3VsYXIgcG9seWZpbGxzIHBhdGNoZXMgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSwgYnV0IHN3aXRjaCB0byBEb21BZGFwdGVyIEFQSSAoVE9ETylcbiAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBbmltYXRlV2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZHJhd2VyLCAnd2lkdGgnLCB4ID8gTWF0aC5hYnMoeCkgKyAncHgnIDogJycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZHJhd2VyLCAndHJhbnNmb3JtJywgeCA/ICd0cmFuc2xhdGUzZCgnICsgeCArICdweCwwLDApJyA6ICcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZHJhd2VyLCAnLXdlYmtpdC10cmFuc2Zvcm0nLCB4ID8gJ3RyYW5zbGF0ZTNkKCcgKyB4ICsgJ3B4LDAsMCknIDogJycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wYWNpdHkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5vdmVybGF5LCAnb3BhY2l0eScsIG9wYWNpdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHRvZ2dsZU9wZW5lZEV2ZW50ID0gKGV2dD8pID0+IHtcbiAgICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndHJhbnNpdGlvbmVuZCcsIHRoaXMudG9nZ2xlT3BlbmVkRXZlbnQsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5vcGVuZWQuZW1pdCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgdG9nZ2xlQ2xvc2VkRXZlbnQgPSAoZXZ0PykgPT4ge1xuICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0cmFuc2l0aW9uZW5kJywgdGhpcy50b2dnbGVDbG9zZWRFdmVudCwgZmFsc2UpO1xuICAgICAgICB0aGlzLmNsb3NlZC5lbWl0KCk7XG4gICAgfVxufVxuIl19