@excalidraw/excalidraw 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2375,7 +2375,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2375
2375
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2376
2376
 
2377
2377
  "use strict";
2378
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"trackEvent\": () => (/* binding */ trackEvent)\n/* harmony export */ });\nconst trackEvent = (category, action, label, value) => {\n try {\n // place here categories that you want to track as events\n // KEEP IN MIND THE PRICING\n const ALLOWED_CATEGORIES_TO_TRACK = []; // Uncomment the next line to track locally\n // console.log(\"Track Event\", { category, action, label, value });\n\n if (typeof window === \"undefined\" || ({\"VITE_APP_BACKEND_V2_GET_URL\":\"https://json-dev.excalidraw.com/api/v2/\",\"VITE_APP_BACKEND_V2_POST_URL\":\"https://json-dev.excalidraw.com/api/v2/post/\",\"VITE_APP_LIBRARY_URL\":\"https://libraries.excalidraw.com\",\"VITE_APP_LIBRARY_BACKEND\":\"https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries\",\"VITE_APP_WS_SERVER_URL\":\"http://localhost:3002\",\"VITE_APP_PORTAL_URL\":\"\",\"VITE_APP_PLUS_LP\":\"https://plus.excalidraw.com\",\"VITE_APP_PLUS_APP\":\"https://app.excalidraw.com\",\"VITE_APP_FIREBASE_CONFIG\":\"{\\\"apiKey\\\":\\\"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8\\\",\\\"authDomain\\\":\\\"excalidraw-oss-dev.firebaseapp.com\\\",\\\"projectId\\\":\\\"excalidraw-oss-dev\\\",\\\"storageBucket\\\":\\\"excalidraw-oss-dev.appspot.com\\\",\\\"messagingSenderId\\\":\\\"664559512677\\\",\\\"appId\\\":\\\"1:664559512677:web:a385181f2928d328a7aa8c\\\"}\",\"VITE_APP_DEV_ENABLE_SW\":\"\",\"VITE_APP_DEV_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_DISABLE_TRACKING\":\"true\",\"FAST_REFRESH\":\"false\",\"VITE_APP_PORT\":\"3000\",\"VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX\":\"\",\"VITE_APP_COLLAPSE_OVERLAY\":\"true\",\"VITE_APP_ENABLE_ESLINT\":\"true\",\"VITE_PKG_NAME\":\"@excalidraw/excalidraw\",\"VITE_PKG_VERSION\":\"0.16.0\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).VITE_WORKER_ID) {\n return;\n }\n\n if (!ALLOWED_CATEGORIES_TO_TRACK.includes(category)) {\n return;\n }\n\n if (window.sa_event) {\n window.sa_event(action, {\n category,\n label,\n value\n });\n }\n } catch (error) {\n console.error(\"error during analytics\", error);\n }\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vYW5hbHl0aWNzLnRzLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QyxvQ0FBb0MsZ0NBQWdDOztBQUVwRSx5Q0FBeUMsc3FDQUFXO0FBQ3BEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2FuYWx5dGljcy50cz81NjYxIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCB0cmFja0V2ZW50ID0gKGNhdGVnb3J5LCBhY3Rpb24sIGxhYmVsLCB2YWx1ZSkgPT4ge1xuICB0cnkge1xuICAgIC8vIHBsYWNlIGhlcmUgY2F0ZWdvcmllcyB0aGF0IHlvdSB3YW50IHRvIHRyYWNrIGFzIGV2ZW50c1xuICAgIC8vIEtFRVAgSU4gTUlORCBUSEUgUFJJQ0lOR1xuICAgIGNvbnN0IEFMTE9XRURfQ0FURUdPUklFU19UT19UUkFDSyA9IFtdOyAvLyBVbmNvbW1lbnQgdGhlIG5leHQgbGluZSB0byB0cmFjayBsb2NhbGx5XG4gICAgLy8gY29uc29sZS5sb2coXCJUcmFjayBFdmVudFwiLCB7IGNhdGVnb3J5LCBhY3Rpb24sIGxhYmVsLCB2YWx1ZSB9KTtcblxuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiIHx8IHByb2Nlc3MuZW52LlZJVEVfV09SS0VSX0lEKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFBTExPV0VEX0NBVEVHT1JJRVNfVE9fVFJBQ0suaW5jbHVkZXMoY2F0ZWdvcnkpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHdpbmRvdy5zYV9ldmVudCkge1xuICAgICAgd2luZG93LnNhX2V2ZW50KGFjdGlvbiwge1xuICAgICAgICBjYXRlZ29yeSxcbiAgICAgICAgbGFiZWwsXG4gICAgICAgIHZhbHVlXG4gICAgICB9KTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihcImVycm9yIGR1cmluZyBhbmFseXRpY3NcIiwgZXJyb3IpO1xuICB9XG59OyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///../../analytics.ts\n");
2378
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"trackEvent\": () => (/* binding */ trackEvent)\n/* harmony export */ });\nconst trackEvent = (category, action, label, value) => {\n try {\n // place here categories that you want to track as events\n // KEEP IN MIND THE PRICING\n const ALLOWED_CATEGORIES_TO_TRACK = []; // Uncomment the next line to track locally\n // console.log(\"Track Event\", { category, action, label, value });\n\n if (typeof window === \"undefined\" || ({\"VITE_APP_BACKEND_V2_GET_URL\":\"https://json-dev.excalidraw.com/api/v2/\",\"VITE_APP_BACKEND_V2_POST_URL\":\"https://json-dev.excalidraw.com/api/v2/post/\",\"VITE_APP_LIBRARY_URL\":\"https://libraries.excalidraw.com\",\"VITE_APP_LIBRARY_BACKEND\":\"https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries\",\"VITE_APP_WS_SERVER_URL\":\"http://localhost:3002\",\"VITE_APP_PORTAL_URL\":\"\",\"VITE_APP_PLUS_LP\":\"https://plus.excalidraw.com\",\"VITE_APP_PLUS_APP\":\"https://app.excalidraw.com\",\"VITE_APP_FIREBASE_CONFIG\":\"{\\\"apiKey\\\":\\\"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8\\\",\\\"authDomain\\\":\\\"excalidraw-oss-dev.firebaseapp.com\\\",\\\"projectId\\\":\\\"excalidraw-oss-dev\\\",\\\"storageBucket\\\":\\\"excalidraw-oss-dev.appspot.com\\\",\\\"messagingSenderId\\\":\\\"664559512677\\\",\\\"appId\\\":\\\"1:664559512677:web:a385181f2928d328a7aa8c\\\"}\",\"VITE_APP_DEV_ENABLE_SW\":\"\",\"VITE_APP_DEV_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_DISABLE_TRACKING\":\"true\",\"FAST_REFRESH\":\"false\",\"VITE_APP_PORT\":\"3000\",\"VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX\":\"\",\"VITE_APP_COLLAPSE_OVERLAY\":\"true\",\"VITE_APP_ENABLE_ESLINT\":\"true\",\"VITE_PKG_NAME\":\"@excalidraw/excalidraw\",\"VITE_PKG_VERSION\":\"0.16.1\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).VITE_WORKER_ID) {\n return;\n }\n\n if (!ALLOWED_CATEGORIES_TO_TRACK.includes(category)) {\n return;\n }\n\n if (window.sa_event) {\n window.sa_event(action, {\n category,\n label,\n value\n });\n }\n } catch (error) {\n console.error(\"error during analytics\", error);\n }\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vYW5hbHl0aWNzLnRzLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QyxvQ0FBb0MsZ0NBQWdDOztBQUVwRSx5Q0FBeUMsc3FDQUFXO0FBQ3BEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2FuYWx5dGljcy50cz81NjYxIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCB0cmFja0V2ZW50ID0gKGNhdGVnb3J5LCBhY3Rpb24sIGxhYmVsLCB2YWx1ZSkgPT4ge1xuICB0cnkge1xuICAgIC8vIHBsYWNlIGhlcmUgY2F0ZWdvcmllcyB0aGF0IHlvdSB3YW50IHRvIHRyYWNrIGFzIGV2ZW50c1xuICAgIC8vIEtFRVAgSU4gTUlORCBUSEUgUFJJQ0lOR1xuICAgIGNvbnN0IEFMTE9XRURfQ0FURUdPUklFU19UT19UUkFDSyA9IFtdOyAvLyBVbmNvbW1lbnQgdGhlIG5leHQgbGluZSB0byB0cmFjayBsb2NhbGx5XG4gICAgLy8gY29uc29sZS5sb2coXCJUcmFjayBFdmVudFwiLCB7IGNhdGVnb3J5LCBhY3Rpb24sIGxhYmVsLCB2YWx1ZSB9KTtcblxuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiIHx8IHByb2Nlc3MuZW52LlZJVEVfV09SS0VSX0lEKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFBTExPV0VEX0NBVEVHT1JJRVNfVE9fVFJBQ0suaW5jbHVkZXMoY2F0ZWdvcnkpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHdpbmRvdy5zYV9ldmVudCkge1xuICAgICAgd2luZG93LnNhX2V2ZW50KGFjdGlvbiwge1xuICAgICAgICBjYXRlZ29yeSxcbiAgICAgICAgbGFiZWwsXG4gICAgICAgIHZhbHVlXG4gICAgICB9KTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihcImVycm9yIGR1cmluZyBhbmFseXRpY3NcIiwgZXJyb3IpO1xuICB9XG59OyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///../../analytics.ts\n");
2379
2379
 
2380
2380
  /***/ }),
2381
2381
 
@@ -2463,7 +2463,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2463
2463
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2464
2464
 
2465
2465
  "use strict";
2466
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ExcalidrawContainerContext\": () => (/* binding */ ExcalidrawContainerContext),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ \"useApp\": () => (/* binding */ useApp),\n/* harmony export */ \"useAppProps\": () => (/* binding */ useAppProps),\n/* harmony export */ \"useDevice\": () => (/* binding */ useDevice),\n/* harmony export */ \"useExcalidrawActionManager\": () => (/* binding */ useExcalidrawActionManager),\n/* harmony export */ \"useExcalidrawAppState\": () => (/* binding */ useExcalidrawAppState),\n/* harmony export */ \"useExcalidrawContainer\": () => (/* binding */ useExcalidrawContainer),\n/* harmony export */ \"useExcalidrawElements\": () => (/* binding */ useExcalidrawElements),\n/* harmony export */ \"useExcalidrawSetAppState\": () => (/* binding */ useExcalidrawSetAppState)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var nanoid__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! nanoid */ \"../../../node_modules/nanoid/index.browser.js\");\n/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../actions */ \"../../actions/index.ts\");\n/* harmony import */ var _actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../actions/actionHistory */ \"../../actions/actionHistory.tsx\");\n/* harmony import */ var _actions_manager__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../actions/manager */ \"../../actions/manager.tsx\");\n/* harmony import */ var _actions_register__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../actions/register */ \"../../actions/register.ts\");\n/* harmony import */ var _analytics__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../analytics */ \"../../analytics.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../appState */ \"../../appState.ts\");\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../clipboard */ \"../../clipboard.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../data */ \"../../data/index.ts\");\n/* harmony import */ var _data_library__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../data/library */ \"../../data/library.ts\");\n/* harmony import */ var _data_restore__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../data/restore */ \"../../data/restore.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../element */ \"../../element/index.ts\");\n/* harmony import */ var _element_binding__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../element/binding */ \"../../element/binding.ts\");\n/* harmony import */ var _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../element/linearElementEditor */ \"../../element/linearElementEditor.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../element/mutateElement */ \"../../element/mutateElement.ts\");\n/* harmony import */ var _element_newElement__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../element/newElement */ \"../../element/newElement.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../element/typeChecks */ \"../../element/typeChecks.ts\");\n/* harmony import */ var _gesture__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../gesture */ \"../../gesture.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../groups */ \"../../groups.ts\");\n/* harmony import */ var _history__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../history */ \"../../history.ts\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../i18n */ \"../../i18n.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../keys */ \"../../keys.ts\");\n/* harmony import */ var _element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../element/sizeHelpers */ \"../../element/sizeHelpers.ts\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../math */ \"../../math.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../scene */ \"../../scene/index.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../scene/Scene */ \"../../scene/Scene.ts\");\n/* harmony import */ var _scene_zoom__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../scene/zoom */ \"../../scene/zoom.ts\");\n/* harmony import */ var _shapes__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../shapes */ \"../../shapes.tsx\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../utils */ \"../../utils.ts\");\n/* harmony import */ var _element_embeddable__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ../element/embeddable */ \"../../element/embeddable.ts\");\n/* harmony import */ var _ContextMenu__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./ContextMenu */ \"../../components/ContextMenu.tsx\");\n/* harmony import */ var _LayerUI__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./LayerUI */ \"../../components/LayerUI.tsx\");\n/* harmony import */ var _Toast__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./Toast */ \"../../components/Toast.tsx\");\n/* harmony import */ var _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../actions/actionToggleViewMode */ \"../../actions/actionToggleViewMode.tsx\");\n/* harmony import */ var _data_blob__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../data/blob */ \"../../data/blob.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../element/image */ \"../../element/image.ts\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! lodash.throttle */ \"../../../node_modules/lodash.throttle/index.js\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_41___default = /*#__PURE__*/__webpack_require__.n(lodash_throttle__WEBPACK_IMPORTED_MODULE_41__);\n/* harmony import */ var _data_filesystem__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ../data/filesystem */ \"../../data/filesystem.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ../element/textElement */ \"../../element/textElement.ts\");\n/* harmony import */ var _element_collision__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ../element/collision */ \"../../element/collision.ts\");\n/* harmony import */ var _element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ../element/Hyperlink */ \"../../element/Hyperlink.tsx\");\n/* harmony import */ var _data_url__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ../data/url */ \"../../data/url.ts\");\n/* harmony import */ var _element_transformHandles__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ../element/transformHandles */ \"../../element/transformHandles.ts\");\n/* harmony import */ var _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ../actions/actionElementLock */ \"../../actions/actionElementLock.ts\");\n/* harmony import */ var _scene_Fonts__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ../scene/Fonts */ \"../../scene/Fonts.ts\");\n/* harmony import */ var _frame__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ../frame */ \"../../frame.ts\");\n/* harmony import */ var _scene_selection__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ../scene/selection */ \"../../scene/selection.ts\");\n/* harmony import */ var _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ../actions/actionClipboard */ \"../../actions/actionClipboard.tsx\");\n/* harmony import */ var _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ../actions/actionFrame */ \"../../actions/actionFrame.ts\");\n/* harmony import */ var _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ../actions/actionCanvas */ \"../../actions/actionCanvas.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ../jotai */ \"../../jotai.ts\");\n/* harmony import */ var _ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./ActiveConfirmDialog */ \"../../components/ActiveConfirmDialog.tsx\");\n/* harmony import */ var _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ../actions/actionBoundText */ \"../../actions/actionBoundText.tsx\");\n/* harmony import */ var _BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ./BraveMeasureTextError */ \"../../components/BraveMeasureTextError.tsx\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ./EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var _data_transform__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ../data/transform */ \"../../data/transform.ts\");\n/* harmony import */ var _Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./Sidebar/Sidebar */ \"../../components/Sidebar/Sidebar.tsx\");\n/* harmony import */ var _canvases__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ./canvases */ \"../../components/canvases/index.tsx\");\n/* harmony import */ var _scene_Renderer__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ../scene/Renderer */ \"../../scene/Renderer.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ../scene/ShapeCache */ \"../../scene/ShapeCache.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst AppContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst AppPropsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst deviceContextInitialValue = {\n isSmScreen: false,\n isMobile: false,\n isTouchScreen: false,\n canDeviceFitSidebar: false,\n isLandscape: false\n};\nconst DeviceContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(deviceContextInitialValue);\nDeviceContext.displayName = \"DeviceContext\";\nconst ExcalidrawContainerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext({\n container: null,\n id: null\n});\nExcalidrawContainerContext.displayName = \"ExcalidrawContainerContext\";\nconst ExcalidrawElementsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext([]);\nExcalidrawElementsContext.displayName = \"ExcalidrawElementsContext\";\nconst ExcalidrawAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n width: 0,\n height: 0,\n offsetLeft: 0,\n offsetTop: 0\n}));\nExcalidrawAppStateContext.displayName = \"ExcalidrawAppStateContext\";\nconst ExcalidrawSetAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(() => {\n console.warn(\"unitialized ExcalidrawSetAppStateContext context!\");\n});\nExcalidrawSetAppStateContext.displayName = \"ExcalidrawSetAppStateContext\";\nconst ExcalidrawActionManagerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nExcalidrawActionManagerContext.displayName = \"ExcalidrawActionManagerContext\";\nconst useApp = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppContext);\nconst useAppProps = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppPropsContext);\nconst useDevice = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(DeviceContext);\nconst useExcalidrawContainer = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawContainerContext);\nconst useExcalidrawElements = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawElementsContext);\nconst useExcalidrawAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawAppStateContext);\nconst useExcalidrawSetAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawSetAppStateContext);\nconst useExcalidrawActionManager = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawActionManagerContext);\nlet didTapTwice = false;\nlet tappedTwiceTimer = 0;\nlet isHoldingSpace = false;\nlet isPanning = false;\nlet isDraggingScrollBar = false;\nlet currentScrollBars = {\n horizontal: null,\n vertical: null\n};\nlet touchTimeout = 0;\nlet invalidateContextMenu = false;\n/**\n * Map of youtube embed video states\n */\n\nconst YOUTUBE_VIDEO_STATES = new Map();\nlet IS_PLAIN_PASTE = false;\nlet IS_PLAIN_PASTE_TIMER = 0;\nlet PLAIN_PASTE_TOAST_SHOWN = false;\nlet lastPointerUp = null;\nconst gesture = {\n pointers: new Map(),\n lastCenter: null,\n initialDistance: null,\n initialScale: null\n};\n\nclass App extends (react__WEBPACK_IMPORTED_MODULE_1___default().Component) {\n constructor(props) {\n var _a;\n\n super(props);\n this.interactiveCanvas = null;\n this.unmounted = false;\n this.device = deviceContextInitialValue;\n this.excalidrawContainerRef = react__WEBPACK_IMPORTED_MODULE_1___default().createRef();\n this.files = {};\n this.imageCache = new Map();\n this.iFrameRefs = new Map();\n this.lastPointerDown = null;\n this.lastPointerUp = null;\n this.lastViewportPosition = {\n x: 0,\n y: 0\n };\n\n this.updateEmbeddables = () => {\n const embeddableElements = new Map();\n let updated = false;\n this.scene.getNonDeletedElements().filter(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(element)) {\n embeddableElements.set(element.id, true);\n\n if (element.validated == null) {\n updated = true;\n const validated = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.embeddableURLValidator)(element.link, this.props.validateEmbeddable);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n validated\n }, false);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element);\n }\n }\n\n return false;\n });\n\n if (updated) {\n this.scene.informMutation();\n } // GC\n\n\n this.iFrameRefs.forEach((ref, id) => {\n if (!embeddableElements.has(id)) {\n this.iFrameRefs.delete(id);\n }\n });\n };\n\n this.getFrameNameDOMId = frameElement => {\n return `${this.id}-frame-name-${frameElement.id}`;\n };\n\n this.frameNameBoundsCache = {\n get: frameElement => {\n let bounds = this.frameNameBoundsCache._cache.get(frameElement.id);\n\n if (!bounds || bounds.zoom !== this.state.zoom.value || bounds.versionNonce !== frameElement.versionNonce) {\n const frameNameDiv = document.getElementById(this.getFrameNameDOMId(frameElement));\n\n if (frameNameDiv) {\n const box = frameNameDiv.getBoundingClientRect();\n const boxSceneTopLeft = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: box.x,\n clientY: box.y\n }, this.state);\n const boxSceneBottomRight = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: box.right,\n clientY: box.bottom\n }, this.state);\n bounds = {\n x: boxSceneTopLeft.x,\n y: boxSceneTopLeft.y,\n width: boxSceneBottomRight.x - boxSceneTopLeft.x,\n height: boxSceneBottomRight.y - boxSceneTopLeft.y,\n angle: 0,\n zoom: this.state.zoom.value,\n versionNonce: frameElement.versionNonce\n };\n\n this.frameNameBoundsCache._cache.set(frameElement.id, bounds);\n\n return bounds;\n }\n\n return null;\n }\n\n return bounds;\n },\n\n /**\n * @private\n */\n _cache: new Map()\n };\n\n this.renderFrameNames = () => {\n if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {\n return null;\n }\n\n const isDarkTheme = this.state.theme === \"dark\";\n return this.scene.getNonDeletedFrames().map((f, index) => {\n if (!(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(f, this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n })) {\n // if frame not visible, don't render its name\n return null;\n }\n\n const {\n x: x1,\n y: y1\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: f.x,\n sceneY: f.y\n }, this.state);\n const {\n x: x2\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: f.x + f.width,\n sceneY: f.y + f.height\n }, this.state);\n const FRAME_NAME_GAP = 20;\n const FRAME_NAME_EDIT_PADDING = 6;\n\n const reset = () => {\n var _a;\n\n if (((_a = f.name) === null || _a === void 0 ? void 0 : _a.trim()) === \"\") {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: null\n });\n }\n\n this.setState({\n editingFrame: null\n });\n };\n\n let frameNameJSX;\n\n if (f.id === this.state.editingFrame) {\n const frameNameInEdit = f.name == null ? `Frame ${index + 1}` : f.name;\n frameNameJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"input\", {\n autoFocus: true,\n value: frameNameInEdit,\n onChange: e => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: e.target.value\n });\n },\n onBlur: () => reset(),\n onKeyDown: event => {\n // for some inexplicable reason, `onBlur` triggered on ESC\n // does not reset `state.editingFrame` despite being called,\n // and we need to reset it here as well\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n reset();\n }\n },\n style: {\n background: this.state.viewBackgroundColor,\n filter: isDarkTheme ? _constants__WEBPACK_IMPORTED_MODULE_12__.THEME_FILTER : \"none\",\n zIndex: 2,\n border: \"none\",\n display: \"block\",\n padding: `${FRAME_NAME_EDIT_PADDING}px`,\n borderRadius: 4,\n boxShadow: \"inset 0 0 0 1px var(--color-primary)\",\n fontFamily: \"Assistant\",\n fontSize: \"14px\",\n transform: `translateY(-${FRAME_NAME_EDIT_PADDING}px)`,\n color: \"var(--color-gray-80)\",\n overflow: \"hidden\",\n maxWidth: `${Math.min(x2 - x1 - FRAME_NAME_EDIT_PADDING, document.body.clientWidth - x1 - FRAME_NAME_EDIT_PADDING)}px`\n },\n size: frameNameInEdit.length + 1 || 1,\n dir: \"auto\",\n autoComplete: \"off\",\n autoCapitalize: \"off\",\n autoCorrect: \"off\"\n });\n } else {\n frameNameJSX = f.name == null || f.name.trim() === \"\" ? `Frame ${index + 1}` : f.name.trim();\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n id: this.getFrameNameDOMId(f),\n style: {\n position: \"absolute\",\n top: `${y1 - FRAME_NAME_GAP - this.state.offsetTop}px`,\n left: `${x1 - this.state.offsetLeft - (this.state.editingFrame === f.id ? FRAME_NAME_EDIT_PADDING : 0)}px`,\n zIndex: 2,\n fontSize: \"14px\",\n color: isDarkTheme ? \"var(--color-gray-60)\" : \"var(--color-gray-50)\",\n width: \"max-content\",\n maxWidth: `${x2 - x1 + FRAME_NAME_EDIT_PADDING * 2}px`,\n overflow: f.id === this.state.editingFrame ? \"visible\" : \"hidden\",\n whiteSpace: \"nowrap\",\n textOverflow: \"ellipsis\",\n cursor: _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE,\n pointerEvents: this.state.viewModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.inheritFromUI\n },\n onPointerDown: event => this.handleCanvasPointerDown(event),\n onWheel: event => this.handleWheel(event),\n onContextMenu: this.handleCanvasContextMenu,\n onDoubleClick: () => {\n this.setState({\n editingFrame: f.id\n });\n }\n }, {\n children: frameNameJSX\n }), f.id);\n });\n };\n\n this.focusContainer = () => {\n var _a;\n\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.focus();\n };\n\n this.getSceneElementsIncludingDeleted = () => {\n return this.scene.getElementsIncludingDeleted();\n };\n\n this.getSceneElements = () => {\n return this.scene.getNonDeletedElements();\n };\n\n this.onInsertElements = elements => {\n this.addElementsFromPasteOrLibrary({\n elements,\n position: \"center\",\n files: null\n });\n };\n\n this.onExportImage = (type, elements) => __awaiter(this, void 0, void 0, function* () {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"export\", type, \"ui\");\n const fileHandle = yield (0,_data__WEBPACK_IMPORTED_MODULE_13__.exportCanvas)(type, elements, this.state, this.files, {\n exportBackground: this.state.exportBackground,\n name: this.state.name,\n viewBackgroundColor: this.state.viewBackgroundColor\n }).catch(_utils__WEBPACK_IMPORTED_MODULE_33__.muteFSAbortError).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: error.message\n });\n });\n\n if (this.state.exportEmbedScene && fileHandle && (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isImageFileHandle)(fileHandle)) {\n this.setState({\n fileHandle\n });\n }\n });\n\n this.openEyeDropper = ({\n type\n }) => {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_EyeDropper__WEBPACK_IMPORTED_MODULE_59__.activeEyeDropperAtom, {\n swapPreviewOnAlt: true,\n previewType: type === \"stroke\" ? \"strokeColor\" : \"backgroundColor\",\n onSelect: (color, event) => {\n const shouldUpdateStrokeColor = type === \"background\" && event.altKey || type === \"stroke\" && !event.altKey;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (!selectedElements.length || this.state.activeTool.type !== \"selection\") {\n if (shouldUpdateStrokeColor) {\n this.setState({\n currentItemStrokeColor: color\n });\n } else {\n this.setState({\n currentItemBackgroundColor: color\n });\n }\n } else {\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().map(el => {\n if (this.state.selectedElementIds[el.id]) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(el, {\n [shouldUpdateStrokeColor ? \"strokeColor\" : \"backgroundColor\"]: color\n });\n }\n\n return el;\n })\n });\n }\n },\n keepOpenOnAlt: false\n });\n };\n\n this.syncActionResult = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(actionResult => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j;\n\n if (this.unmounted || actionResult === false) {\n return;\n }\n\n let editingElement = null;\n\n if (actionResult.elements) {\n actionResult.elements.forEach(element => {\n var _a;\n\n if (((_a = this.state.editingElement) === null || _a === void 0 ? void 0 : _a.id) === element.id && this.state.editingElement !== element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element)) {\n editingElement = element;\n }\n });\n this.scene.replaceAllElements(actionResult.elements);\n\n if (actionResult.commitToHistory) {\n this.history.resumeRecording();\n }\n }\n\n if (actionResult.files) {\n this.files = actionResult.replaceFiles ? actionResult.files : Object.assign(Object.assign({}, this.files), actionResult.files);\n this.addNewImagesToImageCache();\n }\n\n if (actionResult.appState || editingElement || this.state.contextMenu) {\n if (actionResult.commitToHistory) {\n this.history.resumeRecording();\n }\n\n let viewModeEnabled = ((_a = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _a === void 0 ? void 0 : _a.viewModeEnabled) || false;\n let zenModeEnabled = ((_b = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _b === void 0 ? void 0 : _b.zenModeEnabled) || false;\n let gridSize = ((_c = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _c === void 0 ? void 0 : _c.gridSize) || null;\n const theme = ((_d = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _d === void 0 ? void 0 : _d.theme) || this.props.theme || _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.LIGHT;\n let name = (_f = (_e = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : this.state.name;\n const errorMessage = (_h = (_g = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _g === void 0 ? void 0 : _g.errorMessage) !== null && _h !== void 0 ? _h : this.state.errorMessage;\n\n if (typeof this.props.viewModeEnabled !== \"undefined\") {\n viewModeEnabled = this.props.viewModeEnabled;\n }\n\n if (typeof this.props.zenModeEnabled !== \"undefined\") {\n zenModeEnabled = this.props.zenModeEnabled;\n }\n\n if (typeof this.props.gridModeEnabled !== \"undefined\") {\n gridSize = this.props.gridModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.GRID_SIZE : null;\n }\n\n if (typeof this.props.name !== \"undefined\") {\n name = this.props.name;\n }\n\n editingElement = editingElement || ((_j = actionResult.appState) === null || _j === void 0 ? void 0 : _j.editingElement) || null;\n\n if (editingElement === null || editingElement === void 0 ? void 0 : editingElement.isDeleted) {\n editingElement = null;\n }\n\n this.setState(state => {\n // using Object.assign instead of spread to fool TS 4.2.2+ into\n // regarding the resulting type as not containing undefined\n // (which the following expression will never contain)\n return Object.assign(actionResult.appState || {}, {\n // NOTE this will prevent opening context menu using an action\n // or programmatically from the host, so it will need to be\n // rewritten later\n contextMenu: null,\n editingElement,\n viewModeEnabled,\n zenModeEnabled,\n gridSize,\n theme,\n name,\n errorMessage\n });\n }, () => {\n if (actionResult.syncHistory) {\n this.history.setCurrentState(this.state, this.scene.getElementsIncludingDeleted());\n }\n });\n }\n }); // Lifecycle\n\n this.onBlur = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(() => {\n isHoldingSpace = false;\n this.setState({\n isBindingEnabled: true\n });\n });\n\n this.onUnload = () => {\n this.onBlur();\n };\n\n this.disableEvent = event => {\n event.preventDefault();\n };\n\n this.resetHistory = () => {\n this.history.clear();\n };\n /**\n * Resets scene & history.\n * ! Do not use to clear scene user action !\n */\n\n\n this.resetScene = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(opts => {\n this.scene.replaceAllElements([]);\n this.setState(state => Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n isLoading: (opts === null || opts === void 0 ? void 0 : opts.resetLoadingState) ? false : state.isLoading,\n theme: this.state.theme\n }));\n this.resetHistory();\n });\n\n this.initializeScene = () => __awaiter(this, void 0, void 0, function* () {\n var _b;\n\n if (\"launchQueue\" in window && \"LaunchParams\" in window) {\n window.launchQueue.setConsumer(launchParams => __awaiter(this, void 0, void 0, function* () {\n if (!launchParams.files.length) {\n return;\n }\n\n const fileHandle = launchParams.files[0];\n const blob = yield fileHandle.getFile();\n this.loadFileToCanvas(new File([blob], blob.name || \"\", {\n type: blob.type\n }), fileHandle);\n }));\n }\n\n if (this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n if (!this.state.isLoading) {\n this.setState({\n isLoading: true\n });\n }\n\n let initialData = null;\n\n try {\n initialData = (yield this.props.initialData) || null;\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.libraryItems) {\n this.library.updateLibrary({\n libraryItems: initialData.libraryItems,\n merge: true\n }).catch(error => {\n console.error(error);\n });\n }\n } catch (error) {\n console.error(error);\n initialData = {\n appState: {\n errorMessage: error.message || \"Encountered an error during importing or restoring scene data\"\n }\n };\n }\n\n const scene = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restore)(initialData, null, null, {\n repairBindings: true\n });\n scene.appState = Object.assign(Object.assign({}, scene.appState), {\n theme: this.props.theme || scene.appState.theme,\n // we're falling back to current (pre-init) state when deciding\n // whether to open the library, to handle a case where we\n // update the state outside of initialData (e.g. when loading the app\n // with a library install link, which should auto-open the library)\n openSidebar: ((_b = scene.appState) === null || _b === void 0 ? void 0 : _b.openSidebar) || this.state.openSidebar,\n activeTool: scene.appState.activeTool.type === \"image\" ? Object.assign(Object.assign({}, scene.appState.activeTool), {\n type: \"selection\"\n }) : scene.appState.activeTool,\n isLoading: false,\n toast: this.state.toast\n });\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.scrollToContent) {\n scene.appState = Object.assign(Object.assign({}, scene.appState), (0,_scene__WEBPACK_IMPORTED_MODULE_29__.calculateScrollCenter)(scene.elements, Object.assign(Object.assign({}, scene.appState), {\n width: this.state.width,\n height: this.state.height,\n offsetTop: this.state.offsetTop,\n offsetLeft: this.state.offsetLeft\n })));\n } // FontFaceSet loadingdone event we listen on may not always fire\n // (looking at you Safari), so on init we manually load fonts for current\n // text elements on canvas, and rerender them once done. This also\n // seems faster even in browsers that do fire the loadingdone event.\n\n\n this.fonts.loadFontsForElements(scene.elements);\n this.resetHistory();\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n commitToHistory: true\n }));\n });\n\n this.refreshDeviceState = container => {\n const {\n width,\n height\n } = container.getBoundingClientRect();\n const sidebarBreakpoint = this.props.UIOptions.dockedSidebarBreakpoint != null ? this.props.UIOptions.dockedSidebarBreakpoint : _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_RIGHT_SIDEBAR_MIN_WIDTH;\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateObject)(this.device, {\n isLandscape: width > height,\n isSmScreen: width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_SM_MAX_WIDTH,\n isMobile: width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_PORTRAIT || height < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_HEIGHT_LANDSCAPE && width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_LANDSCAPE,\n canDeviceFitSidebar: width > sidebarBreakpoint\n });\n };\n\n this.onResize = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(() => {\n this.scene.getElementsIncludingDeleted().forEach(element => _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element));\n this.setState({});\n });\n\n this.renderInteractiveSceneCallback = ({\n atLeastOneVisibleElement,\n scrollBars,\n elements\n }) => {\n if (scrollBars) {\n currentScrollBars = scrollBars;\n }\n\n const scrolledOutside = // hide when editing text\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement) ? false : !atLeastOneVisibleElement && elements.length > 0;\n\n if (this.state.scrolledOutside !== scrolledOutside) {\n this.setState({\n scrolledOutside\n });\n }\n\n this.scheduleImageRefresh();\n };\n\n this.onScroll = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.debounce)(() => {\n const {\n offsetTop,\n offsetLeft\n } = this.getCanvasOffsets();\n this.setState(state => {\n if (state.offsetLeft === offsetLeft && state.offsetTop === offsetTop) {\n return null;\n }\n\n return {\n offsetTop,\n offsetLeft\n };\n });\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.SCROLL_TIMEOUT); // Copy/paste\n\n this.onCut = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target)) {\n return;\n }\n\n this.cutAll();\n event.preventDefault();\n event.stopPropagation();\n });\n this.onCopy = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target)) {\n return;\n }\n\n this.copyAll();\n event.preventDefault();\n event.stopPropagation();\n });\n\n this.cutAll = () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, \"keyboard\");\n };\n\n this.copyAll = () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, \"keyboard\");\n };\n\n this.onTouchStart = event => {\n // fix for Apple Pencil Scribble\n // On Android, preventing the event would disable contextMenu on tap-hold\n if (!_constants__WEBPACK_IMPORTED_MODULE_12__.isAndroid) {\n event.preventDefault();\n }\n\n if (!didTapTwice) {\n didTapTwice = true;\n clearTimeout(tappedTwiceTimer);\n tappedTwiceTimer = window.setTimeout(App.resetTapTwice, _constants__WEBPACK_IMPORTED_MODULE_12__.TAP_TWICE_TIMEOUT);\n return;\n } // insert text only if we tapped twice with a single finger\n // event.touches.length === 1 will also prevent inserting text when user's zooming\n\n\n if (didTapTwice && event.touches.length === 1) {\n const touch = event.touches[0]; // @ts-ignore\n\n this.handleCanvasDoubleClick({\n clientX: touch.clientX,\n clientY: touch.clientY\n });\n didTapTwice = false;\n clearTimeout(tappedTwiceTimer);\n }\n\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.isAndroid) {\n event.preventDefault();\n }\n\n if (event.touches.length === 2) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n };\n\n this.onTouchEnd = event => {\n this.resetContextMenuTimer();\n\n if (event.touches.length > 0) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n } else {\n gesture.pointers.clear();\n }\n };\n\n this.pasteFromClipboard = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => __awaiter(this, void 0, void 0, function* () {\n var _c, _d, _e;\n\n const isPlainPaste = !!(IS_PLAIN_PASTE && event); // #686\n\n const target = document.activeElement;\n const isExcalidrawActive = (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.contains(target);\n\n if (event && !isExcalidrawActive) {\n return;\n }\n\n const elementUnderCursor = document.elementFromPoint(this.lastViewportPosition.x, this.lastViewportPosition.y);\n\n if (event && (!(elementUnderCursor instanceof HTMLCanvasElement) || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(target))) {\n return;\n } // must be called in the same frame (thus before any awaits) as the paste\n // event else some browsers (FF...) will clear the clipboardData\n // (something something security)\n\n\n let file = (_d = event === null || event === void 0 ? void 0 : event.clipboardData) === null || _d === void 0 ? void 0 : _d.files[0];\n const data = yield (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.parseClipboard)(event, isPlainPaste);\n\n if (!file && data.text && !isPlainPaste) {\n const string = data.text.trim();\n\n if (string.startsWith(\"<svg\") && string.endsWith(\"</svg>\")) {\n // ignore SVG validation/normalization which will be done during image\n // initialization\n file = (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.SVGStringToFile)(string);\n }\n }\n\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state); // prefer spreadsheet data over image file (MS Office/Libre Office)\n\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isSupportedImageFile)(file) && !data.spreadsheet) {\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n\n if (this.props.onPaste) {\n try {\n if ((yield this.props.onPaste(data, event)) === false) {\n return;\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n if (data.errorMessage) {\n this.setState({\n errorMessage: data.errorMessage\n });\n } else if (data.spreadsheet && !isPlainPaste) {\n this.setState({\n pasteDialog: {\n data: data.spreadsheet,\n shown: true\n }\n });\n } else if (data.elements) {\n const elements = data.programmaticAPI ? (0,_data_transform__WEBPACK_IMPORTED_MODULE_60__.convertToExcalidrawElements)(data.elements) : data.elements; // TODO remove formatting from elements if isPlainPaste\n\n this.addElementsFromPasteOrLibrary({\n elements,\n files: data.files || null,\n position: \"cursor\",\n retainSeed: isPlainPaste\n });\n } else if (data.text) {\n const maybeUrl = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.extractSrc)(data.text);\n\n if (!isPlainPaste && (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.embeddableURLValidator)(maybeUrl, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(maybeUrl) || ((_e = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)(maybeUrl)) === null || _e === void 0 ? void 0 : _e.type) === \"video\")) {\n const embeddable = this.insertEmbeddableElement({\n sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(maybeUrl)\n });\n\n if (embeddable) {\n this.setState({\n selectedElementIds: {\n [embeddable.id]: true\n }\n });\n }\n\n return;\n }\n\n this.addTextFromPaste(data.text, isPlainPaste);\n }\n\n this.setActiveTool({\n type: \"selection\"\n });\n event === null || event === void 0 ? void 0 : event.preventDefault();\n }));\n\n this.addElementsFromPasteOrLibrary = opts => {\n const elements = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restoreElements)(opts.elements, null, undefined);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(elements);\n const elementsCenterX = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(minX, maxX) / 2;\n const elementsCenterY = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(minY, maxY) / 2;\n const clientX = typeof opts.position === \"object\" ? opts.position.clientX : opts.position === \"cursor\" ? this.lastViewportPosition.x : this.state.width / 2 + this.state.offsetLeft;\n const clientY = typeof opts.position === \"object\" ? opts.position.clientY : opts.position === \"cursor\" ? this.lastViewportPosition.y : this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const dx = x - elementsCenterX;\n const dy = y - elementsCenterY;\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(dx, dy, this.state.gridSize);\n const newElements = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.duplicateElements)(elements.map(element => {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n x: element.x + gridX - minX,\n y: element.y + gridY - minY\n });\n }), {\n randomizeSeed: !opts.retainSeed\n });\n const nextElements = [...this.scene.getElementsIncludingDeleted(), ...newElements];\n this.scene.replaceAllElements(nextElements);\n newElements.forEach(newElement => {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(newElement) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(newElement)) {\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerElement)(newElement);\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.redrawTextBoundingBox)(newElement, container);\n }\n });\n\n if (opts.files) {\n this.files = Object.assign(Object.assign({}, this.files), opts.files);\n }\n\n this.history.resumeRecording();\n const nextElementsToSelect = (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.excludeElementsInFramesFromSelection)(newElements);\n this.setState(Object.assign(Object.assign(Object.assign({}, this.state), {\n // keep sidebar (presumably the library) open if it's docked and\n // can fit.\n //\n // Note, we should close the sidebar only if we're dropping items\n // from library, not when pasting from clipboard. Alas.\n openSidebar: this.state.openSidebar && this.device.canDeviceFitSidebar && _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.get(_Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_61__.isSidebarDockedAtom) ? this.state.openSidebar : null\n }), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: null,\n selectedElementIds: nextElementsToSelect.reduce((acc, element) => {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(element)) {\n acc[element.id] = true;\n }\n\n return acc;\n }, {})\n }, this.scene.getNonDeletedElements(), this.state, this)), () => {\n if (opts.files) {\n this.addNewImagesToImageCache();\n }\n });\n this.setActiveTool({\n type: \"selection\"\n });\n };\n\n this.setAppState = (state, callback) => {\n this.setState(state, callback);\n };\n\n this.removePointer = event => {\n if (touchTimeout) {\n this.resetContextMenuTimer();\n }\n\n gesture.pointers.delete(event.pointerId);\n };\n\n this.toggleLock = (source = \"ui\") => {\n if (!this.state.activeTool.locked) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", \"toggleLock\", `${source} (${this.device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n this.setState(prevState => {\n return {\n activeTool: Object.assign(Object.assign(Object.assign({}, prevState.activeTool), (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, prevState.activeTool.locked ? {\n type: \"selection\"\n } : prevState.activeTool)), {\n locked: !prevState.activeTool.locked\n })\n };\n });\n };\n\n this.updateFrameRendering = opts => {\n this.setState(prevState => {\n var _a, _b, _c, _d;\n\n const next = typeof opts === \"function\" ? opts(prevState.frameRendering) : opts;\n return {\n frameRendering: {\n enabled: (_a = next === null || next === void 0 ? void 0 : next.enabled) !== null && _a !== void 0 ? _a : prevState.frameRendering.enabled,\n clip: (_b = next === null || next === void 0 ? void 0 : next.clip) !== null && _b !== void 0 ? _b : prevState.frameRendering.clip,\n name: (_c = next === null || next === void 0 ? void 0 : next.name) !== null && _c !== void 0 ? _c : prevState.frameRendering.name,\n outline: (_d = next === null || next === void 0 ? void 0 : next.outline) !== null && _d !== void 0 ? _d : prevState.frameRendering.outline\n }\n };\n });\n };\n\n this.togglePenMode = () => {\n this.setState(prevState => {\n return {\n penMode: !prevState.penMode\n };\n });\n };\n\n this.onHandToolToggle = () => {\n this.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleHandTool);\n };\n /**\n * Zooms on canvas viewport center\n */\n\n\n this.zoomCanvas = (\n /** decimal fraction between 0.1 (10% zoom) and 30 (3000% zoom) */\n value) => {\n this.setState(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: this.state.width / 2 + this.state.offsetLeft,\n viewportY: this.state.height / 2 + this.state.offsetTop,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(value)\n }, this.state)));\n };\n\n this.cancelInProgresAnimation = null;\n\n this.scrollToContent = (target = this.scene.getNonDeletedElements(), opts) => {\n var _a, _b;\n\n (_a = this.cancelInProgresAnimation) === null || _a === void 0 ? void 0 : _a.call(this); // convert provided target into ExcalidrawElement[] if necessary\n\n const targetElements = Array.isArray(target) ? target : [target];\n let zoom = this.state.zoom;\n let scrollX = this.state.scrollX;\n let scrollY = this.state.scrollY;\n\n if ((opts === null || opts === void 0 ? void 0 : opts.fitToContent) || (opts === null || opts === void 0 ? void 0 : opts.fitToViewport)) {\n const {\n appState\n } = (0,_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.zoomToFit)({\n targetElements,\n appState: this.state,\n fitToViewport: !!(opts === null || opts === void 0 ? void 0 : opts.fitToViewport),\n viewportZoomFactor: opts === null || opts === void 0 ? void 0 : opts.viewportZoomFactor\n });\n zoom = appState.zoom;\n scrollX = appState.scrollX;\n scrollY = appState.scrollY;\n } else {\n // compute only the viewport location, without any zoom adjustment\n const scroll = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.calculateScrollCenter)(targetElements, this.state);\n scrollX = scroll.scrollX;\n scrollY = scroll.scrollY;\n } // when animating, we use RequestAnimationFrame to prevent the animation\n // from slowing down other processes\n\n\n if (opts === null || opts === void 0 ? void 0 : opts.animate) {\n const origScrollX = this.state.scrollX;\n const origScrollY = this.state.scrollY;\n const origZoom = this.state.zoom.value;\n const cancel = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.easeToValuesRAF)({\n fromValues: {\n scrollX: origScrollX,\n scrollY: origScrollY,\n zoom: origZoom\n },\n toValues: {\n scrollX,\n scrollY,\n zoom: zoom.value\n },\n interpolateValue: (from, to, progress, key) => {\n // for zoom, use different easing\n if (key === \"zoom\") {\n return from * Math.pow(to / from, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.easeOut)(progress));\n } // handle using default\n\n\n return undefined;\n },\n onStep: ({\n scrollX,\n scrollY,\n zoom\n }) => {\n this.setState({\n scrollX,\n scrollY,\n zoom: {\n value: zoom\n }\n });\n },\n onStart: () => {\n this.setState({\n shouldCacheIgnoreZoom: true\n });\n },\n onEnd: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n onCancel: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n duration: (_b = opts === null || opts === void 0 ? void 0 : opts.duration) !== null && _b !== void 0 ? _b : 500\n });\n\n this.cancelInProgresAnimation = () => {\n cancel();\n this.cancelInProgresAnimation = null;\n };\n } else {\n this.setState({\n scrollX,\n scrollY,\n zoom\n });\n }\n };\n /** use when changing scrollX/scrollY/zoom based on user interaction */\n\n\n this.translateCanvas = state => {\n var _a;\n\n (_a = this.cancelInProgresAnimation) === null || _a === void 0 ? void 0 : _a.call(this);\n this.setState(state);\n };\n\n this.setToast = toast => {\n this.setState({\n toast\n });\n };\n\n this.restoreFileFromShare = () => __awaiter(this, void 0, void 0, function* () {\n try {\n const webShareTargetCache = yield caches.open(\"web-share-target\");\n const response = yield webShareTargetCache.match(\"shared-file\");\n\n if (response) {\n const blob = yield response.blob();\n const file = new File([blob], blob.name || \"\", {\n type: blob.type\n });\n this.loadFileToCanvas(file, null);\n yield webShareTargetCache.delete(\"shared-file\");\n window.history.replaceState(null, _constants__WEBPACK_IMPORTED_MODULE_12__.APP_NAME, window.location.pathname);\n }\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n });\n /** adds supplied files to existing files in the appState */\n\n\n this.addFiles = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(files => {\n const filesMap = files.reduce((acc, fileData) => {\n acc.set(fileData.id, fileData);\n return acc;\n }, new Map());\n this.files = Object.assign(Object.assign({}, this.files), Object.fromEntries(filesMap));\n this.scene.getNonDeletedElements().forEach(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && filesMap.has(element.fileId)) {\n this.imageCache.delete(element.fileId);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element);\n }\n });\n this.scene.informMutation();\n this.addNewImagesToImageCache();\n });\n this.updateScene = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(sceneData => {\n if (sceneData.commitToHistory) {\n this.history.resumeRecording();\n }\n\n if (sceneData.appState) {\n this.setState(sceneData.appState);\n }\n\n if (sceneData.elements) {\n this.scene.replaceAllElements(sceneData.elements);\n }\n\n if (sceneData.collaborators) {\n this.setState({\n collaborators: sceneData.collaborators\n });\n }\n });\n\n this.onSceneUpdated = () => {\n this.setState({});\n };\n /**\n * @returns whether the menu was toggled on or off\n */\n\n\n this.toggleSidebar = ({\n name,\n tab,\n force\n }) => {\n var _a;\n\n let nextName;\n\n if (force === undefined) {\n nextName = ((_a = this.state.openSidebar) === null || _a === void 0 ? void 0 : _a.name) === name ? null : name;\n } else {\n nextName = force ? name : null;\n }\n\n this.setState({\n openSidebar: nextName ? {\n name: nextName,\n tab\n } : null\n });\n return !!nextName;\n };\n\n this.updateCurrentCursorPosition = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n this.lastViewportPosition.x = event.clientX;\n this.lastViewportPosition.y = event.clientY;\n }); // Input handling\n\n this.onKeyDown = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n // normalize `event.key` when CapsLock is pressed #2372\n if (\"Proxy\" in window && (!event.shiftKey && /^[A-Z]$/.test(event.key) || event.shiftKey && /^[a-z]$/.test(event.key))) {\n event = new Proxy(event, {\n get(ev, prop) {\n const value = ev[prop];\n\n if (typeof value === \"function\") {\n // fix for Proxies hijacking `this`\n return value.bind(ev);\n }\n\n return prop === \"key\" ? // CapsLock inverts capitalization based on ShiftKey, so invert\n // it back\n event.shiftKey ? ev.key.toUpperCase() : ev.key.toLowerCase() : value;\n }\n\n });\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.V) {\n IS_PLAIN_PASTE = event.shiftKey;\n clearTimeout(IS_PLAIN_PASTE_TIMER); // reset (100ms to be safe that we it runs after the ensuing\n // paste event). Though, technically unnecessary to reset since we\n // (re)set the flag before each paste event.\n\n IS_PLAIN_PASTE_TIMER = window.setTimeout(() => {\n IS_PLAIN_PASTE = false;\n }, 100);\n } // prevent browser zoom in input fields\n\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target)) {\n if (event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.MINUS || event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.EQUAL) {\n event.preventDefault();\n return;\n }\n } // bail if\n\n\n if ( // inside an input\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target) && // unless pressing escape (finalize action)\n event.key !== _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || // or unless using arrows (to move between buttons)\n (0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key) && (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isInputLike)(event.target)) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.QUESTION_MARK) {\n this.setState({\n openDialog: \"help\"\n });\n return;\n } else if (event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.E && event.shiftKey && event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n this.setState({\n openDialog: \"imageExport\"\n });\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_UP || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n let offset = (event.shiftKey ? this.state.width : this.state.height) / this.state.zoom.value;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n offset = -offset;\n }\n\n if (event.shiftKey) {\n this.translateCanvas(state => ({\n scrollX: state.scrollX + offset\n }));\n } else {\n this.translateCanvas(state => ({\n scrollY: state.scrollY + offset\n }));\n }\n }\n\n if (this.actionManager.handleKeyDown(event)) {\n return;\n }\n\n if (this.state.viewModeEnabled) {\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: false\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n const step = this.state.gridSize && (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT : this.state.gridSize) || (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_SHIFT_TRANSLATE_AMOUNT : _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT);\n let offsetX = 0;\n let offsetY = 0;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_LEFT) {\n offsetX = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_RIGHT) {\n offsetX = step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_UP) {\n offsetY = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_DOWN) {\n offsetY = step;\n }\n\n const selectedElements = this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n });\n selectedElements.forEach(element => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: element.x + offsetX,\n y: element.y + offsetY\n });\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element, {\n simultaneouslyUpdated: selectedElements\n });\n });\n this.maybeSuggestBindingForAll(selectedElements);\n event.preventDefault();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n const selectedElement = selectedElements[0];\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElement)) {\n if (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id) {\n this.history.resumeRecording();\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElement, this.scene)\n });\n }\n }\n } else if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.isValidTextContainer)(selectedElement)) {\n let container;\n\n if (!(0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement)) {\n container = selectedElement;\n }\n\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerCenter)(selectedElement, this.state);\n const sceneX = midPoint.x;\n const sceneY = midPoint.y;\n this.startTextEditing({\n sceneX,\n sceneY,\n container\n });\n event.preventDefault();\n return;\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameElement)(selectedElement)) {\n this.setState({\n editingFrame: selectedElement.id\n });\n }\n }\n } else if (!event.ctrlKey && !event.altKey && !event.metaKey && this.state.draggingElement === null) {\n const shape = (0,_shapes__WEBPACK_IMPORTED_MODULE_32__.findShapeByKey)(event.key);\n\n if (shape) {\n if (this.state.activeTool.type !== shape) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", shape, `keyboard (${this.device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n this.setActiveTool({\n type: shape\n });\n event.stopPropagation();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.Q) {\n this.toggleLock(\"keyboard\");\n event.stopPropagation();\n }\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE && gesture.pointers.size === 0) {\n isHoldingSpace = true;\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n event.preventDefault();\n }\n\n if ((event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (this.state.activeTool.type === \"selection\" && !selectedElements.length) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && ((0,_scene__WEBPACK_IMPORTED_MODULE_29__.hasBackground)(this.state.activeTool.type) || selectedElements.some(element => (0,_scene__WEBPACK_IMPORTED_MODULE_29__.hasBackground)(element.type)))) {\n this.setState({\n openPopup: \"elementBackground\"\n });\n event.stopPropagation();\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) {\n this.setState({\n openPopup: \"elementStroke\"\n });\n event.stopPropagation();\n }\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.BACKSPACE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.DELETE)) {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__.activeConfirmDialogAtom, \"clearCanvas\");\n } // eye dropper\n // -----------------------------------------------------------------------\n\n\n const lowerCased = event.key.toLocaleLowerCase();\n const isPickingStroke = lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S && event.shiftKey;\n const isPickingBackground = event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.I || lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && event.shiftKey;\n\n if (isPickingStroke || isPickingBackground) {\n this.openEyeDropper({\n type: isPickingStroke ? \"stroke\" : \"background\"\n });\n } // -----------------------------------------------------------------------\n\n });\n this.onWheel = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n // prevent browser pinch zoom on DOM elements\n if (!(event.target instanceof HTMLCanvasElement) && event.ctrlKey) {\n event.preventDefault();\n }\n });\n this.onKeyUp = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE) {\n if (this.state.viewModeEnabled) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (this.state.activeTool.type === \"selection\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n isHoldingSpace = false;\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: true\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) ? (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindSelectedElements)(selectedElements) : (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.unbindLinearElements)(selectedElements);\n this.setState({\n suggestedBindings: []\n });\n }\n });\n\n this.setActiveTool = tool => {\n const nextActiveTool = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, tool);\n\n if (nextActiveTool.type === \"hand\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (!isHoldingSpace) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_33__.isToolIcon)(document.activeElement)) {\n this.focusContainer();\n }\n\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElementType)(nextActiveTool.type)) {\n this.setState({\n suggestedBindings: []\n });\n }\n\n if (nextActiveTool.type === \"image\") {\n this.onImageAction();\n }\n\n if (nextActiveTool.type !== \"selection\") {\n this.setState({\n activeTool: nextActiveTool,\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } else {\n this.setState({\n activeTool: nextActiveTool,\n activeEmbeddable: null\n });\n }\n };\n\n this.setCursor = cursor => {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, cursor);\n };\n\n this.resetCursor = () => {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n };\n /**\n * returns whether user is making a gesture with >= 2 fingers (points)\n * on o touch screen (not on a trackpad). Currently only relates to Darwin\n * (iOS/iPadOS,MacOS), but may work on other devices in the future if\n * GestureEvent is standardized.\n */\n\n\n this.isTouchScreenMultiTouchGesture = () => {\n // we don't want to deselect when using trackpad, and multi-point gestures\n // only work on touch screens, so checking for >= pointers means we're on a\n // touchscreen\n return gesture.pointers.size >= 2;\n }; // fires only on Safari\n\n\n this.onGestureStart = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault(); // we only want to deselect on touch screens because user may have selected\n // elements by mistake while zooming\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n\n gesture.initialScale = this.state.zoom.value;\n }); // fires only on Safari\n\n this.onGestureChange = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault(); // onGestureChange only has zoom factor but not the center.\n // If we're on iPad or iPhone, then we recognize multi-touch and will\n // zoom in at the right location in the touchmove handler\n // (handleCanvasPointerMove).\n //\n // On Macbook trackpad, we don't have those events so will zoom in at the\n // current location instead.\n //\n // As such, bail from this handler on touch devices.\n\n if (this.isTouchScreenMultiTouchGesture()) {\n return;\n }\n\n const initialScale = gesture.initialScale;\n\n if (initialScale) {\n this.setState(state => Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(initialScale * event.scale)\n }, state)));\n }\n }); // fires only on Safari\n\n this.onGestureEnd = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault(); // reselect elements only on touch screens (see onGestureStart)\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n }\n\n gesture.initialScale = null;\n });\n\n this.startTextEditing = ({\n sceneX,\n sceneY,\n insertAtParentCenter = true,\n container\n }) => {\n var _a, _b;\n\n let shouldBindToContainer = false;\n let parentCenterPosition = insertAtParentCenter && this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n\n if (container && parentCenterPosition) {\n const boundTextElementToContainer = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getBoundTextElement)(container);\n\n if (!boundTextElementToContainer) {\n shouldBindToContainer = true;\n }\n }\n\n let existingTextElement = null;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElements[0])) {\n existingTextElement = selectedElements[0];\n } else if (container) {\n existingTextElement = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getBoundTextElement)(selectedElements[0]);\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n\n const fontFamily = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.fontFamily) || this.state.currentItemFontFamily;\n const lineHeight = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.lineHeight) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getDefaultLineHeight)(fontFamily);\n const fontSize = this.state.currentItemFontSize;\n\n if (!existingTextElement && shouldBindToContainer && container && !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(container)) {\n const fontString = {\n fontSize,\n fontFamily\n };\n const minWidth = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getApproxMinLineWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_33__.getFontString)(fontString), lineHeight);\n const minHeight = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getApproxMinLineHeight)(fontSize, lineHeight);\n const newHeight = Math.max(container.height, minHeight);\n const newWidth = Math.max(container.width, minWidth);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n height: newHeight,\n width: newWidth\n });\n sceneX = container.x + newWidth / 2;\n sceneY = container.y + newHeight / 2;\n\n if (parentCenterPosition) {\n parentCenterPosition = this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n }\n }\n\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: sceneX,\n y: sceneY\n });\n const element = existingTextElement ? existingTextElement : (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)({\n x: parentCenterPosition ? parentCenterPosition.elementCenterX : sceneX,\n y: parentCenterPosition ? parentCenterPosition.elementCenterY : sceneY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text: \"\",\n fontSize,\n fontFamily,\n textAlign: parentCenterPosition ? \"center\" : this.state.currentItemTextAlign,\n verticalAlign: parentCenterPosition ? _constants__WEBPACK_IMPORTED_MODULE_12__.VERTICAL_ALIGN.MIDDLE : _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n containerId: shouldBindToContainer ? container === null || container === void 0 ? void 0 : container.id : undefined,\n groupIds: (_a = container === null || container === void 0 ? void 0 : container.groupIds) !== null && _a !== void 0 ? _a : [],\n lineHeight,\n angle: (_b = container === null || container === void 0 ? void 0 : container.angle) !== null && _b !== void 0 ? _b : 0,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n\n if (!existingTextElement && shouldBindToContainer && container) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: element.id\n })\n });\n }\n\n this.setState({\n editingElement: element\n });\n\n if (!existingTextElement) {\n if (container && shouldBindToContainer) {\n const containerIndex = this.scene.getElementIndex(container.id);\n this.scene.insertElementAtIndex(element, containerIndex + 1);\n } else {\n this.scene.addNewElement(element);\n }\n }\n\n this.setState({\n editingElement: element\n });\n this.handleTextWysiwyg(element, {\n isExistingElement: !!existingTextElement\n });\n };\n\n this.handleCanvasDoubleClick = event => {\n // case: double-clicking with arrow/line tool selected would both create\n // text and enter multiElement mode\n if (this.state.multiElement) {\n return;\n } // we should only be able to double click when mode is selection\n\n\n if (this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0])) {\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id)) {\n this.history.resumeRecording();\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElements[0], this.scene)\n });\n return;\n } else if (this.state.editingLinearElement && this.state.editingLinearElement.elementId === selectedElements[0].id) {\n return;\n }\n }\n\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n let {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedGroupIds = (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIds)(this.state);\n\n if (selectedGroupIds.length > 0) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n const selectedGroupId = hitElement && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIdForElement)(hitElement, this.state.selectedGroupIds);\n\n if (selectedGroupId) {\n this.setState(prevState => Object.assign(Object.assign({}, prevState), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: selectedGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)));\n return;\n }\n }\n\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.viewModeEnabled) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement)) {\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"active\"\n }\n });\n return;\n }\n\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getTextBindableContainerAtPosition)(this.scene.getNonDeletedElements(), this.state, sceneX, sceneY);\n\n if (container) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(container) || !(0,_utils__WEBPACK_IMPORTED_MODULE_33__.isTransparent)(container.backgroundColor) || (0,_element_collision__WEBPACK_IMPORTED_MODULE_44__.isHittingElementNotConsideringBoundingBox)(container, this.state, this.frameNameBoundsCache, [sceneX, sceneY])) {\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerCenter)(container, this.state);\n sceneX = midPoint.x;\n sceneY = midPoint.y;\n }\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container\n });\n }\n };\n\n this.getElementLinkAtPosition = (scenePointer, hitElement) => {\n // Reversing so we traverse the elements in decreasing order\n // of z-index\n const elements = this.scene.getNonDeletedElements().slice().reverse();\n let hitElementIndex = Infinity;\n return elements.find((element, index) => {\n if (hitElement && element.id === hitElement.id) {\n hitElementIndex = index;\n }\n\n return element.link && index <= hitElementIndex && (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLink)(element, this.state, [scenePointer.x, scenePointer.y], this.device.isMobile);\n });\n };\n\n this.redirectToLink = (event, isTouchScreen) => {\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(this.lastPointerDown.clientX, this.lastPointerDown.clientY, this.lastPointerUp.clientX, this.lastPointerUp.clientY);\n\n if (!this.hitLinkElement || // For touch screen allow dragging threshold else strict check\n isTouchScreen && draggedDistance > _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD || !isTouchScreen && draggedDistance !== 0) {\n return;\n }\n\n const lastPointerDownCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(this.lastPointerDown, this.state);\n const lastPointerDownHittingLinkIcon = (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLink)(this.hitLinkElement, this.state, [lastPointerDownCoords.x, lastPointerDownCoords.y], this.device.isMobile);\n const lastPointerUpCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(this.lastPointerUp, this.state);\n const lastPointerUpHittingLinkIcon = (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLink)(this.hitLinkElement, this.state, [lastPointerUpCoords.x, lastPointerUpCoords.y], this.device.isMobile);\n\n if (lastPointerDownHittingLinkIcon && lastPointerUpHittingLinkIcon) {\n let url = this.hitLinkElement.link;\n\n if (url) {\n url = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(url);\n let customEvent;\n\n if (this.props.onLinkOpen) {\n customEvent = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.wrapEvent)(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.EXCALIDRAW_LINK, event.nativeEvent);\n this.props.onLinkOpen(Object.assign(Object.assign({}, this.hitLinkElement), {\n link: url\n }), customEvent);\n }\n\n if (!(customEvent === null || customEvent === void 0 ? void 0 : customEvent.defaultPrevented)) {\n const target = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.isLocalLink)(url) ? \"_self\" : \"_blank\";\n const newWindow = window.open(undefined, target); // https://mathiasbynens.github.io/rel-noopener/\n\n if (newWindow) {\n newWindow.opener = null;\n newWindow.location = url;\n }\n }\n }\n }\n };\n\n this.getTopLayerFrameAtSceneCoords = sceneCoords => {\n const frames = this.scene.getNonDeletedFrames().filter(frame => (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)(sceneCoords, frame));\n return frames.length ? frames[frames.length - 1] : null;\n };\n\n this.handleCanvasPointerMove = event => {\n var _a, _b;\n\n this.savePointer(event.clientX, event.clientY, this.state.cursorButton);\n\n if (gesture.pointers.has(event.pointerId)) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n }\n\n const initialScale = gesture.initialScale;\n\n if (gesture.pointers.size === 2 && gesture.lastCenter && initialScale && gesture.initialDistance) {\n const center = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n const deltaX = center.x - gesture.lastCenter.x;\n const deltaY = center.y - gesture.lastCenter.y;\n gesture.lastCenter = center;\n const distance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n const scaleFactor = this.state.activeTool.type === \"freedraw\" && this.state.penMode ? 1 : distance / gesture.initialDistance;\n const nextZoom = scaleFactor ? (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(initialScale * scaleFactor) : this.state.zoom.value;\n this.setState(state => {\n const zoomState = (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: center.x,\n viewportY: center.y,\n nextZoom\n }, state);\n this.translateCanvas({\n zoom: zoomState.zoom,\n scrollX: zoomState.scrollX + deltaX / nextZoom,\n scrollY: zoomState.scrollY + deltaY / nextZoom,\n shouldCacheIgnoreZoom: true\n });\n });\n this.resetShouldCacheIgnoreZoomDebounced();\n } else {\n gesture.lastCenter = gesture.initialDistance = gesture.initialScale = null;\n }\n\n if (isHoldingSpace || isPanning || isDraggingScrollBar || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state)) {\n return;\n }\n\n const isPointerOverScrollBars = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop);\n const isOverScrollBar = isPointerOverScrollBars.isOverEither;\n\n if (!this.state.draggingElement && !this.state.multiElement) {\n if (isOverScrollBar) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const {\n x: scenePointerX,\n y: scenePointerY\n } = scenePointer;\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerMove(event, scenePointerX, scenePointerY, this.state);\n\n if (editingLinearElement && editingLinearElement !== this.state.editingLinearElement) {\n // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n editingLinearElement\n });\n });\n }\n\n if ((editingLinearElement === null || editingLinearElement === void 0 ? void 0 : editingLinearElement.lastUncommittedPoint) != null) {\n this.maybeSuggestBindingAtCursor(scenePointer);\n } else {\n // causes stack overflow if not sync\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n suggestedBindings: []\n });\n });\n }\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElementType)(this.state.activeTool.type)) {\n // Hovering with a selected tool or creating new linear element via click\n // and point\n const {\n draggingElement\n } = this.state;\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(draggingElement, false)) {\n this.maybeSuggestBindingsForLinearElementAtCoords(draggingElement, [scenePointer], this.state.startBoundElement);\n } else {\n this.maybeSuggestBindingAtCursor(scenePointer);\n }\n }\n\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state;\n const {\n x: rx,\n y: ry\n } = multiElement;\n const {\n points,\n lastCommittedPoint\n } = multiElement;\n const lastPoint = points[points.length - 1];\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n\n if (lastPoint === lastCommittedPoint) {\n // if we haven't yet created a temp point and we're beyond commit-zone\n // threshold, add a point\n if ((0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(scenePointerX - rx, scenePointerY - ry, lastPoint[0], lastPoint[1]) >= _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points, [scenePointerX - rx, scenePointerY - ry]]\n });\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER); // in this branch, we're inside the commit zone, and no uncommitted\n // point exists. Thus do nothing (don't add/remove points).\n }\n } else if (points.length > 2 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(scenePointerX - rx, scenePointerY - ry, lastCommittedPoint[0], lastCommittedPoint[1]) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: points.slice(0, -1)\n });\n } else {\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(scenePointerX, scenePointerY, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const [lastCommittedX, lastCommittedY] = (_a = multiElement === null || multiElement === void 0 ? void 0 : multiElement.lastCommittedPoint) !== null && _a !== void 0 ? _a : [0, 0];\n let dxFromLastCommitted = gridX - rx - lastCommittedX;\n let dyFromLastCommitted = gridY - ry - lastCommittedY;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event)) {\n ({\n width: dxFromLastCommitted,\n height: dyFromLastCommitted\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)( // actual coordinate of the last committed point\n lastCommittedX + rx, lastCommittedY + ry, // cursor-grid coordinate\n gridX, gridY));\n }\n\n if ((0,_math__WEBPACK_IMPORTED_MODULE_28__.isPathALoop)(points, this.state.zoom.value)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } // update last uncommitted point\n\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points.slice(0, -1), [lastCommittedX + dxFromLastCommitted, lastCommittedY + dyFromLastCommitted]]\n });\n }\n\n return;\n }\n\n const hasDeselectedButton = Boolean(event.buttons);\n\n if (hasDeselectedButton || this.state.activeTool.type !== \"selection\" && this.state.activeTool.type !== \"text\" && this.state.activeTool.type !== \"eraser\") {\n return;\n }\n\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !isOverScrollBar && !this.state.editingLinearElement) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType);\n\n if (elementWithTransformHandleType && elementWithTransformHandleType.transformHandleType) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)(elementWithTransformHandleType));\n return;\n }\n } else if (selectedElements.length > 1 && !isOverScrollBar) {\n const transformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType);\n\n if (transformHandleType) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)({\n transformHandleType\n }));\n return;\n }\n }\n\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n return;\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.showHyperlinkTooltip)(this.hitLinkElement, this.state);\n } else {\n (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.hideHyperlinkToolip)();\n\n if (hitElement && (hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement)) && this.state.selectedElementIds[hitElement.id] && !this.state.contextMenu && !this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: \"info\"\n });\n } else if (this.state.activeTool.type === \"text\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(hitElement) ? _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.TEXT : _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR);\n } else if (this.state.viewModeEnabled) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (isOverScrollBar) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n } else if (this.state.selectedLinearElement) {\n this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);\n } else if ( // if using cmd/ctrl, we're not dragging\n !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((hitElement || this.isHittingCommonBoundingBoxOfSelectedElements(scenePointer, selectedElements)) && !(hitElement === null || hitElement === void 0 ? void 0 : hitElement.locked)) {\n if (hitElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) && this.isEmbeddableCenter(hitElement, event, scenePointerX, scenePointerY)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"hover\"\n }\n });\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n\n if (((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\") {\n this.setState({\n activeEmbeddable: null\n });\n }\n }\n }\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n };\n\n this.handleEraser = (event, pointerDownState, scenePointer) => {\n const updateElementIds = elements => {\n elements.forEach(element => {\n if (element.locked) {\n return;\n }\n\n idsToUpdate.push(element.id);\n\n if (event.altKey) {\n if (pointerDownState.elementIdsToErase[element.id] && pointerDownState.elementIdsToErase[element.id].erase) {\n pointerDownState.elementIdsToErase[element.id].erase = false;\n }\n } else if (!pointerDownState.elementIdsToErase[element.id]) {\n pointerDownState.elementIdsToErase[element.id] = {\n erase: true,\n opacity: element.opacity\n };\n }\n });\n };\n\n const idsToUpdate = [];\n const distance = (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y, scenePointer.x, scenePointer.y);\n const threshold = 10 / this.state.zoom.value;\n const point = Object.assign({}, pointerDownState.lastCoords);\n let samplingInterval = 0;\n\n while (samplingInterval <= distance) {\n const hitElements = this.getElementsAtPosition(point.x, point.y);\n updateElementIds(hitElements); // Exit since we reached current point\n\n if (samplingInterval === distance) {\n break;\n } // Calculate next point in the line at a distance of sampling interval\n\n\n samplingInterval = Math.min(samplingInterval + threshold, distance);\n const distanceRatio = samplingInterval / distance;\n const nextX = (1 - distanceRatio) * point.x + distanceRatio * scenePointer.x;\n const nextY = (1 - distanceRatio) * point.y + distanceRatio * scenePointer.y;\n point.x = nextX;\n point.y = nextY;\n }\n\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n const id = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && idsToUpdate.includes(ele.containerId) ? ele.containerId : ele.id;\n\n if (idsToUpdate.includes(id)) {\n if (event.altKey) {\n if (pointerDownState.elementIdsToErase[id] && pointerDownState.elementIdsToErase[id].erase === false) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[id].opacity\n });\n }\n } else {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_READY_TO_ERASE_OPACITY\n });\n }\n }\n\n return ele;\n });\n this.scene.replaceAllElements(elements);\n pointerDownState.lastCoords.x = scenePointer.x;\n pointerDownState.lastCoords.y = scenePointer.y;\n }; // set touch moving for mobile context menu\n\n\n this.handleTouchMove = event => {\n invalidateContextMenu = true;\n };\n\n this.handleCanvasPointerDown = event => {\n var _a, _b; // since contextMenu options are potentially evaluated on each render,\n // and an contextMenu action may depend on selection state, we must\n // close the contextMenu before we update the selection on pointerDown\n // (e.g. resetting selection)\n\n\n if (this.state.contextMenu) {\n this.setState({\n contextMenu: null\n });\n }\n\n this.updateGestureOnPointerDown(event); // if dragging element is freedraw and another pointerdown event occurs\n // a second finger is on the screen\n // discard the freedraw element if it is very short because it is likely\n // just a spike, otherwise finalize the freedraw element when the second\n // finger is lifted\n\n if (event.pointerType === \"touch\" && this.state.draggingElement && this.state.draggingElement.type === \"freedraw\") {\n const element = this.state.draggingElement;\n this.updateScene(Object.assign(Object.assign({}, element.points.length < 10 ? {\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== element.id)\n } : {}), {\n appState: {\n draggingElement: null,\n editingElement: null,\n startBoundElement: null,\n suggestedBindings: [],\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.keys(this.state.selectedElementIds).filter(key => key !== element.id).reduce((obj, key) => {\n obj[key] = this.state.selectedElementIds[key];\n return obj;\n }, {}), this.state)\n }\n }));\n return;\n } // remove any active selection when we start to interact with canvas\n // (mainly, we care about removing selection outside the component which\n // would prevent our copy handling otherwise)\n\n\n const selection = document.getSelection();\n\n if (selection === null || selection === void 0 ? void 0 : selection.anchorNode) {\n selection.removeAllRanges();\n }\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices(event);\n this.maybeCleanupAfterMissingPointerUp(event); //fires only once, if pen is detected, penMode is enabled\n //the user can disable this by toggling the penMode button\n\n if (!this.state.penDetected && event.pointerType === \"pen\") {\n this.setState(prevState => {\n return {\n penMode: true,\n penDetected: true\n };\n });\n }\n\n if (!this.device.isTouchScreen && [\"pen\", \"touch\"].includes(event.pointerType)) {\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateObject)(this.device, {\n isTouchScreen: true\n });\n }\n\n if (isPanning) {\n return;\n }\n\n this.lastPointerDown = event;\n this.setState({\n lastPointerDownWith: event.pointerType,\n cursorButton: \"down\"\n });\n this.savePointer(event.clientX, event.clientY, \"down\");\n\n if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {\n return;\n } // only handle left mouse button or touch\n\n\n if (event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.TOUCH) {\n return;\n } // don't select while panning\n\n\n if (gesture.pointers.size > 1) {\n return;\n } // State for the duration of a pointer interaction, which starts with a\n // pointerDown event, ends with a pointerUp event (or another pointerDown)\n\n\n const pointerDownState = this.initialPointerDownState(event);\n this.setState({\n selectedElementsAreBeingDragged: false\n });\n\n if (this.handleDraggingScrollBar(event, pointerDownState)) {\n return;\n }\n\n this.clearSelectionIfNotUsingSelection();\n this.updateBindingEnabledOnPointerMove(event);\n\n if (this.handleSelectionOnPointerDown(event, pointerDownState)) {\n return;\n }\n\n const allowOnPointerDown = !this.state.penMode || event.pointerType !== \"touch\" || this.state.activeTool.type === \"selection\" || this.state.activeTool.type === \"text\" || this.state.activeTool.type === \"image\";\n\n if (!allowOnPointerDown) {\n return;\n }\n\n if (this.state.activeTool.type === \"text\") {\n this.handleTextOnPointerDown(event, pointerDownState);\n return;\n } else if (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\") {\n this.handleLinearElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"image\") {\n // reset image preview on pointerdown\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR); // retrieve the latest element as the state may be stale\n\n const pendingImageElement = this.state.pendingImageElementId && this.scene.getElement(this.state.pendingImageElementId);\n\n if (!pendingImageElement) {\n return;\n }\n\n this.setState({\n draggingElement: pendingImageElement,\n editingElement: pendingImageElement,\n pendingImageElementId: null,\n multiElement: null\n });\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(pendingImageElement, {\n x,\n y\n });\n } else if (this.state.activeTool.type === \"freedraw\") {\n this.handleFreeDrawElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"custom\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n } else if (this.state.activeTool.type === \"frame\") {\n this.createFrameElementOnPointerDown(pointerDownState);\n } else if (this.state.activeTool.type !== \"eraser\" && this.state.activeTool.type !== \"hand\") {\n this.createGenericElementOnPointerDown(this.state.activeTool.type, pointerDownState);\n }\n\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onPointerDown) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.activeTool, pointerDownState);\n const onPointerMove = this.onPointerMoveFromPointerDownHandler(pointerDownState);\n const onPointerUp = this.onPointerUpFromPointerDownHandler(pointerDownState);\n const onKeyDown = this.onKeyDownFromPointerDownHandler(pointerDownState);\n const onKeyUp = this.onKeyUpFromPointerDownHandler(pointerDownState);\n lastPointerUp = onPointerUp;\n\n if (!this.state.viewModeEnabled) {\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, onKeyDown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, onKeyUp);\n pointerDownState.eventListeners.onMove = onPointerMove;\n pointerDownState.eventListeners.onUp = onPointerUp;\n pointerDownState.eventListeners.onKeyUp = onKeyUp;\n pointerDownState.eventListeners.onKeyDown = onKeyDown;\n }\n };\n\n this.handleCanvasPointerUp = event => {\n var _a, _b;\n\n this.removePointer(event);\n this.lastPointerUp = event;\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: event.clientX,\n clientY: event.clientY\n }, this.state);\n const clicklength = event.timeStamp - ((_b = (_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a.timeStamp) !== null && _b !== void 0 ? _b : 0);\n\n if (this.device.isMobile && clicklength < 300) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) && this.isEmbeddableCenter(hitElement, event, scenePointer.x, scenePointer.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n return;\n }\n }\n\n if (this.device.isTouchScreen) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n if (clicklength < 300 && this.hitLinkElement.type === \"embeddable\" && !(0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLinkIcon)(this.hitLinkElement, this.state, [scenePointer.x, scenePointer.y])) {\n this.handleEmbeddableCenterClick(this.hitLinkElement);\n } else {\n this.redirectToLink(event, this.device.isTouchScreen);\n }\n } else if (this.state.viewModeEnabled) {\n this.setState({\n activeEmbeddable: null,\n selectedElementIds: {}\n });\n }\n };\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices = event => {\n // deal with opening context menu on touch devices\n if (event.pointerType === \"touch\") {\n invalidateContextMenu = false;\n\n if (touchTimeout) {\n // If there's already a touchTimeout, this means that there's another\n // touch down and we are doing another touch, so we shouldn't open the\n // context menu.\n invalidateContextMenu = true;\n } else {\n // open the context menu with the first touch's clientX and clientY\n // if the touch is not moving\n touchTimeout = window.setTimeout(() => {\n touchTimeout = 0;\n\n if (!invalidateContextMenu) {\n this.handleCanvasContextMenu(event);\n }\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.TOUCH_CTX_MENU_TIMEOUT);\n }\n }\n };\n\n this.resetContextMenuTimer = () => {\n clearTimeout(touchTimeout);\n touchTimeout = 0;\n invalidateContextMenu = false;\n }; // Returns whether the event is a panning\n\n\n this.handleCanvasPanUsingWheelOrSpaceDrag = event => {\n if (!(gesture.pointers.size <= 1 && (event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.WHEEL || event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && isHoldingSpace || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state) || this.state.viewModeEnabled)) || (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement)) {\n return false;\n }\n\n isPanning = true;\n event.preventDefault();\n let nextPastePrevented = false;\n const isLinux = /Linux/.test(window.navigator.platform);\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRABBING);\n let {\n clientX: lastX,\n clientY: lastY\n } = event;\n const onPointerMove = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdatesThrottled)(event => {\n const deltaX = lastX - event.clientX;\n const deltaY = lastY - event.clientY;\n lastX = event.clientX;\n lastY = event.clientY;\n /*\n * Prevent paste event if we move while middle clicking on Linux.\n * See issue #1383.\n */\n\n if (isLinux && !nextPastePrevented && (Math.abs(deltaX) > 1 || Math.abs(deltaY) > 1)) {\n nextPastePrevented = true;\n /* Prevent the next paste event */\n\n const preventNextPaste = event => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n event.stopPropagation();\n };\n /*\n * Reenable next paste in case of disabled middle click paste for\n * any reason:\n * - right click paste\n * - empty clipboard\n */\n\n\n const enableNextPaste = () => {\n setTimeout(() => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }, 100);\n };\n\n document.body.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }\n\n this.translateCanvas({\n scrollX: this.state.scrollX - deltaX / this.state.zoom.value,\n scrollY: this.state.scrollY - deltaY / this.state.zoom.value\n });\n });\n const teardown = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(lastPointerUp = () => {\n lastPointerUp = null;\n isPanning = false;\n\n if (!isHoldingSpace) {\n if (this.state.viewModeEnabled) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n onPointerMove.flush();\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove, {\n passive: true\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n return true;\n };\n\n this.clearSelectionIfNotUsingSelection = () => {\n if (this.state.activeTool.type !== \"selection\") {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n };\n /**\n * @returns whether the pointer event has been completely handled\n */\n\n\n this.handleSelectionOnPointerDown = (event, pointerDownState) => {\n var _a;\n\n if (this.state.activeTool.type === \"selection\") {\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !this.state.editingLinearElement) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);\n\n if (elementWithTransformHandleType != null) {\n this.setState({\n resizingElement: elementWithTransformHandleType.element\n });\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n }\n } else if (selectedElements.length > 1) {\n pointerDownState.resize.handleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);\n }\n\n if (pointerDownState.resize.handleType) {\n pointerDownState.resize.isResizing = true;\n pointerDownState.resize.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeOffsetXY)(pointerDownState.resize.handleType, selectedElements, pointerDownState.origin.x, pointerDownState.origin.y));\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0]) && selectedElements[0].points.length === 2) {\n pointerDownState.resize.arrowDirection = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeArrowDirection)(pointerDownState.resize.handleType, selectedElements[0]);\n }\n } else {\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerDown(event, this.state, this.history, pointerDownState.origin, linearElementEditor);\n\n if (ret.hitElement) {\n pointerDownState.hit.element = ret.hitElement;\n }\n\n if (ret.linearElementEditor) {\n this.setState({\n selectedLinearElement: ret.linearElementEditor\n });\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: ret.linearElementEditor\n });\n }\n }\n\n if (ret.didAddPoint) {\n return true;\n }\n } // hitElement may already be set above, so check first\n\n\n pointerDownState.hit.element = (_a = pointerDownState.hit.element) !== null && _a !== void 0 ? _a : this.getElementAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n\n if (pointerDownState.hit.element) {\n // Early return if pointer is hitting link icon\n const hitLinkElement = this.getElementLinkAtPosition({\n x: pointerDownState.origin.x,\n y: pointerDownState.origin.y\n }, pointerDownState.hit.element);\n\n if (hitLinkElement) {\n return false;\n }\n } // For overlapped elements one position may hit\n // multiple elements\n\n\n pointerDownState.hit.allHitElements = this.getElementsAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n const hitElement = pointerDownState.hit.element;\n const someHitElementIsSelected = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n\n if ((hitElement === null || !someHitElementIsSelected) && !event.shiftKey && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.clearSelection(hitElement);\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [this.state.editingLinearElement.elementId]: true\n }, this.state)\n }); // If we click on something\n } else if (hitElement != null) {\n // on CMD/CTRL, drill down to hit element regardless of groups etc.\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (!this.state.selectedElementIds[hitElement.id]) {\n pointerDownState.hit.wasAddedToSelection = true;\n }\n\n this.setState(prevState => Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.editGroupForSelectedElement)(prevState, hitElement)), {\n previousSelectedElementIds: this.state.selectedElementIds\n })); // mark as not completely handled so as to allow dragging etc.\n\n return false;\n } // deselect if item is selected\n // if shift is not clicked, this will always return true\n // otherwise, it will trigger selection based on current\n // state of the box\n\n\n if (!this.state.selectedElementIds[hitElement.id]) {\n // if we are currently editing a group, exiting editing mode and deselect the group.\n if (this.state.editingGroupId && !(0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, this.state.editingGroupId)) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } // Add hit element to selection. At this point if we're not holding\n // SHIFT the previously selected element(s) were deselected above\n // (make sure you use setState updater to use latest state)\n // With shift-selection, we want to make sure that frames and their containing\n // elements are not selected at the same time.\n\n\n if (!someHitElementIsSelected && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n });\n const previouslySelectedElements = [];\n Object.keys(prevState.selectedElementIds).forEach(id => {\n const element = this.scene.getElement(id);\n element && previouslySelectedElements.push(element);\n }); // if hitElement is frame, deselect all of its elements if they are selected\n\n if (hitElement.type === \"frame\") {\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameElements)(previouslySelectedElements, hitElement.id).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n } else if (hitElement.frameId) {\n // if hitElement is in a frame and its frame has been selected\n // disable selection for the given element\n if (nextSelectedElementIds[hitElement.frameId]) {\n delete nextSelectedElementIds[hitElement.id];\n }\n } else {\n // hitElement is neither a frame nor an element in a frame\n // but since hitElement could be in a group with some frames\n // this means selecting hitElement will have the frames selected as well\n // because we want to keep the invariant:\n // - frames and their elements are not selected at the same time\n // we deselect elements in those frames that were previously selected\n const groupIds = hitElement.groupIds;\n const framesInGroups = new Set(groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).filter(element => element.type === \"frame\").map(frame => frame.id));\n\n if (framesInGroups.size > 0) {\n previouslySelectedElements.forEach(element => {\n if (element.frameId && framesInGroups.has(element.frameId)) {\n // deselect element and groups containing the element\n delete nextSelectedElementIds[element.id];\n element.groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n }\n });\n }\n }\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n pointerDownState.hit.wasAddedToSelection = true;\n }\n }\n }\n\n this.setState({\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n }\n\n return false;\n };\n\n this.handleTextOnPointerDown = (event, pointerDownState) => {\n // if we're currently still editing text, clicking outside\n // should only finalize it, not create another (irrespective\n // of state.activeTool.locked)\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement)) {\n return;\n }\n\n let sceneX = pointerDownState.origin.x;\n let sceneY = pointerDownState.origin.y;\n const element = this.getElementAtPosition(sceneX, sceneY, {\n includeBoundTextElement: true\n }); // FIXME\n\n let container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getTextBindableContainerAtPosition)(this.scene.getNonDeletedElements(), this.state, sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(element)) {\n container = element;\n sceneX = element.x + element.width / 2;\n sceneY = element.y + element.height / 2;\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container\n });\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n\n if (!this.state.activeTool.locked) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n };\n\n this.handleFreeDrawElementOnPointerDown = (event, elementType, pointerDownState) => {\n // Begin a mark capture. This does not have to update state yet.\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, null);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFreeDrawElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: null,\n simulatePressure: event.pressure === 0.5,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n const pressures = element.simulatePressure ? element.pressures : [...element.pressures, event.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n points: [[0, 0]],\n pressures\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene);\n this.scene.addNewElement(element);\n this.setState({\n draggingElement: element,\n editingElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n }; //create rectangle element with youtube top left on nearest grid point width / hight 640/360\n\n\n this.insertEmbeddableElement = ({\n sceneX,\n sceneY,\n link\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)(link);\n\n if (!embedLink) {\n return;\n }\n\n if (embedLink.warning) {\n this.setToast({\n message: embedLink.warning,\n closable: true\n });\n }\n\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)({\n type: \"embeddable\",\n x: gridX,\n y: gridY,\n strokeColor: \"transparent\",\n backgroundColor: \"transparent\",\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: this.getCurrentItemRoundness(\"embeddable\"),\n opacity: this.state.currentItemOpacity,\n locked: false,\n width: embedLink.aspectRatio.w,\n height: embedLink.aspectRatio.h,\n link,\n validated: null\n });\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted(), element]);\n return element;\n };\n\n this.createImageElement = ({\n sceneX,\n sceneY\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newImageElement)({\n type: \"image\",\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: null,\n opacity: this.state.currentItemOpacity,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n return element;\n };\n\n this.handleLinearElementOnPointerDown = (event, elementType, pointerDownState) => {\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state; // finalize if completing a loop\n\n if (multiElement.type === \"line\" && (0,_math__WEBPACK_IMPORTED_MODULE_28__.isPathALoop)(multiElement.points, this.state.zoom.value)) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n const {\n x: rx,\n y: ry,\n lastCommittedPoint\n } = multiElement; // clicking inside commit zone → finalize arrow\n\n if (multiElement.points.length > 1 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(pointerDownState.origin.x - rx, pointerDownState.origin.y - ry, lastCommittedPoint[0], lastCommittedPoint[1]) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [multiElement.id]: true\n }), prevState)\n })); // clicking outside commit zone → update reference for last committed\n // point\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else {\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n /* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.\n If so, we want it to be null for start and \"arrow\" for end. If the linear item is not\n an arrow, we want it to be null for both. Otherwise, we want it to use the\n values from appState. */\n\n const {\n currentItemStartArrowhead,\n currentItemEndArrowhead\n } = this.state;\n const [startArrowhead, endArrowhead] = elementType === \"arrow\" ? [currentItemStartArrowhead, currentItemEndArrowhead] : [null, null];\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newLinearElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.state.currentItemRoundness === \"round\" ? {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null,\n startArrowhead,\n endArrowhead,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n points: [...element.points, [0, 0]]\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene);\n this.scene.addNewElement(element);\n this.setState({\n draggingElement: element,\n editingElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n }\n };\n\n this.createGenericElementOnPointerDown = (elementType, pointerDownState) => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const baseElementAttributes = {\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.getCurrentItemRoundness(elementType),\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n };\n let element;\n\n if (elementType === \"embeddable\") {\n element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)(Object.assign({\n type: \"embeddable\",\n validated: null\n }, baseElementAttributes));\n } else {\n element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newElement)(Object.assign({\n type: elementType\n }, baseElementAttributes));\n }\n\n if (element.type === \"selection\") {\n this.setState({\n selectionElement: element,\n draggingElement: element\n });\n } else {\n this.scene.addNewElement(element);\n this.setState({\n multiElement: null,\n draggingElement: element,\n editingElement: element\n });\n }\n };\n\n this.createFrameElementOnPointerDown = pointerDownState => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const frame = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFrameElement)(Object.assign({\n x: gridX,\n y: gridY,\n opacity: this.state.currentItemOpacity,\n locked: false\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE));\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted(), frame]);\n this.setState({\n multiElement: null,\n draggingElement: frame,\n editingElement: frame\n });\n };\n\n this.restoreReadyToEraseElements = pointerDownState => {\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n if (pointerDownState.elementIdsToErase[ele.id] && pointerDownState.elementIdsToErase[ele.id].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[ele.id].opacity\n });\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && pointerDownState.elementIdsToErase[ele.containerId] && pointerDownState.elementIdsToErase[ele.containerId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[ele.containerId].opacity\n });\n } else if (ele.frameId && pointerDownState.elementIdsToErase[ele.frameId] && pointerDownState.elementIdsToErase[ele.frameId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[ele.frameId].opacity\n });\n }\n\n return ele;\n });\n this.scene.replaceAllElements(elements);\n };\n\n this.eraseElements = pointerDownState => {\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n if (pointerDownState.elementIdsToErase[ele.id] && pointerDownState.elementIdsToErase[ele.id].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && pointerDownState.elementIdsToErase[ele.containerId] && pointerDownState.elementIdsToErase[ele.containerId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n } else if (ele.frameId && pointerDownState.elementIdsToErase[ele.frameId] && pointerDownState.elementIdsToErase[ele.frameId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n }\n\n return ele;\n });\n this.history.resumeRecording();\n this.scene.replaceAllElements(elements);\n };\n\n this.initializeImage = ({\n imageFile,\n imageElement: _imageElement,\n showCursorImagePreview = false\n }) => __awaiter(this, void 0, void 0, function* () {\n var _f, _g, _h, _j; // at this point this should be guaranteed image file, but we do this check\n // to satisfy TS down the line\n\n\n if (!(0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isSupportedImageFile)(imageFile)) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\"));\n }\n\n const mimeType = imageFile.type;\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, \"wait\");\n\n if (mimeType === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n imageFile = (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.SVGStringToFile)(yield (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.normalizeSVG)(yield imageFile.text()), imageFile.name);\n } catch (error) {\n console.warn(error);\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.svgImageInsertError\"));\n }\n } // generate image id (by default the file digest) before any\n // resizing/compression takes place to keep it more portable\n\n\n const fileId = yield ((_g = (_f = this.props).generateIdForFile) === null || _g === void 0 ? void 0 : _g.call(_f, imageFile)) || (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.generateIdFromFile)(imageFile);\n\n if (!fileId) {\n console.warn(\"Couldn't generate file id or the supplied `generateIdForFile` didn't resolve to one.\");\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\"));\n }\n\n const existingFileData = this.files[fileId];\n\n if (!(existingFileData === null || existingFileData === void 0 ? void 0 : existingFileData.dataURL)) {\n try {\n imageFile = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT\n });\n } catch (error) {\n console.error(\"error trying to resing image file on insertion\", error);\n }\n\n if (imageFile.size > _constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.fileTooBig\", {\n maxSize: `${Math.trunc(_constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES / 1024 / 1024)}MB`\n }));\n }\n }\n\n if (showCursorImagePreview) {\n const dataURL = (_h = this.files[fileId]) === null || _h === void 0 ? void 0 : _h.dataURL; // optimization so that we don't unnecessarily resize the original\n // full-size file for cursor preview\n // (it's much faster to convert the resized dataURL to File)\n\n const resizedFile = dataURL && (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.dataURLToFile)(dataURL);\n this.setImagePreviewCursor(resizedFile || imageFile);\n }\n\n const dataURL = ((_j = this.files[fileId]) === null || _j === void 0 ? void 0 : _j.dataURL) || (yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.getDataURL)(imageFile));\n const imageElement = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(_imageElement, {\n fileId\n }, false);\n return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {\n var _k;\n\n try {\n this.files = Object.assign(Object.assign({}, this.files), {\n [fileId]: {\n mimeType,\n id: fileId,\n dataURL,\n created: Date.now(),\n lastRetrieved: Date.now()\n }\n });\n const cachedImageData = this.imageCache.get(fileId);\n\n if (!cachedImageData) {\n this.addNewImagesToImageCache();\n yield this.updateImageCache([imageElement]);\n }\n\n if ((cachedImageData === null || cachedImageData === void 0 ? void 0 : cachedImageData.image) instanceof Promise) {\n yield cachedImageData.image;\n }\n\n if (this.state.pendingImageElementId !== imageElement.id && ((_k = this.state.draggingElement) === null || _k === void 0 ? void 0 : _k.id) !== imageElement.id) {\n this.initializeImageDimensions(imageElement, true);\n }\n\n resolve(imageElement);\n } catch (error) {\n console.error(error);\n reject(new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")));\n } finally {\n if (!showCursorImagePreview) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n }\n }\n }));\n });\n /**\n * inserts image into elements array and rerenders\n */\n\n\n this.insertImageElement = (imageElement, imageFile, showCursorImagePreview) => __awaiter(this, void 0, void 0, function* () {\n this.scene.addNewElement(imageElement);\n\n try {\n yield this.initializeImage({\n imageFile,\n imageElement,\n showCursorImagePreview\n });\n } catch (error) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n isDeleted: true\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n this.setState({\n errorMessage: error.message || (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")\n });\n }\n });\n\n this.setImagePreviewCursor = imageFile => __awaiter(this, void 0, void 0, function* () {\n // mustn't be larger than 128 px\n // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Basic_User_Interface/Using_URL_values_for_the_cursor_property\n const cursorImageSizePx = 96;\n const imagePreview = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: cursorImageSizePx\n });\n let previewDataURL = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.getDataURL)(imagePreview); // SVG cannot be resized via `resizeImageFile` so we resize by rendering to\n // a small canvas\n\n if (imageFile.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n const img = yield (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.loadHTMLImageElement)(previewDataURL);\n let height = Math.min(img.height, cursorImageSizePx);\n let width = height * (img.width / img.height);\n\n if (width > cursorImageSizePx) {\n width = cursorImageSizePx;\n height = width * (img.height / img.width);\n }\n\n const canvas = document.createElement(\"canvas\");\n canvas.height = height;\n canvas.width = width;\n const context = canvas.getContext(\"2d\");\n context.drawImage(img, 0, 0, width, height);\n previewDataURL = canvas.toDataURL(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg);\n }\n\n if (this.state.pendingImageElementId) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, `url(${previewDataURL}) 4 4, auto`);\n }\n });\n\n this.onImageAction = ({\n insertOnCanvasDirectly\n } = {\n insertOnCanvasDirectly: false\n }) => __awaiter(this, void 0, void 0, function* () {\n try {\n const clientX = this.state.width / 2 + this.state.offsetLeft;\n const clientY = this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const imageFile = yield (0,_data_filesystem__WEBPACK_IMPORTED_MODULE_42__.fileOpen)({\n description: \"Image\",\n extensions: Object.keys(_constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_MIME_TYPES)\n });\n const imageElement = this.createImageElement({\n sceneX: x,\n sceneY: y\n });\n\n if (insertOnCanvasDirectly) {\n this.insertImageElement(imageElement, imageFile);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } else {\n this.setState({\n pendingImageElementId: imageElement.id\n }, () => {\n this.insertImageElement(imageElement, imageFile,\n /* showCursorImagePreview */\n true);\n });\n }\n } catch (error) {\n if (error.name !== \"AbortError\") {\n console.error(error);\n } else {\n console.warn(error);\n }\n\n this.setState({\n pendingImageElementId: null,\n editingElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n }\n });\n\n this.initializeImageDimensions = (imageElement, forceNaturalSize = false) => {\n var _a;\n\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(imageElement) && ((_a = this.imageCache.get(imageElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n\n if (!image || image instanceof Promise) {\n if (imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const placeholderSize = 100 / this.state.zoom.value;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x: imageElement.x - placeholderSize / 2,\n y: imageElement.y - placeholderSize / 2,\n width: placeholderSize,\n height: placeholderSize\n });\n }\n\n return;\n }\n\n if (forceNaturalSize || // if user-created bounding box is below threshold, assume the\n // intention was to click instead of drag, and use the image's\n // intrinsic size\n imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const minHeight = Math.max(this.state.height - 120, 160); // max 65% of canvas height, clamped to <300px, vh - 120px>\n\n const maxHeight = Math.min(minHeight, Math.floor(this.state.height * 0.5) / this.state.zoom.value);\n const height = Math.min(image.naturalHeight, maxHeight);\n const width = height * (image.naturalWidth / image.naturalHeight); // add current imageElement width/height to account for previous centering\n // of the placeholder image\n\n const x = imageElement.x + imageElement.width / 2 - width / 2;\n const y = imageElement.y + imageElement.height / 2 - height / 2;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x,\n y,\n width,\n height\n });\n }\n };\n /** updates image cache, refreshing updated elements and/or setting status\n to error for images that fail during <img> element creation */\n\n\n this.updateImageCache = (elements, files = this.files) => __awaiter(this, void 0, void 0, function* () {\n const {\n updatedFiles,\n erroredFiles\n } = yield (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.updateImageCache)({\n imageCache: this.imageCache,\n fileIds: elements.map(element => element.fileId),\n files\n });\n\n if (updatedFiles.size || erroredFiles.size) {\n for (const element of elements) {\n if (updatedFiles.has(element.fileId)) {\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element);\n }\n }\n }\n\n if (erroredFiles.size) {\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().map(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && erroredFiles.has(element.fileId)) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n status: \"error\"\n });\n }\n\n return element;\n }));\n }\n\n return {\n updatedFiles,\n erroredFiles\n };\n });\n /** adds new images to imageCache and re-renders if needed */\n\n\n this.addNewImagesToImageCache = (imageElements = (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.getInitializedImageElements)(this.scene.getNonDeletedElements()), files = this.files) => __awaiter(this, void 0, void 0, function* () {\n const uncachedImageElements = imageElements.filter(element => !element.isDeleted && !this.imageCache.has(element.fileId));\n\n if (uncachedImageElements.length) {\n const {\n updatedFiles\n } = yield this.updateImageCache(uncachedImageElements, files);\n\n if (updatedFiles.size) {\n this.scene.informMutation();\n }\n }\n });\n /** generally you should use `addNewImagesToImageCache()` directly if you need\n * to render new images. This is just a failsafe */\n\n\n this.scheduleImageRefresh = lodash_throttle__WEBPACK_IMPORTED_MODULE_41___default()(() => {\n this.addNewImagesToImageCache();\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_RENDER_TIMEOUT);\n\n this.updateBindingEnabledOnPointerMove = event => {\n const shouldEnableBinding = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.shouldEnableBindingForPointerEvent)(event);\n\n if (this.state.isBindingEnabled !== shouldEnableBinding) {\n this.setState({\n isBindingEnabled: shouldEnableBinding\n });\n }\n };\n\n this.maybeSuggestBindingAtCursor = pointerCoords => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerCoords, this.scene);\n this.setState({\n suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : []\n });\n };\n\n this.maybeSuggestBindingsForLinearElementAtCoords = (linearElement,\n /** scene coords */\n pointerCoords, // During line creation the start binding hasn't been written yet\n // into `linearElement`\n oppositeBindingBoundElement) => {\n if (!pointerCoords.length) {\n return;\n }\n\n const suggestedBindings = pointerCoords.reduce((acc, coords) => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(coords, this.scene);\n\n if (hoveredBindableElement != null && !(0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isLinearElementSimpleAndAlreadyBound)(linearElement, oppositeBindingBoundElement === null || oppositeBindingBoundElement === void 0 ? void 0 : oppositeBindingBoundElement.id, hoveredBindableElement)) {\n acc.push(hoveredBindableElement);\n }\n\n return acc;\n }, []);\n this.setState({\n suggestedBindings\n });\n };\n\n this.handleInteractiveCanvasRef = canvas => {\n var _a, _b, _c; // canvas is null when unmounting\n\n\n if (canvas !== null) {\n this.interactiveCanvas = canvas; // -----------------------------------------------------------------------\n // NOTE wheel, touchstart, touchend events must be registered outside\n // of react because react binds them them passively (so we can't prevent\n // default on them)\n\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel);\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd); // -----------------------------------------------------------------------\n } else {\n (_a = this.interactiveCanvas) === null || _a === void 0 ? void 0 : _a.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel);\n (_b = this.interactiveCanvas) === null || _b === void 0 ? void 0 : _b.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n (_c = this.interactiveCanvas) === null || _c === void 0 ? void 0 : _c.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd);\n }\n };\n\n this.handleAppOnDrop = event => __awaiter(this, void 0, void 0, function* () {\n var _l, _m, _o, _p; // must be retrieved first, in the same frame\n\n\n const {\n file,\n fileHandle\n } = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.getFileFromEvent)(event);\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n\n try {\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isSupportedImageFile)(file)) {\n // first attempt to decode scene from the image if it's embedded\n // ---------------------------------------------------------------------\n if ((file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.png || (file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n const scene = yield (0,_data__WEBPACK_IMPORTED_MODULE_13__.loadFromBlob)(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n appState: Object.assign(Object.assign({}, scene.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n commitToHistory: true\n }));\n return;\n } catch (error) {\n if (error.name !== \"EncodingError\") {\n throw error;\n }\n }\n } // if no scene is embedded or we fail for whatever reason, fall back\n // to importing as regular image\n // ---------------------------------------------------------------------\n\n\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n } catch (error) {\n return this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n\n const libraryJSON = event.dataTransfer.getData(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib);\n\n if (libraryJSON && typeof libraryJSON === \"string\") {\n try {\n const libraryItems = (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.parseLibraryJSON)(libraryJSON);\n this.addElementsFromPasteOrLibrary({\n elements: (0,_data_library__WEBPACK_IMPORTED_MODULE_14__.distributeLibraryItemsOnSquareGrid)(libraryItems),\n position: event,\n files: null\n });\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n\n return;\n }\n\n if (file) {\n // atetmpt to parse an excalidraw/excalidrawlib file\n yield this.loadFileToCanvas(file, fileHandle);\n }\n\n if ((_m = (_l = event.dataTransfer) === null || _l === void 0 ? void 0 : _l.types) === null || _m === void 0 ? void 0 : _m.includes(\"text/plain\")) {\n const text = (_o = event.dataTransfer) === null || _o === void 0 ? void 0 : _o.getData(\"text\");\n\n if (text && (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.embeddableURLValidator)(text, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(text) || ((_p = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)(text)) === null || _p === void 0 ? void 0 : _p.type) === \"video\")) {\n const embeddable = this.insertEmbeddableElement({\n sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(text)\n });\n\n if (embeddable) {\n this.setState({\n selectedElementIds: {\n [embeddable.id]: true\n }\n });\n }\n }\n }\n });\n\n this.loadFileToCanvas = (file, fileHandle) => __awaiter(this, void 0, void 0, function* () {\n file = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.normalizeFile)(file);\n\n try {\n const ret = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.loadSceneOrLibraryFromBlob)(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);\n\n if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidraw) {\n this.setState({\n isLoading: true\n });\n this.syncActionResult(Object.assign(Object.assign({}, ret.data), {\n appState: Object.assign(Object.assign({}, ret.data.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n commitToHistory: true\n }));\n } else if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib) {\n yield this.library.updateLibrary({\n libraryItems: file,\n merge: true,\n openLibraryMenu: true\n }).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.importLibraryError\")\n });\n });\n }\n } catch (error) {\n this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n });\n\n this.handleCanvasContextMenu = event => {\n event.preventDefault();\n\n if ((\"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"touch\" || \"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"pen\" && // always allow if user uses a pen secondary button\n event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.SECONDARY) && this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const element = this.getElementAtPosition(x, y, {\n preferSelected: true,\n includeLockedElements: true\n });\n const selectedElements = this.scene.getSelectedElements(this.state);\n const isHittignCommonBoundBox = this.isHittingCommonBoundingBoxOfSelectedElements({\n x,\n y\n }, selectedElements);\n const type = element || isHittignCommonBoundBox ? \"element\" : \"canvas\";\n const container = this.excalidrawContainerRef.current;\n const {\n top: offsetTop,\n left: offsetLeft\n } = container.getBoundingClientRect();\n const left = event.clientX - offsetLeft;\n const top = event.clientY - offsetTop;\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"contextMenu\", \"openContextMenu\", type);\n this.setState(Object.assign(Object.assign({}, element && !this.state.selectedElementIds[element.id] ? Object.assign(Object.assign(Object.assign({}, this.state), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: this.state.editingGroupId,\n selectedElementIds: {\n [element.id]: true\n }\n }, this.scene.getNonDeletedElements(), this.state, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(element) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(element, this.scene) : null\n }) : this.state), {\n showHyperlinkPopup: false\n }), () => {\n this.setState({\n contextMenu: {\n top,\n left,\n items: this.getContextMenuItems(type)\n }\n });\n });\n };\n\n this.maybeDragNewGenericElement = (pointerDownState, event) => {\n var _a;\n\n const draggingElement = this.state.draggingElement;\n const pointerCoords = pointerDownState.lastCoords;\n\n if (!draggingElement) {\n return;\n }\n\n if (draggingElement.type === \"selection\" && this.state.activeTool.type !== \"eraser\") {\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)(draggingElement, this.state.activeTool.type, pointerDownState.origin.x, pointerDownState.origin.y, pointerCoords.x, pointerCoords.y, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.origin.x, pointerCoords.x), (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.origin.y, pointerCoords.y), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event));\n } else {\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(draggingElement) && ((_a = this.imageCache.get(draggingElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n const aspectRatio = image && !(image instanceof Promise) ? image.width / image.height : null;\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)(draggingElement, this.state.activeTool.type, pointerDownState.originInGrid.x, pointerDownState.originInGrid.y, gridX, gridY, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.originInGrid.x, gridX), (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.originInGrid.y, gridY), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(draggingElement) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event), aspectRatio);\n this.maybeSuggestBindingForAll([draggingElement]); // highlight elements that are to be added to frames on frames creation\n\n if (this.state.activeTool.type === \"frame\") {\n this.setState({\n elementsToHighlight: (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), draggingElement, this.state)\n });\n }\n }\n };\n\n this.maybeHandleResize = (pointerDownState, event) => {\n const selectedElements = this.scene.getSelectedElements(this.state);\n const selectedFrames = selectedElements.filter(element => element.type === \"frame\");\n const transformHandleType = pointerDownState.resize.handleType;\n\n if (selectedFrames.length > 0 && transformHandleType === \"rotation\") {\n return false;\n }\n\n this.setState({\n // TODO: rename this state field to \"isScaling\" to distinguish\n // it from the generic \"isResizing\" which includes scaling and\n // rotating\n isResizing: transformHandleType && transformHandleType !== \"rotation\",\n isRotating: transformHandleType === \"rotation\",\n activeEmbeddable: null\n });\n const pointerCoords = pointerDownState.lastCoords;\n const [resizeX, resizeY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x - pointerDownState.resize.offset.x, pointerCoords.y - pointerDownState.resize.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const frameElementsOffsetsMap = new Map();\n selectedFrames.forEach(frame => {\n const elementsInFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameElements)(this.scene.getNonDeletedElements(), frame.id);\n elementsInFrame.forEach(element => {\n frameElementsOffsetsMap.set(frame.id + element.id, {\n x: element.x - frame.x,\n y: element.y - frame.y\n });\n });\n });\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.transformElements)(pointerDownState, transformHandleType, selectedElements, pointerDownState.resize.arrowDirection, (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event), selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(selectedElements[0]) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {\n this.maybeSuggestBindingForAll(selectedElements);\n const elementsToHighlight = new Set();\n selectedFrames.forEach(frame => {\n const elementsInFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameElements)(this.scene.getNonDeletedElements(), frame.id); // keep elements' positions relative to their frames on frames resizing\n\n if (transformHandleType) {\n if (transformHandleType.includes(\"w\")) {\n elementsInFrame.forEach(element => {\n var _a, _b;\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: frame.x + (((_a = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _a === void 0 ? void 0 : _a.x) || 0),\n y: frame.y + (((_b = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _b === void 0 ? void 0 : _b.y) || 0)\n });\n });\n }\n\n if (transformHandleType.includes(\"n\")) {\n elementsInFrame.forEach(element => {\n var _a, _b;\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: frame.x + (((_a = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _a === void 0 ? void 0 : _a.x) || 0),\n y: frame.y + (((_b = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _b === void 0 ? void 0 : _b.y) || 0)\n });\n });\n }\n }\n\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), frame, this.state).forEach(element => elementsToHighlight.add(element));\n });\n this.setState({\n elementsToHighlight: [...elementsToHighlight]\n });\n return true;\n }\n\n return false;\n };\n\n this.getContextMenuItems = type => {\n const options = [];\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg); // canvas contextMenu\n // -------------------------------------------------------------------------\n\n if (type === \"canvas\") {\n if (this.state.viewModeEnabled) {\n return [...options, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_38__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats];\n }\n\n return [_actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg, _actions__WEBPACK_IMPORTED_MODULE_5__.copyText, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSelectAll, _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__.actionUnlockAllElements, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_38__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats];\n } // element contextMenu\n // -------------------------------------------------------------------------\n\n\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.copyText);\n\n if (this.state.viewModeEnabled) {\n return [_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, ...options];\n }\n\n return [_actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionSelectAllElementsInFrame, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionRemoveAllElementsFromFrame, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, ...options, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyStyles, _actions__WEBPACK_IMPORTED_MODULE_5__.actionPasteStyles, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionGroup, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUnbindText, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBindText, _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_57__.actionWrapTextInContainer, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUngroup, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionAddToLibrary, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendBackward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringForward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendToBack, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringToFront, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipHorizontal, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipVertical, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleLinearEditor, _actions__WEBPACK_IMPORTED_MODULE_5__.actionLink, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDuplicateSelection, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleElementLock, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDeleteSelected];\n };\n\n this.handleWheel = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault();\n\n if (isPanning) {\n return;\n }\n\n const {\n deltaX,\n deltaY\n } = event; // note that event.ctrlKey is necessary to handle pinch zooming\n\n if (event.metaKey || event.ctrlKey) {\n const sign = Math.sign(deltaY);\n const MAX_STEP = _constants__WEBPACK_IMPORTED_MODULE_12__.ZOOM_STEP * 100;\n const absDelta = Math.abs(deltaY);\n let delta = deltaY;\n\n if (absDelta > MAX_STEP) {\n delta = MAX_STEP * sign;\n }\n\n let newZoom = this.state.zoom.value - delta / 100; // increase zoom steps the more zoomed-in we are (applies to >100% only)\n\n newZoom += Math.log10(Math.max(1, this.state.zoom.value)) * -sign * // reduced amplification for small deltas (small movements on a trackpad)\n Math.min(1, absDelta / 20);\n this.translateCanvas(state => Object.assign(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(newZoom)\n }, state)), {\n shouldCacheIgnoreZoom: true\n }));\n this.resetShouldCacheIgnoreZoomDebounced();\n return;\n } // scroll horizontally when shift pressed\n\n\n if (event.shiftKey) {\n this.translateCanvas(({\n zoom,\n scrollX\n }) => ({\n // on Mac, shift+wheel tends to result in deltaX\n scrollX: scrollX - (deltaY || deltaX) / zoom.value\n }));\n return;\n }\n\n this.translateCanvas(({\n zoom,\n scrollX,\n scrollY\n }) => ({\n scrollX: scrollX - deltaX / zoom.value,\n scrollY: scrollY - deltaY / zoom.value\n }));\n });\n\n this.savePointer = (x, y, button) => {\n var _a, _b;\n\n if (!x || !y) {\n return;\n }\n\n const pointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: x,\n clientY: y\n }, this.state);\n\n if (isNaN(pointer.x) || isNaN(pointer.y)) {// sometimes the pointer goes off screen\n }\n\n (_b = (_a = this.props).onPointerUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, {\n pointer,\n button,\n pointersMap: gesture.pointers\n });\n };\n\n this.resetShouldCacheIgnoreZoomDebounced = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.debounce)(() => {\n if (!this.unmounted) {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n }\n }, 300);\n\n this.updateDOMRect = cb => {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n width,\n height,\n left: offsetLeft,\n top: offsetTop\n } = excalidrawContainer.getBoundingClientRect();\n const {\n width: currentWidth,\n height: currentHeight,\n offsetTop: currentOffsetTop,\n offsetLeft: currentOffsetLeft\n } = this.state;\n\n if (width === currentWidth && height === currentHeight && offsetLeft === currentOffsetLeft && offsetTop === currentOffsetTop) {\n if (cb) {\n cb();\n }\n\n return;\n }\n\n this.setState({\n width,\n height,\n offsetLeft,\n offsetTop\n }, () => {\n cb && cb();\n });\n }\n };\n\n this.refresh = () => {\n this.setState(Object.assign({}, this.getCanvasOffsets()));\n };\n\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)();\n const {\n excalidrawRef,\n viewModeEnabled = false,\n zenModeEnabled = false,\n gridModeEnabled = false,\n theme = defaultAppState.theme,\n name = defaultAppState.name\n } = props;\n this.state = Object.assign(Object.assign(Object.assign(Object.assign({}, defaultAppState), {\n theme,\n isLoading: true\n }), this.getCanvasOffsets()), {\n viewModeEnabled,\n zenModeEnabled,\n gridSize: gridModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.GRID_SIZE : null,\n name,\n width: window.innerWidth,\n height: window.innerHeight\n });\n this.id = (0,nanoid__WEBPACK_IMPORTED_MODULE_65__.nanoid)();\n this.library = new _data_library__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this);\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_30__[\"default\"]();\n this.canvas = document.createElement(\"canvas\");\n this.rc = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__[\"default\"].canvas(this.canvas);\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_63__.Renderer(this.scene);\n\n if (excalidrawRef) {\n const readyPromise = \"current\" in excalidrawRef && ((_a = excalidrawRef.current) === null || _a === void 0 ? void 0 : _a.readyPromise) || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resolvablePromise)();\n const api = {\n ready: true,\n readyPromise,\n updateScene: this.updateScene,\n updateLibrary: this.library.updateLibrary,\n addFiles: this.addFiles,\n resetScene: this.resetScene,\n getSceneElementsIncludingDeleted: this.getSceneElementsIncludingDeleted,\n history: {\n clear: this.resetHistory\n },\n scrollToContent: this.scrollToContent,\n getSceneElements: this.getSceneElements,\n getAppState: () => this.state,\n getFiles: () => this.files,\n refresh: this.refresh,\n setToast: this.setToast,\n id: this.id,\n setActiveTool: this.setActiveTool,\n setCursor: this.setCursor,\n resetCursor: this.resetCursor,\n updateFrameRendering: this.updateFrameRendering,\n toggleSidebar: this.toggleSidebar\n };\n\n if (typeof excalidrawRef === \"function\") {\n excalidrawRef(api);\n } else {\n excalidrawRef.current = api;\n }\n\n readyPromise.resolve(api);\n }\n\n this.excalidrawContainerValue = {\n container: this.excalidrawContainerRef.current,\n id: this.id\n };\n this.fonts = new _scene_Fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts({\n scene: this.scene,\n onSceneUpdated: this.onSceneUpdated\n });\n this.history = new _history__WEBPACK_IMPORTED_MODULE_24__[\"default\"]();\n this.actionManager = new _actions_manager__WEBPACK_IMPORTED_MODULE_7__.ActionManager(this.syncActionResult, () => this.state, () => this.scene.getElementsIncludingDeleted(), this);\n this.actionManager.registerAll(_actions_register__WEBPACK_IMPORTED_MODULE_8__.actions);\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createUndoAction)(this.history));\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createRedoAction)(this.history));\n }\n\n onWindowMessage(event) {\n if (event.origin !== \"https://player.vimeo.com\" && event.origin !== \"https://www.youtube.com\") {\n return;\n }\n\n let data = null;\n\n try {\n data = JSON.parse(event.data);\n } catch (e) {}\n\n if (!data) {\n return;\n }\n\n switch (event.origin) {\n case \"https://player.vimeo.com\":\n //Allowing for multiple instances of Excalidraw running in the window\n if (data.method === \"paused\") {\n let source = null;\n const iframes = document.body.querySelectorAll(\"iframe.excalidraw__embeddable\");\n\n if (!iframes) {\n break;\n }\n\n for (const iframe of iframes) {\n if (iframe.contentWindow === event.source) {\n source = iframe.contentWindow;\n }\n }\n\n source === null || source === void 0 ? void 0 : source.postMessage(JSON.stringify({\n method: data.value ? \"play\" : \"pause\",\n value: true\n }), \"*\");\n }\n\n break;\n\n case \"https://www.youtube.com\":\n if (data.event === \"infoDelivery\" && data.info && data.id && typeof data.info.playerState === \"number\") {\n const id = data.id;\n const playerState = data.info.playerState;\n\n if (Object.values(_constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES).includes(playerState)) {\n YOUTUBE_VIDEO_STATES.set(id, playerState);\n }\n }\n\n break;\n }\n }\n\n updateEmbeddableRef(id, ref) {\n if (ref) {\n this.iFrameRefs.set(id, ref);\n }\n }\n\n getHTMLIFrameElement(id) {\n return this.iFrameRefs.get(id);\n }\n\n handleEmbeddableCenterClick(element) {\n var _a, _b, _c, _d;\n\n if (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) === element && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"active\") {\n return;\n } // The delay serves two purposes\n // 1. To prevent first click propagating to iframe on mobile,\n // else the click will immediately start and stop the video\n // 2. If the user double clicks the frame center to activate it\n // without the delay youtube will immediately open the video\n // in fullscreen mode\n\n\n setTimeout(() => {\n this.setState({\n activeEmbeddable: {\n element,\n state: \"active\"\n },\n selectedElementIds: {\n [element.id]: true\n },\n draggingElement: null,\n selectionElement: null\n });\n }, 100);\n const iframe = this.getHTMLIFrameElement(element.id);\n\n if (!(iframe === null || iframe === void 0 ? void 0 : iframe.contentWindow)) {\n return;\n }\n\n if (iframe.src.includes(\"youtube\")) {\n const state = YOUTUBE_VIDEO_STATES.get(element.id);\n\n if (!state) {\n YOUTUBE_VIDEO_STATES.set(element.id, _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.UNSTARTED);\n iframe.contentWindow.postMessage(JSON.stringify({\n event: \"listening\",\n id: element.id\n }), \"*\");\n }\n\n switch (state) {\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.PLAYING:\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.BUFFERING:\n (_c = iframe.contentWindow) === null || _c === void 0 ? void 0 : _c.postMessage(JSON.stringify({\n event: \"command\",\n func: \"pauseVideo\",\n args: \"\"\n }), \"*\");\n break;\n\n default:\n (_d = iframe.contentWindow) === null || _d === void 0 ? void 0 : _d.postMessage(JSON.stringify({\n event: \"command\",\n func: \"playVideo\",\n args: \"\"\n }), \"*\");\n }\n }\n\n if (iframe.src.includes(\"player.vimeo.com\")) {\n iframe.contentWindow.postMessage(JSON.stringify({\n method: \"paused\" //video play/pause in onWindowMessage handler\n\n }), \"*\");\n }\n }\n\n isEmbeddableCenter(el, event, sceneX, sceneY) {\n var _a, _b;\n\n return el && !event.altKey && !event.shiftKey && !event.metaKey && !event.ctrlKey && (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) !== el || ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\" || !this.state.activeEmbeddable) && sceneX >= el.x + el.width / 3 && sceneX <= el.x + 2 * el.width / 3 && sceneY >= el.y + el.height / 3 && sceneY <= el.y + 2 * el.height / 3;\n }\n\n renderEmbeddables() {\n const scale = this.state.zoom.value;\n const normalizedWidth = this.state.width;\n const normalizedHeight = this.state.height;\n const embeddableElements = this.scene.getNonDeletedElements().filter(el => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(el) && !!el.validated);\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: embeddableElements.map(el => {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: el.x,\n sceneY: el.y\n }, this.state);\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)((0,_data_url__WEBPACK_IMPORTED_MODULE_46__.toValidURL)(el.link || \"\"));\n const isVisible = (0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(el, normalizedWidth, normalizedHeight, this.state);\n const isActive = ((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) === el && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"active\";\n const isHovered = ((_c = this.state.activeEmbeddable) === null || _c === void 0 ? void 0 : _c.element) === el && ((_d = this.state.activeEmbeddable) === null || _d === void 0 ? void 0 : _d.state) === \"hover\";\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw__embeddable-container\", {\n \"is-hovered\": isHovered\n }),\n style: {\n transform: isVisible ? `translate(${x - this.state.offsetLeft}px, ${y - this.state.offsetTop}px) scale(${scale})` : \"none\",\n display: isVisible ? \"block\" : \"none\",\n opacity: el.opacity / 100,\n [\"--embeddable-radius\"]: `${(0,_math__WEBPACK_IMPORTED_MODULE_28__.getCornerRadius)(Math.min(el.width, el.height), el)}px`\n }\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n //this is a hack that addresses isse with embedded excalidraw.com embeddable\n //https://github.com/excalidraw/excalidraw/pull/6691#issuecomment-1607383938\n\n /*ref={(ref) => {\n if (!this.excalidrawContainerRef.current) {\n return;\n }\n const container = this.excalidrawContainerRef.current;\n const sh = container.scrollHeight;\n const ch = container.clientHeight;\n if (sh !== ch) {\n container.style.height = `${sh}px`;\n setTimeout(() => {\n container.style.height = `100%`;\n });\n }\n }}*/\n className: \"excalidraw__embeddable-container__inner\",\n style: {\n width: isVisible ? `${el.width}px` : 0,\n height: isVisible ? `${el.height}px` : 0,\n transform: isVisible ? `rotate(${el.angle}rad)` : \"none\",\n pointerEvents: isActive ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled\n }\n }, {\n children: [isHovered && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable-hint\"\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"buttons.embeddableInteractionButton\")\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable__outer\",\n style: {\n padding: `${el.strokeWidth}px`\n }\n }, {\n children: (_g = (_f = (_e = this.props).renderEmbeddable) === null || _f === void 0 ? void 0 : _f.call(_e, el, this.state)) !== null && _g !== void 0 ? _g : (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"iframe\", {\n ref: ref => this.updateEmbeddableRef(el.id, ref),\n className: \"excalidraw__embeddable\",\n srcDoc: (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) === \"document\" ? embedLink.srcdoc(this.state.theme) : undefined,\n src: (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) !== \"document\" ? (_h = embedLink === null || embedLink === void 0 ? void 0 : embedLink.link) !== null && _h !== void 0 ? _h : \"\" : undefined,\n // https://stackoverflow.com/q/18470015\n scrolling: \"no\",\n referrerPolicy: \"no-referrer-when-downgrade\",\n title: \"Excalidraw Embedded Content\",\n allow: \"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\",\n allowFullScreen: true,\n sandbox: \"allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads\"\n })\n }))]\n }))\n }), el.id);\n })\n });\n }\n\n render() {\n var _a, _b, _c;\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n const {\n renderTopRightUI,\n renderCustomStats\n } = this.props;\n const versionNonce = this.scene.getVersionNonce();\n const {\n canvasElements,\n visibleElements\n } = this.renderer.getRenderableElements({\n versionNonce,\n zoom: this.state.zoom,\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n height: this.state.height,\n width: this.state.width,\n editingElement: this.state.editingElement,\n pendingImageElementId: this.state.pendingImageElementId\n });\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw excalidraw-container\", {\n \"excalidraw--view-mode\": this.state.viewModeEnabled,\n \"excalidraw--mobile\": this.device.isMobile\n }),\n style: {\n [\"--ui-pointerEvents\"]: this.state.selectionElement || this.state.draggingElement || this.state.resizingElement || this.state.editingElement && !(0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement) ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled\n },\n ref: this.excalidrawContainerRef,\n onDrop: this.handleAppOnDrop,\n tabIndex: 0,\n onKeyDown: this.props.handleKeyboardGlobally ? undefined : this.onKeyDown\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppContext.Provider, Object.assign({\n value: this\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppPropsContext.Provider, Object.assign({\n value: this.props\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawContainerContext.Provider, Object.assign({\n value: this.excalidrawContainerValue\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DeviceContext.Provider, Object.assign({\n value: this.device\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawSetAppStateContext.Provider, Object.assign({\n value: this.setAppState\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawAppStateContext.Provider, Object.assign({\n value: this.state\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawElementsContext.Provider, Object.assign({\n value: this.scene.getNonDeletedElements()\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawActionManagerContext.Provider, Object.assign({\n value: this.actionManager\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LayerUI__WEBPACK_IMPORTED_MODULE_36__[\"default\"], Object.assign({\n canvas: this.canvas,\n interactiveCanvas: this.interactiveCanvas,\n appState: this.state,\n files: this.files,\n setAppState: this.setAppState,\n actionManager: this.actionManager,\n elements: this.scene.getNonDeletedElements(),\n onLockToggle: this.toggleLock,\n onPenModeToggle: this.togglePenMode,\n onHandToolToggle: this.onHandToolToggle,\n langCode: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.getLanguage)().code,\n renderTopRightUI: renderTopRightUI,\n renderCustomStats: renderCustomStats,\n showExitZenModeBtn: typeof ((_a = this.props) === null || _a === void 0 ? void 0 : _a.zenModeEnabled) === \"undefined\" && this.state.zenModeEnabled,\n UIOptions: this.props.UIOptions,\n onImageAction: this.onImageAction,\n onExportImage: this.onExportImage,\n renderWelcomeScreen: !this.state.isLoading && this.state.showWelcomeScreen && this.state.activeTool.type === \"selection\" && !this.state.zenModeEnabled && !this.scene.getElementsIncludingDeleted().length,\n app: this\n }, {\n children: this.props.children\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-textEditorContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-contextMenuContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-eye-dropper-container\"\n }), selectedElements.length === 1 && !this.state.contextMenu && this.state.showHyperlinkPopup && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.Hyperlink, {\n element: selectedElements[0],\n setAppState: this.setAppState,\n onLinkOpen: this.props.onLinkOpen,\n setToast: this.setToast\n }, selectedElements[0].id), this.state.toast !== null && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Toast__WEBPACK_IMPORTED_MODULE_37__.Toast, {\n message: this.state.toast.message,\n onClose: () => this.setToast(null),\n duration: this.state.toast.duration,\n closable: this.state.toast.closable\n }), this.state.contextMenu && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ContextMenu__WEBPACK_IMPORTED_MODULE_35__.ContextMenu, {\n items: this.state.contextMenu.items,\n top: this.state.contextMenu.top,\n left: this.state.contextMenu.left,\n actionManager: this.actionManager\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_62__.StaticCanvas, {\n canvas: this.canvas,\n rc: this.rc,\n elements: canvasElements,\n visibleElements: visibleElements,\n versionNonce: versionNonce,\n selectionNonce: (_b = this.state.selectionElement) === null || _b === void 0 ? void 0 : _b.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: true\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_62__.InteractiveCanvas, {\n containerRef: this.excalidrawContainerRef,\n canvas: this.interactiveCanvas,\n elements: canvasElements,\n visibleElements: visibleElements,\n selectedElements: selectedElements,\n versionNonce: versionNonce,\n selectionNonce: (_c = this.state.selectionElement) === null || _c === void 0 ? void 0 : _c.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n renderInteractiveSceneCallback: this.renderInteractiveSceneCallback,\n handleCanvasRef: this.handleInteractiveCanvasRef,\n onContextMenu: this.handleCanvasContextMenu,\n onPointerMove: this.handleCanvasPointerMove,\n onPointerUp: this.handleCanvasPointerUp,\n onPointerCancel: this.removePointer,\n onTouchMove: this.handleTouchMove,\n onPointerDown: this.handleCanvasPointerDown,\n onDoubleClick: this.handleCanvasDoubleClick\n }), this.renderFrameNames()]\n })), this.renderEmbeddables()]\n }))\n }))\n }))\n }))\n }))\n }))\n }))\n }));\n }\n\n componentDidMount() {\n var _a, _b;\n\n return __awaiter(this, void 0, void 0, function* () {\n this.unmounted = false;\n this.excalidrawContainerValue.container = this.excalidrawContainerRef.current;\n\n if (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_12__.ENV.TEST || \"development\" !== \"production\") {\n const setState = this.setState.bind(this);\n Object.defineProperties(window.h, {\n state: {\n configurable: true,\n get: () => {\n return this.state;\n }\n },\n setState: {\n configurable: true,\n value: (...args) => {\n return this.setState(...args);\n }\n },\n app: {\n configurable: true,\n value: this\n },\n history: {\n configurable: true,\n value: this.history\n }\n });\n }\n\n this.scene.addCallback(this.onSceneUpdated);\n this.addEventListeners();\n\n if (this.props.autoFocus && this.excalidrawContainerRef.current) {\n this.focusContainer();\n }\n\n if (this.excalidrawContainerRef.current && // bounding rects don't work in tests so updating\n // the state on init would result in making the test enviro run\n // in mobile breakpoint (0 width/height), making everything fail\n !(0,_utils__WEBPACK_IMPORTED_MODULE_33__.isTestEnv)()) {\n this.refreshDeviceState(this.excalidrawContainerRef.current);\n }\n\n if (\"ResizeObserver\" in window && ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current)) {\n this.resizeObserver = new ResizeObserver(() => {\n // recompute device dimensions state\n // ---------------------------------------------------------------------\n this.refreshDeviceState(this.excalidrawContainerRef.current); // refresh offsets\n // ---------------------------------------------------------------------\n\n this.updateDOMRect();\n });\n (_b = this.resizeObserver) === null || _b === void 0 ? void 0 : _b.observe(this.excalidrawContainerRef.current);\n } else if (window.matchMedia) {\n const mdScreenQuery = window.matchMedia(`(max-width: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_PORTRAIT}px), (max-height: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_HEIGHT_LANDSCAPE}px) and (max-width: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_LANDSCAPE}px)`);\n const smScreenQuery = window.matchMedia(`(max-width: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_SM_MAX_WIDTH}px)`);\n const canDeviceFitSidebarMediaQuery = window.matchMedia(`(min-width: ${// NOTE this won't update if a different breakpoint is supplied\n // after mount\n this.props.UIOptions.dockedSidebarBreakpoint != null ? this.props.UIOptions.dockedSidebarBreakpoint : _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_RIGHT_SIDEBAR_MIN_WIDTH}px)`);\n\n const handler = () => {\n this.excalidrawContainerRef.current.getBoundingClientRect();\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateObject)(this.device, {\n isSmScreen: smScreenQuery.matches,\n isMobile: mdScreenQuery.matches,\n canDeviceFitSidebar: canDeviceFitSidebarMediaQuery.matches\n });\n };\n\n mdScreenQuery.addListener(handler);\n\n this.detachIsMobileMqHandler = () => mdScreenQuery.removeListener(handler);\n }\n\n const searchParams = new URLSearchParams(window.location.search.slice(1));\n\n if (searchParams.has(\"web-share-target\")) {\n // Obtain a file that was shared via the Web Share Target API.\n this.restoreFileFromShare();\n } else {\n this.updateDOMRect(this.initializeScene);\n } // note that this check seems to always pass in localhost\n\n\n if ((0,_constants__WEBPACK_IMPORTED_MODULE_12__.isBrave)() && !(0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.isMeasureTextSupported)()) {\n this.setState({\n errorMessage: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_58__[\"default\"], {})\n });\n }\n });\n }\n\n componentWillUnmount() {\n var _a;\n\n this.renderer.destroy();\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_30__[\"default\"]();\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_63__.Renderer(this.scene);\n this.files = {};\n this.imageCache.clear();\n (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();\n this.unmounted = true;\n this.removeEventListeners();\n this.scene.destroy();\n this.library.destroy();\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache.destroy();\n clearTimeout(touchTimeout);\n _scene__WEBPACK_IMPORTED_MODULE_29__.isSomeElementSelected.clearCache();\n _groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements.clearCache();\n touchTimeout = 0;\n }\n\n removeEventListeners() {\n var _a, _b, _c, _d, _e;\n\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, this.removePointer);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.COPY, this.onCopy);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, this.pasteFromClipboard);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.CUT, this.onCut);\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.onWheel);\n (_b = this.nearestScrollableContainer) === null || _b === void 0 ? void 0 : _b.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.SCROLL, this.onScroll);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, this.onKeyDown, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MOUSE_MOVE, this.updateCurrentCursorPosition, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, this.onKeyUp);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.RESIZE, this.onResize, false);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.UNLOAD, this.onUnload, false);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, this.onBlur, false);\n (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DRAG_OVER, this.disableEvent, false);\n (_d = this.excalidrawContainerRef.current) === null || _d === void 0 ? void 0 : _d.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DROP, this.disableEvent, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_START, this.onGestureStart, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_CHANGE, this.onGestureChange, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_END, this.onGestureEnd, false);\n (_e = this.detachIsMobileMqHandler) === null || _e === void 0 ? void 0 : _e.call(this);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MESSAGE, this.onWindowMessage, false);\n }\n\n addEventListeners() {\n var _a, _b, _c, _d, _e;\n\n this.removeEventListeners();\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MESSAGE, this.onWindowMessage, false);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, this.removePointer); // #3553\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.COPY, this.onCopy);\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.onWheel, {\n passive: false\n });\n\n if (this.props.handleKeyboardGlobally) {\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, this.onKeyDown, false);\n }\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, this.onKeyUp, {\n passive: true\n });\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MOUSE_MOVE, this.updateCurrentCursorPosition); // rerender text elements on font load to fix #637 && #1553\n\n (_c = (_b = document.fonts) === null || _b === void 0 ? void 0 : _b.addEventListener) === null || _c === void 0 ? void 0 : _c.call(_b, \"loadingdone\", event => {\n const loadedFontFaces = event.fontfaces;\n this.fonts.onFontsLoaded(loadedFontFaces);\n }); // Safari-only desktop pinch zoom\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_START, this.onGestureStart, false);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_CHANGE, this.onGestureChange, false);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_END, this.onGestureEnd, false);\n\n if (this.state.viewModeEnabled) {\n return;\n }\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, this.pasteFromClipboard);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.CUT, this.onCut);\n\n if (this.props.detectScroll) {\n this.nearestScrollableContainer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.getNearestScrollableContainer)(this.excalidrawContainerRef.current);\n this.nearestScrollableContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.SCROLL, this.onScroll);\n }\n\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.RESIZE, this.onResize, false);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.UNLOAD, this.onUnload, false);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, this.onBlur, false);\n (_d = this.excalidrawContainerRef.current) === null || _d === void 0 ? void 0 : _d.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DRAG_OVER, this.disableEvent, false);\n (_e = this.excalidrawContainerRef.current) === null || _e === void 0 ? void 0 : _e.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DROP, this.disableEvent, false);\n }\n\n componentDidUpdate(prevProps, prevState) {\n var _a, _b, _c, _d, _e, _f;\n\n this.updateEmbeddables();\n\n if (!this.state.showWelcomeScreen && !this.scene.getElementsIncludingDeleted().length) {\n this.setState({\n showWelcomeScreen: true\n });\n }\n\n if (this.excalidrawContainerRef.current && prevProps.UIOptions.dockedSidebarBreakpoint !== this.props.UIOptions.dockedSidebarBreakpoint) {\n this.refreshDeviceState(this.excalidrawContainerRef.current);\n }\n\n if (prevState.scrollX !== this.state.scrollX || prevState.scrollY !== this.state.scrollY) {\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onScrollChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.scrollX, this.state.scrollY);\n }\n\n if (Object.keys(this.state.selectedElementIds).length && (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n\n if (this.state.activeTool.type === \"eraser\" && prevState.theme !== this.state.theme) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setEraserCursor)(this.interactiveCanvas, this.state.theme);\n } // Hide hyperlink popup if shown when element type is not selection\n\n\n if (prevState.activeTool.type === \"selection\" && this.state.activeTool.type !== \"selection\" && this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: false\n });\n }\n\n if (prevProps.langCode !== this.props.langCode) {\n this.updateLanguage();\n }\n\n if (prevProps.viewModeEnabled !== this.props.viewModeEnabled) {\n this.setState({\n viewModeEnabled: !!this.props.viewModeEnabled\n });\n }\n\n if (prevState.viewModeEnabled !== this.state.viewModeEnabled) {\n this.addEventListeners();\n this.deselectElements();\n }\n\n if (prevProps.zenModeEnabled !== this.props.zenModeEnabled) {\n this.setState({\n zenModeEnabled: !!this.props.zenModeEnabled\n });\n }\n\n if (prevProps.theme !== this.props.theme && this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n if (prevProps.gridModeEnabled !== this.props.gridModeEnabled) {\n this.setState({\n gridSize: this.props.gridModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.GRID_SIZE : null\n });\n }\n\n if (this.props.name && prevProps.name !== this.props.name) {\n this.setState({\n name: this.props.name\n });\n }\n\n (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.classList.toggle(\"theme--dark\", this.state.theme === \"dark\");\n\n if (this.state.editingLinearElement && !this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {\n // defer so that the commitToHistory flag isn't reset via current update\n setTimeout(() => {\n // execute only if the condition still holds when the deferred callback\n // executes (it can be scheduled multiple times depending on how\n // many times the component renders)\n this.state.editingLinearElement && this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } // failsafe in case the state is being updated in incorrect order resulting\n // in the editingElement being now a deleted element\n\n\n if ((_d = this.state.editingElement) === null || _d === void 0 ? void 0 : _d.isDeleted) {\n this.setState({\n editingElement: null\n });\n }\n\n if (this.state.selectedLinearElement && !this.state.selectedElementIds[this.state.selectedLinearElement.elementId]) {\n // To make sure `selectedLinearElement` is in sync with `selectedElementIds`, however this shouldn't be needed once\n // we have a single API to update `selectedElementIds`\n this.setState({\n selectedLinearElement: null\n });\n }\n\n const {\n multiElement\n } = prevState;\n\n if (prevState.activeTool !== this.state.activeTool && multiElement != null && (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(multiElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(multiElement, this.state, this.scene, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)(_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1)));\n }\n\n this.history.record(this.state, this.scene.getElementsIncludingDeleted()); // Do not notify consumers if we're still loading the scene. Among other\n // potential issues, this fixes a case where the tab isn't focused during\n // init, which would trigger onChange with empty elements, which would then\n // override whatever is in localStorage currently.\n\n if (!this.state.isLoading) {\n (_f = (_e = this.props).onChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.scene.getElementsIncludingDeleted(), this.state, this.files);\n }\n }\n\n static resetTapTwice() {\n didTapTwice = false;\n }\n\n addTextFromPaste(text, isPlainPaste = false) {\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state);\n const textElementProps = {\n x,\n y,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roundness: null,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text,\n fontSize: this.state.currentItemFontSize,\n fontFamily: this.state.currentItemFontFamily,\n textAlign: this.state.currentItemTextAlign,\n verticalAlign: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n locked: false\n };\n const LINE_GAP = 10;\n let currentY = y;\n const lines = isPlainPaste ? [text] : text.split(\"\\n\");\n const textElements = lines.reduce((acc, line, idx) => {\n var _a;\n\n const text = line.trim();\n const lineHeight = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getDefaultLineHeight)(textElementProps.fontFamily);\n\n if (text.length) {\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x,\n y: currentY\n });\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)(Object.assign(Object.assign({}, textElementProps), {\n x,\n y: currentY,\n text,\n lineHeight,\n frameId: topLayerFrame ? topLayerFrame.id : null\n }));\n acc.push(element);\n currentY += element.height + LINE_GAP;\n } else {\n const prevLine = (_a = lines[idx - 1]) === null || _a === void 0 ? void 0 : _a.trim(); // add paragraph only if previous line was not empty, IOW don't add\n // more than one empty line\n\n if (prevLine) {\n currentY += (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getLineHeightInPx)(textElementProps.fontSize, lineHeight) + LINE_GAP;\n }\n }\n\n return acc;\n }, []);\n\n if (textElements.length === 0) {\n return;\n }\n\n const frameId = textElements[0].frameId;\n\n if (frameId) {\n this.scene.insertElementsAtIndex(textElements, this.scene.getElementIndex(frameId));\n } else {\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted(), ...textElements]);\n }\n\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.fromEntries(textElements.map(el => [el.id, true])), this.state)\n });\n\n if (!isPlainPaste && textElements.length > 1 && PLAIN_PASTE_TOAST_SHOWN === false && !this.device.isMobile) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"toast.pasteAsSingleElement\", {\n shortcut: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.getShortcutKey)(\"CtrlOrCmd+Shift+V\")\n }),\n duration: 5000\n });\n PLAIN_PASTE_TOAST_SHOWN = true;\n }\n\n this.history.resumeRecording();\n }\n\n handleTextWysiwyg(element, {\n isExistingElement = false\n }) {\n const updateElement = (text, originalText, isDeleted) => {\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted().map(_element => {\n if (_element.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(_element)) {\n return (0,_element__WEBPACK_IMPORTED_MODULE_16__.updateTextElement)(_element, {\n text,\n isDeleted,\n originalText\n });\n }\n\n return _element;\n })]);\n };\n\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.textWysiwyg)({\n id: element.id,\n canvas: this.canvas,\n getViewportCoords: (x, y) => {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: x,\n sceneY: y\n }, this.state);\n return [viewportX - this.state.offsetLeft, viewportY - this.state.offsetTop];\n },\n onChange: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(text => {\n updateElement(text, text, false);\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element);\n }\n }),\n onSubmit: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(({\n text,\n viaKeyboard,\n originalText\n }) => {\n const isDeleted = !text.trim();\n updateElement(text, originalText, isDeleted); // select the created text element only if submitting via keyboard\n // (when submitting via click it should act as signal to deselect)\n\n if (!isDeleted && viaKeyboard) {\n const elementIdToSelect = element.containerId ? element.containerId : element.id;\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [elementIdToSelect]: true\n }), prevState)\n }));\n }\n\n if (isDeleted) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDeletion)(this.scene.getNonDeletedElements(), [element]);\n }\n\n if (!isDeleted || isExistingElement) {\n this.history.resumeRecording();\n }\n\n this.setState({\n draggingElement: null,\n editingElement: null\n });\n\n if (this.state.activeTool.locked) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n this.focusContainer();\n }),\n element,\n excalidrawContainer: this.excalidrawContainerRef.current,\n app: this\n }); // deselect all other elements when inserting text\n\n this.deselectElements(); // do an initial update to re-initialize element position since we were\n // modifying element's x/y for sake of editor (case: syncing to remote)\n\n updateElement(element.text, element.originalText, false);\n }\n\n deselectElements() {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n getTextElementAtPosition(x, y) {\n const element = this.getElementAtPosition(x, y, {\n includeBoundTextElement: true\n });\n\n if (element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && !element.isDeleted) {\n return element;\n }\n\n return null;\n }\n\n getElementAtPosition(x, y, opts) {\n const allHitElements = this.getElementsAtPosition(x, y, opts === null || opts === void 0 ? void 0 : opts.includeBoundTextElement, opts === null || opts === void 0 ? void 0 : opts.includeLockedElements);\n\n if (allHitElements.length > 1) {\n if (opts === null || opts === void 0 ? void 0 : opts.preferSelected) {\n for (let index = allHitElements.length - 1; index > -1; index--) {\n if (this.state.selectedElementIds[allHitElements[index].id]) {\n return allHitElements[index];\n }\n }\n }\n\n const elementWithHighestZIndex = allHitElements[allHitElements.length - 1]; // If we're hitting element with highest z-index only on its bounding box\n // while also hitting other element figure, the latter should be considered.\n\n return (0,_element__WEBPACK_IMPORTED_MODULE_16__.isHittingElementBoundingBoxWithoutHittingElement)(elementWithHighestZIndex, this.state, this.frameNameBoundsCache, x, y) ? allHitElements[allHitElements.length - 2] : elementWithHighestZIndex;\n }\n\n if (allHitElements.length === 1) {\n return allHitElements[0];\n }\n\n return null;\n }\n\n getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {\n const elements = includeBoundTextElement && includeLockedElements ? this.scene.getNonDeletedElements() : this.scene.getNonDeletedElements().filter(element => (includeLockedElements || !element.locked) && (includeBoundTextElement || !((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && element.containerId)));\n return (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getElementsAtPosition)(elements, element => (0,_element__WEBPACK_IMPORTED_MODULE_16__.hitTest)(element, this.state, this.frameNameBoundsCache, x, y)).filter(element => {\n // hitting a frame's element from outside the frame is not considered a hit\n const containingFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(element);\n return containingFrame && this.state.frameRendering.enabled && this.state.frameRendering.clip ? (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)({\n x,\n y\n }, containingFrame) : true;\n });\n }\n\n handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {\n const element = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getElement(linearElementEditor.elementId);\n const boundTextElement = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getBoundTextElement)(element);\n\n if (!element) {\n return;\n }\n\n if (this.state.selectedLinearElement) {\n let hoverPointIndex = -1;\n let segmentMidPointHoveredCoords = null;\n\n if ((0,_element_collision__WEBPACK_IMPORTED_MODULE_44__.isHittingElementNotConsideringBoundingBox)(element, this.state, this.frameNameBoundsCache, [scenePointerX, scenePointerY])) {\n hoverPointIndex = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointIndexUnderCursor(element, this.state.zoom, scenePointerX, scenePointerY);\n segmentMidPointHoveredCoords = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, {\n x: scenePointerX,\n y: scenePointerY\n }, this.state);\n\n if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n } else if ((0,_element_transformHandles__WEBPACK_IMPORTED_MODULE_47__.shouldShowBoundingBox)([element], this.state) && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isHittingElementBoundingBoxWithoutHittingElement)(element, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n } else if (boundTextElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.hitTest)(boundTextElement, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n\n if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n hoverPointIndex\n })\n });\n }\n\n if (!_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.arePointsEqual(this.state.selectedLinearElement.segmentMidPointHoveredCoords, segmentMidPointHoveredCoords)) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n segmentMidPointHoveredCoords\n })\n });\n }\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n\n maybeCleanupAfterMissingPointerUp(event) {\n if (lastPointerUp !== null) {\n // Unfortunately, sometimes we don't get a pointerup after a pointerdown,\n // this can happen when a contextual menu or alert is triggered. In order to avoid\n // being in a weird state, we clean up on the next pointerdown\n lastPointerUp(event);\n }\n }\n\n updateGestureOnPointerDown(event) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n\n if (gesture.pointers.size === 2) {\n gesture.lastCenter = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n gesture.initialScale = this.state.zoom.value;\n gesture.initialDistance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n }\n }\n\n initialPointerDownState(event) {\n const origin = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedElements = this.scene.getSelectedElements(this.state);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n return {\n origin,\n withCmdOrCtrl: event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD],\n originInGrid: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)((0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(origin.x, origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize)),\n scrollbars: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop),\n // we need to duplicate because we'll be updating this state\n lastCoords: Object.assign({}, origin),\n originalElements: this.scene.getNonDeletedElements().reduce((acc, element) => {\n acc.set(element.id, (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.deepCopyElement)(element));\n return acc;\n }, new Map()),\n resize: {\n handleType: false,\n isResizing: false,\n offset: {\n x: 0,\n y: 0\n },\n arrowDirection: \"origin\",\n center: {\n x: (maxX + minX) / 2,\n y: (maxY + minY) / 2\n }\n },\n hit: {\n element: null,\n allHitElements: [],\n wasAddedToSelection: false,\n hasBeenDuplicated: false,\n hasHitCommonBoundingBoxOfSelectedElements: this.isHittingCommonBoundingBoxOfSelectedElements(origin, selectedElements)\n },\n drag: {\n hasOccurred: false,\n offset: null\n },\n eventListeners: {\n onMove: null,\n onUp: null,\n onKeyUp: null,\n onKeyDown: null\n },\n boxSelection: {\n hasOccurred: false\n },\n elementIdsToErase: {}\n };\n } // Returns whether the event is a dragging a scrollbar\n\n\n handleDraggingScrollBar(event, pointerDownState) {\n if (!(pointerDownState.scrollbars.isOverEither && !this.state.multiElement)) {\n return false;\n }\n\n isDraggingScrollBar = true;\n pointerDownState.lastCoords.x = event.clientX;\n pointerDownState.lastCoords.y = event.clientY;\n const onPointerMove = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdatesThrottled)(event => {\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n this.handlePointerMoveOverScrollbars(event, pointerDownState);\n });\n const onPointerUp = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(() => {\n isDraggingScrollBar = false;\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n lastPointerUp = null;\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n onPointerMove.flush();\n });\n lastPointerUp = onPointerUp;\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n return true;\n }\n\n isASelectedElement(hitElement) {\n return hitElement != null && this.state.selectedElementIds[hitElement.id];\n }\n\n isHittingCommonBoundingBoxOfSelectedElements(point, selectedElements) {\n if (selectedElements.length < 2) {\n return false;\n } // How many pixels off the shape boundary we still consider a hit\n\n\n const threshold = 10 / this.state.zoom.value;\n const [x1, y1, x2, y2] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n return point.x > x1 - threshold && point.x < x2 + threshold && point.y > y1 - threshold && point.y < y2 + threshold;\n }\n\n getCurrentItemRoundness(elementType) {\n return this.state.currentItemRoundness === \"round\" ? {\n type: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isUsingAdaptiveRadius)(elementType) ? _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.ADAPTIVE_RADIUS : _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null;\n }\n\n onKeyDownFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onKeyUpFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n // Prevents focus from escaping excalidraw tab\n event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ALT && event.preventDefault();\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onPointerMoveFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdatesThrottled)(event => {\n var _a, _b; // We need to initialize dragOffsetXY only after we've updated\n // `state.selectedElementIds` on pointerDown. Doing it here in pointerMove\n // event handler should hopefully ensure we're already working with\n // the updated state.\n\n\n if (pointerDownState.drag.offset === null) {\n pointerDownState.drag.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getDragOffsetXY)(this.scene.getSelectedElements(this.state), pointerDownState.origin.x, pointerDownState.origin.y));\n }\n\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n if (this.handlePointerMoveOverScrollbars(event, pointerDownState)) {\n return;\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.handleEraser(event, pointerDownState, pointerCoords);\n return;\n }\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize); // for arrows/lines, don't start dragging until a given threshold\n // to ensure we don't create a 2-point arrow by mistake when\n // user clicks mouse in a way that it moves a tiny bit (thus\n // triggering pointermove)\n\n if (!pointerDownState.drag.hasOccurred && (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\")) {\n if ((0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(pointerCoords.x, pointerCoords.y, pointerDownState.origin.x, pointerDownState.origin.y) < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD) {\n return;\n }\n }\n\n if (pointerDownState.resize.isResizing) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return true;\n }\n }\n\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n\n if (_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.shouldAddMidpoint(this.state.selectedLinearElement, pointerCoords, this.state)) {\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.addMidpoint(this.state.selectedLinearElement, pointerCoords, this.state, !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]);\n\n if (!ret) {\n return;\n } // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n if (this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n });\n return;\n } else if (linearElementEditor.pointerDownState.segmentMidpoint.value !== null && !linearElementEditor.pointerDownState.segmentMidpoint.added) {\n return;\n }\n\n const didDrag = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointDragging(event, this.state, pointerCoords.x, pointerCoords.y, (element, pointsSceneCoords) => {\n this.maybeSuggestBindingsForLinearElementAtCoords(element, pointsSceneCoords);\n }, linearElementEditor);\n\n if (didDrag) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n pointerDownState.drag.hasOccurred = true;\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n isDragging: true\n })\n });\n }\n\n if (!this.state.selectedLinearElement.isDragging) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n isDragging: true\n })\n });\n }\n\n return;\n }\n }\n\n const hasHitASelectedElement = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n const isSelectingPointsInLineEditor = this.state.editingLinearElement && event.shiftKey && this.state.editingLinearElement.elementId === ((_a = pointerDownState.hit.element) === null || _a === void 0 ? void 0 : _a.id);\n\n if ((hasHitASelectedElement || pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) && !isSelectingPointsInLineEditor) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.every(element => element.locked)) {\n return;\n }\n\n const selectedElementsHasAFrame = selectedElements.find(e => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameElement)(e));\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(pointerCoords);\n this.setState({\n frameToHighlight: topLayerFrame && !selectedElementsHasAFrame ? topLayerFrame : null\n }); // Marking that click was used for dragging to check\n // if elements should be deselected on pointerup\n\n pointerDownState.drag.hasOccurred = true;\n this.setState({\n selectedElementsAreBeingDragged: true\n }); // prevent dragging even if we're no longer holding cmd/ctrl otherwise\n // it would have weird results (stuff jumping all over the screen)\n // Checking for editingElement to avoid jump while editing on mobile #6503\n\n if (selectedElements.length > 0 && !pointerDownState.withCmdOrCtrl && !this.state.editingElement && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) !== \"active\") {\n const [dragX, dragY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x - pointerDownState.drag.offset.x, pointerCoords.y - pointerDownState.drag.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const [dragDistanceX, dragDistanceY] = [Math.abs(pointerCoords.x - pointerDownState.origin.x), Math.abs(pointerCoords.y - pointerDownState.origin.y)]; // We only drag in one direction if shift is pressed\n\n const lockDirection = event.shiftKey; // when we're editing the name of a frame, we want the user to be\n // able to select and interact with the text input\n\n !this.state.editingFrame && (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragSelectedElements)(pointerDownState, selectedElements, dragX, dragY, lockDirection, dragDistanceX, dragDistanceY, this.state, this.scene);\n this.maybeSuggestBindingForAll(selectedElements); // We duplicate the selected element if alt is pressed on pointer move\n\n if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {\n // Move the currently selected elements to the top of the z index stack, and\n // put the duplicates where the selected elements used to be.\n // (the origin point where the dragging started)\n pointerDownState.hit.hasBeenDuplicated = true;\n const nextElements = [];\n const elementsToAppend = [];\n const groupIdMap = new Map();\n const oldIdToDuplicatedId = new Map();\n const hitElement = pointerDownState.hit.element;\n const selectedElementIds = new Set(this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n }).map(element => element.id));\n const elements = this.scene.getElementsIncludingDeleted();\n\n for (const element of elements) {\n if (selectedElementIds.has(element.id) || // case: the state.selectedElementIds might not have been\n // updated yet by the time this mousemove event is fired\n element.id === (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && pointerDownState.hit.wasAddedToSelection) {\n const duplicatedElement = (0,_element__WEBPACK_IMPORTED_MODULE_16__.duplicateElement)(this.state.editingGroupId, groupIdMap, element);\n const [originDragX, originDragY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x - pointerDownState.drag.offset.x, pointerDownState.origin.y - pointerDownState.drag.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(duplicatedElement, {\n x: duplicatedElement.x + (originDragX - dragX),\n y: duplicatedElement.y + (originDragY - dragY)\n });\n nextElements.push(duplicatedElement);\n elementsToAppend.push(element);\n oldIdToDuplicatedId.set(element.id, duplicatedElement.id);\n } else {\n nextElements.push(element);\n }\n }\n\n const nextSceneElements = [...nextElements, ...elementsToAppend];\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.bindTextToShapeAfterDuplication)(nextElements, elementsToAppend, oldIdToDuplicatedId);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, \"duplicatesServeAsOld\");\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.bindElementsToFramesAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);\n this.scene.replaceAllElements(nextSceneElements);\n }\n\n return;\n }\n } // It is very important to read this.state within each move event,\n // otherwise we would read a stale one!\n\n\n const draggingElement = this.state.draggingElement;\n\n if (!draggingElement) {\n return;\n }\n\n if (draggingElement.type === \"freedraw\") {\n const points = draggingElement.points;\n const dx = pointerCoords.x - draggingElement.x;\n const dy = pointerCoords.y - draggingElement.y;\n const lastPoint = points.length > 0 && points[points.length - 1];\n const discardPoint = lastPoint && lastPoint[0] === dx && lastPoint[1] === dy;\n\n if (!discardPoint) {\n const pressures = draggingElement.simulatePressure ? draggingElement.pressures : [...draggingElement.pressures, event.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points, [dx, dy]],\n pressures\n });\n }\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(draggingElement)) {\n pointerDownState.drag.hasOccurred = true;\n this.setState({\n selectedElementsAreBeingDragged: true\n });\n const points = draggingElement.points;\n let dx = gridX - draggingElement.x;\n let dy = gridY - draggingElement.y;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event) && points.length === 2) {\n ({\n width: dx,\n height: dy\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)(draggingElement.x, draggingElement.y, pointerCoords.x, pointerCoords.y));\n }\n\n if (points.length === 1) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points, [dx, dy]]\n });\n } else if (points.length === 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points.slice(0, -1), [dx, dy]]\n });\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(draggingElement, false)) {\n // When creating a linear element by dragging\n this.maybeSuggestBindingsForLinearElementAtCoords(draggingElement, [pointerCoords], this.state.startBoundElement);\n }\n } else {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n this.maybeDragNewGenericElement(pointerDownState, event);\n }\n\n if (this.state.activeTool.type === \"selection\") {\n pointerDownState.boxSelection.hasOccurred = true;\n const elements = this.scene.getNonDeletedElements(); // box-select line editor points\n\n if (this.state.editingLinearElement) {\n _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handleBoxSelection(event, this.state, this.setState.bind(this)); // regular box-select\n } else {\n let shouldReuseSelection = true;\n\n if (!event.shiftKey && (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isSomeElementSelected)(elements, this.state)) {\n if (pointerDownState.withCmdOrCtrl && pointerDownState.hit.element) {\n this.setState(prevState => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)(Object.assign(Object.assign({}, prevState), {\n selectedElementIds: {\n [pointerDownState.hit.element.id]: true\n }\n }), this.scene.getNonDeletedElements(), prevState, this));\n } else {\n shouldReuseSelection = false;\n }\n }\n\n const elementsWithinSelection = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getElementsWithinSelection)(elements, draggingElement);\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, shouldReuseSelection && prevState.selectedElementIds), elementsWithinSelection.reduce((acc, element) => {\n acc[element.id] = true;\n return acc;\n }, {}));\n\n if (pointerDownState.hit.element) {\n // if using ctrl/cmd, select the hitElement only if we\n // haven't box-selected anything else\n if (!elementsWithinSelection.length) {\n nextSelectedElementIds[pointerDownState.hit.element.id] = true;\n } else {\n delete nextSelectedElementIds[pointerDownState.hit.element.id];\n }\n }\n\n prevState = !shouldReuseSelection ? Object.assign(Object.assign({}, prevState), {\n selectedGroupIds: {},\n editingGroupId: null\n }) : prevState;\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // select linear element only when we haven't box-selected anything else\n selectedLinearElement: elementsWithinSelection.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(elementsWithinSelection[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(elementsWithinSelection[0], this.scene) : null,\n showHyperlinkPopup: elementsWithinSelection.length === 1 && (elementsWithinSelection[0].link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(elementsWithinSelection[0])) ? \"info\" : false\n });\n });\n }\n }\n });\n } // Returns whether the pointer move happened over either scrollbar\n\n\n handlePointerMoveOverScrollbars(event, pointerDownState) {\n if (pointerDownState.scrollbars.isOverHorizontal) {\n const x = event.clientX;\n const dx = x - pointerDownState.lastCoords.x;\n this.translateCanvas({\n scrollX: this.state.scrollX - dx / this.state.zoom.value\n });\n pointerDownState.lastCoords.x = x;\n return true;\n }\n\n if (pointerDownState.scrollbars.isOverVertical) {\n const y = event.clientY;\n const dy = y - pointerDownState.lastCoords.y;\n this.translateCanvas({\n scrollY: this.state.scrollY - dy / this.state.zoom.value\n });\n pointerDownState.lastCoords.y = y;\n return true;\n }\n\n return false;\n }\n\n onPointerUpFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(childEvent => {\n var _a, _b, _c, _d, _e, _f;\n\n if (pointerDownState.eventListeners.onMove) {\n pointerDownState.eventListeners.onMove.flush();\n }\n\n const {\n draggingElement,\n resizingElement,\n multiElement,\n activeTool,\n isResizing,\n isRotating\n } = this.state;\n this.setState({\n isResizing: false,\n isRotating: false,\n resizingElement: null,\n selectionElement: null,\n frameToHighlight: null,\n elementsToHighlight: null,\n cursorButton: \"up\",\n // text elements are reset on finalize, and resetting on pointerup\n // may cause issues with double taps\n editingElement: multiElement || (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement) ? this.state.editingElement : null\n });\n this.savePointer(childEvent.clientX, childEvent.clientY, \"up\");\n this.setState({\n selectedElementsAreBeingDragged: false\n }); // Handle end of dragging a point of a linear element, might close a loop\n // and sets binding element\n\n if (this.state.editingLinearElement) {\n if (!pointerDownState.boxSelection.hasOccurred && ((_b = (_a = pointerDownState.hit) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.id) !== this.state.editingLinearElement.elementId) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n } else {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state);\n\n if (editingLinearElement !== this.state.editingLinearElement) {\n this.setState({\n editingLinearElement,\n suggestedBindings: []\n });\n }\n }\n } else if (this.state.selectedLinearElement) {\n if (((_d = (_c = pointerDownState.hit) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.id) !== this.state.selectedLinearElement.elementId) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement to null if there is more than one element selected since we don't want to show linear element handles\n\n if (selectedELements.length > 1) {\n this.setState({\n selectedLinearElement: null\n });\n }\n } else {\n const linearElementEditor = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state);\n const {\n startBindingElement,\n endBindingElement\n } = linearElementEditor;\n const element = this.scene.getElement(linearElementEditor.elementId);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElement)(element, startBindingElement, endBindingElement);\n }\n\n if (linearElementEditor !== this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, linearElementEditor), {\n selectedPointsIndices: null\n }),\n suggestedBindings: []\n });\n }\n }\n }\n\n lastPointerUp = null;\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, pointerDownState.eventListeners.onMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, pointerDownState.eventListeners.onUp);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, pointerDownState.eventListeners.onKeyDown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, pointerDownState.eventListeners.onKeyUp);\n\n if (this.state.pendingImageElementId) {\n this.setState({\n pendingImageElementId: null\n });\n }\n\n if ((draggingElement === null || draggingElement === void 0 ? void 0 : draggingElement.type) === \"freedraw\") {\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(childEvent, this.state);\n const points = draggingElement.points;\n let dx = pointerCoords.x - draggingElement.x;\n let dy = pointerCoords.y - draggingElement.y; // Allows dots to avoid being flagged as infinitely small\n\n if (dx === points[0][0] && dy === points[0][1]) {\n dy += 0.0001;\n dx += 0.0001;\n }\n\n const pressures = draggingElement.simulatePressure ? [] : [...draggingElement.pressures, childEvent.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points, [dx, dy]],\n pressures,\n lastCommittedPoint: [dx, dy]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(draggingElement)) {\n const imageElement = draggingElement;\n\n try {\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } catch (error) {\n console.error(error);\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().filter(el => el.id !== imageElement.id));\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n }\n\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(draggingElement)) {\n if (draggingElement.points.length > 1) {\n this.history.resumeRecording();\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(childEvent, this.state);\n\n if (!pointerDownState.drag.hasOccurred && draggingElement && !multiElement) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...draggingElement.points, [pointerCoords.x - draggingElement.x, pointerCoords.y - draggingElement.y]]\n });\n this.setState({\n multiElement: draggingElement,\n editingElement: this.state.draggingElement\n });\n } else if (pointerDownState.drag.hasOccurred && !multiElement) {\n if ((0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(draggingElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(draggingElement, this.state, this.scene, pointerCoords);\n }\n\n this.setState({\n suggestedBindings: [],\n startBoundElement: null\n });\n\n if (!activeTool.locked) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n this.setState(prevState => ({\n draggingElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n }),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [draggingElement.id]: true\n }), prevState),\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(draggingElement, this.scene)\n }));\n } else {\n this.setState(prevState => ({\n draggingElement: null\n }));\n }\n }\n\n return;\n }\n\n if (activeTool.type !== \"selection\" && draggingElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(draggingElement)) {\n // remove invisible element which was added in onPointerDown\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().slice(0, -1));\n this.setState({\n draggingElement: null\n });\n return;\n }\n\n if (draggingElement) {\n if (pointerDownState.drag.hasOccurred) {\n const sceneCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(childEvent, this.state); // when editing the points of a linear element, we check if the\n // linear element still is in the frame afterwards\n // if not, the linear element will be removed from its frame (if any)\n\n if (this.state.selectedLinearElement && this.state.selectedLinearElement.isDragging) {\n const linearElement = this.scene.getElement(this.state.selectedLinearElement.elementId);\n\n if (linearElement === null || linearElement === void 0 ? void 0 : linearElement.frameId) {\n const frame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(linearElement);\n\n if (frame && linearElement) {\n if (!(0,_frame__WEBPACK_IMPORTED_MODULE_50__.elementOverlapsWithFrame)(linearElement, frame)) {\n // remove the linear element from all groups\n // before removing it from the frame as well\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(linearElement, {\n groupIds: []\n });\n this.scene.replaceAllElements((0,_frame__WEBPACK_IMPORTED_MODULE_50__.removeElementsFromFrame)(this.scene.getElementsIncludingDeleted(), [linearElement], this.state));\n }\n }\n }\n } else {\n // update the relationships between selected elements and frames\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(sceneCoords);\n const selectedElements = this.scene.getSelectedElements(this.state);\n let nextElements = this.scene.getElementsIncludingDeleted();\n\n const updateGroupIdsAfterEditingGroup = elements => {\n if (elements.length > 0) {\n for (const element of elements) {\n const index = element.groupIds.indexOf(this.state.editingGroupId);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: element.groupIds.slice(0, index)\n }, false);\n }\n\n nextElements.forEach(element => {\n if (element.groupIds.length && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(nextElements, element.groupIds[element.groupIds.length - 1]).length < 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: []\n }, false);\n }\n });\n this.setState({\n editingGroupId: null\n });\n }\n };\n\n if (topLayerFrame && !this.state.selectedElementIds[topLayerFrame.id]) {\n const elementsToAdd = selectedElements.filter(element => element.frameId !== topLayerFrame.id && (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n\n if (this.state.editingGroupId) {\n updateGroupIdsAfterEditingGroup(elementsToAdd);\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(nextElements, elementsToAdd, topLayerFrame);\n } else if (!topLayerFrame) {\n if (this.state.editingGroupId) {\n const elementsToRemove = selectedElements.filter(element => element.frameId && !(0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n updateGroupIdsAfterEditingGroup(elementsToRemove);\n }\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(nextElements, this.state, this);\n this.scene.replaceAllElements(nextElements);\n }\n }\n\n if (draggingElement.type === \"frame\") {\n const elementsInsideFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInNewFrame)(this.scene.getElementsIncludingDeleted(), draggingElement);\n this.scene.replaceAllElements((0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(this.scene.getElementsIncludingDeleted(), elementsInsideFrame, draggingElement));\n }\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getNormalizedDimensions)(draggingElement));\n }\n\n if (resizingElement) {\n this.history.resumeRecording();\n }\n\n if (resizingElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(resizingElement)) {\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().filter(el => el.id !== resizingElement.id));\n } // handle frame membership for resizing frames and/or selected elements\n\n\n if (pointerDownState.resize.isResizing) {\n let nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(this.scene.getElementsIncludingDeleted(), this.state, this);\n const selectedFrames = this.scene.getSelectedElements(this.state).filter(element => element.type === \"frame\");\n\n for (const frame of selectedFrames) {\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.replaceAllElementsInFrame)(nextElements, (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getElementsIncludingDeleted(), frame, this.state), frame, this.state);\n }\n\n this.scene.replaceAllElements(nextElements);\n } // Code below handles selection when element(s) weren't\n // drag or added to selection on pointer down phase.\n\n\n const hitElement = pointerDownState.hit.element;\n\n if (((_e = this.state.selectedLinearElement) === null || _e === void 0 ? void 0 : _e.elementId) !== (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement)) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement when no other element selected except\n // the one we've hit\n\n if (selectedELements.length === 1) {\n this.setState({\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement, this.scene)\n });\n }\n }\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(this.lastPointerDown.clientX, this.lastPointerDown.clientY, this.lastPointerUp.clientX, this.lastPointerUp.clientY);\n\n if (draggedDistance === 0) {\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: this.lastPointerUp.clientX,\n clientY: this.lastPointerUp.clientY\n }, this.state);\n const hitElements = this.getElementsAtPosition(scenePointer.x, scenePointer.y);\n hitElements.forEach(hitElement => pointerDownState.elementIdsToErase[hitElement.id] = {\n erase: true,\n opacity: hitElement.opacity\n });\n }\n\n this.eraseElements(pointerDownState);\n return;\n } else if (Object.keys(pointerDownState.elementIdsToErase).length) {\n this.restoreReadyToEraseElements(pointerDownState);\n }\n\n if (hitElement && !pointerDownState.drag.hasOccurred && !pointerDownState.hit.wasAddedToSelection && ( // if we're editing a line, pointerup shouldn't switch selection if\n // box selected\n !this.state.editingLinearElement || !pointerDownState.boxSelection.hasOccurred)) {\n // when inside line editor, shift selects points instead\n if (childEvent.shiftKey && !this.state.editingLinearElement) {\n if (this.state.selectedElementIds[hitElement.id]) {\n if ((0,_groups__WEBPACK_IMPORTED_MODULE_23__.isSelectedViaGroup)(this.state, hitElement)) {\n this.setState(_prevState => {\n const nextSelectedElementIds = Object.assign({}, _prevState.selectedElementIds); // We want to unselect all groups hitElement is part of\n // as well as all elements that are part of the groups\n // hitElement is part of\n\n for (const groupedElement of hitElement.groupIds.flatMap(groupId => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), groupId))) {\n delete nextSelectedElementIds[groupedElement.id];\n }\n\n return {\n selectedGroupIds: Object.assign(Object.assign({}, _prevState.selectedElementIds), hitElement.groupIds.map(gId => ({\n [gId]: false\n })).reduce((prev, acc) => Object.assign(Object.assign({}, prev), acc), {})),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, _prevState)\n };\n }); // if not gragging a linear element point (outside editor)\n } else if (!((_f = this.state.selectedLinearElement) === null || _f === void 0 ? void 0 : _f.isDragging)) {\n // remove element from selection while\n // keeping prev elements selected\n this.setState(prevState => {\n const newSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete newSelectedElementIds[hitElement.id];\n const newSelectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getSelectedElements)(this.scene.getNonDeletedElements(), {\n selectedElementIds: newSelectedElementIds\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: newSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // set selectedLinearElement only if thats the only element selected\n selectedLinearElement: newSelectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newSelectedElements[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(newSelectedElements[0], this.scene) : prevState.selectedLinearElement\n });\n });\n }\n } else if (hitElement.frameId && this.state.selectedElementIds[hitElement.frameId]) {\n // when hitElement is part of a selected frame, deselect the frame\n // to avoid frame and containing elements selected simultaneously\n this.setState(prevState => {\n var _a, _b;\n\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n }); // deselect the frame\n\n delete nextSelectedElementIds[hitElement.frameId]; // deselect groups containing the frame\n\n ((_b = (_a = this.scene.getElement(hitElement.frameId)) === null || _a === void 0 ? void 0 : _a.groupIds) !== null && _b !== void 0 ? _b : []).flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n } else {\n // add element to selection while keeping prev elements selected\n this.setState(_prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, _prevState.selectedElementIds), {\n [hitElement.id]: true\n }), _prevState)\n }));\n }\n } else {\n this.setState(prevState => {\n var _a;\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement) && // Don't set `selectedLinearElement` if its same as the hitElement, this is mainly to prevent resetting the `hoverPointIndex` to -1.\n // Future we should update the API to take care of setting the correct `hoverPointIndex` when initialized\n ((_a = prevState.selectedLinearElement) === null || _a === void 0 ? void 0 : _a.elementId) !== hitElement.id ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement, this.scene) : prevState.selectedLinearElement\n });\n });\n }\n }\n\n if (!pointerDownState.drag.hasOccurred && !this.state.isResizing && (hitElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isHittingElementBoundingBoxWithoutHittingElement)(hitElement, this.state, this.frameNameBoundsCache, pointerDownState.origin.x, pointerDownState.origin.y) || !hitElement && pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements)) {\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: null\n });\n } else {\n // Deselect selected elements\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n return;\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\" && draggingElement && draggingElement.type !== \"selection\") {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [draggingElement.id]: true\n }), prevState),\n showHyperlinkPopup: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(draggingElement) && !draggingElement.link ? \"editor\" : prevState.showHyperlinkPopup\n }));\n }\n\n if (activeTool.type !== \"selection\" || (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isSomeElementSelected)(this.scene.getNonDeletedElements(), this.state)) {\n this.history.resumeRecording();\n }\n\n if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {\n ((0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) ? _element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindSelectedElements : _element_binding__WEBPACK_IMPORTED_MODULE_17__.unbindLinearElements)(this.scene.getSelectedElements(this.state));\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n this.setState({\n draggingElement: null,\n suggestedBindings: [],\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n } else {\n this.setState({\n draggingElement: null,\n suggestedBindings: []\n });\n }\n\n if (hitElement && this.lastPointerUp && this.lastPointerDown && this.lastPointerUp.timeStamp - this.lastPointerDown.timeStamp < 300 && gesture.pointers.size <= 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) && this.isEmbeddableCenter(hitElement, this.lastPointerUp, pointerDownState.origin.x, pointerDownState.origin.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n }\n });\n }\n\n maybeSuggestBindingForAll(selectedElements) {\n if (selectedElements.length > 50) {\n return;\n }\n\n const suggestedBindings = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getEligibleElementsForBinding)(selectedElements);\n this.setState({\n suggestedBindings\n });\n }\n\n clearSelection(hitElement) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, prevState),\n activeEmbeddable: null,\n selectedGroupIds: {},\n // Continue editing the same group if the user selected a different\n // element from it\n editingGroupId: prevState.editingGroupId && hitElement != null && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, prevState.editingGroupId) ? prevState.editingGroupId : null\n }));\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null,\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n\n getTextWysiwygSnappedToCenterPosition(x, y, appState, container) {\n if (container) {\n let elementCenterX = container.x + container.width / 2;\n let elementCenterY = container.y + container.height / 2;\n const elementCenter = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerCenter)(container, appState);\n\n if (elementCenter) {\n elementCenterX = elementCenter.x;\n elementCenterY = elementCenter.y;\n }\n\n const distanceToCenter = Math.hypot(x - elementCenterX, y - elementCenterY);\n const isSnappedToCenter = distanceToCenter < _constants__WEBPACK_IMPORTED_MODULE_12__.TEXT_TO_CENTER_SNAP_THRESHOLD;\n\n if (isSnappedToCenter) {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: elementCenterX,\n sceneY: elementCenterY\n }, appState);\n return {\n viewportX,\n viewportY,\n elementCenterX,\n elementCenterY\n };\n }\n }\n }\n\n getCanvasOffsets() {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n left,\n top\n } = excalidrawContainer.getBoundingClientRect();\n return {\n offsetLeft: left,\n offsetTop: top\n };\n }\n\n return {\n offsetLeft: 0,\n offsetTop: 0\n };\n }\n\n updateLanguage() {\n return __awaiter(this, void 0, void 0, function* () {\n const currentLang = _i18n__WEBPACK_IMPORTED_MODULE_25__.languages.find(lang => lang.code === this.props.langCode) || _i18n__WEBPACK_IMPORTED_MODULE_25__.defaultLang;\n yield (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.setLanguage)(currentLang);\n this.setAppState({});\n });\n }\n\n}\n\nApp.defaultProps = {\n // needed for tests to pass since we directly render App in many tests\n UIOptions: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_UI_OPTIONS\n};\n\nif (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_12__.ENV.TEST || \"development\" !== \"production\") {\n window.h = window.h || {};\n Object.defineProperties(window.h, {\n elements: {\n configurable: true,\n\n get() {\n var _a;\n\n return (_a = this.app) === null || _a === void 0 ? void 0 : _a.scene.getElementsIncludingDeleted();\n },\n\n set(elements) {\n var _a;\n\n return (_a = this.app) === null || _a === void 0 ? void 0 : _a.scene.replaceAllElements(elements);\n }\n\n }\n });\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QSxtREFBbUQsc0VBQTZCOztBQUVoRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsRUFBRSxvRUFBMkI7QUFDdkM7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMEJBQTBCLGtEQUFjLCtDQUErQywrQ0FBVztBQUNsRyxZQUFZLG1EQUFXO0FBQ3ZCLHlCQUF5QjtBQUN6QixLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGFBQWEsMkRBQWtCO0FBQy9COztBQUVBLElBQUksYUFBb0IsS0FBSyxpREFBUSxJQUFJLGFBQW9CO0FBQzdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPOztBQUVQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDs7QUFFQSxpRUFBZSxHQUFHIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2NvbXBvbmVudHMvQXBwLnRzeD8wNjI0Il0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2F3YWl0ZXIgPSB0aGlzICYmIHRoaXMuX19hd2FpdGVyIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7XG4gICAgICB0cnkge1xuICAgICAgICBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkge1xuICAgICAgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7XG4gICAgfVxuXG4gICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICB9KTtcbn07XG5cbmltcG9ydCB7IGpzeCBhcyBfanN4LCBqc3hzIGFzIF9qc3hzLCBGcmFnbWVudCBhcyBfRnJhZ21lbnQgfSBmcm9tIFwicmVhY3QvanN4LXJ1bnRpbWVcIjtcbmltcG9ydCBSZWFjdCwgeyB1c2VDb250ZXh0IH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBmbHVzaFN5bmMgfSBmcm9tIFwicmVhY3QtZG9tXCI7XG5pbXBvcnQgcm91Z2ggZnJvbSBcInJvdWdoanMvYmluL3JvdWdoXCI7XG5pbXBvcnQgY2xzeCBmcm9tIFwiY2xzeFwiO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSBcIm5hbm9pZFwiO1xuaW1wb3J0IHsgYWN0aW9uQWRkVG9MaWJyYXJ5LCBhY3Rpb25CcmluZ0ZvcndhcmQsIGFjdGlvbkJyaW5nVG9Gcm9udCwgYWN0aW9uQ29weSwgYWN0aW9uQ29weUFzUG5nLCBhY3Rpb25Db3B5QXNTdmcsIGNvcHlUZXh0LCBhY3Rpb25Db3B5U3R5bGVzLCBhY3Rpb25DdXQsIGFjdGlvbkRlbGV0ZVNlbGVjdGVkLCBhY3Rpb25EdXBsaWNhdGVTZWxlY3Rpb24sIGFjdGlvbkZpbmFsaXplLCBhY3Rpb25GbGlwSG9yaXpvbnRhbCwgYWN0aW9uRmxpcFZlcnRpY2FsLCBhY3Rpb25Hcm91cCwgYWN0aW9uUGFzdGVTdHlsZXMsIGFjdGlvblNlbGVjdEFsbCwgYWN0aW9uU2VuZEJhY2t3YXJkLCBhY3Rpb25TZW5kVG9CYWNrLCBhY3Rpb25Ub2dnbGVHcmlkTW9kZSwgYWN0aW9uVG9nZ2xlU3RhdHMsIGFjdGlvblRvZ2dsZVplbk1vZGUsIGFjdGlvblVuYmluZFRleHQsIGFjdGlvbkJpbmRUZXh0LCBhY3Rpb25Vbmdyb3VwLCBhY3Rpb25MaW5rLCBhY3Rpb25Ub2dnbGVFbGVtZW50TG9jaywgYWN0aW9uVG9nZ2xlTGluZWFyRWRpdG9yIH0gZnJvbSBcIi4uL2FjdGlvbnNcIjtcbmltcG9ydCB7IGNyZWF0ZVJlZG9BY3Rpb24sIGNyZWF0ZVVuZG9BY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9ucy9hY3Rpb25IaXN0b3J5XCI7XG5pbXBvcnQgeyBBY3Rpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL2FjdGlvbnMvbWFuYWdlclwiO1xuaW1wb3J0IHsgYWN0aW9ucyB9IGZyb20gXCIuLi9hY3Rpb25zL3JlZ2lzdGVyXCI7XG5pbXBvcnQgeyB0cmFja0V2ZW50IH0gZnJvbSBcIi4uL2FuYWx5dGljc1wiO1xuaW1wb3J0IHsgZ2V0RGVmYXVsdEFwcFN0YXRlLCBpc0VyYXNlckFjdGl2ZSwgaXNIYW5kVG9vbEFjdGl2ZSB9IGZyb20gXCIuLi9hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgcGFyc2VDbGlwYm9hcmQgfSBmcm9tIFwiLi4vY2xpcGJvYXJkXCI7XG5pbXBvcnQgeyBBUFBfTkFNRSwgQ1VSU09SX1RZUEUsIERFRkFVTFRfTUFYX0lNQUdFX1dJRFRIX09SX0hFSUdIVCwgREVGQVVMVF9VSV9PUFRJT05TLCBERUZBVUxUX1ZFUlRJQ0FMX0FMSUdOLCBEUkFHR0lOR19USFJFU0hPTEQsIEVMRU1FTlRfUkVBRFlfVE9fRVJBU0VfT1BBQ0lUWSwgRUxFTUVOVF9TSElGVF9UUkFOU0xBVEVfQU1PVU5ULCBFTEVNRU5UX1RSQU5TTEFURV9BTU9VTlQsIEVOViwgRVZFTlQsIEZSQU1FX1NUWUxFLCBHUklEX1NJWkUsIElNQUdFX01JTUVfVFlQRVMsIElNQUdFX1JFTkRFUl9USU1FT1VULCBpc0FuZHJvaWQsIGlzQnJhdmUsIExJTkVfQ09ORklSTV9USFJFU0hPTEQsIE1BWF9BTExPV0VEX0ZJTEVfQllURVMsIE1JTUVfVFlQRVMsIE1RX01BWF9IRUlHSFRfTEFORFNDQVBFLCBNUV9NQVhfV0lEVEhfTEFORFNDQVBFLCBNUV9NQVhfV0lEVEhfUE9SVFJBSVQsIE1RX1JJR0hUX1NJREVCQVJfTUlOX1dJRFRILCBNUV9TTV9NQVhfV0lEVEgsIFBPSU5URVJfQlVUVE9OLCBST1VORE5FU1MsIFNDUk9MTF9USU1FT1VULCBUQVBfVFdJQ0VfVElNRU9VVCwgVEVYVF9UT19DRU5URVJfU05BUF9USFJFU0hPTEQsIFRIRU1FLCBUSEVNRV9GSUxURVIsIFRPVUNIX0NUWF9NRU5VX1RJTUVPVVQsIFZFUlRJQ0FMX0FMSUdOLCBZT1VUVUJFX1NUQVRFUywgWk9PTV9TVEVQLCBQT0lOVEVSX0VWRU5UUyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IGV4cG9ydENhbnZhcywgbG9hZEZyb21CbG9iIH0gZnJvbSBcIi4uL2RhdGFcIjtcbmltcG9ydCBMaWJyYXJ5LCB7IGRpc3RyaWJ1dGVMaWJyYXJ5SXRlbXNPblNxdWFyZUdyaWQgfSBmcm9tIFwiLi4vZGF0YS9saWJyYXJ5XCI7XG5pbXBvcnQgeyByZXN0b3JlLCByZXN0b3JlRWxlbWVudHMgfSBmcm9tIFwiLi4vZGF0YS9yZXN0b3JlXCI7XG5pbXBvcnQgeyBkcmFnTmV3RWxlbWVudCwgZHJhZ1NlbGVjdGVkRWxlbWVudHMsIGR1cGxpY2F0ZUVsZW1lbnQsIGdldENvbW1vbkJvdW5kcywgZ2V0Q3Vyc29yRm9yUmVzaXppbmdFbGVtZW50LCBnZXREcmFnT2Zmc2V0WFksIGdldEVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZSwgZ2V0Tm9ybWFsaXplZERpbWVuc2lvbnMsIGdldFJlc2l6ZUFycm93RGlyZWN0aW9uLCBnZXRSZXNpemVPZmZzZXRYWSwgZ2V0TG9ja2VkTGluZWFyQ3Vyc29yQWxpZ25TaXplLCBnZXRUcmFuc2Zvcm1IYW5kbGVUeXBlRnJvbUNvb3JkcywgaGl0VGVzdCwgaXNIaXR0aW5nRWxlbWVudEJvdW5kaW5nQm94V2l0aG91dEhpdHRpbmdFbGVtZW50LCBpc0ludmlzaWJseVNtYWxsRWxlbWVudCwgaXNOb25EZWxldGVkRWxlbWVudCwgaXNUZXh0RWxlbWVudCwgbmV3RWxlbWVudCwgbmV3TGluZWFyRWxlbWVudCwgbmV3VGV4dEVsZW1lbnQsIG5ld0ltYWdlRWxlbWVudCwgdGV4dFd5c2l3eWcsIHRyYW5zZm9ybUVsZW1lbnRzLCB1cGRhdGVUZXh0RWxlbWVudCwgcmVkcmF3VGV4dEJvdW5kaW5nQm94IH0gZnJvbSBcIi4uL2VsZW1lbnRcIjtcbmltcG9ydCB7IGJpbmRPclVuYmluZExpbmVhckVsZW1lbnQsIGJpbmRPclVuYmluZFNlbGVjdGVkRWxlbWVudHMsIGZpeEJpbmRpbmdzQWZ0ZXJEZWxldGlvbiwgZml4QmluZGluZ3NBZnRlckR1cGxpY2F0aW9uLCBnZXRFbGlnaWJsZUVsZW1lbnRzRm9yQmluZGluZywgZ2V0SG92ZXJlZEVsZW1lbnRGb3JCaW5kaW5nLCBpc0JpbmRpbmdFbmFibGVkLCBpc0xpbmVhckVsZW1lbnRTaW1wbGVBbmRBbHJlYWR5Qm91bmQsIG1heWJlQmluZExpbmVhckVsZW1lbnQsIHNob3VsZEVuYWJsZUJpbmRpbmdGb3JQb2ludGVyRXZlbnQsIHVuYmluZExpbmVhckVsZW1lbnRzLCB1cGRhdGVCb3VuZEVsZW1lbnRzIH0gZnJvbSBcIi4uL2VsZW1lbnQvYmluZGluZ1wiO1xuaW1wb3J0IHsgTGluZWFyRWxlbWVudEVkaXRvciB9IGZyb20gXCIuLi9lbGVtZW50L2xpbmVhckVsZW1lbnRFZGl0b3JcIjtcbmltcG9ydCB7IG11dGF0ZUVsZW1lbnQsIG5ld0VsZW1lbnRXaXRoIH0gZnJvbSBcIi4uL2VsZW1lbnQvbXV0YXRlRWxlbWVudFwiO1xuaW1wb3J0IHsgZGVlcENvcHlFbGVtZW50LCBkdXBsaWNhdGVFbGVtZW50cywgbmV3RnJhbWVFbGVtZW50LCBuZXdGcmVlRHJhd0VsZW1lbnQsIG5ld0VtYmVkZGFibGVFbGVtZW50IH0gZnJvbSBcIi4uL2VsZW1lbnQvbmV3RWxlbWVudFwiO1xuaW1wb3J0IHsgaGFzQm91bmRUZXh0RWxlbWVudCwgaXNBcnJvd0VsZW1lbnQsIGlzQmluZGluZ0VsZW1lbnQsIGlzQmluZGluZ0VsZW1lbnRUeXBlLCBpc0JvdW5kVG9Db250YWluZXIsIGlzRnJhbWVFbGVtZW50LCBpc0ltYWdlRWxlbWVudCwgaXNFbWJlZGRhYmxlRWxlbWVudCwgaXNJbml0aWFsaXplZEltYWdlRWxlbWVudCwgaXNMaW5lYXJFbGVtZW50LCBpc0xpbmVhckVsZW1lbnRUeXBlLCBpc1VzaW5nQWRhcHRpdmVSYWRpdXMgfSBmcm9tIFwiLi4vZWxlbWVudC90eXBlQ2hlY2tzXCI7XG5pbXBvcnQgeyBnZXRDZW50ZXIsIGdldERpc3RhbmNlIH0gZnJvbSBcIi4uL2dlc3R1cmVcIjtcbmltcG9ydCB7IGVkaXRHcm91cEZvclNlbGVjdGVkRWxlbWVudCwgZ2V0RWxlbWVudHNJbkdyb3VwLCBnZXRTZWxlY3RlZEdyb3VwSWRGb3JFbGVtZW50LCBnZXRTZWxlY3RlZEdyb3VwSWRzLCBpc0VsZW1lbnRJbkdyb3VwLCBpc1NlbGVjdGVkVmlhR3JvdXAsIHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMgfSBmcm9tIFwiLi4vZ3JvdXBzXCI7XG5pbXBvcnQgSGlzdG9yeSBmcm9tIFwiLi4vaGlzdG9yeVwiO1xuaW1wb3J0IHsgZGVmYXVsdExhbmcsIGdldExhbmd1YWdlLCBsYW5ndWFnZXMsIHNldExhbmd1YWdlLCB0IH0gZnJvbSBcIi4uL2kxOG5cIjtcbmltcG9ydCB7IENPREVTLCBzaG91bGRSZXNpemVGcm9tQ2VudGVyLCBzaG91bGRNYWludGFpbkFzcGVjdFJhdGlvLCBzaG91bGRSb3RhdGVXaXRoRGlzY3JldGVBbmdsZSwgaXNBcnJvd0tleSwgS0VZUyB9IGZyb20gXCIuLi9rZXlzXCI7XG5pbXBvcnQgeyBpc0VsZW1lbnRJblZpZXdwb3J0IH0gZnJvbSBcIi4uL2VsZW1lbnQvc2l6ZUhlbHBlcnNcIjtcbmltcG9ydCB7IGRpc3RhbmNlMmQsIGdldENvcm5lclJhZGl1cywgZ2V0R3JpZFBvaW50LCBpc1BhdGhBTG9vcCB9IGZyb20gXCIuLi9tYXRoXCI7XG5pbXBvcnQgeyBjYWxjdWxhdGVTY3JvbGxDZW50ZXIsIGdldEVsZW1lbnRzQXRQb3NpdGlvbiwgZ2V0RWxlbWVudHNXaXRoaW5TZWxlY3Rpb24sIGdldE5vcm1hbGl6ZWRab29tLCBnZXRTZWxlY3RlZEVsZW1lbnRzLCBoYXNCYWNrZ3JvdW5kLCBpc092ZXJTY3JvbGxCYXJzLCBpc1NvbWVFbGVtZW50U2VsZWN0ZWQgfSBmcm9tIFwiLi4vc2NlbmVcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vc2NlbmUvU2NlbmVcIjtcbmltcG9ydCB7IGdldFN0YXRlRm9yWm9vbSB9IGZyb20gXCIuLi9zY2VuZS96b29tXCI7XG5pbXBvcnQgeyBmaW5kU2hhcGVCeUtleSB9IGZyb20gXCIuLi9zaGFwZXNcIjtcbmltcG9ydCB7IGRlYm91bmNlLCBkaXN0YW5jZSwgZ2V0Rm9udFN0cmluZywgZ2V0TmVhcmVzdFNjcm9sbGFibGVDb250YWluZXIsIGlzSW5wdXRMaWtlLCBpc1Rvb2xJY29uLCBpc1dyaXRhYmxlRWxlbWVudCwgcmVzZXRDdXJzb3IsIHJlc29sdmFibGVQcm9taXNlLCBzY2VuZUNvb3Jkc1RvVmlld3BvcnRDb29yZHMsIHNldEN1cnNvciwgc2V0Q3Vyc29yRm9yU2hhcGUsIHR1cGxlVG9Db29ycywgdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzLCB3aXRoQmF0Y2hlZFVwZGF0ZXMsIHdyYXBFdmVudCwgd2l0aEJhdGNoZWRVcGRhdGVzVGhyb3R0bGVkLCB1cGRhdGVPYmplY3QsIHNldEVyYXNlckN1cnNvciwgdXBkYXRlQWN0aXZlVG9vbCwgZ2V0U2hvcnRjdXRLZXksIGlzVHJhbnNwYXJlbnQsIGVhc2VUb1ZhbHVlc1JBRiwgbXV0ZUZTQWJvcnRFcnJvciwgaXNUZXN0RW52LCBlYXNlT3V0IH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQgeyBlbWJlZGRhYmxlVVJMVmFsaWRhdG9yLCBleHRyYWN0U3JjLCBnZXRFbWJlZExpbmsgfSBmcm9tIFwiLi4vZWxlbWVudC9lbWJlZGRhYmxlXCI7XG5pbXBvcnQgeyBDb250ZXh0TWVudSwgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiB9IGZyb20gXCIuL0NvbnRleHRNZW51XCI7XG5pbXBvcnQgTGF5ZXJVSSBmcm9tIFwiLi9MYXllclVJXCI7XG5pbXBvcnQgeyBUb2FzdCB9IGZyb20gXCIuL1RvYXN0XCI7XG5pbXBvcnQgeyBhY3Rpb25Ub2dnbGVWaWV3TW9kZSB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvblRvZ2dsZVZpZXdNb2RlXCI7XG5pbXBvcnQgeyBkYXRhVVJMVG9GaWxlLCBnZW5lcmF0ZUlkRnJvbUZpbGUsIGdldERhdGFVUkwsIGdldEZpbGVGcm9tRXZlbnQsIGlzSW1hZ2VGaWxlSGFuZGxlLCBpc1N1cHBvcnRlZEltYWdlRmlsZSwgbG9hZFNjZW5lT3JMaWJyYXJ5RnJvbUJsb2IsIG5vcm1hbGl6ZUZpbGUsIHBhcnNlTGlicmFyeUpTT04sIHJlc2l6ZUltYWdlRmlsZSwgU1ZHU3RyaW5nVG9GaWxlIH0gZnJvbSBcIi4uL2RhdGEvYmxvYlwiO1xuaW1wb3J0IHsgZ2V0SW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnRzLCBsb2FkSFRNTEltYWdlRWxlbWVudCwgbm9ybWFsaXplU1ZHLCB1cGRhdGVJbWFnZUNhY2hlIGFzIF91cGRhdGVJbWFnZUNhY2hlIH0gZnJvbSBcIi4uL2VsZW1lbnQvaW1hZ2VcIjtcbmltcG9ydCB0aHJvdHRsZSBmcm9tIFwibG9kYXNoLnRocm90dGxlXCI7XG5pbXBvcnQgeyBmaWxlT3BlbiB9IGZyb20gXCIuLi9kYXRhL2ZpbGVzeXN0ZW1cIjtcbmltcG9ydCB7IGJpbmRUZXh0VG9TaGFwZUFmdGVyRHVwbGljYXRpb24sIGdldEFwcHJveE1pbkxpbmVIZWlnaHQsIGdldEFwcHJveE1pbkxpbmVXaWR0aCwgZ2V0Qm91bmRUZXh0RWxlbWVudCwgZ2V0Q29udGFpbmVyQ2VudGVyLCBnZXRDb250YWluZXJFbGVtZW50LCBnZXREZWZhdWx0TGluZUhlaWdodCwgZ2V0TGluZUhlaWdodEluUHgsIGdldFRleHRCaW5kYWJsZUNvbnRhaW5lckF0UG9zaXRpb24sIGlzTWVhc3VyZVRleHRTdXBwb3J0ZWQsIGlzVmFsaWRUZXh0Q29udGFpbmVyIH0gZnJvbSBcIi4uL2VsZW1lbnQvdGV4dEVsZW1lbnRcIjtcbmltcG9ydCB7IGlzSGl0dGluZ0VsZW1lbnROb3RDb25zaWRlcmluZ0JvdW5kaW5nQm94IH0gZnJvbSBcIi4uL2VsZW1lbnQvY29sbGlzaW9uXCI7XG5pbXBvcnQgeyBzaG93SHlwZXJsaW5rVG9vbHRpcCwgaGlkZUh5cGVybGlua1Rvb2xpcCwgSHlwZXJsaW5rLCBpc1BvaW50SGl0dGluZ0xpbmssIGlzUG9pbnRIaXR0aW5nTGlua0ljb24gfSBmcm9tIFwiLi4vZWxlbWVudC9IeXBlcmxpbmtcIjtcbmltcG9ydCB7IGlzTG9jYWxMaW5rLCBub3JtYWxpemVMaW5rLCB0b1ZhbGlkVVJMIH0gZnJvbSBcIi4uL2RhdGEvdXJsXCI7XG5pbXBvcnQgeyBzaG91bGRTaG93Qm91bmRpbmdCb3ggfSBmcm9tIFwiLi4vZWxlbWVudC90cmFuc2Zvcm1IYW5kbGVzXCI7XG5pbXBvcnQgeyBhY3Rpb25VbmxvY2tBbGxFbGVtZW50cyB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvbkVsZW1lbnRMb2NrXCI7XG5pbXBvcnQgeyBGb250cyB9IGZyb20gXCIuLi9zY2VuZS9Gb250c1wiO1xuaW1wb3J0IHsgZ2V0RnJhbWVFbGVtZW50cywgaXNDdXJzb3JJbkZyYW1lLCBiaW5kRWxlbWVudHNUb0ZyYW1lc0FmdGVyRHVwbGljYXRpb24sIGFkZEVsZW1lbnRzVG9GcmFtZSwgcmVwbGFjZUFsbEVsZW1lbnRzSW5GcmFtZSwgcmVtb3ZlRWxlbWVudHNGcm9tRnJhbWUsIGdldEVsZW1lbnRzSW5SZXNpemluZ0ZyYW1lLCBnZXRFbGVtZW50c0luTmV3RnJhbWUsIGdldENvbnRhaW5pbmdGcmFtZSwgZWxlbWVudE92ZXJsYXBzV2l0aEZyYW1lLCB1cGRhdGVGcmFtZU1lbWJlcnNoaXBPZlNlbGVjdGVkRWxlbWVudHMsIGlzRWxlbWVudEluRnJhbWUgfSBmcm9tIFwiLi4vZnJhbWVcIjtcbmltcG9ydCB7IGV4Y2x1ZGVFbGVtZW50c0luRnJhbWVzRnJvbVNlbGVjdGlvbiwgbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMgfSBmcm9tIFwiLi4vc2NlbmUvc2VsZWN0aW9uXCI7XG5pbXBvcnQgeyBhY3Rpb25QYXN0ZSB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvbkNsaXBib2FyZFwiO1xuaW1wb3J0IHsgYWN0aW9uUmVtb3ZlQWxsRWxlbWVudHNGcm9tRnJhbWUsIGFjdGlvblNlbGVjdEFsbEVsZW1lbnRzSW5GcmFtZSB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvbkZyYW1lXCI7XG5pbXBvcnQgeyBhY3Rpb25Ub2dnbGVIYW5kVG9vbCwgem9vbVRvRml0IH0gZnJvbSBcIi4uL2FjdGlvbnMvYWN0aW9uQ2FudmFzXCI7XG5pbXBvcnQgeyBqb3RhaVN0b3JlIH0gZnJvbSBcIi4uL2pvdGFpXCI7XG5pbXBvcnQgeyBhY3RpdmVDb25maXJtRGlhbG9nQXRvbSB9IGZyb20gXCIuL0FjdGl2ZUNvbmZpcm1EaWFsb2dcIjtcbmltcG9ydCB7IGFjdGlvbldyYXBUZXh0SW5Db250YWluZXIgfSBmcm9tIFwiLi4vYWN0aW9ucy9hY3Rpb25Cb3VuZFRleHRcIjtcbmltcG9ydCBCcmF2ZU1lYXN1cmVUZXh0RXJyb3IgZnJvbSBcIi4vQnJhdmVNZWFzdXJlVGV4dEVycm9yXCI7XG5pbXBvcnQgeyBhY3RpdmVFeWVEcm9wcGVyQXRvbSB9IGZyb20gXCIuL0V5ZURyb3BwZXJcIjtcbmltcG9ydCB7IGNvbnZlcnRUb0V4Y2FsaWRyYXdFbGVtZW50cyB9IGZyb20gXCIuLi9kYXRhL3RyYW5zZm9ybVwiO1xuaW1wb3J0IHsgaXNTaWRlYmFyRG9ja2VkQXRvbSB9IGZyb20gXCIuL1NpZGViYXIvU2lkZWJhclwiO1xuaW1wb3J0IHsgU3RhdGljQ2FudmFzLCBJbnRlcmFjdGl2ZUNhbnZhcyB9IGZyb20gXCIuL2NhbnZhc2VzXCI7XG5pbXBvcnQgeyBSZW5kZXJlciB9IGZyb20gXCIuLi9zY2VuZS9SZW5kZXJlclwiO1xuaW1wb3J0IHsgU2hhcGVDYWNoZSB9IGZyb20gXCIuLi9zY2VuZS9TaGFwZUNhY2hlXCI7XG5jb25zdCBBcHBDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dChudWxsKTtcbmNvbnN0IEFwcFByb3BzQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQobnVsbCk7XG5jb25zdCBkZXZpY2VDb250ZXh0SW5pdGlhbFZhbHVlID0ge1xuICBpc1NtU2NyZWVuOiBmYWxzZSxcbiAgaXNNb2JpbGU6IGZhbHNlLFxuICBpc1RvdWNoU2NyZWVuOiBmYWxzZSxcbiAgY2FuRGV2aWNlRml0U2lkZWJhcjogZmFsc2UsXG4gIGlzTGFuZHNjYXBlOiBmYWxzZVxufTtcbmNvbnN0IERldmljZUNvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KGRldmljZUNvbnRleHRJbml0aWFsVmFsdWUpO1xuRGV2aWNlQ29udGV4dC5kaXNwbGF5TmFtZSA9IFwiRGV2aWNlQ29udGV4dFwiO1xuZXhwb3J0IGNvbnN0IEV4Y2FsaWRyYXdDb250YWluZXJDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dCh7XG4gIGNvbnRhaW5lcjogbnVsbCxcbiAgaWQ6IG51bGxcbn0pO1xuRXhjYWxpZHJhd0NvbnRhaW5lckNvbnRleHQuZGlzcGxheU5hbWUgPSBcIkV4Y2FsaWRyYXdDb250YWluZXJDb250ZXh0XCI7XG5jb25zdCBFeGNhbGlkcmF3RWxlbWVudHNDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dChbXSk7XG5FeGNhbGlkcmF3RWxlbWVudHNDb250ZXh0LmRpc3BsYXlOYW1lID0gXCJFeGNhbGlkcmF3RWxlbWVudHNDb250ZXh0XCI7XG5jb25zdCBFeGNhbGlkcmF3QXBwU3RhdGVDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGdldERlZmF1bHRBcHBTdGF0ZSgpKSwge1xuICB3aWR0aDogMCxcbiAgaGVpZ2h0OiAwLFxuICBvZmZzZXRMZWZ0OiAwLFxuICBvZmZzZXRUb3A6IDBcbn0pKTtcbkV4Y2FsaWRyYXdBcHBTdGF0ZUNvbnRleHQuZGlzcGxheU5hbWUgPSBcIkV4Y2FsaWRyYXdBcHBTdGF0ZUNvbnRleHRcIjtcbmNvbnN0IEV4Y2FsaWRyYXdTZXRBcHBTdGF0ZUNvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KCgpID0+IHtcbiAgY29uc29sZS53YXJuKFwidW5pdGlhbGl6ZWQgRXhjYWxpZHJhd1NldEFwcFN0YXRlQ29udGV4dCBjb250ZXh0IVwiKTtcbn0pO1xuRXhjYWxpZHJhd1NldEFwcFN0YXRlQ29udGV4dC5kaXNwbGF5TmFtZSA9IFwiRXhjYWxpZHJhd1NldEFwcFN0YXRlQ29udGV4dFwiO1xuY29uc3QgRXhjYWxpZHJhd0FjdGlvbk1hbmFnZXJDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dChudWxsKTtcbkV4Y2FsaWRyYXdBY3Rpb25NYW5hZ2VyQ29udGV4dC5kaXNwbGF5TmFtZSA9IFwiRXhjYWxpZHJhd0FjdGlvbk1hbmFnZXJDb250ZXh0XCI7XG5leHBvcnQgY29uc3QgdXNlQXBwID0gKCkgPT4gdXNlQ29udGV4dChBcHBDb250ZXh0KTtcbmV4cG9ydCBjb25zdCB1c2VBcHBQcm9wcyA9ICgpID0+IHVzZUNvbnRleHQoQXBwUHJvcHNDb250ZXh0KTtcbmV4cG9ydCBjb25zdCB1c2VEZXZpY2UgPSAoKSA9PiB1c2VDb250ZXh0KERldmljZUNvbnRleHQpO1xuZXhwb3J0IGNvbnN0IHVzZUV4Y2FsaWRyYXdDb250YWluZXIgPSAoKSA9PiB1c2VDb250ZXh0KEV4Y2FsaWRyYXdDb250YWluZXJDb250ZXh0KTtcbmV4cG9ydCBjb25zdCB1c2VFeGNhbGlkcmF3RWxlbWVudHMgPSAoKSA9PiB1c2VDb250ZXh0KEV4Y2FsaWRyYXdFbGVtZW50c0NvbnRleHQpO1xuZXhwb3J0IGNvbnN0IHVzZUV4Y2FsaWRyYXdBcHBTdGF0ZSA9ICgpID0+IHVzZUNvbnRleHQoRXhjYWxpZHJhd0FwcFN0YXRlQ29udGV4dCk7XG5leHBvcnQgY29uc3QgdXNlRXhjYWxpZHJhd1NldEFwcFN0YXRlID0gKCkgPT4gdXNlQ29udGV4dChFeGNhbGlkcmF3U2V0QXBwU3RhdGVDb250ZXh0KTtcbmV4cG9ydCBjb25zdCB1c2VFeGNhbGlkcmF3QWN0aW9uTWFuYWdlciA9ICgpID0+IHVzZUNvbnRleHQoRXhjYWxpZHJhd0FjdGlvbk1hbmFnZXJDb250ZXh0KTtcbmxldCBkaWRUYXBUd2ljZSA9IGZhbHNlO1xubGV0IHRhcHBlZFR3aWNlVGltZXIgPSAwO1xubGV0IGlzSG9sZGluZ1NwYWNlID0gZmFsc2U7XG5sZXQgaXNQYW5uaW5nID0gZmFsc2U7XG5sZXQgaXNEcmFnZ2luZ1Njcm9sbEJhciA9IGZhbHNlO1xubGV0IGN1cnJlbnRTY3JvbGxCYXJzID0ge1xuICBob3Jpem9udGFsOiBudWxsLFxuICB2ZXJ0aWNhbDogbnVsbFxufTtcbmxldCB0b3VjaFRpbWVvdXQgPSAwO1xubGV0IGludmFsaWRhdGVDb250ZXh0TWVudSA9IGZhbHNlO1xuLyoqXG4gKiBNYXAgb2YgeW91dHViZSBlbWJlZCB2aWRlbyBzdGF0ZXNcbiAqL1xuXG5jb25zdCBZT1VUVUJFX1ZJREVPX1NUQVRFUyA9IG5ldyBNYXAoKTtcbmxldCBJU19QTEFJTl9QQVNURSA9IGZhbHNlO1xubGV0IElTX1BMQUlOX1BBU1RFX1RJTUVSID0gMDtcbmxldCBQTEFJTl9QQVNURV9UT0FTVF9TSE9XTiA9IGZhbHNlO1xubGV0IGxhc3RQb2ludGVyVXAgPSBudWxsO1xuY29uc3QgZ2VzdHVyZSA9IHtcbiAgcG9pbnRlcnM6IG5ldyBNYXAoKSxcbiAgbGFzdENlbnRlcjogbnVsbCxcbiAgaW5pdGlhbERpc3RhbmNlOiBudWxsLFxuICBpbml0aWFsU2NhbGU6IG51bGxcbn07XG5cbmNsYXNzIEFwcCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgdmFyIF9hO1xuXG4gICAgc3VwZXIocHJvcHMpO1xuICAgIHRoaXMuaW50ZXJhY3RpdmVDYW52YXMgPSBudWxsO1xuICAgIHRoaXMudW5tb3VudGVkID0gZmFsc2U7XG4gICAgdGhpcy5kZXZpY2UgPSBkZXZpY2VDb250ZXh0SW5pdGlhbFZhbHVlO1xuICAgIHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZiA9IFJlYWN0LmNyZWF0ZVJlZigpO1xuICAgIHRoaXMuZmlsZXMgPSB7fTtcbiAgICB0aGlzLmltYWdlQ2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5pRnJhbWVSZWZzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGFzdFBvaW50ZXJEb3duID0gbnVsbDtcbiAgICB0aGlzLmxhc3RQb2ludGVyVXAgPSBudWxsO1xuICAgIHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24gPSB7XG4gICAgICB4OiAwLFxuICAgICAgeTogMFxuICAgIH07XG5cbiAgICB0aGlzLnVwZGF0ZUVtYmVkZGFibGVzID0gKCkgPT4ge1xuICAgICAgY29uc3QgZW1iZWRkYWJsZUVsZW1lbnRzID0gbmV3IE1hcCgpO1xuICAgICAgbGV0IHVwZGF0ZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkuZmlsdGVyKGVsZW1lbnQgPT4ge1xuICAgICAgICBpZiAoaXNFbWJlZGRhYmxlRWxlbWVudChlbGVtZW50KSkge1xuICAgICAgICAgIGVtYmVkZGFibGVFbGVtZW50cy5zZXQoZWxlbWVudC5pZCwgdHJ1ZSk7XG5cbiAgICAgICAgICBpZiAoZWxlbWVudC52YWxpZGF0ZWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgdXBkYXRlZCA9IHRydWU7XG4gICAgICAgICAgICBjb25zdCB2YWxpZGF0ZWQgPSBlbWJlZGRhYmxlVVJMVmFsaWRhdG9yKGVsZW1lbnQubGluaywgdGhpcy5wcm9wcy52YWxpZGF0ZUVtYmVkZGFibGUpO1xuICAgICAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgICAgIHZhbGlkYXRlZFxuICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgU2hhcGVDYWNoZS5kZWxldGUoZWxlbWVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG5cbiAgICAgIGlmICh1cGRhdGVkKSB7XG4gICAgICAgIHRoaXMuc2NlbmUuaW5mb3JtTXV0YXRpb24oKTtcbiAgICAgIH0gLy8gR0NcblxuXG4gICAgICB0aGlzLmlGcmFtZVJlZnMuZm9yRWFjaCgocmVmLCBpZCkgPT4ge1xuICAgICAgICBpZiAoIWVtYmVkZGFibGVFbGVtZW50cy5oYXMoaWQpKSB7XG4gICAgICAgICAgdGhpcy5pRnJhbWVSZWZzLmRlbGV0ZShpZCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLmdldEZyYW1lTmFtZURPTUlkID0gZnJhbWVFbGVtZW50ID0+IHtcbiAgICAgIHJldHVybiBgJHt0aGlzLmlkfS1mcmFtZS1uYW1lLSR7ZnJhbWVFbGVtZW50LmlkfWA7XG4gICAgfTtcblxuICAgIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUgPSB7XG4gICAgICBnZXQ6IGZyYW1lRWxlbWVudCA9PiB7XG4gICAgICAgIGxldCBib3VuZHMgPSB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLl9jYWNoZS5nZXQoZnJhbWVFbGVtZW50LmlkKTtcblxuICAgICAgICBpZiAoIWJvdW5kcyB8fCBib3VuZHMuem9vbSAhPT0gdGhpcy5zdGF0ZS56b29tLnZhbHVlIHx8IGJvdW5kcy52ZXJzaW9uTm9uY2UgIT09IGZyYW1lRWxlbWVudC52ZXJzaW9uTm9uY2UpIHtcbiAgICAgICAgICBjb25zdCBmcmFtZU5hbWVEaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldEZyYW1lTmFtZURPTUlkKGZyYW1lRWxlbWVudCkpO1xuXG4gICAgICAgICAgaWYgKGZyYW1lTmFtZURpdikge1xuICAgICAgICAgICAgY29uc3QgYm94ID0gZnJhbWVOYW1lRGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgY29uc3QgYm94U2NlbmVUb3BMZWZ0ID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKHtcbiAgICAgICAgICAgICAgY2xpZW50WDogYm94LngsXG4gICAgICAgICAgICAgIGNsaWVudFk6IGJveC55XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgICAgIGNvbnN0IGJveFNjZW5lQm90dG9tUmlnaHQgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICAgICAgICBjbGllbnRYOiBib3gucmlnaHQsXG4gICAgICAgICAgICAgIGNsaWVudFk6IGJveC5ib3R0b21cbiAgICAgICAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgICAgICAgYm91bmRzID0ge1xuICAgICAgICAgICAgICB4OiBib3hTY2VuZVRvcExlZnQueCxcbiAgICAgICAgICAgICAgeTogYm94U2NlbmVUb3BMZWZ0LnksXG4gICAgICAgICAgICAgIHdpZHRoOiBib3hTY2VuZUJvdHRvbVJpZ2h0LnggLSBib3hTY2VuZVRvcExlZnQueCxcbiAgICAgICAgICAgICAgaGVpZ2h0OiBib3hTY2VuZUJvdHRvbVJpZ2h0LnkgLSBib3hTY2VuZVRvcExlZnQueSxcbiAgICAgICAgICAgICAgYW5nbGU6IDAsXG4gICAgICAgICAgICAgIHpvb206IHRoaXMuc3RhdGUuem9vbS52YWx1ZSxcbiAgICAgICAgICAgICAgdmVyc2lvbk5vbmNlOiBmcmFtZUVsZW1lbnQudmVyc2lvbk5vbmNlXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLl9jYWNoZS5zZXQoZnJhbWVFbGVtZW50LmlkLCBib3VuZHMpO1xuXG4gICAgICAgICAgICByZXR1cm4gYm91bmRzO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGJvdW5kcztcbiAgICAgIH0sXG5cbiAgICAgIC8qKlxuICAgICAgICogQHByaXZhdGVcbiAgICAgICAqL1xuICAgICAgX2NhY2hlOiBuZXcgTWFwKClcbiAgICB9O1xuXG4gICAgdGhpcy5yZW5kZXJGcmFtZU5hbWVzID0gKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLnN0YXRlLmZyYW1lUmVuZGVyaW5nLmVuYWJsZWQgfHwgIXRoaXMuc3RhdGUuZnJhbWVSZW5kZXJpbmcubmFtZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaXNEYXJrVGhlbWUgPSB0aGlzLnN0YXRlLnRoZW1lID09PSBcImRhcmtcIjtcbiAgICAgIHJldHVybiB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRGcmFtZXMoKS5tYXAoKGYsIGluZGV4KSA9PiB7XG4gICAgICAgIGlmICghaXNFbGVtZW50SW5WaWV3cG9ydChmLCB0aGlzLmNhbnZhcy53aWR0aCAvIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLCB0aGlzLmNhbnZhcy5oZWlnaHQgLyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywge1xuICAgICAgICAgIG9mZnNldExlZnQ6IHRoaXMuc3RhdGUub2Zmc2V0TGVmdCxcbiAgICAgICAgICBvZmZzZXRUb3A6IHRoaXMuc3RhdGUub2Zmc2V0VG9wLFxuICAgICAgICAgIHNjcm9sbFg6IHRoaXMuc3RhdGUuc2Nyb2xsWCxcbiAgICAgICAgICBzY3JvbGxZOiB0aGlzLnN0YXRlLnNjcm9sbFksXG4gICAgICAgICAgem9vbTogdGhpcy5zdGF0ZS56b29tXG4gICAgICAgIH0pKSB7XG4gICAgICAgICAgLy8gaWYgZnJhbWUgbm90IHZpc2libGUsIGRvbid0IHJlbmRlciBpdHMgbmFtZVxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgIHk6IHkxXG4gICAgICAgIH0gPSBzY2VuZUNvb3Jkc1RvVmlld3BvcnRDb29yZHMoe1xuICAgICAgICAgIHNjZW5lWDogZi54LFxuICAgICAgICAgIHNjZW5lWTogZi55XG4gICAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeDogeDJcbiAgICAgICAgfSA9IHNjZW5lQ29vcmRzVG9WaWV3cG9ydENvb3Jkcyh7XG4gICAgICAgICAgc2NlbmVYOiBmLnggKyBmLndpZHRoLFxuICAgICAgICAgIHNjZW5lWTogZi55ICsgZi5oZWlnaHRcbiAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIGNvbnN0IEZSQU1FX05BTUVfR0FQID0gMjA7XG4gICAgICAgIGNvbnN0IEZSQU1FX05BTUVfRURJVF9QQURESU5HID0gNjtcblxuICAgICAgICBjb25zdCByZXNldCA9ICgpID0+IHtcbiAgICAgICAgICB2YXIgX2E7XG5cbiAgICAgICAgICBpZiAoKChfYSA9IGYubmFtZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnRyaW0oKSkgPT09IFwiXCIpIHtcbiAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZiwge1xuICAgICAgICAgICAgICBuYW1lOiBudWxsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGVkaXRpbmdGcmFtZTogbnVsbFxuICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGxldCBmcmFtZU5hbWVKU1g7XG5cbiAgICAgICAgaWYgKGYuaWQgPT09IHRoaXMuc3RhdGUuZWRpdGluZ0ZyYW1lKSB7XG4gICAgICAgICAgY29uc3QgZnJhbWVOYW1lSW5FZGl0ID0gZi5uYW1lID09IG51bGwgPyBgRnJhbWUgJHtpbmRleCArIDF9YCA6IGYubmFtZTtcbiAgICAgICAgICBmcmFtZU5hbWVKU1ggPSBfanN4KFwiaW5wdXRcIiwge1xuICAgICAgICAgICAgYXV0b0ZvY3VzOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IGZyYW1lTmFtZUluRWRpdCxcbiAgICAgICAgICAgIG9uQ2hhbmdlOiBlID0+IHtcbiAgICAgICAgICAgICAgbXV0YXRlRWxlbWVudChmLCB7XG4gICAgICAgICAgICAgICAgbmFtZTogZS50YXJnZXQudmFsdWVcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb25CbHVyOiAoKSA9PiByZXNldCgpLFxuICAgICAgICAgICAgb25LZXlEb3duOiBldmVudCA9PiB7XG4gICAgICAgICAgICAgIC8vIGZvciBzb21lIGluZXhwbGljYWJsZSByZWFzb24sIGBvbkJsdXJgIHRyaWdnZXJlZCBvbiBFU0NcbiAgICAgICAgICAgICAgLy8gZG9lcyBub3QgcmVzZXQgYHN0YXRlLmVkaXRpbmdGcmFtZWAgZGVzcGl0ZSBiZWluZyBjYWxsZWQsXG4gICAgICAgICAgICAgIC8vIGFuZCB3ZSBuZWVkIHRvIHJlc2V0IGl0IGhlcmUgYXMgd2VsbFxuICAgICAgICAgICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkVTQ0FQRSB8fCBldmVudC5rZXkgPT09IEtFWVMuRU5URVIpIHtcbiAgICAgICAgICAgICAgICByZXNldCgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgICAgYmFja2dyb3VuZDogdGhpcy5zdGF0ZS52aWV3QmFja2dyb3VuZENvbG9yLFxuICAgICAgICAgICAgICBmaWx0ZXI6IGlzRGFya1RoZW1lID8gVEhFTUVfRklMVEVSIDogXCJub25lXCIsXG4gICAgICAgICAgICAgIHpJbmRleDogMixcbiAgICAgICAgICAgICAgYm9yZGVyOiBcIm5vbmVcIixcbiAgICAgICAgICAgICAgZGlzcGxheTogXCJibG9ja1wiLFxuICAgICAgICAgICAgICBwYWRkaW5nOiBgJHtGUkFNRV9OQU1FX0VESVRfUEFERElOR31weGAsXG4gICAgICAgICAgICAgIGJvcmRlclJhZGl1czogNCxcbiAgICAgICAgICAgICAgYm94U2hhZG93OiBcImluc2V0IDAgMCAwIDFweCB2YXIoLS1jb2xvci1wcmltYXJ5KVwiLFxuICAgICAgICAgICAgICBmb250RmFtaWx5OiBcIkFzc2lzdGFudFwiLFxuICAgICAgICAgICAgICBmb250U2l6ZTogXCIxNHB4XCIsXG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZVkoLSR7RlJBTUVfTkFNRV9FRElUX1BBRERJTkd9cHgpYCxcbiAgICAgICAgICAgICAgY29sb3I6IFwidmFyKC0tY29sb3ItZ3JheS04MClcIixcbiAgICAgICAgICAgICAgb3ZlcmZsb3c6IFwiaGlkZGVuXCIsXG4gICAgICAgICAgICAgIG1heFdpZHRoOiBgJHtNYXRoLm1pbih4MiAtIHgxIC0gRlJBTUVfTkFNRV9FRElUX1BBRERJTkcsIGRvY3VtZW50LmJvZHkuY2xpZW50V2lkdGggLSB4MSAtIEZSQU1FX05BTUVfRURJVF9QQURESU5HKX1weGBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzaXplOiBmcmFtZU5hbWVJbkVkaXQubGVuZ3RoICsgMSB8fCAxLFxuICAgICAgICAgICAgZGlyOiBcImF1dG9cIixcbiAgICAgICAgICAgIGF1dG9Db21wbGV0ZTogXCJvZmZcIixcbiAgICAgICAgICAgIGF1dG9DYXBpdGFsaXplOiBcIm9mZlwiLFxuICAgICAgICAgICAgYXV0b0NvcnJlY3Q6IFwib2ZmXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmcmFtZU5hbWVKU1ggPSBmLm5hbWUgPT0gbnVsbCB8fCBmLm5hbWUudHJpbSgpID09PSBcIlwiID8gYEZyYW1lICR7aW5kZXggKyAxfWAgOiBmLm5hbWUudHJpbSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIF9qc3goXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgaWQ6IHRoaXMuZ2V0RnJhbWVOYW1lRE9NSWQoZiksXG4gICAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgIHBvc2l0aW9uOiBcImFic29sdXRlXCIsXG4gICAgICAgICAgICB0b3A6IGAke3kxIC0gRlJBTUVfTkFNRV9HQVAgLSB0aGlzLnN0YXRlLm9mZnNldFRvcH1weGAsXG4gICAgICAgICAgICBsZWZ0OiBgJHt4MSAtIHRoaXMuc3RhdGUub2Zmc2V0TGVmdCAtICh0aGlzLnN0YXRlLmVkaXRpbmdGcmFtZSA9PT0gZi5pZCA/IEZSQU1FX05BTUVfRURJVF9QQURESU5HIDogMCl9cHhgLFxuICAgICAgICAgICAgekluZGV4OiAyLFxuICAgICAgICAgICAgZm9udFNpemU6IFwiMTRweFwiLFxuICAgICAgICAgICAgY29sb3I6IGlzRGFya1RoZW1lID8gXCJ2YXIoLS1jb2xvci1ncmF5LTYwKVwiIDogXCJ2YXIoLS1jb2xvci1ncmF5LTUwKVwiLFxuICAgICAgICAgICAgd2lkdGg6IFwibWF4LWNvbnRlbnRcIixcbiAgICAgICAgICAgIG1heFdpZHRoOiBgJHt4MiAtIHgxICsgRlJBTUVfTkFNRV9FRElUX1BBRERJTkcgKiAyfXB4YCxcbiAgICAgICAgICAgIG92ZXJmbG93OiBmLmlkID09PSB0aGlzLnN0YXRlLmVkaXRpbmdGcmFtZSA/IFwidmlzaWJsZVwiIDogXCJoaWRkZW5cIixcbiAgICAgICAgICAgIHdoaXRlU3BhY2U6IFwibm93cmFwXCIsXG4gICAgICAgICAgICB0ZXh0T3ZlcmZsb3c6IFwiZWxsaXBzaXNcIixcbiAgICAgICAgICAgIGN1cnNvcjogQ1VSU09SX1RZUEUuTU9WRSxcbiAgICAgICAgICAgIHBvaW50ZXJFdmVudHM6IHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkID8gUE9JTlRFUl9FVkVOVFMuZGlzYWJsZWQgOiBQT0lOVEVSX0VWRU5UUy5pbmhlcml0RnJvbVVJXG4gICAgICAgICAgfSxcbiAgICAgICAgICBvblBvaW50ZXJEb3duOiBldmVudCA9PiB0aGlzLmhhbmRsZUNhbnZhc1BvaW50ZXJEb3duKGV2ZW50KSxcbiAgICAgICAgICBvbldoZWVsOiBldmVudCA9PiB0aGlzLmhhbmRsZVdoZWVsKGV2ZW50KSxcbiAgICAgICAgICBvbkNvbnRleHRNZW51OiB0aGlzLmhhbmRsZUNhbnZhc0NvbnRleHRNZW51LFxuICAgICAgICAgIG9uRG91YmxlQ2xpY2s6ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBlZGl0aW5nRnJhbWU6IGYuaWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgIGNoaWxkcmVuOiBmcmFtZU5hbWVKU1hcbiAgICAgICAgfSksIGYuaWQpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuZm9jdXNDb250YWluZXIgPSAoKSA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIChfYSA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZm9jdXMoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5nZXRTY2VuZUVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCA9ICgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpO1xuICAgIH07XG5cbiAgICB0aGlzLmdldFNjZW5lRWxlbWVudHMgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5vbkluc2VydEVsZW1lbnRzID0gZWxlbWVudHMgPT4ge1xuICAgICAgdGhpcy5hZGRFbGVtZW50c0Zyb21QYXN0ZU9yTGlicmFyeSh7XG4gICAgICAgIGVsZW1lbnRzLFxuICAgICAgICBwb3NpdGlvbjogXCJjZW50ZXJcIixcbiAgICAgICAgZmlsZXM6IG51bGxcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLm9uRXhwb3J0SW1hZ2UgPSAodHlwZSwgZWxlbWVudHMpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIHRyYWNrRXZlbnQoXCJleHBvcnRcIiwgdHlwZSwgXCJ1aVwiKTtcbiAgICAgIGNvbnN0IGZpbGVIYW5kbGUgPSB5aWVsZCBleHBvcnRDYW52YXModHlwZSwgZWxlbWVudHMsIHRoaXMuc3RhdGUsIHRoaXMuZmlsZXMsIHtcbiAgICAgICAgZXhwb3J0QmFja2dyb3VuZDogdGhpcy5zdGF0ZS5leHBvcnRCYWNrZ3JvdW5kLFxuICAgICAgICBuYW1lOiB0aGlzLnN0YXRlLm5hbWUsXG4gICAgICAgIHZpZXdCYWNrZ3JvdW5kQ29sb3I6IHRoaXMuc3RhdGUudmlld0JhY2tncm91bmRDb2xvclxuICAgICAgfSkuY2F0Y2gobXV0ZUZTQWJvcnRFcnJvcikuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnJvci5tZXNzYWdlXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmV4cG9ydEVtYmVkU2NlbmUgJiYgZmlsZUhhbmRsZSAmJiBpc0ltYWdlRmlsZUhhbmRsZShmaWxlSGFuZGxlKSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBmaWxlSGFuZGxlXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5vcGVuRXllRHJvcHBlciA9ICh7XG4gICAgICB0eXBlXG4gICAgfSkgPT4ge1xuICAgICAgam90YWlTdG9yZS5zZXQoYWN0aXZlRXllRHJvcHBlckF0b20sIHtcbiAgICAgICAgc3dhcFByZXZpZXdPbkFsdDogdHJ1ZSxcbiAgICAgICAgcHJldmlld1R5cGU6IHR5cGUgPT09IFwic3Ryb2tlXCIgPyBcInN0cm9rZUNvbG9yXCIgOiBcImJhY2tncm91bmRDb2xvclwiLFxuICAgICAgICBvblNlbGVjdDogKGNvbG9yLCBldmVudCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHNob3VsZFVwZGF0ZVN0cm9rZUNvbG9yID0gdHlwZSA9PT0gXCJiYWNrZ3JvdW5kXCIgJiYgZXZlbnQuYWx0S2V5IHx8IHR5cGUgPT09IFwic3Ryb2tlXCIgJiYgIWV2ZW50LmFsdEtleTtcbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICAgICAgaWYgKCFzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCB8fCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICAgICAgaWYgKHNob3VsZFVwZGF0ZVN0cm9rZUNvbG9yKSB7XG4gICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtU3Ryb2tlQ29sb3I6IGNvbG9yXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgY3VycmVudEl0ZW1CYWNrZ3JvdW5kQ29sb3I6IGNvbG9yXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNjZW5lKHtcbiAgICAgICAgICAgICAgZWxlbWVudHM6IHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkubWFwKGVsID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbZWwuaWRdKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWwsIHtcbiAgICAgICAgICAgICAgICAgICAgW3Nob3VsZFVwZGF0ZVN0cm9rZUNvbG9yID8gXCJzdHJva2VDb2xvclwiIDogXCJiYWNrZ3JvdW5kQ29sb3JcIl06IGNvbG9yXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZWw7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGtlZXBPcGVuT25BbHQ6IGZhbHNlXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5zeW5jQWN0aW9uUmVzdWx0ID0gd2l0aEJhdGNoZWRVcGRhdGVzKGFjdGlvblJlc3VsdCA9PiB7XG4gICAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lLCBfZiwgX2csIF9oLCBfajtcblxuICAgICAgaWYgKHRoaXMudW5tb3VudGVkIHx8IGFjdGlvblJlc3VsdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgZWRpdGluZ0VsZW1lbnQgPSBudWxsO1xuXG4gICAgICBpZiAoYWN0aW9uUmVzdWx0LmVsZW1lbnRzKSB7XG4gICAgICAgIGFjdGlvblJlc3VsdC5lbGVtZW50cy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgIHZhciBfYTtcblxuICAgICAgICAgIGlmICgoKF9hID0gdGhpcy5zdGF0ZS5lZGl0aW5nRWxlbWVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmlkKSA9PT0gZWxlbWVudC5pZCAmJiB0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50ICE9PSBlbGVtZW50ICYmIGlzTm9uRGVsZXRlZEVsZW1lbnQoZWxlbWVudCkpIHtcbiAgICAgICAgICAgIGVkaXRpbmdFbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhhY3Rpb25SZXN1bHQuZWxlbWVudHMpO1xuXG4gICAgICAgIGlmIChhY3Rpb25SZXN1bHQuY29tbWl0VG9IaXN0b3J5KSB7XG4gICAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChhY3Rpb25SZXN1bHQuZmlsZXMpIHtcbiAgICAgICAgdGhpcy5maWxlcyA9IGFjdGlvblJlc3VsdC5yZXBsYWNlRmlsZXMgPyBhY3Rpb25SZXN1bHQuZmlsZXMgOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZmlsZXMpLCBhY3Rpb25SZXN1bHQuZmlsZXMpO1xuICAgICAgICB0aGlzLmFkZE5ld0ltYWdlc1RvSW1hZ2VDYWNoZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWN0aW9uUmVzdWx0LmFwcFN0YXRlIHx8IGVkaXRpbmdFbGVtZW50IHx8IHRoaXMuc3RhdGUuY29udGV4dE1lbnUpIHtcbiAgICAgICAgaWYgKGFjdGlvblJlc3VsdC5jb21taXRUb0hpc3RvcnkpIHtcbiAgICAgICAgICB0aGlzLmhpc3RvcnkucmVzdW1lUmVjb3JkaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdmlld01vZGVFbmFibGVkID0gKChfYSA9IGFjdGlvblJlc3VsdCA9PT0gbnVsbCB8fCBhY3Rpb25SZXN1bHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGFjdGlvblJlc3VsdC5hcHBTdGF0ZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnZpZXdNb2RlRW5hYmxlZCkgfHwgZmFsc2U7XG4gICAgICAgIGxldCB6ZW5Nb2RlRW5hYmxlZCA9ICgoX2IgPSBhY3Rpb25SZXN1bHQgPT09IG51bGwgfHwgYWN0aW9uUmVzdWx0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhY3Rpb25SZXN1bHQuYXBwU3RhdGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi56ZW5Nb2RlRW5hYmxlZCkgfHwgZmFsc2U7XG4gICAgICAgIGxldCBncmlkU2l6ZSA9ICgoX2MgPSBhY3Rpb25SZXN1bHQgPT09IG51bGwgfHwgYWN0aW9uUmVzdWx0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhY3Rpb25SZXN1bHQuYXBwU3RhdGUpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5ncmlkU2l6ZSkgfHwgbnVsbDtcbiAgICAgICAgY29uc3QgdGhlbWUgPSAoKF9kID0gYWN0aW9uUmVzdWx0ID09PSBudWxsIHx8IGFjdGlvblJlc3VsdCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYWN0aW9uUmVzdWx0LmFwcFN0YXRlKSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QudGhlbWUpIHx8IHRoaXMucHJvcHMudGhlbWUgfHwgVEhFTUUuTElHSFQ7XG4gICAgICAgIGxldCBuYW1lID0gKF9mID0gKF9lID0gYWN0aW9uUmVzdWx0ID09PSBudWxsIHx8IGFjdGlvblJlc3VsdCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYWN0aW9uUmVzdWx0LmFwcFN0YXRlKSA9PT0gbnVsbCB8fCBfZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2UubmFtZSkgIT09IG51bGwgJiYgX2YgIT09IHZvaWQgMCA/IF9mIDogdGhpcy5zdGF0ZS5uYW1lO1xuICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSAoX2ggPSAoX2cgPSBhY3Rpb25SZXN1bHQgPT09IG51bGwgfHwgYWN0aW9uUmVzdWx0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhY3Rpb25SZXN1bHQuYXBwU3RhdGUpID09PSBudWxsIHx8IF9nID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZy5lcnJvck1lc3NhZ2UpICE9PSBudWxsICYmIF9oICE9PSB2b2lkIDAgPyBfaCA6IHRoaXMuc3RhdGUuZXJyb3JNZXNzYWdlO1xuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy52aWV3TW9kZUVuYWJsZWQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICB2aWV3TW9kZUVuYWJsZWQgPSB0aGlzLnByb3BzLnZpZXdNb2RlRW5hYmxlZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy56ZW5Nb2RlRW5hYmxlZCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgIHplbk1vZGVFbmFibGVkID0gdGhpcy5wcm9wcy56ZW5Nb2RlRW5hYmxlZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy5ncmlkTW9kZUVuYWJsZWQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICBncmlkU2l6ZSA9IHRoaXMucHJvcHMuZ3JpZE1vZGVFbmFibGVkID8gR1JJRF9TSVpFIDogbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcm9wcy5uYW1lICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgbmFtZSA9IHRoaXMucHJvcHMubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVkaXRpbmdFbGVtZW50ID0gZWRpdGluZ0VsZW1lbnQgfHwgKChfaiA9IGFjdGlvblJlc3VsdC5hcHBTdGF0ZSkgPT09IG51bGwgfHwgX2ogPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9qLmVkaXRpbmdFbGVtZW50KSB8fCBudWxsO1xuXG4gICAgICAgIGlmIChlZGl0aW5nRWxlbWVudCA9PT0gbnVsbCB8fCBlZGl0aW5nRWxlbWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogZWRpdGluZ0VsZW1lbnQuaXNEZWxldGVkKSB7XG4gICAgICAgICAgZWRpdGluZ0VsZW1lbnQgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSA9PiB7XG4gICAgICAgICAgLy8gdXNpbmcgT2JqZWN0LmFzc2lnbiBpbnN0ZWFkIG9mIHNwcmVhZCB0byBmb29sIFRTIDQuMi4yKyBpbnRvXG4gICAgICAgICAgLy8gcmVnYXJkaW5nIHRoZSByZXN1bHRpbmcgdHlwZSBhcyBub3QgY29udGFpbmluZyB1bmRlZmluZWRcbiAgICAgICAgICAvLyAod2hpY2ggdGhlIGZvbGxvd2luZyBleHByZXNzaW9uIHdpbGwgbmV2ZXIgY29udGFpbilcbiAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihhY3Rpb25SZXN1bHQuYXBwU3RhdGUgfHwge30sIHtcbiAgICAgICAgICAgIC8vIE5PVEUgdGhpcyB3aWxsIHByZXZlbnQgb3BlbmluZyBjb250ZXh0IG1lbnUgdXNpbmcgYW4gYWN0aW9uXG4gICAgICAgICAgICAvLyBvciBwcm9ncmFtbWF0aWNhbGx5IGZyb20gdGhlIGhvc3QsIHNvIGl0IHdpbGwgbmVlZCB0byBiZVxuICAgICAgICAgICAgLy8gcmV3cml0dGVuIGxhdGVyXG4gICAgICAgICAgICBjb250ZXh0TWVudTogbnVsbCxcbiAgICAgICAgICAgIGVkaXRpbmdFbGVtZW50LFxuICAgICAgICAgICAgdmlld01vZGVFbmFibGVkLFxuICAgICAgICAgICAgemVuTW9kZUVuYWJsZWQsXG4gICAgICAgICAgICBncmlkU2l6ZSxcbiAgICAgICAgICAgIHRoZW1lLFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgaWYgKGFjdGlvblJlc3VsdC5zeW5jSGlzdG9yeSkge1xuICAgICAgICAgICAgdGhpcy5oaXN0b3J5LnNldEN1cnJlbnRTdGF0ZSh0aGlzLnN0YXRlLCB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pOyAvLyBMaWZlY3ljbGVcblxuICAgIHRoaXMub25CbHVyID0gd2l0aEJhdGNoZWRVcGRhdGVzKCgpID0+IHtcbiAgICAgIGlzSG9sZGluZ1NwYWNlID0gZmFsc2U7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgaXNCaW5kaW5nRW5hYmxlZDogdHJ1ZVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm9uVW5sb2FkID0gKCkgPT4ge1xuICAgICAgdGhpcy5vbkJsdXIoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5kaXNhYmxlRXZlbnQgPSBldmVudCA9PiB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlc2V0SGlzdG9yeSA9ICgpID0+IHtcbiAgICAgIHRoaXMuaGlzdG9yeS5jbGVhcigpO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogUmVzZXRzIHNjZW5lICYgaGlzdG9yeS5cbiAgICAgKiAhIERvIG5vdCB1c2UgdG8gY2xlYXIgc2NlbmUgdXNlciBhY3Rpb24gIVxuICAgICAqL1xuXG5cbiAgICB0aGlzLnJlc2V0U2NlbmUgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMob3B0cyA9PiB7XG4gICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhbXSk7XG4gICAgICB0aGlzLnNldFN0YXRlKHN0YXRlID0+IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZ2V0RGVmYXVsdEFwcFN0YXRlKCkpLCB7XG4gICAgICAgIGlzTG9hZGluZzogKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5yZXNldExvYWRpbmdTdGF0ZSkgPyBmYWxzZSA6IHN0YXRlLmlzTG9hZGluZyxcbiAgICAgICAgdGhlbWU6IHRoaXMuc3RhdGUudGhlbWVcbiAgICAgIH0pKTtcbiAgICAgIHRoaXMucmVzZXRIaXN0b3J5KCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmluaXRpYWxpemVTY2VuZSA9ICgpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIHZhciBfYjtcblxuICAgICAgaWYgKFwibGF1bmNoUXVldWVcIiBpbiB3aW5kb3cgJiYgXCJMYXVuY2hQYXJhbXNcIiBpbiB3aW5kb3cpIHtcbiAgICAgICAgd2luZG93LmxhdW5jaFF1ZXVlLnNldENvbnN1bWVyKGxhdW5jaFBhcmFtcyA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgaWYgKCFsYXVuY2hQYXJhbXMuZmlsZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZmlsZUhhbmRsZSA9IGxhdW5jaFBhcmFtcy5maWxlc1swXTtcbiAgICAgICAgICBjb25zdCBibG9iID0geWllbGQgZmlsZUhhbmRsZS5nZXRGaWxlKCk7XG4gICAgICAgICAgdGhpcy5sb2FkRmlsZVRvQ2FudmFzKG5ldyBGaWxlKFtibG9iXSwgYmxvYi5uYW1lIHx8IFwiXCIsIHtcbiAgICAgICAgICAgIHR5cGU6IGJsb2IudHlwZVxuICAgICAgICAgIH0pLCBmaWxlSGFuZGxlKTtcbiAgICAgICAgfSkpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5wcm9wcy50aGVtZSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICB0aGVtZTogdGhpcy5wcm9wcy50aGVtZVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLnN0YXRlLmlzTG9hZGluZykge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc0xvYWRpbmc6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGxldCBpbml0aWFsRGF0YSA9IG51bGw7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGluaXRpYWxEYXRhID0gKHlpZWxkIHRoaXMucHJvcHMuaW5pdGlhbERhdGEpIHx8IG51bGw7XG5cbiAgICAgICAgaWYgKGluaXRpYWxEYXRhID09PSBudWxsIHx8IGluaXRpYWxEYXRhID09PSB2b2lkIDAgPyB2b2lkIDAgOiBpbml0aWFsRGF0YS5saWJyYXJ5SXRlbXMpIHtcbiAgICAgICAgICB0aGlzLmxpYnJhcnkudXBkYXRlTGlicmFyeSh7XG4gICAgICAgICAgICBsaWJyYXJ5SXRlbXM6IGluaXRpYWxEYXRhLmxpYnJhcnlJdGVtcyxcbiAgICAgICAgICAgIG1lcmdlOiB0cnVlXG4gICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICBpbml0aWFsRGF0YSA9IHtcbiAgICAgICAgICBhcHBTdGF0ZToge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnJvci5tZXNzYWdlIHx8IFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgZHVyaW5nIGltcG9ydGluZyBvciByZXN0b3Jpbmcgc2NlbmUgZGF0YVwiXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzY2VuZSA9IHJlc3RvcmUoaW5pdGlhbERhdGEsIG51bGwsIG51bGwsIHtcbiAgICAgICAgcmVwYWlyQmluZGluZ3M6IHRydWVcbiAgICAgIH0pO1xuICAgICAgc2NlbmUuYXBwU3RhdGUgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNjZW5lLmFwcFN0YXRlKSwge1xuICAgICAgICB0aGVtZTogdGhpcy5wcm9wcy50aGVtZSB8fCBzY2VuZS5hcHBTdGF0ZS50aGVtZSxcbiAgICAgICAgLy8gd2UncmUgZmFsbGluZyBiYWNrIHRvIGN1cnJlbnQgKHByZS1pbml0KSBzdGF0ZSB3aGVuIGRlY2lkaW5nXG4gICAgICAgIC8vIHdoZXRoZXIgdG8gb3BlbiB0aGUgbGlicmFyeSwgdG8gaGFuZGxlIGEgY2FzZSB3aGVyZSB3ZVxuICAgICAgICAvLyB1cGRhdGUgdGhlIHN0YXRlIG91dHNpZGUgb2YgaW5pdGlhbERhdGEgKGUuZy4gd2hlbiBsb2FkaW5nIHRoZSBhcHBcbiAgICAgICAgLy8gd2l0aCBhIGxpYnJhcnkgaW5zdGFsbCBsaW5rLCB3aGljaCBzaG91bGQgYXV0by1vcGVuIHRoZSBsaWJyYXJ5KVxuICAgICAgICBvcGVuU2lkZWJhcjogKChfYiA9IHNjZW5lLmFwcFN0YXRlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iub3BlblNpZGViYXIpIHx8IHRoaXMuc3RhdGUub3BlblNpZGViYXIsXG4gICAgICAgIGFjdGl2ZVRvb2w6IHNjZW5lLmFwcFN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJpbWFnZVwiID8gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzY2VuZS5hcHBTdGF0ZS5hY3RpdmVUb29sKSwge1xuICAgICAgICAgIHR5cGU6IFwic2VsZWN0aW9uXCJcbiAgICAgICAgfSkgOiBzY2VuZS5hcHBTdGF0ZS5hY3RpdmVUb29sLFxuICAgICAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgICAgICB0b2FzdDogdGhpcy5zdGF0ZS50b2FzdFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChpbml0aWFsRGF0YSA9PT0gbnVsbCB8fCBpbml0aWFsRGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogaW5pdGlhbERhdGEuc2Nyb2xsVG9Db250ZW50KSB7XG4gICAgICAgIHNjZW5lLmFwcFN0YXRlID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzY2VuZS5hcHBTdGF0ZSksIGNhbGN1bGF0ZVNjcm9sbENlbnRlcihzY2VuZS5lbGVtZW50cywgT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzY2VuZS5hcHBTdGF0ZSksIHtcbiAgICAgICAgICB3aWR0aDogdGhpcy5zdGF0ZS53aWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IHRoaXMuc3RhdGUuaGVpZ2h0LFxuICAgICAgICAgIG9mZnNldFRvcDogdGhpcy5zdGF0ZS5vZmZzZXRUb3AsXG4gICAgICAgICAgb2Zmc2V0TGVmdDogdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0XG4gICAgICAgIH0pKSk7XG4gICAgICB9IC8vIEZvbnRGYWNlU2V0IGxvYWRpbmdkb25lIGV2ZW50IHdlIGxpc3RlbiBvbiBtYXkgbm90IGFsd2F5cyBmaXJlXG4gICAgICAvLyAobG9va2luZyBhdCB5b3UgU2FmYXJpKSwgc28gb24gaW5pdCB3ZSBtYW51YWxseSBsb2FkIGZvbnRzIGZvciBjdXJyZW50XG4gICAgICAvLyB0ZXh0IGVsZW1lbnRzIG9uIGNhbnZhcywgYW5kIHJlcmVuZGVyIHRoZW0gb25jZSBkb25lLiBUaGlzIGFsc29cbiAgICAgIC8vIHNlZW1zIGZhc3RlciBldmVuIGluIGJyb3dzZXJzIHRoYXQgZG8gZmlyZSB0aGUgbG9hZGluZ2RvbmUgZXZlbnQuXG5cblxuICAgICAgdGhpcy5mb250cy5sb2FkRm9udHNGb3JFbGVtZW50cyhzY2VuZS5lbGVtZW50cyk7XG4gICAgICB0aGlzLnJlc2V0SGlzdG9yeSgpO1xuICAgICAgdGhpcy5zeW5jQWN0aW9uUmVzdWx0KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2NlbmUpLCB7XG4gICAgICAgIGNvbW1pdFRvSGlzdG9yeTogdHJ1ZVxuICAgICAgfSkpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5yZWZyZXNoRGV2aWNlU3RhdGUgPSBjb250YWluZXIgPT4ge1xuICAgICAgY29uc3Qge1xuICAgICAgICB3aWR0aCxcbiAgICAgICAgaGVpZ2h0XG4gICAgICB9ID0gY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3Qgc2lkZWJhckJyZWFrcG9pbnQgPSB0aGlzLnByb3BzLlVJT3B0aW9ucy5kb2NrZWRTaWRlYmFyQnJlYWtwb2ludCAhPSBudWxsID8gdGhpcy5wcm9wcy5VSU9wdGlvbnMuZG9ja2VkU2lkZWJhckJyZWFrcG9pbnQgOiBNUV9SSUdIVF9TSURFQkFSX01JTl9XSURUSDtcbiAgICAgIHRoaXMuZGV2aWNlID0gdXBkYXRlT2JqZWN0KHRoaXMuZGV2aWNlLCB7XG4gICAgICAgIGlzTGFuZHNjYXBlOiB3aWR0aCA+IGhlaWdodCxcbiAgICAgICAgaXNTbVNjcmVlbjogd2lkdGggPCBNUV9TTV9NQVhfV0lEVEgsXG4gICAgICAgIGlzTW9iaWxlOiB3aWR0aCA8IE1RX01BWF9XSURUSF9QT1JUUkFJVCB8fCBoZWlnaHQgPCBNUV9NQVhfSEVJR0hUX0xBTkRTQ0FQRSAmJiB3aWR0aCA8IE1RX01BWF9XSURUSF9MQU5EU0NBUEUsXG4gICAgICAgIGNhbkRldmljZUZpdFNpZGViYXI6IHdpZHRoID4gc2lkZWJhckJyZWFrcG9pbnRcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLm9uUmVzaXplID0gd2l0aEJhdGNoZWRVcGRhdGVzKCgpID0+IHtcbiAgICAgIHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkuZm9yRWFjaChlbGVtZW50ID0+IFNoYXBlQ2FjaGUuZGVsZXRlKGVsZW1lbnQpKTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe30pO1xuICAgIH0pO1xuXG4gICAgdGhpcy5yZW5kZXJJbnRlcmFjdGl2ZVNjZW5lQ2FsbGJhY2sgPSAoe1xuICAgICAgYXRMZWFzdE9uZVZpc2libGVFbGVtZW50LFxuICAgICAgc2Nyb2xsQmFycyxcbiAgICAgIGVsZW1lbnRzXG4gICAgfSkgPT4ge1xuICAgICAgaWYgKHNjcm9sbEJhcnMpIHtcbiAgICAgICAgY3VycmVudFNjcm9sbEJhcnMgPSBzY3JvbGxCYXJzO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzY3JvbGxlZE91dHNpZGUgPSAvLyBoaWRlIHdoZW4gZWRpdGluZyB0ZXh0XG4gICAgICBpc1RleHRFbGVtZW50KHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQpID8gZmFsc2UgOiAhYXRMZWFzdE9uZVZpc2libGVFbGVtZW50ICYmIGVsZW1lbnRzLmxlbmd0aCA+IDA7XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLnNjcm9sbGVkT3V0c2lkZSAhPT0gc2Nyb2xsZWRPdXRzaWRlKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNjcm9sbGVkT3V0c2lkZVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zY2hlZHVsZUltYWdlUmVmcmVzaCgpO1xuICAgIH07XG5cbiAgICB0aGlzLm9uU2Nyb2xsID0gZGVib3VuY2UoKCkgPT4ge1xuICAgICAgY29uc3Qge1xuICAgICAgICBvZmZzZXRUb3AsXG4gICAgICAgIG9mZnNldExlZnRcbiAgICAgIH0gPSB0aGlzLmdldENhbnZhc09mZnNldHMoKTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoc3RhdGUgPT4ge1xuICAgICAgICBpZiAoc3RhdGUub2Zmc2V0TGVmdCA9PT0gb2Zmc2V0TGVmdCAmJiBzdGF0ZS5vZmZzZXRUb3AgPT09IG9mZnNldFRvcCkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvZmZzZXRUb3AsXG4gICAgICAgICAgb2Zmc2V0TGVmdFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfSwgU0NST0xMX1RJTUVPVVQpOyAvLyBDb3B5L3Bhc3RlXG5cbiAgICB0aGlzLm9uQ3V0ID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgY29uc3QgaXNFeGNhbGlkcmF3QWN0aXZlID0gKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jb250YWlucyhkb2N1bWVudC5hY3RpdmVFbGVtZW50KTtcblxuICAgICAgaWYgKCFpc0V4Y2FsaWRyYXdBY3RpdmUgfHwgaXNXcml0YWJsZUVsZW1lbnQoZXZlbnQudGFyZ2V0KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY3V0QWxsKCk7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSk7XG4gICAgdGhpcy5vbkNvcHkgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBpc0V4Y2FsaWRyYXdBY3RpdmUgPSAoX2EgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNvbnRhaW5zKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpO1xuXG4gICAgICBpZiAoIWlzRXhjYWxpZHJhd0FjdGl2ZSB8fCBpc1dyaXRhYmxlRWxlbWVudChldmVudC50YXJnZXQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb3B5QWxsKCk7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmN1dEFsbCA9ICgpID0+IHtcbiAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkN1dCwgXCJrZXlib2FyZFwiKTtcbiAgICB9O1xuXG4gICAgdGhpcy5jb3B5QWxsID0gKCkgPT4ge1xuICAgICAgdGhpcy5hY3Rpb25NYW5hZ2VyLmV4ZWN1dGVBY3Rpb24oYWN0aW9uQ29weSwgXCJrZXlib2FyZFwiKTtcbiAgICB9O1xuXG4gICAgdGhpcy5vblRvdWNoU3RhcnQgPSBldmVudCA9PiB7XG4gICAgICAvLyBmaXggZm9yIEFwcGxlIFBlbmNpbCBTY3JpYmJsZVxuICAgICAgLy8gT24gQW5kcm9pZCwgcHJldmVudGluZyB0aGUgZXZlbnQgd291bGQgZGlzYWJsZSBjb250ZXh0TWVudSBvbiB0YXAtaG9sZFxuICAgICAgaWYgKCFpc0FuZHJvaWQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFkaWRUYXBUd2ljZSkge1xuICAgICAgICBkaWRUYXBUd2ljZSA9IHRydWU7XG4gICAgICAgIGNsZWFyVGltZW91dCh0YXBwZWRUd2ljZVRpbWVyKTtcbiAgICAgICAgdGFwcGVkVHdpY2VUaW1lciA9IHdpbmRvdy5zZXRUaW1lb3V0KEFwcC5yZXNldFRhcFR3aWNlLCBUQVBfVFdJQ0VfVElNRU9VVCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gaW5zZXJ0IHRleHQgb25seSBpZiB3ZSB0YXBwZWQgdHdpY2Ugd2l0aCBhIHNpbmdsZSBmaW5nZXJcbiAgICAgIC8vIGV2ZW50LnRvdWNoZXMubGVuZ3RoID09PSAxIHdpbGwgYWxzbyBwcmV2ZW50IGluc2VydGluZyB0ZXh0IHdoZW4gdXNlcidzIHpvb21pbmdcblxuXG4gICAgICBpZiAoZGlkVGFwVHdpY2UgJiYgZXZlbnQudG91Y2hlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgY29uc3QgdG91Y2ggPSBldmVudC50b3VjaGVzWzBdOyAvLyBAdHMtaWdub3JlXG5cbiAgICAgICAgdGhpcy5oYW5kbGVDYW52YXNEb3VibGVDbGljayh7XG4gICAgICAgICAgY2xpZW50WDogdG91Y2guY2xpZW50WCxcbiAgICAgICAgICBjbGllbnRZOiB0b3VjaC5jbGllbnRZXG4gICAgICAgIH0pO1xuICAgICAgICBkaWRUYXBUd2ljZSA9IGZhbHNlO1xuICAgICAgICBjbGVhclRpbWVvdXQodGFwcGVkVHdpY2VUaW1lcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0FuZHJvaWQpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50LnRvdWNoZXMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe30sIHRoaXMuc3RhdGUpLFxuICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMub25Ub3VjaEVuZCA9IGV2ZW50ID0+IHtcbiAgICAgIHRoaXMucmVzZXRDb250ZXh0TWVudVRpbWVyKCk7XG5cbiAgICAgIGlmIChldmVudC50b3VjaGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgcHJldmlvdXNTZWxlY3RlZEVsZW1lbnRJZHM6IHt9LFxuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHModGhpcy5zdGF0ZS5wcmV2aW91c1NlbGVjdGVkRWxlbWVudElkcywgdGhpcy5zdGF0ZSlcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnZXN0dXJlLnBvaW50ZXJzLmNsZWFyKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMucGFzdGVGcm9tQ2xpcGJvYXJkID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIHZhciBfYywgX2QsIF9lO1xuXG4gICAgICBjb25zdCBpc1BsYWluUGFzdGUgPSAhIShJU19QTEFJTl9QQVNURSAmJiBldmVudCk7IC8vICM2ODZcblxuICAgICAgY29uc3QgdGFyZ2V0ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICAgIGNvbnN0IGlzRXhjYWxpZHJhd0FjdGl2ZSA9IChfYyA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MuY29udGFpbnModGFyZ2V0KTtcblxuICAgICAgaWYgKGV2ZW50ICYmICFpc0V4Y2FsaWRyYXdBY3RpdmUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBlbGVtZW50VW5kZXJDdXJzb3IgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueCwgdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi55KTtcblxuICAgICAgaWYgKGV2ZW50ICYmICghKGVsZW1lbnRVbmRlckN1cnNvciBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50KSB8fCBpc1dyaXRhYmxlRWxlbWVudCh0YXJnZXQpKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIG11c3QgYmUgY2FsbGVkIGluIHRoZSBzYW1lIGZyYW1lICh0aHVzIGJlZm9yZSBhbnkgYXdhaXRzKSBhcyB0aGUgcGFzdGVcbiAgICAgIC8vIGV2ZW50IGVsc2Ugc29tZSBicm93c2VycyAoRkYuLi4pIHdpbGwgY2xlYXIgdGhlIGNsaXBib2FyZERhdGFcbiAgICAgIC8vIChzb21ldGhpbmcgc29tZXRoaW5nIHNlY3VyaXR5KVxuXG5cbiAgICAgIGxldCBmaWxlID0gKF9kID0gZXZlbnQgPT09IG51bGwgfHwgZXZlbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGV2ZW50LmNsaXBib2FyZERhdGEpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5maWxlc1swXTtcbiAgICAgIGNvbnN0IGRhdGEgPSB5aWVsZCBwYXJzZUNsaXBib2FyZChldmVudCwgaXNQbGFpblBhc3RlKTtcblxuICAgICAgaWYgKCFmaWxlICYmIGRhdGEudGV4dCAmJiAhaXNQbGFpblBhc3RlKSB7XG4gICAgICAgIGNvbnN0IHN0cmluZyA9IGRhdGEudGV4dC50cmltKCk7XG5cbiAgICAgICAgaWYgKHN0cmluZy5zdGFydHNXaXRoKFwiPHN2Z1wiKSAmJiBzdHJpbmcuZW5kc1dpdGgoXCI8L3N2Zz5cIikpIHtcbiAgICAgICAgICAvLyBpZ25vcmUgU1ZHIHZhbGlkYXRpb24vbm9ybWFsaXphdGlvbiB3aGljaCB3aWxsIGJlIGRvbmUgZHVyaW5nIGltYWdlXG4gICAgICAgICAgLy8gaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICBmaWxlID0gU1ZHU3RyaW5nVG9GaWxlKHN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qge1xuICAgICAgICB4OiBzY2VuZVgsXG4gICAgICAgIHk6IHNjZW5lWVxuICAgICAgfSA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICAgIGNsaWVudFg6IHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueCxcbiAgICAgICAgY2xpZW50WTogdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi55XG4gICAgICB9LCB0aGlzLnN0YXRlKTsgLy8gcHJlZmVyIHNwcmVhZHNoZWV0IGRhdGEgb3ZlciBpbWFnZSBmaWxlIChNUyBPZmZpY2UvTGlicmUgT2ZmaWNlKVxuXG4gICAgICBpZiAoaXNTdXBwb3J0ZWRJbWFnZUZpbGUoZmlsZSkgJiYgIWRhdGEuc3ByZWFkc2hlZXQpIHtcbiAgICAgICAgY29uc3QgaW1hZ2VFbGVtZW50ID0gdGhpcy5jcmVhdGVJbWFnZUVsZW1lbnQoe1xuICAgICAgICAgIHNjZW5lWCxcbiAgICAgICAgICBzY2VuZVlcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW5zZXJ0SW1hZ2VFbGVtZW50KGltYWdlRWxlbWVudCwgZmlsZSk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZUltYWdlRGltZW5zaW9ucyhpbWFnZUVsZW1lbnQpO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHtcbiAgICAgICAgICAgIFtpbWFnZUVsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgfSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucHJvcHMub25QYXN0ZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGlmICgoeWllbGQgdGhpcy5wcm9wcy5vblBhc3RlKGRhdGEsIGV2ZW50KSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChkYXRhLmVycm9yTWVzc2FnZSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGRhdGEuZXJyb3JNZXNzYWdlXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLnNwcmVhZHNoZWV0ICYmICFpc1BsYWluUGFzdGUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgcGFzdGVEaWFsb2c6IHtcbiAgICAgICAgICAgIGRhdGE6IGRhdGEuc3ByZWFkc2hlZXQsXG4gICAgICAgICAgICBzaG93bjogdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGRhdGEuZWxlbWVudHMpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSBkYXRhLnByb2dyYW1tYXRpY0FQSSA/IGNvbnZlcnRUb0V4Y2FsaWRyYXdFbGVtZW50cyhkYXRhLmVsZW1lbnRzKSA6IGRhdGEuZWxlbWVudHM7IC8vIFRPRE8gcmVtb3ZlIGZvcm1hdHRpbmcgZnJvbSBlbGVtZW50cyBpZiBpc1BsYWluUGFzdGVcblxuICAgICAgICB0aGlzLmFkZEVsZW1lbnRzRnJvbVBhc3RlT3JMaWJyYXJ5KHtcbiAgICAgICAgICBlbGVtZW50cyxcbiAgICAgICAgICBmaWxlczogZGF0YS5maWxlcyB8fCBudWxsLFxuICAgICAgICAgIHBvc2l0aW9uOiBcImN1cnNvclwiLFxuICAgICAgICAgIHJldGFpblNlZWQ6IGlzUGxhaW5QYXN0ZVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS50ZXh0KSB7XG4gICAgICAgIGNvbnN0IG1heWJlVXJsID0gZXh0cmFjdFNyYyhkYXRhLnRleHQpO1xuXG4gICAgICAgIGlmICghaXNQbGFpblBhc3RlICYmIGVtYmVkZGFibGVVUkxWYWxpZGF0b3IobWF5YmVVcmwsIHRoaXMucHJvcHMudmFsaWRhdGVFbWJlZGRhYmxlKSAmJiAoL14oaHR0cHxodHRwcyk6XFwvXFwvW15cXHMvJC4/I10uW15cXHNdKiQvLnRlc3QobWF5YmVVcmwpIHx8ICgoX2UgPSBnZXRFbWJlZExpbmsobWF5YmVVcmwpKSA9PT0gbnVsbCB8fCBfZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2UudHlwZSkgPT09IFwidmlkZW9cIikpIHtcbiAgICAgICAgICBjb25zdCBlbWJlZGRhYmxlID0gdGhpcy5pbnNlcnRFbWJlZGRhYmxlRWxlbWVudCh7XG4gICAgICAgICAgICBzY2VuZVgsXG4gICAgICAgICAgICBzY2VuZVksXG4gICAgICAgICAgICBsaW5rOiBub3JtYWxpemVMaW5rKG1heWJlVXJsKVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGVtYmVkZGFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHtcbiAgICAgICAgICAgICAgICBbZW1iZWRkYWJsZS5pZF06IHRydWVcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hZGRUZXh0RnJvbVBhc3RlKGRhdGEudGV4dCwgaXNQbGFpblBhc3RlKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRBY3RpdmVUb29sKHtcbiAgICAgICAgdHlwZTogXCJzZWxlY3Rpb25cIlxuICAgICAgfSk7XG4gICAgICBldmVudCA9PT0gbnVsbCB8fCBldmVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9KSk7XG5cbiAgICB0aGlzLmFkZEVsZW1lbnRzRnJvbVBhc3RlT3JMaWJyYXJ5ID0gb3B0cyA9PiB7XG4gICAgICBjb25zdCBlbGVtZW50cyA9IHJlc3RvcmVFbGVtZW50cyhvcHRzLmVsZW1lbnRzLCBudWxsLCB1bmRlZmluZWQpO1xuICAgICAgY29uc3QgW21pblgsIG1pblksIG1heFgsIG1heFldID0gZ2V0Q29tbW9uQm91bmRzKGVsZW1lbnRzKTtcbiAgICAgIGNvbnN0IGVsZW1lbnRzQ2VudGVyWCA9IGRpc3RhbmNlKG1pblgsIG1heFgpIC8gMjtcbiAgICAgIGNvbnN0IGVsZW1lbnRzQ2VudGVyWSA9IGRpc3RhbmNlKG1pblksIG1heFkpIC8gMjtcbiAgICAgIGNvbnN0IGNsaWVudFggPSB0eXBlb2Ygb3B0cy5wb3NpdGlvbiA9PT0gXCJvYmplY3RcIiA/IG9wdHMucG9zaXRpb24uY2xpZW50WCA6IG9wdHMucG9zaXRpb24gPT09IFwiY3Vyc29yXCIgPyB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLnggOiB0aGlzLnN0YXRlLndpZHRoIC8gMiArIHRoaXMuc3RhdGUub2Zmc2V0TGVmdDtcbiAgICAgIGNvbnN0IGNsaWVudFkgPSB0eXBlb2Ygb3B0cy5wb3NpdGlvbiA9PT0gXCJvYmplY3RcIiA/IG9wdHMucG9zaXRpb24uY2xpZW50WSA6IG9wdHMucG9zaXRpb24gPT09IFwiY3Vyc29yXCIgPyB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLnkgOiB0aGlzLnN0YXRlLmhlaWdodCAvIDIgKyB0aGlzLnN0YXRlLm9mZnNldFRvcDtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgeCxcbiAgICAgICAgeVxuICAgICAgfSA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICAgIGNsaWVudFgsXG4gICAgICAgIGNsaWVudFlcbiAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgY29uc3QgZHggPSB4IC0gZWxlbWVudHNDZW50ZXJYO1xuICAgICAgY29uc3QgZHkgPSB5IC0gZWxlbWVudHNDZW50ZXJZO1xuICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQoZHgsIGR5LCB0aGlzLnN0YXRlLmdyaWRTaXplKTtcbiAgICAgIGNvbnN0IG5ld0VsZW1lbnRzID0gZHVwbGljYXRlRWxlbWVudHMoZWxlbWVudHMubWFwKGVsZW1lbnQgPT4ge1xuICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlbWVudCwge1xuICAgICAgICAgIHg6IGVsZW1lbnQueCArIGdyaWRYIC0gbWluWCxcbiAgICAgICAgICB5OiBlbGVtZW50LnkgKyBncmlkWSAtIG1pbllcbiAgICAgICAgfSk7XG4gICAgICB9KSwge1xuICAgICAgICByYW5kb21pemVTZWVkOiAhb3B0cy5yZXRhaW5TZWVkXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IG5leHRFbGVtZW50cyA9IFsuLi50aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCAuLi5uZXdFbGVtZW50c107XG4gICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhuZXh0RWxlbWVudHMpO1xuICAgICAgbmV3RWxlbWVudHMuZm9yRWFjaChuZXdFbGVtZW50ID0+IHtcbiAgICAgICAgaWYgKGlzVGV4dEVsZW1lbnQobmV3RWxlbWVudCkgJiYgaXNCb3VuZFRvQ29udGFpbmVyKG5ld0VsZW1lbnQpKSB7XG4gICAgICAgICAgY29uc3QgY29udGFpbmVyID0gZ2V0Q29udGFpbmVyRWxlbWVudChuZXdFbGVtZW50KTtcbiAgICAgICAgICByZWRyYXdUZXh0Qm91bmRpbmdCb3gobmV3RWxlbWVudCwgY29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGlmIChvcHRzLmZpbGVzKSB7XG4gICAgICAgIHRoaXMuZmlsZXMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZmlsZXMpLCBvcHRzLmZpbGVzKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgY29uc3QgbmV4dEVsZW1lbnRzVG9TZWxlY3QgPSBleGNsdWRlRWxlbWVudHNJbkZyYW1lc0Zyb21TZWxlY3Rpb24obmV3RWxlbWVudHMpO1xuICAgICAgdGhpcy5zZXRTdGF0ZShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZSksIHtcbiAgICAgICAgLy8ga2VlcCBzaWRlYmFyIChwcmVzdW1hYmx5IHRoZSBsaWJyYXJ5KSBvcGVuIGlmIGl0J3MgZG9ja2VkIGFuZFxuICAgICAgICAvLyBjYW4gZml0LlxuICAgICAgICAvL1xuICAgICAgICAvLyBOb3RlLCB3ZSBzaG91bGQgY2xvc2UgdGhlIHNpZGViYXIgb25seSBpZiB3ZSdyZSBkcm9wcGluZyBpdGVtc1xuICAgICAgICAvLyBmcm9tIGxpYnJhcnksIG5vdCB3aGVuIHBhc3RpbmcgZnJvbSBjbGlwYm9hcmQuIEFsYXMuXG4gICAgICAgIG9wZW5TaWRlYmFyOiB0aGlzLnN0YXRlLm9wZW5TaWRlYmFyICYmIHRoaXMuZGV2aWNlLmNhbkRldmljZUZpdFNpZGViYXIgJiYgam90YWlTdG9yZS5nZXQoaXNTaWRlYmFyRG9ja2VkQXRvbSkgPyB0aGlzLnN0YXRlLm9wZW5TaWRlYmFyIDogbnVsbFxuICAgICAgfSksIHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICBlZGl0aW5nR3JvdXBJZDogbnVsbCxcbiAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBuZXh0RWxlbWVudHNUb1NlbGVjdC5yZWR1Y2UoKGFjYywgZWxlbWVudCkgPT4ge1xuICAgICAgICAgIGlmICghaXNCb3VuZFRvQ29udGFpbmVyKGVsZW1lbnQpKSB7XG4gICAgICAgICAgICBhY2NbZWxlbWVudC5pZF0gPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIH0sIHt9KVxuICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgdGhpcy5zdGF0ZSwgdGhpcykpLCAoKSA9PiB7XG4gICAgICAgIGlmIChvcHRzLmZpbGVzKSB7XG4gICAgICAgICAgdGhpcy5hZGROZXdJbWFnZXNUb0ltYWdlQ2FjaGUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB0aGlzLnNldEFjdGl2ZVRvb2woe1xuICAgICAgICB0eXBlOiBcInNlbGVjdGlvblwiXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZXRBcHBTdGF0ZSA9IChzdGF0ZSwgY2FsbGJhY2spID0+IHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoc3RhdGUsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZW1vdmVQb2ludGVyID0gZXZlbnQgPT4ge1xuICAgICAgaWYgKHRvdWNoVGltZW91dCkge1xuICAgICAgICB0aGlzLnJlc2V0Q29udGV4dE1lbnVUaW1lcigpO1xuICAgICAgfVxuXG4gICAgICBnZXN0dXJlLnBvaW50ZXJzLmRlbGV0ZShldmVudC5wb2ludGVySWQpO1xuICAgIH07XG5cbiAgICB0aGlzLnRvZ2dsZUxvY2sgPSAoc291cmNlID0gXCJ1aVwiKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuc3RhdGUuYWN0aXZlVG9vbC5sb2NrZWQpIHtcbiAgICAgICAgdHJhY2tFdmVudChcInRvb2xiYXJcIiwgXCJ0b2dnbGVMb2NrXCIsIGAke3NvdXJjZX0gKCR7dGhpcy5kZXZpY2UuaXNNb2JpbGUgPyBcIm1vYmlsZVwiIDogXCJkZXNrdG9wXCJ9KWApO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYWN0aXZlVG9vbDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5hY3RpdmVUb29sKSwgdXBkYXRlQWN0aXZlVG9vbCh0aGlzLnN0YXRlLCBwcmV2U3RhdGUuYWN0aXZlVG9vbC5sb2NrZWQgPyB7XG4gICAgICAgICAgICB0eXBlOiBcInNlbGVjdGlvblwiXG4gICAgICAgICAgfSA6IHByZXZTdGF0ZS5hY3RpdmVUb29sKSksIHtcbiAgICAgICAgICAgIGxvY2tlZDogIXByZXZTdGF0ZS5hY3RpdmVUb29sLmxvY2tlZFxuICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy51cGRhdGVGcmFtZVJlbmRlcmluZyA9IG9wdHMgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICB2YXIgX2EsIF9iLCBfYywgX2Q7XG5cbiAgICAgICAgY29uc3QgbmV4dCA9IHR5cGVvZiBvcHRzID09PSBcImZ1bmN0aW9uXCIgPyBvcHRzKHByZXZTdGF0ZS5mcmFtZVJlbmRlcmluZykgOiBvcHRzO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGZyYW1lUmVuZGVyaW5nOiB7XG4gICAgICAgICAgICBlbmFibGVkOiAoX2EgPSBuZXh0ID09PSBudWxsIHx8IG5leHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG5leHQuZW5hYmxlZCkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogcHJldlN0YXRlLmZyYW1lUmVuZGVyaW5nLmVuYWJsZWQsXG4gICAgICAgICAgICBjbGlwOiAoX2IgPSBuZXh0ID09PSBudWxsIHx8IG5leHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG5leHQuY2xpcCkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogcHJldlN0YXRlLmZyYW1lUmVuZGVyaW5nLmNsaXAsXG4gICAgICAgICAgICBuYW1lOiAoX2MgPSBuZXh0ID09PSBudWxsIHx8IG5leHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG5leHQubmFtZSkgIT09IG51bGwgJiYgX2MgIT09IHZvaWQgMCA/IF9jIDogcHJldlN0YXRlLmZyYW1lUmVuZGVyaW5nLm5hbWUsXG4gICAgICAgICAgICBvdXRsaW5lOiAoX2QgPSBuZXh0ID09PSBudWxsIHx8IG5leHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG5leHQub3V0bGluZSkgIT09IG51bGwgJiYgX2QgIT09IHZvaWQgMCA/IF9kIDogcHJldlN0YXRlLmZyYW1lUmVuZGVyaW5nLm91dGxpbmVcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy50b2dnbGVQZW5Nb2RlID0gKCkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHBlbk1vZGU6ICFwcmV2U3RhdGUucGVuTW9kZVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMub25IYW5kVG9vbFRvZ2dsZSA9ICgpID0+IHtcbiAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvblRvZ2dsZUhhbmRUb29sKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFpvb21zIG9uIGNhbnZhcyB2aWV3cG9ydCBjZW50ZXJcbiAgICAgKi9cblxuXG4gICAgdGhpcy56b29tQ2FudmFzID0gKFxuICAgIC8qKiBkZWNpbWFsIGZyYWN0aW9uIGJldHdlZW4gMC4xICgxMCUgem9vbSkgYW5kIDMwICgzMDAwJSB6b29tKSAqL1xuICAgIHZhbHVlKSA9PiB7XG4gICAgICB0aGlzLnNldFN0YXRlKE9iamVjdC5hc3NpZ24oe30sIGdldFN0YXRlRm9yWm9vbSh7XG4gICAgICAgIHZpZXdwb3J0WDogdGhpcy5zdGF0ZS53aWR0aCAvIDIgKyB0aGlzLnN0YXRlLm9mZnNldExlZnQsXG4gICAgICAgIHZpZXdwb3J0WTogdGhpcy5zdGF0ZS5oZWlnaHQgLyAyICsgdGhpcy5zdGF0ZS5vZmZzZXRUb3AsXG4gICAgICAgIG5leHRab29tOiBnZXROb3JtYWxpemVkWm9vbSh2YWx1ZSlcbiAgICAgIH0sIHRoaXMuc3RhdGUpKSk7XG4gICAgfTtcblxuICAgIHRoaXMuY2FuY2VsSW5Qcm9ncmVzQW5pbWF0aW9uID0gbnVsbDtcblxuICAgIHRoaXMuc2Nyb2xsVG9Db250ZW50ID0gKHRhcmdldCA9IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIG9wdHMpID0+IHtcbiAgICAgIHZhciBfYSwgX2I7XG5cbiAgICAgIChfYSA9IHRoaXMuY2FuY2VsSW5Qcm9ncmVzQW5pbWF0aW9uKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY2FsbCh0aGlzKTsgLy8gY29udmVydCBwcm92aWRlZCB0YXJnZXQgaW50byBFeGNhbGlkcmF3RWxlbWVudFtdIGlmIG5lY2Vzc2FyeVxuXG4gICAgICBjb25zdCB0YXJnZXRFbGVtZW50cyA9IEFycmF5LmlzQXJyYXkodGFyZ2V0KSA/IHRhcmdldCA6IFt0YXJnZXRdO1xuICAgICAgbGV0IHpvb20gPSB0aGlzLnN0YXRlLnpvb207XG4gICAgICBsZXQgc2Nyb2xsWCA9IHRoaXMuc3RhdGUuc2Nyb2xsWDtcbiAgICAgIGxldCBzY3JvbGxZID0gdGhpcy5zdGF0ZS5zY3JvbGxZO1xuXG4gICAgICBpZiAoKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5maXRUb0NvbnRlbnQpIHx8IChvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMuZml0VG9WaWV3cG9ydCkpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIGFwcFN0YXRlXG4gICAgICAgIH0gPSB6b29tVG9GaXQoe1xuICAgICAgICAgIHRhcmdldEVsZW1lbnRzLFxuICAgICAgICAgIGFwcFN0YXRlOiB0aGlzLnN0YXRlLFxuICAgICAgICAgIGZpdFRvVmlld3BvcnQ6ICEhKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5maXRUb1ZpZXdwb3J0KSxcbiAgICAgICAgICB2aWV3cG9ydFpvb21GYWN0b3I6IG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy52aWV3cG9ydFpvb21GYWN0b3JcbiAgICAgICAgfSk7XG4gICAgICAgIHpvb20gPSBhcHBTdGF0ZS56b29tO1xuICAgICAgICBzY3JvbGxYID0gYXBwU3RhdGUuc2Nyb2xsWDtcbiAgICAgICAgc2Nyb2xsWSA9IGFwcFN0YXRlLnNjcm9sbFk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjb21wdXRlIG9ubHkgdGhlIHZpZXdwb3J0IGxvY2F0aW9uLCB3aXRob3V0IGFueSB6b29tIGFkanVzdG1lbnRcbiAgICAgICAgY29uc3Qgc2Nyb2xsID0gY2FsY3VsYXRlU2Nyb2xsQ2VudGVyKHRhcmdldEVsZW1lbnRzLCB0aGlzLnN0YXRlKTtcbiAgICAgICAgc2Nyb2xsWCA9IHNjcm9sbC5zY3JvbGxYO1xuICAgICAgICBzY3JvbGxZID0gc2Nyb2xsLnNjcm9sbFk7XG4gICAgICB9IC8vIHdoZW4gYW5pbWF0aW5nLCB3ZSB1c2UgUmVxdWVzdEFuaW1hdGlvbkZyYW1lIHRvIHByZXZlbnQgdGhlIGFuaW1hdGlvblxuICAgICAgLy8gZnJvbSBzbG93aW5nIGRvd24gb3RoZXIgcHJvY2Vzc2VzXG5cblxuICAgICAgaWYgKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5hbmltYXRlKSB7XG4gICAgICAgIGNvbnN0IG9yaWdTY3JvbGxYID0gdGhpcy5zdGF0ZS5zY3JvbGxYO1xuICAgICAgICBjb25zdCBvcmlnU2Nyb2xsWSA9IHRoaXMuc3RhdGUuc2Nyb2xsWTtcbiAgICAgICAgY29uc3Qgb3JpZ1pvb20gPSB0aGlzLnN0YXRlLnpvb20udmFsdWU7XG4gICAgICAgIGNvbnN0IGNhbmNlbCA9IGVhc2VUb1ZhbHVlc1JBRih7XG4gICAgICAgICAgZnJvbVZhbHVlczoge1xuICAgICAgICAgICAgc2Nyb2xsWDogb3JpZ1Njcm9sbFgsXG4gICAgICAgICAgICBzY3JvbGxZOiBvcmlnU2Nyb2xsWSxcbiAgICAgICAgICAgIHpvb206IG9yaWdab29tXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0b1ZhbHVlczoge1xuICAgICAgICAgICAgc2Nyb2xsWCxcbiAgICAgICAgICAgIHNjcm9sbFksXG4gICAgICAgICAgICB6b29tOiB6b29tLnZhbHVlXG4gICAgICAgICAgfSxcbiAgICAgICAgICBpbnRlcnBvbGF0ZVZhbHVlOiAoZnJvbSwgdG8sIHByb2dyZXNzLCBrZXkpID0+IHtcbiAgICAgICAgICAgIC8vIGZvciB6b29tLCB1c2UgZGlmZmVyZW50IGVhc2luZ1xuICAgICAgICAgICAgaWYgKGtleSA9PT0gXCJ6b29tXCIpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZyb20gKiBNYXRoLnBvdyh0byAvIGZyb20sIGVhc2VPdXQocHJvZ3Jlc3MpKTtcbiAgICAgICAgICAgIH0gLy8gaGFuZGxlIHVzaW5nIGRlZmF1bHRcblxuXG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgb25TdGVwOiAoe1xuICAgICAgICAgICAgc2Nyb2xsWCxcbiAgICAgICAgICAgIHNjcm9sbFksXG4gICAgICAgICAgICB6b29tXG4gICAgICAgICAgfSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIHNjcm9sbFgsXG4gICAgICAgICAgICAgIHNjcm9sbFksXG4gICAgICAgICAgICAgIHpvb206IHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogem9vbVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uU3RhcnQ6ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzaG91bGRDYWNoZUlnbm9yZVpvb206IHRydWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgb25FbmQ6ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzaG91bGRDYWNoZUlnbm9yZVpvb206IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uQ2FuY2VsOiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2hvdWxkQ2FjaGVJZ25vcmVab29tOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBkdXJhdGlvbjogKF9iID0gb3B0cyA9PT0gbnVsbCB8fCBvcHRzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRzLmR1cmF0aW9uKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiA1MDBcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5jYW5jZWxJblByb2dyZXNBbmltYXRpb24gPSAoKSA9PiB7XG4gICAgICAgICAgY2FuY2VsKCk7XG4gICAgICAgICAgdGhpcy5jYW5jZWxJblByb2dyZXNBbmltYXRpb24gPSBudWxsO1xuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc2Nyb2xsWCxcbiAgICAgICAgICBzY3JvbGxZLFxuICAgICAgICAgIHpvb21cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcbiAgICAvKiogdXNlIHdoZW4gY2hhbmdpbmcgc2Nyb2xsWC9zY3JvbGxZL3pvb20gYmFzZWQgb24gdXNlciBpbnRlcmFjdGlvbiAqL1xuXG5cbiAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcyA9IHN0YXRlID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgKF9hID0gdGhpcy5jYW5jZWxJblByb2dyZXNBbmltYXRpb24pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jYWxsKHRoaXMpO1xuICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSk7XG4gICAgfTtcblxuICAgIHRoaXMuc2V0VG9hc3QgPSB0b2FzdCA9PiB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgdG9hc3RcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLnJlc3RvcmVGaWxlRnJvbVNoYXJlID0gKCkgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgd2ViU2hhcmVUYXJnZXRDYWNoZSA9IHlpZWxkIGNhY2hlcy5vcGVuKFwid2ViLXNoYXJlLXRhcmdldFwiKTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSB5aWVsZCB3ZWJTaGFyZVRhcmdldENhY2hlLm1hdGNoKFwic2hhcmVkLWZpbGVcIik7XG5cbiAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgY29uc3QgYmxvYiA9IHlpZWxkIHJlc3BvbnNlLmJsb2IoKTtcbiAgICAgICAgICBjb25zdCBmaWxlID0gbmV3IEZpbGUoW2Jsb2JdLCBibG9iLm5hbWUgfHwgXCJcIiwge1xuICAgICAgICAgICAgdHlwZTogYmxvYi50eXBlXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy5sb2FkRmlsZVRvQ2FudmFzKGZpbGUsIG51bGwpO1xuICAgICAgICAgIHlpZWxkIHdlYlNoYXJlVGFyZ2V0Q2FjaGUuZGVsZXRlKFwic2hhcmVkLWZpbGVcIik7XG4gICAgICAgICAgd2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKG51bGwsIEFQUF9OQU1FLCB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLm1lc3NhZ2VcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLyoqIGFkZHMgc3VwcGxpZWQgZmlsZXMgdG8gZXhpc3RpbmcgZmlsZXMgaW4gdGhlIGFwcFN0YXRlICovXG5cblxuICAgIHRoaXMuYWRkRmlsZXMgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZmlsZXMgPT4ge1xuICAgICAgY29uc3QgZmlsZXNNYXAgPSBmaWxlcy5yZWR1Y2UoKGFjYywgZmlsZURhdGEpID0+IHtcbiAgICAgICAgYWNjLnNldChmaWxlRGF0YS5pZCwgZmlsZURhdGEpO1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwgbmV3IE1hcCgpKTtcbiAgICAgIHRoaXMuZmlsZXMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZmlsZXMpLCBPYmplY3QuZnJvbUVudHJpZXMoZmlsZXNNYXApKTtcbiAgICAgIHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgaWYgKGlzSW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnQoZWxlbWVudCkgJiYgZmlsZXNNYXAuaGFzKGVsZW1lbnQuZmlsZUlkKSkge1xuICAgICAgICAgIHRoaXMuaW1hZ2VDYWNoZS5kZWxldGUoZWxlbWVudC5maWxlSWQpO1xuICAgICAgICAgIFNoYXBlQ2FjaGUuZGVsZXRlKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuc2NlbmUuaW5mb3JtTXV0YXRpb24oKTtcbiAgICAgIHRoaXMuYWRkTmV3SW1hZ2VzVG9JbWFnZUNhY2hlKCk7XG4gICAgfSk7XG4gICAgdGhpcy51cGRhdGVTY2VuZSA9IHdpdGhCYXRjaGVkVXBkYXRlcyhzY2VuZURhdGEgPT4ge1xuICAgICAgaWYgKHNjZW5lRGF0YS5jb21taXRUb0hpc3RvcnkpIHtcbiAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NlbmVEYXRhLmFwcFN0YXRlKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoc2NlbmVEYXRhLmFwcFN0YXRlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjZW5lRGF0YS5lbGVtZW50cykge1xuICAgICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhzY2VuZURhdGEuZWxlbWVudHMpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NlbmVEYXRhLmNvbGxhYm9yYXRvcnMpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgY29sbGFib3JhdG9yczogc2NlbmVEYXRhLmNvbGxhYm9yYXRvcnNcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLm9uU2NlbmVVcGRhdGVkID0gKCkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7fSk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyB3aGV0aGVyIHRoZSBtZW51IHdhcyB0b2dnbGVkIG9uIG9yIG9mZlxuICAgICAqL1xuXG5cbiAgICB0aGlzLnRvZ2dsZVNpZGViYXIgPSAoe1xuICAgICAgbmFtZSxcbiAgICAgIHRhYixcbiAgICAgIGZvcmNlXG4gICAgfSkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBsZXQgbmV4dE5hbWU7XG5cbiAgICAgIGlmIChmb3JjZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG5leHROYW1lID0gKChfYSA9IHRoaXMuc3RhdGUub3BlblNpZGViYXIpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5uYW1lKSA9PT0gbmFtZSA/IG51bGwgOiBuYW1lO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV4dE5hbWUgPSBmb3JjZSA/IG5hbWUgOiBudWxsO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgb3BlblNpZGViYXI6IG5leHROYW1lID8ge1xuICAgICAgICAgIG5hbWU6IG5leHROYW1lLFxuICAgICAgICAgIHRhYlxuICAgICAgICB9IDogbnVsbFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gISFuZXh0TmFtZTtcbiAgICB9O1xuXG4gICAgdGhpcy51cGRhdGVDdXJyZW50Q3Vyc29yUG9zaXRpb24gPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi54ID0gZXZlbnQuY2xpZW50WDtcbiAgICAgIHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueSA9IGV2ZW50LmNsaWVudFk7XG4gICAgfSk7IC8vIElucHV0IGhhbmRsaW5nXG5cbiAgICB0aGlzLm9uS2V5RG93biA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICAvLyBub3JtYWxpemUgYGV2ZW50LmtleWAgd2hlbiBDYXBzTG9jayBpcyBwcmVzc2VkICMyMzcyXG4gICAgICBpZiAoXCJQcm94eVwiIGluIHdpbmRvdyAmJiAoIWV2ZW50LnNoaWZ0S2V5ICYmIC9eW0EtWl0kLy50ZXN0KGV2ZW50LmtleSkgfHwgZXZlbnQuc2hpZnRLZXkgJiYgL15bYS16XSQvLnRlc3QoZXZlbnQua2V5KSkpIHtcbiAgICAgICAgZXZlbnQgPSBuZXcgUHJveHkoZXZlbnQsIHtcbiAgICAgICAgICBnZXQoZXYsIHByb3ApIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZXZbcHJvcF07XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAvLyBmaXggZm9yIFByb3hpZXMgaGlqYWNraW5nIGB0aGlzYFxuICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuYmluZChldik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBwcm9wID09PSBcImtleVwiID8gLy8gQ2Fwc0xvY2sgaW52ZXJ0cyBjYXBpdGFsaXphdGlvbiBiYXNlZCBvbiBTaGlmdEtleSwgc28gaW52ZXJ0XG4gICAgICAgICAgICAvLyBpdCBiYWNrXG4gICAgICAgICAgICBldmVudC5zaGlmdEtleSA/IGV2LmtleS50b1VwcGVyQ2FzZSgpIDogZXYua2V5LnRvTG93ZXJDYXNlKCkgOiB2YWx1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudFtLRVlTLkNUUkxfT1JfQ01EXSAmJiBldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gS0VZUy5WKSB7XG4gICAgICAgIElTX1BMQUlOX1BBU1RFID0gZXZlbnQuc2hpZnRLZXk7XG4gICAgICAgIGNsZWFyVGltZW91dChJU19QTEFJTl9QQVNURV9USU1FUik7IC8vIHJlc2V0ICgxMDBtcyB0byBiZSBzYWZlIHRoYXQgd2UgaXQgcnVucyBhZnRlciB0aGUgZW5zdWluZ1xuICAgICAgICAvLyBwYXN0ZSBldmVudCkuIFRob3VnaCwgdGVjaG5pY2FsbHkgdW5uZWNlc3NhcnkgdG8gcmVzZXQgc2luY2Ugd2VcbiAgICAgICAgLy8gKHJlKXNldCB0aGUgZmxhZyBiZWZvcmUgZWFjaCBwYXN0ZSBldmVudC5cblxuICAgICAgICBJU19QTEFJTl9QQVNURV9USU1FUiA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBJU19QTEFJTl9QQVNURSA9IGZhbHNlO1xuICAgICAgICB9LCAxMDApO1xuICAgICAgfSAvLyBwcmV2ZW50IGJyb3dzZXIgem9vbSBpbiBpbnB1dCBmaWVsZHNcblxuXG4gICAgICBpZiAoZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgaXNXcml0YWJsZUVsZW1lbnQoZXZlbnQudGFyZ2V0KSkge1xuICAgICAgICBpZiAoZXZlbnQuY29kZSA9PT0gQ09ERVMuTUlOVVMgfHwgZXZlbnQuY29kZSA9PT0gQ09ERVMuRVFVQUwpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSAvLyBiYWlsIGlmXG5cblxuICAgICAgaWYgKCAvLyBpbnNpZGUgYW4gaW5wdXRcbiAgICAgIGlzV3JpdGFibGVFbGVtZW50KGV2ZW50LnRhcmdldCkgJiYgLy8gdW5sZXNzIHByZXNzaW5nIGVzY2FwZSAoZmluYWxpemUgYWN0aW9uKVxuICAgICAgZXZlbnQua2V5ICE9PSBLRVlTLkVTQ0FQRSB8fCAvLyBvciB1bmxlc3MgdXNpbmcgYXJyb3dzICh0byBtb3ZlIGJldHdlZW4gYnV0dG9ucylcbiAgICAgIGlzQXJyb3dLZXkoZXZlbnQua2V5KSAmJiBpc0lucHV0TGlrZShldmVudC50YXJnZXQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5RVUVTVElPTl9NQVJLKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIG9wZW5EaWFsb2c6IFwiaGVscFwiXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleS50b0xvd2VyQ2FzZSgpID09PSBLRVlTLkUgJiYgZXZlbnQuc2hpZnRLZXkgJiYgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0pIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgb3BlbkRpYWxvZzogXCJpbWFnZUV4cG9ydFwiXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuUEFHRV9VUCB8fCBldmVudC5rZXkgPT09IEtFWVMuUEFHRV9ET1dOKSB7XG4gICAgICAgIGxldCBvZmZzZXQgPSAoZXZlbnQuc2hpZnRLZXkgPyB0aGlzLnN0YXRlLndpZHRoIDogdGhpcy5zdGF0ZS5oZWlnaHQpIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuXG4gICAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuUEFHRV9ET1dOKSB7XG4gICAgICAgICAgb2Zmc2V0ID0gLW9mZnNldDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5zaGlmdEtleSkge1xuICAgICAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHN0YXRlID0+ICh7XG4gICAgICAgICAgICBzY3JvbGxYOiBzdGF0ZS5zY3JvbGxYICsgb2Zmc2V0XG4gICAgICAgICAgfSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHN0YXRlID0+ICh7XG4gICAgICAgICAgICBzY3JvbGxZOiBzdGF0ZS5zY3JvbGxZICsgb2Zmc2V0XG4gICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmFjdGlvbk1hbmFnZXIuaGFuZGxlS2V5RG93bihldmVudCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgdGhpcy5zdGF0ZS5pc0JpbmRpbmdFbmFibGVkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGlzQmluZGluZ0VuYWJsZWQ6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNBcnJvd0tleShldmVudC5rZXkpKSB7XG4gICAgICAgIGNvbnN0IHN0ZXAgPSB0aGlzLnN0YXRlLmdyaWRTaXplICYmIChldmVudC5zaGlmdEtleSA/IEVMRU1FTlRfVFJBTlNMQVRFX0FNT1VOVCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpIHx8IChldmVudC5zaGlmdEtleSA/IEVMRU1FTlRfU0hJRlRfVFJBTlNMQVRFX0FNT1VOVCA6IEVMRU1FTlRfVFJBTlNMQVRFX0FNT1VOVCk7XG4gICAgICAgIGxldCBvZmZzZXRYID0gMDtcbiAgICAgICAgbGV0IG9mZnNldFkgPSAwO1xuXG4gICAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuQVJST1dfTEVGVCkge1xuICAgICAgICAgIG9mZnNldFggPSAtc3RlcDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09IEtFWVMuQVJST1dfUklHSFQpIHtcbiAgICAgICAgICBvZmZzZXRYID0gc3RlcDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09IEtFWVMuQVJST1dfVVApIHtcbiAgICAgICAgICBvZmZzZXRZID0gLXN0ZXA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkFSUk9XX0RPV04pIHtcbiAgICAgICAgICBvZmZzZXRZID0gc3RlcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMsXG4gICAgICAgICAgaW5jbHVkZUJvdW5kVGV4dEVsZW1lbnQ6IHRydWUsXG4gICAgICAgICAgaW5jbHVkZUVsZW1lbnRzSW5GcmFtZXM6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIHNlbGVjdGVkRWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KGVsZW1lbnQsIHtcbiAgICAgICAgICAgIHg6IGVsZW1lbnQueCArIG9mZnNldFgsXG4gICAgICAgICAgICB5OiBlbGVtZW50LnkgKyBvZmZzZXRZXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdXBkYXRlQm91bmRFbGVtZW50cyhlbGVtZW50LCB7XG4gICAgICAgICAgICBzaW11bHRhbmVvdXNseVVwZGF0ZWQ6IHNlbGVjdGVkRWxlbWVudHNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubWF5YmVTdWdnZXN0QmluZGluZ0ZvckFsbChzZWxlY3RlZEVsZW1lbnRzKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkVOVEVSKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50ID0gc2VsZWN0ZWRFbGVtZW50c1swXTtcblxuICAgICAgICAgIGlmIChldmVudFtLRVlTLkNUUkxfT1JfQ01EXSkge1xuICAgICAgICAgICAgaWYgKGlzTGluZWFyRWxlbWVudChzZWxlY3RlZEVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgIGlmICghdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCB8fCB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZCAhPT0gc2VsZWN0ZWRFbGVtZW50c1swXS5pZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgIGVkaXRpbmdMaW5lYXJFbGVtZW50OiBuZXcgTGluZWFyRWxlbWVudEVkaXRvcihzZWxlY3RlZEVsZW1lbnQsIHRoaXMuc2NlbmUpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKGlzVGV4dEVsZW1lbnQoc2VsZWN0ZWRFbGVtZW50KSB8fCBpc1ZhbGlkVGV4dENvbnRhaW5lcihzZWxlY3RlZEVsZW1lbnQpKSB7XG4gICAgICAgICAgICBsZXQgY29udGFpbmVyO1xuXG4gICAgICAgICAgICBpZiAoIWlzVGV4dEVsZW1lbnQoc2VsZWN0ZWRFbGVtZW50KSkge1xuICAgICAgICAgICAgICBjb250YWluZXIgPSBzZWxlY3RlZEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IG1pZFBvaW50ID0gZ2V0Q29udGFpbmVyQ2VudGVyKHNlbGVjdGVkRWxlbWVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICAgICAgICBjb25zdCBzY2VuZVggPSBtaWRQb2ludC54O1xuICAgICAgICAgICAgY29uc3Qgc2NlbmVZID0gbWlkUG9pbnQueTtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRUZXh0RWRpdGluZyh7XG4gICAgICAgICAgICAgIHNjZW5lWCxcbiAgICAgICAgICAgICAgc2NlbmVZLFxuICAgICAgICAgICAgICBjb250YWluZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9IGVsc2UgaWYgKGlzRnJhbWVFbGVtZW50KHNlbGVjdGVkRWxlbWVudCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBlZGl0aW5nRnJhbWU6IHNlbGVjdGVkRWxlbWVudC5pZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCFldmVudC5jdHJsS2V5ICYmICFldmVudC5hbHRLZXkgJiYgIWV2ZW50Lm1ldGFLZXkgJiYgdGhpcy5zdGF0ZS5kcmFnZ2luZ0VsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgY29uc3Qgc2hhcGUgPSBmaW5kU2hhcGVCeUtleShldmVudC5rZXkpO1xuXG4gICAgICAgIGlmIChzaGFwZSkge1xuICAgICAgICAgIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gc2hhcGUpIHtcbiAgICAgICAgICAgIHRyYWNrRXZlbnQoXCJ0b29sYmFyXCIsIHNoYXBlLCBga2V5Ym9hcmQgKCR7dGhpcy5kZXZpY2UuaXNNb2JpbGUgPyBcIm1vYmlsZVwiIDogXCJkZXNrdG9wXCJ9KWApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuc2V0QWN0aXZlVG9vbCh7XG4gICAgICAgICAgICB0eXBlOiBzaGFwZVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5RKSB7XG4gICAgICAgICAgdGhpcy50b2dnbGVMb2NrKFwia2V5Ym9hcmRcIik7XG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5TUEFDRSAmJiBnZXN0dXJlLnBvaW50ZXJzLnNpemUgPT09IDApIHtcbiAgICAgICAgaXNIb2xkaW5nU3BhY2UgPSB0cnVlO1xuICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuR1JBQik7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmICgoZXZlbnQua2V5ID09PSBLRVlTLkcgfHwgZXZlbnQua2V5ID09PSBLRVlTLlMpICYmICFldmVudC5hbHRLZXkgJiYgIWV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInNlbGVjdGlvblwiICYmICFzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuRyAmJiAoaGFzQmFja2dyb3VuZCh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSkgfHwgc2VsZWN0ZWRFbGVtZW50cy5zb21lKGVsZW1lbnQgPT4gaGFzQmFja2dyb3VuZChlbGVtZW50LnR5cGUpKSkpIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIG9wZW5Qb3B1cDogXCJlbGVtZW50QmFja2dyb3VuZFwiXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLlMpIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIG9wZW5Qb3B1cDogXCJlbGVtZW50U3Ryb2tlXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgKGV2ZW50LmtleSA9PT0gS0VZUy5CQUNLU1BBQ0UgfHwgZXZlbnQua2V5ID09PSBLRVlTLkRFTEVURSkpIHtcbiAgICAgICAgam90YWlTdG9yZS5zZXQoYWN0aXZlQ29uZmlybURpYWxvZ0F0b20sIFwiY2xlYXJDYW52YXNcIik7XG4gICAgICB9IC8vIGV5ZSBkcm9wcGVyXG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbiAgICAgIGNvbnN0IGxvd2VyQ2FzZWQgPSBldmVudC5rZXkudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgIGNvbnN0IGlzUGlja2luZ1N0cm9rZSA9IGxvd2VyQ2FzZWQgPT09IEtFWVMuUyAmJiBldmVudC5zaGlmdEtleTtcbiAgICAgIGNvbnN0IGlzUGlja2luZ0JhY2tncm91bmQgPSBldmVudC5rZXkgPT09IEtFWVMuSSB8fCBsb3dlckNhc2VkID09PSBLRVlTLkcgJiYgZXZlbnQuc2hpZnRLZXk7XG5cbiAgICAgIGlmIChpc1BpY2tpbmdTdHJva2UgfHwgaXNQaWNraW5nQmFja2dyb3VuZCkge1xuICAgICAgICB0aGlzLm9wZW5FeWVEcm9wcGVyKHtcbiAgICAgICAgICB0eXBlOiBpc1BpY2tpbmdTdHJva2UgPyBcInN0cm9rZVwiIDogXCJiYWNrZ3JvdW5kXCJcbiAgICAgICAgfSk7XG4gICAgICB9IC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICB9KTtcbiAgICB0aGlzLm9uV2hlZWwgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgLy8gcHJldmVudCBicm93c2VyIHBpbmNoIHpvb20gb24gRE9NIGVsZW1lbnRzXG4gICAgICBpZiAoIShldmVudC50YXJnZXQgaW5zdGFuY2VvZiBIVE1MQ2FudmFzRWxlbWVudCkgJiYgZXZlbnQuY3RybEtleSkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMub25LZXlVcCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLlNQQUNFKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5HUkFCKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICAgIHJlc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNldEN1cnNvckZvclNoYXBlKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIHRoaXMuc3RhdGUpO1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7fSwgdGhpcy5zdGF0ZSksXG4gICAgICAgICAgICBzZWxlY3RlZEdyb3VwSWRzOiB7fSxcbiAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBudWxsLFxuICAgICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaXNIb2xkaW5nU3BhY2UgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFldmVudFtLRVlTLkNUUkxfT1JfQ01EXSAmJiAhdGhpcy5zdGF0ZS5pc0JpbmRpbmdFbmFibGVkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGlzQmluZGluZ0VuYWJsZWQ6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0Fycm93S2V5KGV2ZW50LmtleSkpIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcbiAgICAgICAgaXNCaW5kaW5nRW5hYmxlZCh0aGlzLnN0YXRlKSA/IGJpbmRPclVuYmluZFNlbGVjdGVkRWxlbWVudHMoc2VsZWN0ZWRFbGVtZW50cykgOiB1bmJpbmRMaW5lYXJFbGVtZW50cyhzZWxlY3RlZEVsZW1lbnRzKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc3VnZ2VzdGVkQmluZGluZ3M6IFtdXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXRBY3RpdmVUb29sID0gdG9vbCA9PiB7XG4gICAgICBjb25zdCBuZXh0QWN0aXZlVG9vbCA9IHVwZGF0ZUFjdGl2ZVRvb2wodGhpcy5zdGF0ZSwgdG9vbCk7XG5cbiAgICAgIGlmIChuZXh0QWN0aXZlVG9vbC50eXBlID09PSBcImhhbmRcIikge1xuICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuR1JBQik7XG4gICAgICB9IGVsc2UgaWYgKCFpc0hvbGRpbmdTcGFjZSkge1xuICAgICAgICBzZXRDdXJzb3JGb3JTaGFwZSh0aGlzLmludGVyYWN0aXZlQ2FudmFzLCB0aGlzLnN0YXRlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzVG9vbEljb24oZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkpIHtcbiAgICAgICAgdGhpcy5mb2N1c0NvbnRhaW5lcigpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzTGluZWFyRWxlbWVudFR5cGUobmV4dEFjdGl2ZVRvb2wudHlwZSkpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc3VnZ2VzdGVkQmluZGluZ3M6IFtdXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV4dEFjdGl2ZVRvb2wudHlwZSA9PT0gXCJpbWFnZVwiKSB7XG4gICAgICAgIHRoaXMub25JbWFnZUFjdGlvbigpO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV4dEFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBhY3RpdmVUb29sOiBuZXh0QWN0aXZlVG9vbCxcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgICAgICBzZWxlY3RlZEdyb3VwSWRzOiB7fSxcbiAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogbnVsbCxcbiAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgYWN0aXZlVG9vbDogbmV4dEFjdGl2ZVRvb2wsXG4gICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5zZXRDdXJzb3IgPSBjdXJzb3IgPT4ge1xuICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIGN1cnNvcik7XG4gICAgfTtcblxuICAgIHRoaXMucmVzZXRDdXJzb3IgPSAoKSA9PiB7XG4gICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIHJldHVybnMgd2hldGhlciB1c2VyIGlzIG1ha2luZyBhIGdlc3R1cmUgd2l0aCA+PSAyIGZpbmdlcnMgKHBvaW50cylcbiAgICAgKiBvbiBvIHRvdWNoIHNjcmVlbiAobm90IG9uIGEgdHJhY2twYWQpLiBDdXJyZW50bHkgb25seSByZWxhdGVzIHRvIERhcndpblxuICAgICAqIChpT1MvaVBhZE9TLE1hY09TKSwgYnV0IG1heSB3b3JrIG9uIG90aGVyIGRldmljZXMgaW4gdGhlIGZ1dHVyZSBpZlxuICAgICAqIEdlc3R1cmVFdmVudCBpcyBzdGFuZGFyZGl6ZWQuXG4gICAgICovXG5cblxuICAgIHRoaXMuaXNUb3VjaFNjcmVlbk11bHRpVG91Y2hHZXN0dXJlID0gKCkgPT4ge1xuICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byBkZXNlbGVjdCB3aGVuIHVzaW5nIHRyYWNrcGFkLCBhbmQgbXVsdGktcG9pbnQgZ2VzdHVyZXNcbiAgICAgIC8vIG9ubHkgd29yayBvbiB0b3VjaCBzY3JlZW5zLCBzbyBjaGVja2luZyBmb3IgPj0gcG9pbnRlcnMgbWVhbnMgd2UncmUgb24gYVxuICAgICAgLy8gdG91Y2hzY3JlZW5cbiAgICAgIHJldHVybiBnZXN0dXJlLnBvaW50ZXJzLnNpemUgPj0gMjtcbiAgICB9OyAvLyBmaXJlcyBvbmx5IG9uIFNhZmFyaVxuXG5cbiAgICB0aGlzLm9uR2VzdHVyZVN0YXJ0ID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIHdlIG9ubHkgd2FudCB0byBkZXNlbGVjdCBvbiB0b3VjaCBzY3JlZW5zIGJlY2F1c2UgdXNlciBtYXkgaGF2ZSBzZWxlY3RlZFxuICAgICAgLy8gZWxlbWVudHMgYnkgbWlzdGFrZSB3aGlsZSB6b29taW5nXG5cbiAgICAgIGlmICh0aGlzLmlzVG91Y2hTY3JlZW5NdWx0aVRvdWNoR2VzdHVyZSgpKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe30sIHRoaXMuc3RhdGUpLFxuICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGdlc3R1cmUuaW5pdGlhbFNjYWxlID0gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuICAgIH0pOyAvLyBmaXJlcyBvbmx5IG9uIFNhZmFyaVxuXG4gICAgdGhpcy5vbkdlc3R1cmVDaGFuZ2UgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gb25HZXN0dXJlQ2hhbmdlIG9ubHkgaGFzIHpvb20gZmFjdG9yIGJ1dCBub3QgdGhlIGNlbnRlci5cbiAgICAgIC8vIElmIHdlJ3JlIG9uIGlQYWQgb3IgaVBob25lLCB0aGVuIHdlIHJlY29nbml6ZSBtdWx0aS10b3VjaCBhbmQgd2lsbFxuICAgICAgLy8gem9vbSBpbiBhdCB0aGUgcmlnaHQgbG9jYXRpb24gaW4gdGhlIHRvdWNobW92ZSBoYW5kbGVyXG4gICAgICAvLyAoaGFuZGxlQ2FudmFzUG9pbnRlck1vdmUpLlxuICAgICAgLy9cbiAgICAgIC8vIE9uIE1hY2Jvb2sgdHJhY2twYWQsIHdlIGRvbid0IGhhdmUgdGhvc2UgZXZlbnRzIHNvIHdpbGwgem9vbSBpbiBhdCB0aGVcbiAgICAgIC8vIGN1cnJlbnQgbG9jYXRpb24gaW5zdGVhZC5cbiAgICAgIC8vXG4gICAgICAvLyBBcyBzdWNoLCBiYWlsIGZyb20gdGhpcyBoYW5kbGVyIG9uIHRvdWNoIGRldmljZXMuXG5cbiAgICAgIGlmICh0aGlzLmlzVG91Y2hTY3JlZW5NdWx0aVRvdWNoR2VzdHVyZSgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaW5pdGlhbFNjYWxlID0gZ2VzdHVyZS5pbml0aWFsU2NhbGU7XG5cbiAgICAgIGlmIChpbml0aWFsU2NhbGUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSA9PiBPYmplY3QuYXNzaWduKHt9LCBnZXRTdGF0ZUZvclpvb20oe1xuICAgICAgICAgIHZpZXdwb3J0WDogdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi54LFxuICAgICAgICAgIHZpZXdwb3J0WTogdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi55LFxuICAgICAgICAgIG5leHRab29tOiBnZXROb3JtYWxpemVkWm9vbShpbml0aWFsU2NhbGUgKiBldmVudC5zY2FsZSlcbiAgICAgICAgfSwgc3RhdGUpKSk7XG4gICAgICB9XG4gICAgfSk7IC8vIGZpcmVzIG9ubHkgb24gU2FmYXJpXG5cbiAgICB0aGlzLm9uR2VzdHVyZUVuZCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyByZXNlbGVjdCBlbGVtZW50cyBvbmx5IG9uIHRvdWNoIHNjcmVlbnMgKHNlZSBvbkdlc3R1cmVTdGFydClcblxuICAgICAgaWYgKHRoaXMuaXNUb3VjaFNjcmVlbk11bHRpVG91Y2hHZXN0dXJlKCkpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgcHJldmlvdXNTZWxlY3RlZEVsZW1lbnRJZHM6IHt9LFxuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHModGhpcy5zdGF0ZS5wcmV2aW91c1NlbGVjdGVkRWxlbWVudElkcywgdGhpcy5zdGF0ZSlcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGdlc3R1cmUuaW5pdGlhbFNjYWxlID0gbnVsbDtcbiAgICB9KTtcblxuICAgIHRoaXMuc3RhcnRUZXh0RWRpdGluZyA9ICh7XG4gICAgICBzY2VuZVgsXG4gICAgICBzY2VuZVksXG4gICAgICBpbnNlcnRBdFBhcmVudENlbnRlciA9IHRydWUsXG4gICAgICBjb250YWluZXJcbiAgICB9KSA9PiB7XG4gICAgICB2YXIgX2EsIF9iO1xuXG4gICAgICBsZXQgc2hvdWxkQmluZFRvQ29udGFpbmVyID0gZmFsc2U7XG4gICAgICBsZXQgcGFyZW50Q2VudGVyUG9zaXRpb24gPSBpbnNlcnRBdFBhcmVudENlbnRlciAmJiB0aGlzLmdldFRleHRXeXNpd3lnU25hcHBlZFRvQ2VudGVyUG9zaXRpb24oc2NlbmVYLCBzY2VuZVksIHRoaXMuc3RhdGUsIGNvbnRhaW5lcik7XG5cbiAgICAgIGlmIChjb250YWluZXIgJiYgcGFyZW50Q2VudGVyUG9zaXRpb24pIHtcbiAgICAgICAgY29uc3QgYm91bmRUZXh0RWxlbWVudFRvQ29udGFpbmVyID0gZ2V0Qm91bmRUZXh0RWxlbWVudChjb250YWluZXIpO1xuXG4gICAgICAgIGlmICghYm91bmRUZXh0RWxlbWVudFRvQ29udGFpbmVyKSB7XG4gICAgICAgICAgc2hvdWxkQmluZFRvQ29udGFpbmVyID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsZXQgZXhpc3RpbmdUZXh0RWxlbWVudCA9IG51bGw7XG4gICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgaWYgKGlzVGV4dEVsZW1lbnQoc2VsZWN0ZWRFbGVtZW50c1swXSkpIHtcbiAgICAgICAgICBleGlzdGluZ1RleHRFbGVtZW50ID0gc2VsZWN0ZWRFbGVtZW50c1swXTtcbiAgICAgICAgfSBlbHNlIGlmIChjb250YWluZXIpIHtcbiAgICAgICAgICBleGlzdGluZ1RleHRFbGVtZW50ID0gZ2V0Qm91bmRUZXh0RWxlbWVudChzZWxlY3RlZEVsZW1lbnRzWzBdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBleGlzdGluZ1RleHRFbGVtZW50ID0gdGhpcy5nZXRUZXh0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVYLCBzY2VuZVkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleGlzdGluZ1RleHRFbGVtZW50ID0gdGhpcy5nZXRUZXh0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVYLCBzY2VuZVkpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmb250RmFtaWx5ID0gKGV4aXN0aW5nVGV4dEVsZW1lbnQgPT09IG51bGwgfHwgZXhpc3RpbmdUZXh0RWxlbWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogZXhpc3RpbmdUZXh0RWxlbWVudC5mb250RmFtaWx5KSB8fCB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtRm9udEZhbWlseTtcbiAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSAoZXhpc3RpbmdUZXh0RWxlbWVudCA9PT0gbnVsbCB8fCBleGlzdGluZ1RleHRFbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBleGlzdGluZ1RleHRFbGVtZW50LmxpbmVIZWlnaHQpIHx8IGdldERlZmF1bHRMaW5lSGVpZ2h0KGZvbnRGYW1pbHkpO1xuICAgICAgY29uc3QgZm9udFNpemUgPSB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtRm9udFNpemU7XG5cbiAgICAgIGlmICghZXhpc3RpbmdUZXh0RWxlbWVudCAmJiBzaG91bGRCaW5kVG9Db250YWluZXIgJiYgY29udGFpbmVyICYmICFpc0Fycm93RWxlbWVudChjb250YWluZXIpKSB7XG4gICAgICAgIGNvbnN0IGZvbnRTdHJpbmcgPSB7XG4gICAgICAgICAgZm9udFNpemUsXG4gICAgICAgICAgZm9udEZhbWlseVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBtaW5XaWR0aCA9IGdldEFwcHJveE1pbkxpbmVXaWR0aChnZXRGb250U3RyaW5nKGZvbnRTdHJpbmcpLCBsaW5lSGVpZ2h0KTtcbiAgICAgICAgY29uc3QgbWluSGVpZ2h0ID0gZ2V0QXBwcm94TWluTGluZUhlaWdodChmb250U2l6ZSwgbGluZUhlaWdodCk7XG4gICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IE1hdGgubWF4KGNvbnRhaW5lci5oZWlnaHQsIG1pbkhlaWdodCk7XG4gICAgICAgIGNvbnN0IG5ld1dpZHRoID0gTWF0aC5tYXgoY29udGFpbmVyLndpZHRoLCBtaW5XaWR0aCk7XG4gICAgICAgIG11dGF0ZUVsZW1lbnQoY29udGFpbmVyLCB7XG4gICAgICAgICAgaGVpZ2h0OiBuZXdIZWlnaHQsXG4gICAgICAgICAgd2lkdGg6IG5ld1dpZHRoXG4gICAgICAgIH0pO1xuICAgICAgICBzY2VuZVggPSBjb250YWluZXIueCArIG5ld1dpZHRoIC8gMjtcbiAgICAgICAgc2NlbmVZID0gY29udGFpbmVyLnkgKyBuZXdIZWlnaHQgLyAyO1xuXG4gICAgICAgIGlmIChwYXJlbnRDZW50ZXJQb3NpdGlvbikge1xuICAgICAgICAgIHBhcmVudENlbnRlclBvc2l0aW9uID0gdGhpcy5nZXRUZXh0V3lzaXd5Z1NuYXBwZWRUb0NlbnRlclBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZLCB0aGlzLnN0YXRlLCBjb250YWluZXIpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRvcExheWVyRnJhbWUgPSB0aGlzLmdldFRvcExheWVyRnJhbWVBdFNjZW5lQ29vcmRzKHtcbiAgICAgICAgeDogc2NlbmVYLFxuICAgICAgICB5OiBzY2VuZVlcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZWxlbWVudCA9IGV4aXN0aW5nVGV4dEVsZW1lbnQgPyBleGlzdGluZ1RleHRFbGVtZW50IDogbmV3VGV4dEVsZW1lbnQoe1xuICAgICAgICB4OiBwYXJlbnRDZW50ZXJQb3NpdGlvbiA/IHBhcmVudENlbnRlclBvc2l0aW9uLmVsZW1lbnRDZW50ZXJYIDogc2NlbmVYLFxuICAgICAgICB5OiBwYXJlbnRDZW50ZXJQb3NpdGlvbiA/IHBhcmVudENlbnRlclBvc2l0aW9uLmVsZW1lbnRDZW50ZXJZIDogc2NlbmVZLFxuICAgICAgICBzdHJva2VDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZUNvbG9yLFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1CYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgIGZpbGxTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZpbGxTdHlsZSxcbiAgICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VXaWR0aCxcbiAgICAgICAgc3Ryb2tlU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VTdHlsZSxcbiAgICAgICAgcm91Z2huZXNzOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91Z2huZXNzLFxuICAgICAgICBvcGFjaXR5OiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtT3BhY2l0eSxcbiAgICAgICAgdGV4dDogXCJcIixcbiAgICAgICAgZm9udFNpemUsXG4gICAgICAgIGZvbnRGYW1pbHksXG4gICAgICAgIHRleHRBbGlnbjogcGFyZW50Q2VudGVyUG9zaXRpb24gPyBcImNlbnRlclwiIDogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVRleHRBbGlnbixcbiAgICAgICAgdmVydGljYWxBbGlnbjogcGFyZW50Q2VudGVyUG9zaXRpb24gPyBWRVJUSUNBTF9BTElHTi5NSURETEUgOiBERUZBVUxUX1ZFUlRJQ0FMX0FMSUdOLFxuICAgICAgICBjb250YWluZXJJZDogc2hvdWxkQmluZFRvQ29udGFpbmVyID8gY29udGFpbmVyID09PSBudWxsIHx8IGNvbnRhaW5lciA9PT0gdm9pZCAwID8gdm9pZCAwIDogY29udGFpbmVyLmlkIDogdW5kZWZpbmVkLFxuICAgICAgICBncm91cElkczogKF9hID0gY29udGFpbmVyID09PSBudWxsIHx8IGNvbnRhaW5lciA9PT0gdm9pZCAwID8gdm9pZCAwIDogY29udGFpbmVyLmdyb3VwSWRzKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBbXSxcbiAgICAgICAgbGluZUhlaWdodCxcbiAgICAgICAgYW5nbGU6IChfYiA9IGNvbnRhaW5lciA9PT0gbnVsbCB8fCBjb250YWluZXIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGNvbnRhaW5lci5hbmdsZSkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogMCxcbiAgICAgICAgZnJhbWVJZDogdG9wTGF5ZXJGcmFtZSA/IHRvcExheWVyRnJhbWUuaWQgOiBudWxsXG4gICAgICB9KTtcblxuICAgICAgaWYgKCFleGlzdGluZ1RleHRFbGVtZW50ICYmIHNob3VsZEJpbmRUb0NvbnRhaW5lciAmJiBjb250YWluZXIpIHtcbiAgICAgICAgbXV0YXRlRWxlbWVudChjb250YWluZXIsIHtcbiAgICAgICAgICBib3VuZEVsZW1lbnRzOiAoY29udGFpbmVyLmJvdW5kRWxlbWVudHMgfHwgW10pLmNvbmNhdCh7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIGlkOiBlbGVtZW50LmlkXG4gICAgICAgICAgfSlcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBlZGl0aW5nRWxlbWVudDogZWxlbWVudFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghZXhpc3RpbmdUZXh0RWxlbWVudCkge1xuICAgICAgICBpZiAoY29udGFpbmVyICYmIHNob3VsZEJpbmRUb0NvbnRhaW5lcikge1xuICAgICAgICAgIGNvbnN0IGNvbnRhaW5lckluZGV4ID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50SW5kZXgoY29udGFpbmVyLmlkKTtcbiAgICAgICAgICB0aGlzLnNjZW5lLmluc2VydEVsZW1lbnRBdEluZGV4KGVsZW1lbnQsIGNvbnRhaW5lckluZGV4ICsgMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5zY2VuZS5hZGROZXdFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBlZGl0aW5nRWxlbWVudDogZWxlbWVudFxuICAgICAgfSk7XG4gICAgICB0aGlzLmhhbmRsZVRleHRXeXNpd3lnKGVsZW1lbnQsIHtcbiAgICAgICAgaXNFeGlzdGluZ0VsZW1lbnQ6ICEhZXhpc3RpbmdUZXh0RWxlbWVudFxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuaGFuZGxlQ2FudmFzRG91YmxlQ2xpY2sgPSBldmVudCA9PiB7XG4gICAgICAvLyBjYXNlOiBkb3VibGUtY2xpY2tpbmcgd2l0aCBhcnJvdy9saW5lIHRvb2wgc2VsZWN0ZWQgd291bGQgYm90aCBjcmVhdGVcbiAgICAgIC8vIHRleHQgYW5kIGVudGVyIG11bHRpRWxlbWVudCBtb2RlXG4gICAgICBpZiAodGhpcy5zdGF0ZS5tdWx0aUVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyB3ZSBzaG91bGQgb25seSBiZSBhYmxlIHRvIGRvdWJsZSBjbGljayB3aGVuIG1vZGUgaXMgc2VsZWN0aW9uXG5cblxuICAgICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcInNlbGVjdGlvblwiKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcblxuICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxICYmIGlzTGluZWFyRWxlbWVudChzZWxlY3RlZEVsZW1lbnRzWzBdKSkge1xuICAgICAgICBpZiAoZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgKCF0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50IHx8IHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQuZWxlbWVudElkICE9PSBzZWxlY3RlZEVsZW1lbnRzWzBdLmlkKSkge1xuICAgICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGVkaXRpbmdMaW5lYXJFbGVtZW50OiBuZXcgTGluZWFyRWxlbWVudEVkaXRvcihzZWxlY3RlZEVsZW1lbnRzWzBdLCB0aGlzLnNjZW5lKVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50ICYmIHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQuZWxlbWVudElkID09PSBzZWxlY3RlZEVsZW1lbnRzWzBdLmlkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJlc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMpO1xuICAgICAgbGV0IHtcbiAgICAgICAgeDogc2NlbmVYLFxuICAgICAgICB5OiBzY2VuZVlcbiAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoZXZlbnQsIHRoaXMuc3RhdGUpO1xuICAgICAgY29uc3Qgc2VsZWN0ZWRHcm91cElkcyA9IGdldFNlbGVjdGVkR3JvdXBJZHModGhpcy5zdGF0ZSk7XG5cbiAgICAgIGlmIChzZWxlY3RlZEdyb3VwSWRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgaGl0RWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVYLCBzY2VuZVkpO1xuICAgICAgICBjb25zdCBzZWxlY3RlZEdyb3VwSWQgPSBoaXRFbGVtZW50ICYmIGdldFNlbGVjdGVkR3JvdXBJZEZvckVsZW1lbnQoaGl0RWxlbWVudCwgdGhpcy5zdGF0ZS5zZWxlY3RlZEdyb3VwSWRzKTtcblxuICAgICAgICBpZiAoc2VsZWN0ZWRHcm91cElkKSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUpLCBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBzZWxlY3RlZEdyb3VwSWQsXG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHtcbiAgICAgICAgICAgICAgW2hpdEVsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgcHJldlN0YXRlLCB0aGlzKSkpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcblxuICAgICAgaWYgKCFldmVudFtLRVlTLkNUUkxfT1JfQ01EXSAmJiAhdGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgY29uc3QgaGl0RWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVYLCBzY2VuZVkpO1xuXG4gICAgICAgIGlmIChpc0VtYmVkZGFibGVFbGVtZW50KGhpdEVsZW1lbnQpKSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiB7XG4gICAgICAgICAgICAgIGVsZW1lbnQ6IGhpdEVsZW1lbnQsXG4gICAgICAgICAgICAgIHN0YXRlOiBcImFjdGl2ZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gZ2V0VGV4dEJpbmRhYmxlQ29udGFpbmVyQXRQb3NpdGlvbih0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCB0aGlzLnN0YXRlLCBzY2VuZVgsIHNjZW5lWSk7XG5cbiAgICAgICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICAgIGlmIChoYXNCb3VuZFRleHRFbGVtZW50KGNvbnRhaW5lcikgfHwgIWlzVHJhbnNwYXJlbnQoY29udGFpbmVyLmJhY2tncm91bmRDb2xvcikgfHwgaXNIaXR0aW5nRWxlbWVudE5vdENvbnNpZGVyaW5nQm91bmRpbmdCb3goY29udGFpbmVyLCB0aGlzLnN0YXRlLCB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLCBbc2NlbmVYLCBzY2VuZVldKSkge1xuICAgICAgICAgICAgY29uc3QgbWlkUG9pbnQgPSBnZXRDb250YWluZXJDZW50ZXIoY29udGFpbmVyLCB0aGlzLnN0YXRlKTtcbiAgICAgICAgICAgIHNjZW5lWCA9IG1pZFBvaW50Lng7XG4gICAgICAgICAgICBzY2VuZVkgPSBtaWRQb2ludC55O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RhcnRUZXh0RWRpdGluZyh7XG4gICAgICAgICAgc2NlbmVYLFxuICAgICAgICAgIHNjZW5lWSxcbiAgICAgICAgICBpbnNlcnRBdFBhcmVudENlbnRlcjogIWV2ZW50LmFsdEtleSxcbiAgICAgICAgICBjb250YWluZXJcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuZ2V0RWxlbWVudExpbmtBdFBvc2l0aW9uID0gKHNjZW5lUG9pbnRlciwgaGl0RWxlbWVudCkgPT4ge1xuICAgICAgLy8gUmV2ZXJzaW5nIHNvIHdlIHRyYXZlcnNlIHRoZSBlbGVtZW50cyBpbiBkZWNyZWFzaW5nIG9yZGVyXG4gICAgICAvLyBvZiB6LWluZGV4XG4gICAgICBjb25zdCBlbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgICBsZXQgaGl0RWxlbWVudEluZGV4ID0gSW5maW5pdHk7XG4gICAgICByZXR1cm4gZWxlbWVudHMuZmluZCgoZWxlbWVudCwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGhpdEVsZW1lbnQgJiYgZWxlbWVudC5pZCA9PT0gaGl0RWxlbWVudC5pZCkge1xuICAgICAgICAgIGhpdEVsZW1lbnRJbmRleCA9IGluZGV4O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsZW1lbnQubGluayAmJiBpbmRleCA8PSBoaXRFbGVtZW50SW5kZXggJiYgaXNQb2ludEhpdHRpbmdMaW5rKGVsZW1lbnQsIHRoaXMuc3RhdGUsIFtzY2VuZVBvaW50ZXIueCwgc2NlbmVQb2ludGVyLnldLCB0aGlzLmRldmljZS5pc01vYmlsZSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZWRpcmVjdFRvTGluayA9IChldmVudCwgaXNUb3VjaFNjcmVlbikgPT4ge1xuICAgICAgY29uc3QgZHJhZ2dlZERpc3RhbmNlID0gZGlzdGFuY2UyZCh0aGlzLmxhc3RQb2ludGVyRG93bi5jbGllbnRYLCB0aGlzLmxhc3RQb2ludGVyRG93bi5jbGllbnRZLCB0aGlzLmxhc3RQb2ludGVyVXAuY2xpZW50WCwgdGhpcy5sYXN0UG9pbnRlclVwLmNsaWVudFkpO1xuXG4gICAgICBpZiAoIXRoaXMuaGl0TGlua0VsZW1lbnQgfHwgLy8gRm9yIHRvdWNoIHNjcmVlbiBhbGxvdyBkcmFnZ2luZyB0aHJlc2hvbGQgZWxzZSBzdHJpY3QgY2hlY2tcbiAgICAgIGlzVG91Y2hTY3JlZW4gJiYgZHJhZ2dlZERpc3RhbmNlID4gRFJBR0dJTkdfVEhSRVNIT0xEIHx8ICFpc1RvdWNoU2NyZWVuICYmIGRyYWdnZWREaXN0YW5jZSAhPT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxhc3RQb2ludGVyRG93bkNvb3JkcyA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh0aGlzLmxhc3RQb2ludGVyRG93biwgdGhpcy5zdGF0ZSk7XG4gICAgICBjb25zdCBsYXN0UG9pbnRlckRvd25IaXR0aW5nTGlua0ljb24gPSBpc1BvaW50SGl0dGluZ0xpbmsodGhpcy5oaXRMaW5rRWxlbWVudCwgdGhpcy5zdGF0ZSwgW2xhc3RQb2ludGVyRG93bkNvb3Jkcy54LCBsYXN0UG9pbnRlckRvd25Db29yZHMueV0sIHRoaXMuZGV2aWNlLmlzTW9iaWxlKTtcbiAgICAgIGNvbnN0IGxhc3RQb2ludGVyVXBDb29yZHMgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHModGhpcy5sYXN0UG9pbnRlclVwLCB0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IGxhc3RQb2ludGVyVXBIaXR0aW5nTGlua0ljb24gPSBpc1BvaW50SGl0dGluZ0xpbmsodGhpcy5oaXRMaW5rRWxlbWVudCwgdGhpcy5zdGF0ZSwgW2xhc3RQb2ludGVyVXBDb29yZHMueCwgbGFzdFBvaW50ZXJVcENvb3Jkcy55XSwgdGhpcy5kZXZpY2UuaXNNb2JpbGUpO1xuXG4gICAgICBpZiAobGFzdFBvaW50ZXJEb3duSGl0dGluZ0xpbmtJY29uICYmIGxhc3RQb2ludGVyVXBIaXR0aW5nTGlua0ljb24pIHtcbiAgICAgICAgbGV0IHVybCA9IHRoaXMuaGl0TGlua0VsZW1lbnQubGluaztcblxuICAgICAgICBpZiAodXJsKSB7XG4gICAgICAgICAgdXJsID0gbm9ybWFsaXplTGluayh1cmwpO1xuICAgICAgICAgIGxldCBjdXN0b21FdmVudDtcblxuICAgICAgICAgIGlmICh0aGlzLnByb3BzLm9uTGlua09wZW4pIHtcbiAgICAgICAgICAgIGN1c3RvbUV2ZW50ID0gd3JhcEV2ZW50KEVWRU5ULkVYQ0FMSURSQVdfTElOSywgZXZlbnQubmF0aXZlRXZlbnQpO1xuICAgICAgICAgICAgdGhpcy5wcm9wcy5vbkxpbmtPcGVuKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5oaXRMaW5rRWxlbWVudCksIHtcbiAgICAgICAgICAgICAgbGluazogdXJsXG4gICAgICAgICAgICB9KSwgY3VzdG9tRXZlbnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghKGN1c3RvbUV2ZW50ID09PSBudWxsIHx8IGN1c3RvbUV2ZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBjdXN0b21FdmVudC5kZWZhdWx0UHJldmVudGVkKSkge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gaXNMb2NhbExpbmsodXJsKSA/IFwiX3NlbGZcIiA6IFwiX2JsYW5rXCI7XG4gICAgICAgICAgICBjb25zdCBuZXdXaW5kb3cgPSB3aW5kb3cub3Blbih1bmRlZmluZWQsIHRhcmdldCk7IC8vIGh0dHBzOi8vbWF0aGlhc2J5bmVucy5naXRodWIuaW8vcmVsLW5vb3BlbmVyL1xuXG4gICAgICAgICAgICBpZiAobmV3V2luZG93KSB7XG4gICAgICAgICAgICAgIG5ld1dpbmRvdy5vcGVuZXIgPSBudWxsO1xuICAgICAgICAgICAgICBuZXdXaW5kb3cubG9jYXRpb24gPSB1cmw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuZ2V0VG9wTGF5ZXJGcmFtZUF0U2NlbmVDb29yZHMgPSBzY2VuZUNvb3JkcyA9PiB7XG4gICAgICBjb25zdCBmcmFtZXMgPSB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRGcmFtZXMoKS5maWx0ZXIoZnJhbWUgPT4gaXNDdXJzb3JJbkZyYW1lKHNjZW5lQ29vcmRzLCBmcmFtZSkpO1xuICAgICAgcmV0dXJuIGZyYW1lcy5sZW5ndGggPyBmcmFtZXNbZnJhbWVzLmxlbmd0aCAtIDFdIDogbnVsbDtcbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVDYW52YXNQb2ludGVyTW92ZSA9IGV2ZW50ID0+IHtcbiAgICAgIHZhciBfYSwgX2I7XG5cbiAgICAgIHRoaXMuc2F2ZVBvaW50ZXIoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgdGhpcy5zdGF0ZS5jdXJzb3JCdXR0b24pO1xuXG4gICAgICBpZiAoZ2VzdHVyZS5wb2ludGVycy5oYXMoZXZlbnQucG9pbnRlcklkKSkge1xuICAgICAgICBnZXN0dXJlLnBvaW50ZXJzLnNldChldmVudC5wb2ludGVySWQsIHtcbiAgICAgICAgICB4OiBldmVudC5jbGllbnRYLFxuICAgICAgICAgIHk6IGV2ZW50LmNsaWVudFlcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGluaXRpYWxTY2FsZSA9IGdlc3R1cmUuaW5pdGlhbFNjYWxlO1xuXG4gICAgICBpZiAoZ2VzdHVyZS5wb2ludGVycy5zaXplID09PSAyICYmIGdlc3R1cmUubGFzdENlbnRlciAmJiBpbml0aWFsU2NhbGUgJiYgZ2VzdHVyZS5pbml0aWFsRGlzdGFuY2UpIHtcbiAgICAgICAgY29uc3QgY2VudGVyID0gZ2V0Q2VudGVyKGdlc3R1cmUucG9pbnRlcnMpO1xuICAgICAgICBjb25zdCBkZWx0YVggPSBjZW50ZXIueCAtIGdlc3R1cmUubGFzdENlbnRlci54O1xuICAgICAgICBjb25zdCBkZWx0YVkgPSBjZW50ZXIueSAtIGdlc3R1cmUubGFzdENlbnRlci55O1xuICAgICAgICBnZXN0dXJlLmxhc3RDZW50ZXIgPSBjZW50ZXI7XG4gICAgICAgIGNvbnN0IGRpc3RhbmNlID0gZ2V0RGlzdGFuY2UoQXJyYXkuZnJvbShnZXN0dXJlLnBvaW50ZXJzLnZhbHVlcygpKSk7XG4gICAgICAgIGNvbnN0IHNjYWxlRmFjdG9yID0gdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiZnJlZWRyYXdcIiAmJiB0aGlzLnN0YXRlLnBlbk1vZGUgPyAxIDogZGlzdGFuY2UgLyBnZXN0dXJlLmluaXRpYWxEaXN0YW5jZTtcbiAgICAgICAgY29uc3QgbmV4dFpvb20gPSBzY2FsZUZhY3RvciA/IGdldE5vcm1hbGl6ZWRab29tKGluaXRpYWxTY2FsZSAqIHNjYWxlRmFjdG9yKSA6IHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSA9PiB7XG4gICAgICAgICAgY29uc3Qgem9vbVN0YXRlID0gZ2V0U3RhdGVGb3Jab29tKHtcbiAgICAgICAgICAgIHZpZXdwb3J0WDogY2VudGVyLngsXG4gICAgICAgICAgICB2aWV3cG9ydFk6IGNlbnRlci55LFxuICAgICAgICAgICAgbmV4dFpvb21cbiAgICAgICAgICB9LCBzdGF0ZSk7XG4gICAgICAgICAgdGhpcy50cmFuc2xhdGVDYW52YXMoe1xuICAgICAgICAgICAgem9vbTogem9vbVN0YXRlLnpvb20sXG4gICAgICAgICAgICBzY3JvbGxYOiB6b29tU3RhdGUuc2Nyb2xsWCArIGRlbHRhWCAvIG5leHRab29tLFxuICAgICAgICAgICAgc2Nyb2xsWTogem9vbVN0YXRlLnNjcm9sbFkgKyBkZWx0YVkgLyBuZXh0Wm9vbSxcbiAgICAgICAgICAgIHNob3VsZENhY2hlSWdub3JlWm9vbTogdHJ1ZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZXNldFNob3VsZENhY2hlSWdub3JlWm9vbURlYm91bmNlZCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZ2VzdHVyZS5sYXN0Q2VudGVyID0gZ2VzdHVyZS5pbml0aWFsRGlzdGFuY2UgPSBnZXN0dXJlLmluaXRpYWxTY2FsZSA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0hvbGRpbmdTcGFjZSB8fCBpc1Bhbm5pbmcgfHwgaXNEcmFnZ2luZ1Njcm9sbEJhciB8fCBpc0hhbmRUb29sQWN0aXZlKHRoaXMuc3RhdGUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaXNQb2ludGVyT3ZlclNjcm9sbEJhcnMgPSBpc092ZXJTY3JvbGxCYXJzKGN1cnJlbnRTY3JvbGxCYXJzLCBldmVudC5jbGllbnRYIC0gdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0LCBldmVudC5jbGllbnRZIC0gdGhpcy5zdGF0ZS5vZmZzZXRUb3ApO1xuICAgICAgY29uc3QgaXNPdmVyU2Nyb2xsQmFyID0gaXNQb2ludGVyT3ZlclNjcm9sbEJhcnMuaXNPdmVyRWl0aGVyO1xuXG4gICAgICBpZiAoIXRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50ICYmICF0aGlzLnN0YXRlLm11bHRpRWxlbWVudCkge1xuICAgICAgICBpZiAoaXNPdmVyU2Nyb2xsQmFyKSB7XG4gICAgICAgICAgcmVzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0Q3Vyc29yRm9yU2hhcGUodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2NlbmVQb2ludGVyID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKGV2ZW50LCB0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgeDogc2NlbmVQb2ludGVyWCxcbiAgICAgICAgeTogc2NlbmVQb2ludGVyWVxuICAgICAgfSA9IHNjZW5lUG9pbnRlcjtcblxuICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgJiYgIXRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQuaXNEcmFnZ2luZykge1xuICAgICAgICBjb25zdCBlZGl0aW5nTGluZWFyRWxlbWVudCA9IExpbmVhckVsZW1lbnRFZGl0b3IuaGFuZGxlUG9pbnRlck1vdmUoZXZlbnQsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclksIHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmIChlZGl0aW5nTGluZWFyRWxlbWVudCAmJiBlZGl0aW5nTGluZWFyRWxlbWVudCAhPT0gdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgIC8vIFNpbmNlIHdlIGFyZSByZWFkaW5nIGZyb20gcHJldmlvdXMgc3RhdGUgd2hpY2ggaXMgbm90IHBvc3NpYmxlIHdpdGhcbiAgICAgICAgICAvLyBhdXRvbWF0aWMgYmF0Y2hpbmcgaW4gUmVhY3QgMTggaGVuY2UgdXNpbmcgZmx1c2ggc3luYyB0byBzeW5jaHJvbm91c2x5XG4gICAgICAgICAgLy8gdXBkYXRlIHRoZSBzdGF0ZS4gQ2hlY2sgaHR0cHM6Ly9naXRodWIuY29tL2V4Y2FsaWRyYXcvZXhjYWxpZHJhdy9wdWxsLzU1MDggZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgICBmbHVzaFN5bmMoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIGVkaXRpbmdMaW5lYXJFbGVtZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgoZWRpdGluZ0xpbmVhckVsZW1lbnQgPT09IG51bGwgfHwgZWRpdGluZ0xpbmVhckVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGVkaXRpbmdMaW5lYXJFbGVtZW50Lmxhc3RVbmNvbW1pdHRlZFBvaW50KSAhPSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nQXRDdXJzb3Ioc2NlbmVQb2ludGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBjYXVzZXMgc3RhY2sgb3ZlcmZsb3cgaWYgbm90IHN5bmNcbiAgICAgICAgICBmbHVzaFN5bmMoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGlzQmluZGluZ0VsZW1lbnRUeXBlKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlKSkge1xuICAgICAgICAvLyBIb3ZlcmluZyB3aXRoIGEgc2VsZWN0ZWQgdG9vbCBvciBjcmVhdGluZyBuZXcgbGluZWFyIGVsZW1lbnQgdmlhIGNsaWNrXG4gICAgICAgIC8vIGFuZCBwb2ludFxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgZHJhZ2dpbmdFbGVtZW50XG4gICAgICAgIH0gPSB0aGlzLnN0YXRlO1xuXG4gICAgICAgIGlmIChpc0JpbmRpbmdFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwgZmFsc2UpKSB7XG4gICAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nc0ZvckxpbmVhckVsZW1lbnRBdENvb3JkcyhkcmFnZ2luZ0VsZW1lbnQsIFtzY2VuZVBvaW50ZXJdLCB0aGlzLnN0YXRlLnN0YXJ0Qm91bmRFbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdBdEN1cnNvcihzY2VuZVBvaW50ZXIpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLm11bHRpRWxlbWVudCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgbXVsdGlFbGVtZW50XG4gICAgICAgIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeDogcngsXG4gICAgICAgICAgeTogcnlcbiAgICAgICAgfSA9IG11bHRpRWxlbWVudDtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHBvaW50cyxcbiAgICAgICAgICBsYXN0Q29tbWl0dGVkUG9pbnRcbiAgICAgICAgfSA9IG11bHRpRWxlbWVudDtcbiAgICAgICAgY29uc3QgbGFzdFBvaW50ID0gcG9pbnRzW3BvaW50cy5sZW5ndGggLSAxXTtcbiAgICAgICAgc2V0Q3Vyc29yRm9yU2hhcGUodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZSk7XG5cbiAgICAgICAgaWYgKGxhc3RQb2ludCA9PT0gbGFzdENvbW1pdHRlZFBvaW50KSB7XG4gICAgICAgICAgLy8gaWYgd2UgaGF2ZW4ndCB5ZXQgY3JlYXRlZCBhIHRlbXAgcG9pbnQgYW5kIHdlJ3JlIGJleW9uZCBjb21taXQtem9uZVxuICAgICAgICAgIC8vIHRocmVzaG9sZCwgYWRkIGEgcG9pbnRcbiAgICAgICAgICBpZiAoZGlzdGFuY2UyZChzY2VuZVBvaW50ZXJYIC0gcngsIHNjZW5lUG9pbnRlclkgLSByeSwgbGFzdFBvaW50WzBdLCBsYXN0UG9pbnRbMV0pID49IExJTkVfQ09ORklSTV9USFJFU0hPTEQpIHtcbiAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQobXVsdGlFbGVtZW50LCB7XG4gICAgICAgICAgICAgIHBvaW50czogWy4uLnBvaW50cywgW3NjZW5lUG9pbnRlclggLSByeCwgc2NlbmVQb2ludGVyWSAtIHJ5XV1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuUE9JTlRFUik7IC8vIGluIHRoaXMgYnJhbmNoLCB3ZSdyZSBpbnNpZGUgdGhlIGNvbW1pdCB6b25lLCBhbmQgbm8gdW5jb21taXR0ZWRcbiAgICAgICAgICAgIC8vIHBvaW50IGV4aXN0cy4gVGh1cyBkbyBub3RoaW5nIChkb24ndCBhZGQvcmVtb3ZlIHBvaW50cykuXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHBvaW50cy5sZW5ndGggPiAyICYmIGxhc3RDb21taXR0ZWRQb2ludCAmJiBkaXN0YW5jZTJkKHNjZW5lUG9pbnRlclggLSByeCwgc2NlbmVQb2ludGVyWSAtIHJ5LCBsYXN0Q29tbWl0dGVkUG9pbnRbMF0sIGxhc3RDb21taXR0ZWRQb2ludFsxXSkgPCBMSU5FX0NPTkZJUk1fVEhSRVNIT0xEKSB7XG4gICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLlBPSU5URVIpO1xuICAgICAgICAgIG11dGF0ZUVsZW1lbnQobXVsdGlFbGVtZW50LCB7XG4gICAgICAgICAgICBwb2ludHM6IHBvaW50cy5zbGljZSgwLCAtMSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZLCBldmVudFtLRVlTLkNUUkxfT1JfQ01EXSA/IG51bGwgOiB0aGlzLnN0YXRlLmdyaWRTaXplKTtcbiAgICAgICAgICBjb25zdCBbbGFzdENvbW1pdHRlZFgsIGxhc3RDb21taXR0ZWRZXSA9IChfYSA9IG11bHRpRWxlbWVudCA9PT0gbnVsbCB8fCBtdWx0aUVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG11bHRpRWxlbWVudC5sYXN0Q29tbWl0dGVkUG9pbnQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IFswLCAwXTtcbiAgICAgICAgICBsZXQgZHhGcm9tTGFzdENvbW1pdHRlZCA9IGdyaWRYIC0gcnggLSBsYXN0Q29tbWl0dGVkWDtcbiAgICAgICAgICBsZXQgZHlGcm9tTGFzdENvbW1pdHRlZCA9IGdyaWRZIC0gcnkgLSBsYXN0Q29tbWl0dGVkWTtcblxuICAgICAgICAgIGlmIChzaG91bGRSb3RhdGVXaXRoRGlzY3JldGVBbmdsZShldmVudCkpIHtcbiAgICAgICAgICAgICh7XG4gICAgICAgICAgICAgIHdpZHRoOiBkeEZyb21MYXN0Q29tbWl0dGVkLFxuICAgICAgICAgICAgICBoZWlnaHQ6IGR5RnJvbUxhc3RDb21taXR0ZWRcbiAgICAgICAgICAgIH0gPSBnZXRMb2NrZWRMaW5lYXJDdXJzb3JBbGlnblNpemUoIC8vIGFjdHVhbCBjb29yZGluYXRlIG9mIHRoZSBsYXN0IGNvbW1pdHRlZCBwb2ludFxuICAgICAgICAgICAgbGFzdENvbW1pdHRlZFggKyByeCwgbGFzdENvbW1pdHRlZFkgKyByeSwgLy8gY3Vyc29yLWdyaWQgY29vcmRpbmF0ZVxuICAgICAgICAgICAgZ3JpZFgsIGdyaWRZKSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGlzUGF0aEFMb29wKHBvaW50cywgdGhpcy5zdGF0ZS56b29tLnZhbHVlKSkge1xuICAgICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLlBPSU5URVIpO1xuICAgICAgICAgIH0gLy8gdXBkYXRlIGxhc3QgdW5jb21taXR0ZWQgcG9pbnRcblxuXG4gICAgICAgICAgbXV0YXRlRWxlbWVudChtdWx0aUVsZW1lbnQsIHtcbiAgICAgICAgICAgIHBvaW50czogWy4uLnBvaW50cy5zbGljZSgwLCAtMSksIFtsYXN0Q29tbWl0dGVkWCArIGR4RnJvbUxhc3RDb21taXR0ZWQsIGxhc3RDb21taXR0ZWRZICsgZHlGcm9tTGFzdENvbW1pdHRlZF1dXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGhhc0Rlc2VsZWN0ZWRCdXR0b24gPSBCb29sZWFuKGV2ZW50LmJ1dHRvbnMpO1xuXG4gICAgICBpZiAoaGFzRGVzZWxlY3RlZEJ1dHRvbiB8fCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIiAmJiB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gXCJ0ZXh0XCIgJiYgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwiZXJhc2VyXCIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBlbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCk7XG4gICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDEgJiYgIWlzT3ZlclNjcm9sbEJhciAmJiAhdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICBjb25zdCBlbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUgPSBnZXRFbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUoZWxlbWVudHMsIHRoaXMuc3RhdGUsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclksIHRoaXMuc3RhdGUuem9vbSwgZXZlbnQucG9pbnRlclR5cGUpO1xuXG4gICAgICAgIGlmIChlbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUgJiYgZWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlLnRyYW5zZm9ybUhhbmRsZVR5cGUpIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgZ2V0Q3Vyc29yRm9yUmVzaXppbmdFbGVtZW50KGVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZSkpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA+IDEgJiYgIWlzT3ZlclNjcm9sbEJhcikge1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm1IYW5kbGVUeXBlID0gZ2V0VHJhbnNmb3JtSGFuZGxlVHlwZUZyb21Db29yZHMoZ2V0Q29tbW9uQm91bmRzKHNlbGVjdGVkRWxlbWVudHMpLCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZLCB0aGlzLnN0YXRlLnpvb20sIGV2ZW50LnBvaW50ZXJUeXBlKTtcblxuICAgICAgICBpZiAodHJhbnNmb3JtSGFuZGxlVHlwZSkge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBnZXRDdXJzb3JGb3JSZXNpemluZ0VsZW1lbnQoe1xuICAgICAgICAgICAgdHJhbnNmb3JtSGFuZGxlVHlwZVxuICAgICAgICAgIH0pKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgaGl0RWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55KTtcbiAgICAgIHRoaXMuaGl0TGlua0VsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRMaW5rQXRQb3NpdGlvbihzY2VuZVBvaW50ZXIsIGhpdEVsZW1lbnQpO1xuXG4gICAgICBpZiAoaXNFcmFzZXJBY3RpdmUodGhpcy5zdGF0ZSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5oaXRMaW5rRWxlbWVudCAmJiAhdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbdGhpcy5oaXRMaW5rRWxlbWVudC5pZF0pIHtcbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLlBPSU5URVIpO1xuICAgICAgICBzaG93SHlwZXJsaW5rVG9vbHRpcCh0aGlzLmhpdExpbmtFbGVtZW50LCB0aGlzLnN0YXRlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhpZGVIeXBlcmxpbmtUb29saXAoKTtcblxuICAgICAgICBpZiAoaGl0RWxlbWVudCAmJiAoaGl0RWxlbWVudC5saW5rIHx8IGlzRW1iZWRkYWJsZUVsZW1lbnQoaGl0RWxlbWVudCkpICYmIHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdICYmICF0aGlzLnN0YXRlLmNvbnRleHRNZW51ICYmICF0aGlzLnN0YXRlLnNob3dIeXBlcmxpbmtQb3B1cCkge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc2hvd0h5cGVybGlua1BvcHVwOiBcImluZm9cIlxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInRleHRcIikge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBpc1RleHRFbGVtZW50KGhpdEVsZW1lbnQpID8gQ1VSU09SX1RZUEUuVEVYVCA6IENVUlNPUl9UWVBFLkNST1NTSEFJUik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuR1JBQik7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPdmVyU2Nyb2xsQmFyKSB7XG4gICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkFVVE8pO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVIb3ZlclNlbGVjdGVkTGluZWFyRWxlbWVudCh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCwgc2NlbmVQb2ludGVyWCwgc2NlbmVQb2ludGVyWSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIC8vIGlmIHVzaW5nIGNtZC9jdHJsLCB3ZSdyZSBub3QgZHJhZ2dpbmdcbiAgICAgICAgIWV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdKSB7XG4gICAgICAgICAgaWYgKChoaXRFbGVtZW50IHx8IHRoaXMuaXNIaXR0aW5nQ29tbW9uQm91bmRpbmdCb3hPZlNlbGVjdGVkRWxlbWVudHMoc2NlbmVQb2ludGVyLCBzZWxlY3RlZEVsZW1lbnRzKSkgJiYgIShoaXRFbGVtZW50ID09PSBudWxsIHx8IGhpdEVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGhpdEVsZW1lbnQubG9ja2VkKSkge1xuICAgICAgICAgICAgaWYgKGhpdEVsZW1lbnQgJiYgaXNFbWJlZGRhYmxlRWxlbWVudChoaXRFbGVtZW50KSAmJiB0aGlzLmlzRW1iZWRkYWJsZUNlbnRlcihoaXRFbGVtZW50LCBldmVudCwgc2NlbmVQb2ludGVyWCwgc2NlbmVQb2ludGVyWSkpIHtcbiAgICAgICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLlBPSU5URVIpO1xuICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiB7XG4gICAgICAgICAgICAgICAgICBlbGVtZW50OiBoaXRFbGVtZW50LFxuICAgICAgICAgICAgICAgICAgc3RhdGU6IFwiaG92ZXJcIlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuTU9WRSk7XG5cbiAgICAgICAgICAgICAgaWYgKCgoX2IgPSB0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5zdGF0ZSkgPT09IFwiaG92ZXJcIikge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5BVVRPKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZUVyYXNlciA9IChldmVudCwgcG9pbnRlckRvd25TdGF0ZSwgc2NlbmVQb2ludGVyKSA9PiB7XG4gICAgICBjb25zdCB1cGRhdGVFbGVtZW50SWRzID0gZWxlbWVudHMgPT4ge1xuICAgICAgICBlbGVtZW50cy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgIGlmIChlbGVtZW50LmxvY2tlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlkc1RvVXBkYXRlLnB1c2goZWxlbWVudC5pZCk7XG5cbiAgICAgICAgICBpZiAoZXZlbnQuYWx0S2V5KSB7XG4gICAgICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGVtZW50LmlkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZW1lbnQuaWRdLmVyYXNlKSB7XG4gICAgICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlbWVudC5pZF0uZXJhc2UgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKCFwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZW1lbnQuaWRdKSB7XG4gICAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZW1lbnQuaWRdID0ge1xuICAgICAgICAgICAgICBlcmFzZTogdHJ1ZSxcbiAgICAgICAgICAgICAgb3BhY2l0eTogZWxlbWVudC5vcGFjaXR5XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBjb25zdCBpZHNUb1VwZGF0ZSA9IFtdO1xuICAgICAgY29uc3QgZGlzdGFuY2UgPSBkaXN0YW5jZTJkKHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy54LCBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueSwgc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55KTtcbiAgICAgIGNvbnN0IHRocmVzaG9sZCA9IDEwIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuICAgICAgY29uc3QgcG9pbnQgPSBPYmplY3QuYXNzaWduKHt9LCBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMpO1xuICAgICAgbGV0IHNhbXBsaW5nSW50ZXJ2YWwgPSAwO1xuXG4gICAgICB3aGlsZSAoc2FtcGxpbmdJbnRlcnZhbCA8PSBkaXN0YW5jZSkge1xuICAgICAgICBjb25zdCBoaXRFbGVtZW50cyA9IHRoaXMuZ2V0RWxlbWVudHNBdFBvc2l0aW9uKHBvaW50LngsIHBvaW50LnkpO1xuICAgICAgICB1cGRhdGVFbGVtZW50SWRzKGhpdEVsZW1lbnRzKTsgLy8gRXhpdCBzaW5jZSB3ZSByZWFjaGVkIGN1cnJlbnQgcG9pbnRcblxuICAgICAgICBpZiAoc2FtcGxpbmdJbnRlcnZhbCA9PT0gZGlzdGFuY2UpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfSAvLyBDYWxjdWxhdGUgbmV4dCBwb2ludCBpbiB0aGUgbGluZSBhdCBhIGRpc3RhbmNlIG9mIHNhbXBsaW5nIGludGVydmFsXG5cblxuICAgICAgICBzYW1wbGluZ0ludGVydmFsID0gTWF0aC5taW4oc2FtcGxpbmdJbnRlcnZhbCArIHRocmVzaG9sZCwgZGlzdGFuY2UpO1xuICAgICAgICBjb25zdCBkaXN0YW5jZVJhdGlvID0gc2FtcGxpbmdJbnRlcnZhbCAvIGRpc3RhbmNlO1xuICAgICAgICBjb25zdCBuZXh0WCA9ICgxIC0gZGlzdGFuY2VSYXRpbykgKiBwb2ludC54ICsgZGlzdGFuY2VSYXRpbyAqIHNjZW5lUG9pbnRlci54O1xuICAgICAgICBjb25zdCBuZXh0WSA9ICgxIC0gZGlzdGFuY2VSYXRpbykgKiBwb2ludC55ICsgZGlzdGFuY2VSYXRpbyAqIHNjZW5lUG9pbnRlci55O1xuICAgICAgICBwb2ludC54ID0gbmV4dFg7XG4gICAgICAgIHBvaW50LnkgPSBuZXh0WTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLm1hcChlbGUgPT4ge1xuICAgICAgICBjb25zdCBpZCA9IGlzQm91bmRUb0NvbnRhaW5lcihlbGUpICYmIGlkc1RvVXBkYXRlLmluY2x1ZGVzKGVsZS5jb250YWluZXJJZCkgPyBlbGUuY29udGFpbmVySWQgOiBlbGUuaWQ7XG5cbiAgICAgICAgaWYgKGlkc1RvVXBkYXRlLmluY2x1ZGVzKGlkKSkge1xuICAgICAgICAgIGlmIChldmVudC5hbHRLZXkpIHtcbiAgICAgICAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2lkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2lkXS5lcmFzZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnRXaXRoKGVsZSwge1xuICAgICAgICAgICAgICAgIG9wYWNpdHk6IHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbaWRdLm9wYWNpdHlcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXdFbGVtZW50V2l0aChlbGUsIHtcbiAgICAgICAgICAgICAgb3BhY2l0eTogRUxFTUVOVF9SRUFEWV9UT19FUkFTRV9PUEFDSVRZXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZWxlO1xuICAgICAgfSk7XG4gICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhlbGVtZW50cyk7XG4gICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueCA9IHNjZW5lUG9pbnRlci54O1xuICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnkgPSBzY2VuZVBvaW50ZXIueTtcbiAgICB9OyAvLyBzZXQgdG91Y2ggbW92aW5nIGZvciBtb2JpbGUgY29udGV4dCBtZW51XG5cblxuICAgIHRoaXMuaGFuZGxlVG91Y2hNb3ZlID0gZXZlbnQgPT4ge1xuICAgICAgaW52YWxpZGF0ZUNvbnRleHRNZW51ID0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVDYW52YXNQb2ludGVyRG93biA9IGV2ZW50ID0+IHtcbiAgICAgIHZhciBfYSwgX2I7IC8vIHNpbmNlIGNvbnRleHRNZW51IG9wdGlvbnMgYXJlIHBvdGVudGlhbGx5IGV2YWx1YXRlZCBvbiBlYWNoIHJlbmRlcixcbiAgICAgIC8vIGFuZCBhbiBjb250ZXh0TWVudSBhY3Rpb24gbWF5IGRlcGVuZCBvbiBzZWxlY3Rpb24gc3RhdGUsIHdlIG11c3RcbiAgICAgIC8vIGNsb3NlIHRoZSBjb250ZXh0TWVudSBiZWZvcmUgd2UgdXBkYXRlIHRoZSBzZWxlY3Rpb24gb24gcG9pbnRlckRvd25cbiAgICAgIC8vIChlLmcuIHJlc2V0dGluZyBzZWxlY3Rpb24pXG5cblxuICAgICAgaWYgKHRoaXMuc3RhdGUuY29udGV4dE1lbnUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgY29udGV4dE1lbnU6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudXBkYXRlR2VzdHVyZU9uUG9pbnRlckRvd24oZXZlbnQpOyAvLyBpZiBkcmFnZ2luZyBlbGVtZW50IGlzIGZyZWVkcmF3IGFuZCBhbm90aGVyIHBvaW50ZXJkb3duIGV2ZW50IG9jY3Vyc1xuICAgICAgLy8gYSBzZWNvbmQgZmluZ2VyIGlzIG9uIHRoZSBzY3JlZW5cbiAgICAgIC8vIGRpc2NhcmQgdGhlIGZyZWVkcmF3IGVsZW1lbnQgaWYgaXQgaXMgdmVyeSBzaG9ydCBiZWNhdXNlIGl0IGlzIGxpa2VseVxuICAgICAgLy8ganVzdCBhIHNwaWtlLCBvdGhlcndpc2UgZmluYWxpemUgdGhlIGZyZWVkcmF3IGVsZW1lbnQgd2hlbiB0aGUgc2Vjb25kXG4gICAgICAvLyBmaW5nZXIgaXMgbGlmdGVkXG5cbiAgICAgIGlmIChldmVudC5wb2ludGVyVHlwZSA9PT0gXCJ0b3VjaFwiICYmIHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50ICYmIHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50LnR5cGUgPT09IFwiZnJlZWRyYXdcIikge1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5zdGF0ZS5kcmFnZ2luZ0VsZW1lbnQ7XG4gICAgICAgIHRoaXMudXBkYXRlU2NlbmUoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBlbGVtZW50LnBvaW50cy5sZW5ndGggPCAxMCA/IHtcbiAgICAgICAgICBlbGVtZW50czogdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5maWx0ZXIoZWwgPT4gZWwuaWQgIT09IGVsZW1lbnQuaWQpXG4gICAgICAgIH0gOiB7fSksIHtcbiAgICAgICAgICBhcHBTdGF0ZToge1xuICAgICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBudWxsLFxuICAgICAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgICBzdGFydEJvdW5kRWxlbWVudDogbnVsbCxcbiAgICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXSxcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmtleXModGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLmZpbHRlcihrZXkgPT4ga2V5ICE9PSBlbGVtZW50LmlkKS5yZWR1Y2UoKG9iaiwga2V5KSA9PiB7XG4gICAgICAgICAgICAgIG9ialtrZXldID0gdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNba2V5XTtcbiAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgIH0sIHt9KSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyByZW1vdmUgYW55IGFjdGl2ZSBzZWxlY3Rpb24gd2hlbiB3ZSBzdGFydCB0byBpbnRlcmFjdCB3aXRoIGNhbnZhc1xuICAgICAgLy8gKG1haW5seSwgd2UgY2FyZSBhYm91dCByZW1vdmluZyBzZWxlY3Rpb24gb3V0c2lkZSB0aGUgY29tcG9uZW50IHdoaWNoXG4gICAgICAvLyAgd291bGQgcHJldmVudCBvdXIgY29weSBoYW5kbGluZyBvdGhlcndpc2UpXG5cblxuICAgICAgY29uc3Qgc2VsZWN0aW9uID0gZG9jdW1lbnQuZ2V0U2VsZWN0aW9uKCk7XG5cbiAgICAgIGlmIChzZWxlY3Rpb24gPT09IG51bGwgfHwgc2VsZWN0aW9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzZWxlY3Rpb24uYW5jaG9yTm9kZSkge1xuICAgICAgICBzZWxlY3Rpb24ucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubWF5YmVPcGVuQ29udGV4dE1lbnVBZnRlclBvaW50ZXJEb3duT25Ub3VjaERldmljZXMoZXZlbnQpO1xuICAgICAgdGhpcy5tYXliZUNsZWFudXBBZnRlck1pc3NpbmdQb2ludGVyVXAoZXZlbnQpOyAvL2ZpcmVzIG9ubHkgb25jZSwgaWYgcGVuIGlzIGRldGVjdGVkLCBwZW5Nb2RlIGlzIGVuYWJsZWRcbiAgICAgIC8vdGhlIHVzZXIgY2FuIGRpc2FibGUgdGhpcyBieSB0b2dnbGluZyB0aGUgcGVuTW9kZSBidXR0b25cblxuICAgICAgaWYgKCF0aGlzLnN0YXRlLnBlbkRldGVjdGVkICYmIGV2ZW50LnBvaW50ZXJUeXBlID09PSBcInBlblwiKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcGVuTW9kZTogdHJ1ZSxcbiAgICAgICAgICAgIHBlbkRldGVjdGVkOiB0cnVlXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5kZXZpY2UuaXNUb3VjaFNjcmVlbiAmJiBbXCJwZW5cIiwgXCJ0b3VjaFwiXS5pbmNsdWRlcyhldmVudC5wb2ludGVyVHlwZSkpIHtcbiAgICAgICAgdGhpcy5kZXZpY2UgPSB1cGRhdGVPYmplY3QodGhpcy5kZXZpY2UsIHtcbiAgICAgICAgICBpc1RvdWNoU2NyZWVuOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNQYW5uaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5sYXN0UG9pbnRlckRvd24gPSBldmVudDtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBsYXN0UG9pbnRlckRvd25XaXRoOiBldmVudC5wb2ludGVyVHlwZSxcbiAgICAgICAgY3Vyc29yQnV0dG9uOiBcImRvd25cIlxuICAgICAgfSk7XG4gICAgICB0aGlzLnNhdmVQb2ludGVyKGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIFwiZG93blwiKTtcblxuICAgICAgaWYgKHRoaXMuaGFuZGxlQ2FudmFzUGFuVXNpbmdXaGVlbE9yU3BhY2VEcmFnKGV2ZW50KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIG9ubHkgaGFuZGxlIGxlZnQgbW91c2UgYnV0dG9uIG9yIHRvdWNoXG5cblxuICAgICAgaWYgKGV2ZW50LmJ1dHRvbiAhPT0gUE9JTlRFUl9CVVRUT04uTUFJTiAmJiBldmVudC5idXR0b24gIT09IFBPSU5URVJfQlVUVE9OLlRPVUNIKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gZG9uJ3Qgc2VsZWN0IHdoaWxlIHBhbm5pbmdcblxuXG4gICAgICBpZiAoZ2VzdHVyZS5wb2ludGVycy5zaXplID4gMSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIFN0YXRlIGZvciB0aGUgZHVyYXRpb24gb2YgYSBwb2ludGVyIGludGVyYWN0aW9uLCB3aGljaCBzdGFydHMgd2l0aCBhXG4gICAgICAvLyBwb2ludGVyRG93biBldmVudCwgZW5kcyB3aXRoIGEgcG9pbnRlclVwIGV2ZW50IChvciBhbm90aGVyIHBvaW50ZXJEb3duKVxuXG5cbiAgICAgIGNvbnN0IHBvaW50ZXJEb3duU3RhdGUgPSB0aGlzLmluaXRpYWxQb2ludGVyRG93blN0YXRlKGV2ZW50KTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBzZWxlY3RlZEVsZW1lbnRzQXJlQmVpbmdEcmFnZ2VkOiBmYWxzZVxuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLmhhbmRsZURyYWdnaW5nU2Nyb2xsQmFyKGV2ZW50LCBwb2ludGVyRG93blN0YXRlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2xlYXJTZWxlY3Rpb25JZk5vdFVzaW5nU2VsZWN0aW9uKCk7XG4gICAgICB0aGlzLnVwZGF0ZUJpbmRpbmdFbmFibGVkT25Qb2ludGVyTW92ZShldmVudCk7XG5cbiAgICAgIGlmICh0aGlzLmhhbmRsZVNlbGVjdGlvbk9uUG9pbnRlckRvd24oZXZlbnQsIHBvaW50ZXJEb3duU3RhdGUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYWxsb3dPblBvaW50ZXJEb3duID0gIXRoaXMuc3RhdGUucGVuTW9kZSB8fCBldmVudC5wb2ludGVyVHlwZSAhPT0gXCJ0b3VjaFwiIHx8IHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInNlbGVjdGlvblwiIHx8IHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInRleHRcIiB8fCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJpbWFnZVwiO1xuXG4gICAgICBpZiAoIWFsbG93T25Qb2ludGVyRG93bikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJ0ZXh0XCIpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVUZXh0T25Qb2ludGVyRG93bihldmVudCwgcG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiYXJyb3dcIiB8fCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJsaW5lXCIpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVMaW5lYXJFbGVtZW50T25Qb2ludGVyRG93bihldmVudCwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUsIHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJpbWFnZVwiKSB7XG4gICAgICAgIC8vIHJlc2V0IGltYWdlIHByZXZpZXcgb24gcG9pbnRlcmRvd25cbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkNST1NTSEFJUik7IC8vIHJldHJpZXZlIHRoZSBsYXRlc3QgZWxlbWVudCBhcyB0aGUgc3RhdGUgbWF5IGJlIHN0YWxlXG5cbiAgICAgICAgY29uc3QgcGVuZGluZ0ltYWdlRWxlbWVudCA9IHRoaXMuc3RhdGUucGVuZGluZ0ltYWdlRWxlbWVudElkICYmIHRoaXMuc2NlbmUuZ2V0RWxlbWVudCh0aGlzLnN0YXRlLnBlbmRpbmdJbWFnZUVsZW1lbnRJZCk7XG5cbiAgICAgICAgaWYgKCFwZW5kaW5nSW1hZ2VFbGVtZW50KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBwZW5kaW5nSW1hZ2VFbGVtZW50LFxuICAgICAgICAgIGVkaXRpbmdFbGVtZW50OiBwZW5kaW5nSW1hZ2VFbGVtZW50LFxuICAgICAgICAgIHBlbmRpbmdJbWFnZUVsZW1lbnRJZDogbnVsbCxcbiAgICAgICAgICBtdWx0aUVsZW1lbnQ6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB4LFxuICAgICAgICAgIHlcbiAgICAgICAgfSA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhldmVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIG11dGF0ZUVsZW1lbnQocGVuZGluZ0ltYWdlRWxlbWVudCwge1xuICAgICAgICAgIHgsXG4gICAgICAgICAgeVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiZnJlZWRyYXdcIikge1xuICAgICAgICB0aGlzLmhhbmRsZUZyZWVEcmF3RWxlbWVudE9uUG9pbnRlckRvd24oZXZlbnQsIHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlLCBwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiY3VzdG9tXCIpIHtcbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkFVVE8pO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJmcmFtZVwiKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlRnJhbWVFbGVtZW50T25Qb2ludGVyRG93bihwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwiZXJhc2VyXCIgJiYgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwiaGFuZFwiKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlR2VuZXJpY0VsZW1lbnRPblBvaW50ZXJEb3duKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlLCBwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIH1cblxuICAgICAgKF9iID0gKF9hID0gdGhpcy5wcm9wcykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLm9uUG9pbnRlckRvd24pID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wsIHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgY29uc3Qgb25Qb2ludGVyTW92ZSA9IHRoaXMub25Qb2ludGVyTW92ZUZyb21Qb2ludGVyRG93bkhhbmRsZXIocG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICBjb25zdCBvblBvaW50ZXJVcCA9IHRoaXMub25Qb2ludGVyVXBGcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgY29uc3Qgb25LZXlEb3duID0gdGhpcy5vbktleURvd25Gcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgY29uc3Qgb25LZXlVcCA9IHRoaXMub25LZXlVcEZyb21Qb2ludGVyRG93bkhhbmRsZXIocG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICBsYXN0UG9pbnRlclVwID0gb25Qb2ludGVyVXA7XG5cbiAgICAgIGlmICghdGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9NT1ZFLCBvblBvaW50ZXJNb3ZlKTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgb25Qb2ludGVyVXApO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5LRVlET1dOLCBvbktleURvd24pO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5LRVlVUCwgb25LZXlVcCk7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25Nb3ZlID0gb25Qb2ludGVyTW92ZTtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5ldmVudExpc3RlbmVycy5vblVwID0gb25Qb2ludGVyVXA7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25LZXlVcCA9IG9uS2V5VXA7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25LZXlEb3duID0gb25LZXlEb3duO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZUNhbnZhc1BvaW50ZXJVcCA9IGV2ZW50ID0+IHtcbiAgICAgIHZhciBfYSwgX2I7XG5cbiAgICAgIHRoaXMucmVtb3ZlUG9pbnRlcihldmVudCk7XG4gICAgICB0aGlzLmxhc3RQb2ludGVyVXAgPSBldmVudDtcbiAgICAgIGNvbnN0IHNjZW5lUG9pbnRlciA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICAgIGNsaWVudFg6IGV2ZW50LmNsaWVudFgsXG4gICAgICAgIGNsaWVudFk6IGV2ZW50LmNsaWVudFlcbiAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgY29uc3QgY2xpY2tsZW5ndGggPSBldmVudC50aW1lU3RhbXAgLSAoKF9iID0gKF9hID0gdGhpcy5sYXN0UG9pbnRlckRvd24pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS50aW1lU3RhbXApICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IDApO1xuXG4gICAgICBpZiAodGhpcy5kZXZpY2UuaXNNb2JpbGUgJiYgY2xpY2tsZW5ndGggPCAzMDApIHtcbiAgICAgICAgY29uc3QgaGl0RWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55KTtcblxuICAgICAgICBpZiAoaXNFbWJlZGRhYmxlRWxlbWVudChoaXRFbGVtZW50KSAmJiB0aGlzLmlzRW1iZWRkYWJsZUNlbnRlcihoaXRFbGVtZW50LCBldmVudCwgc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55KSkge1xuICAgICAgICAgIHRoaXMuaGFuZGxlRW1iZWRkYWJsZUNlbnRlckNsaWNrKGhpdEVsZW1lbnQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5kZXZpY2UuaXNUb3VjaFNjcmVlbikge1xuICAgICAgICBjb25zdCBoaXRFbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50QXRQb3NpdGlvbihzY2VuZVBvaW50ZXIueCwgc2NlbmVQb2ludGVyLnkpO1xuICAgICAgICB0aGlzLmhpdExpbmtFbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50TGlua0F0UG9zaXRpb24oc2NlbmVQb2ludGVyLCBoaXRFbGVtZW50KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuaGl0TGlua0VsZW1lbnQgJiYgIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW3RoaXMuaGl0TGlua0VsZW1lbnQuaWRdKSB7XG4gICAgICAgIGlmIChjbGlja2xlbmd0aCA8IDMwMCAmJiB0aGlzLmhpdExpbmtFbGVtZW50LnR5cGUgPT09IFwiZW1iZWRkYWJsZVwiICYmICFpc1BvaW50SGl0dGluZ0xpbmtJY29uKHRoaXMuaGl0TGlua0VsZW1lbnQsIHRoaXMuc3RhdGUsIFtzY2VuZVBvaW50ZXIueCwgc2NlbmVQb2ludGVyLnldKSkge1xuICAgICAgICAgIHRoaXMuaGFuZGxlRW1iZWRkYWJsZUNlbnRlckNsaWNrKHRoaXMuaGl0TGlua0VsZW1lbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMucmVkaXJlY3RUb0xpbmsoZXZlbnQsIHRoaXMuZGV2aWNlLmlzVG91Y2hTY3JlZW4pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGwsXG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiB7fVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5tYXliZU9wZW5Db250ZXh0TWVudUFmdGVyUG9pbnRlckRvd25PblRvdWNoRGV2aWNlcyA9IGV2ZW50ID0+IHtcbiAgICAgIC8vIGRlYWwgd2l0aCBvcGVuaW5nIGNvbnRleHQgbWVudSBvbiB0b3VjaCBkZXZpY2VzXG4gICAgICBpZiAoZXZlbnQucG9pbnRlclR5cGUgPT09IFwidG91Y2hcIikge1xuICAgICAgICBpbnZhbGlkYXRlQ29udGV4dE1lbnUgPSBmYWxzZTtcblxuICAgICAgICBpZiAodG91Y2hUaW1lb3V0KSB7XG4gICAgICAgICAgLy8gSWYgdGhlcmUncyBhbHJlYWR5IGEgdG91Y2hUaW1lb3V0LCB0aGlzIG1lYW5zIHRoYXQgdGhlcmUncyBhbm90aGVyXG4gICAgICAgICAgLy8gdG91Y2ggZG93biBhbmQgd2UgYXJlIGRvaW5nIGFub3RoZXIgdG91Y2gsIHNvIHdlIHNob3VsZG4ndCBvcGVuIHRoZVxuICAgICAgICAgIC8vIGNvbnRleHQgbWVudS5cbiAgICAgICAgICBpbnZhbGlkYXRlQ29udGV4dE1lbnUgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIG9wZW4gdGhlIGNvbnRleHQgbWVudSB3aXRoIHRoZSBmaXJzdCB0b3VjaCdzIGNsaWVudFggYW5kIGNsaWVudFlcbiAgICAgICAgICAvLyBpZiB0aGUgdG91Y2ggaXMgbm90IG1vdmluZ1xuICAgICAgICAgIHRvdWNoVGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRvdWNoVGltZW91dCA9IDA7XG5cbiAgICAgICAgICAgIGlmICghaW52YWxpZGF0ZUNvbnRleHRNZW51KSB7XG4gICAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2FudmFzQ29udGV4dE1lbnUoZXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIFRPVUNIX0NUWF9NRU5VX1RJTUVPVVQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMucmVzZXRDb250ZXh0TWVudVRpbWVyID0gKCkgPT4ge1xuICAgICAgY2xlYXJUaW1lb3V0KHRvdWNoVGltZW91dCk7XG4gICAgICB0b3VjaFRpbWVvdXQgPSAwO1xuICAgICAgaW52YWxpZGF0ZUNvbnRleHRNZW51ID0gZmFsc2U7XG4gICAgfTsgLy8gUmV0dXJucyB3aGV0aGVyIHRoZSBldmVudCBpcyBhIHBhbm5pbmdcblxuXG4gICAgdGhpcy5oYW5kbGVDYW52YXNQYW5Vc2luZ1doZWVsT3JTcGFjZURyYWcgPSBldmVudCA9PiB7XG4gICAgICBpZiAoIShnZXN0dXJlLnBvaW50ZXJzLnNpemUgPD0gMSAmJiAoZXZlbnQuYnV0dG9uID09PSBQT0lOVEVSX0JVVFRPTi5XSEVFTCB8fCBldmVudC5idXR0b24gPT09IFBPSU5URVJfQlVUVE9OLk1BSU4gJiYgaXNIb2xkaW5nU3BhY2UgfHwgaXNIYW5kVG9vbEFjdGl2ZSh0aGlzLnN0YXRlKSB8fCB0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkpIHx8IGlzVGV4dEVsZW1lbnQodGhpcy5zdGF0ZS5lZGl0aW5nRWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpc1Bhbm5pbmcgPSB0cnVlO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGxldCBuZXh0UGFzdGVQcmV2ZW50ZWQgPSBmYWxzZTtcbiAgICAgIGNvbnN0IGlzTGludXggPSAvTGludXgvLnRlc3Qod2luZG93Lm5hdmlnYXRvci5wbGF0Zm9ybSk7XG4gICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuR1JBQkJJTkcpO1xuICAgICAgbGV0IHtcbiAgICAgICAgY2xpZW50WDogbGFzdFgsXG4gICAgICAgIGNsaWVudFk6IGxhc3RZXG4gICAgICB9ID0gZXZlbnQ7XG4gICAgICBjb25zdCBvblBvaW50ZXJNb3ZlID0gd2l0aEJhdGNoZWRVcGRhdGVzVGhyb3R0bGVkKGV2ZW50ID0+IHtcbiAgICAgICAgY29uc3QgZGVsdGFYID0gbGFzdFggLSBldmVudC5jbGllbnRYO1xuICAgICAgICBjb25zdCBkZWx0YVkgPSBsYXN0WSAtIGV2ZW50LmNsaWVudFk7XG4gICAgICAgIGxhc3RYID0gZXZlbnQuY2xpZW50WDtcbiAgICAgICAgbGFzdFkgPSBldmVudC5jbGllbnRZO1xuICAgICAgICAvKlxuICAgICAgICAgKiBQcmV2ZW50IHBhc3RlIGV2ZW50IGlmIHdlIG1vdmUgd2hpbGUgbWlkZGxlIGNsaWNraW5nIG9uIExpbnV4LlxuICAgICAgICAgKiBTZWUgaXNzdWUgIzEzODMuXG4gICAgICAgICAqL1xuXG4gICAgICAgIGlmIChpc0xpbnV4ICYmICFuZXh0UGFzdGVQcmV2ZW50ZWQgJiYgKE1hdGguYWJzKGRlbHRhWCkgPiAxIHx8IE1hdGguYWJzKGRlbHRhWSkgPiAxKSkge1xuICAgICAgICAgIG5leHRQYXN0ZVByZXZlbnRlZCA9IHRydWU7XG4gICAgICAgICAgLyogUHJldmVudCB0aGUgbmV4dCBwYXN0ZSBldmVudCAqL1xuXG4gICAgICAgICAgY29uc3QgcHJldmVudE5leHRQYXN0ZSA9IGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QQVNURSwgcHJldmVudE5leHRQYXN0ZSk7XG4gICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICB9O1xuICAgICAgICAgIC8qXG4gICAgICAgICAgICogUmVlbmFibGUgbmV4dCBwYXN0ZSBpbiBjYXNlIG9mIGRpc2FibGVkIG1pZGRsZSBjbGljayBwYXN0ZSBmb3JcbiAgICAgICAgICAgKiBhbnkgcmVhc29uOlxuICAgICAgICAgICAqIC0gcmlnaHQgY2xpY2sgcGFzdGVcbiAgICAgICAgICAgKiAtIGVtcHR5IGNsaXBib2FyZFxuICAgICAgICAgICAqL1xuXG5cbiAgICAgICAgICBjb25zdCBlbmFibGVOZXh0UGFzdGUgPSAoKSA9PiB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlBBU1RFLCBwcmV2ZW50TmV4dFBhc3RlKTtcbiAgICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgZW5hYmxlTmV4dFBhc3RlKTtcbiAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5QQVNURSwgcHJldmVudE5leHRQYXN0ZSk7XG4gICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgZW5hYmxlTmV4dFBhc3RlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHtcbiAgICAgICAgICBzY3JvbGxYOiB0aGlzLnN0YXRlLnNjcm9sbFggLSBkZWx0YVggLyB0aGlzLnN0YXRlLnpvb20udmFsdWUsXG4gICAgICAgICAgc2Nyb2xsWTogdGhpcy5zdGF0ZS5zY3JvbGxZIC0gZGVsdGFZIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICBjb25zdCB0ZWFyZG93biA9IHdpdGhCYXRjaGVkVXBkYXRlcyhsYXN0UG9pbnRlclVwID0gKCkgPT4ge1xuICAgICAgICBsYXN0UG9pbnRlclVwID0gbnVsbDtcbiAgICAgICAgaXNQYW5uaW5nID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCFpc0hvbGRpbmdTcGFjZSkge1xuICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkdSQUIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRDdXJzb3JGb3JTaGFwZSh0aGlzLmludGVyYWN0aXZlQ2FudmFzLCB0aGlzLnN0YXRlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBjdXJzb3JCdXR0b246IFwidXBcIlxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zYXZlUG9pbnRlcihldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZLCBcInVwXCIpO1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX01PVkUsIG9uUG9pbnRlck1vdmUpO1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCB0ZWFyZG93bik7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkJMVVIsIHRlYXJkb3duKTtcbiAgICAgICAgb25Qb2ludGVyTW92ZS5mbHVzaCgpO1xuICAgICAgfSk7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5CTFVSLCB0ZWFyZG93bik7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX01PVkUsIG9uUG9pbnRlck1vdmUsIHtcbiAgICAgICAgcGFzc2l2ZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCB0ZWFyZG93bik7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuXG4gICAgdGhpcy5jbGVhclNlbGVjdGlvbklmTm90VXNpbmdTZWxlY3Rpb24gPSAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7fSwgdGhpcy5zdGF0ZSksXG4gICAgICAgICAgc2VsZWN0ZWRHcm91cElkczoge30sXG4gICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGwsXG4gICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIHdoZXRoZXIgdGhlIHBvaW50ZXIgZXZlbnQgaGFzIGJlZW4gY29tcGxldGVseSBoYW5kbGVkXG4gICAgICovXG5cblxuICAgIHRoaXMuaGFuZGxlU2VsZWN0aW9uT25Qb2ludGVyRG93biA9IChldmVudCwgcG9pbnRlckRvd25TdGF0ZSkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpO1xuICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmIChzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA9PT0gMSAmJiAhdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgIGNvbnN0IGVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZSA9IGdldEVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZShlbGVtZW50cywgdGhpcy5zdGF0ZSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSwgdGhpcy5zdGF0ZS56b29tLCBldmVudC5wb2ludGVyVHlwZSk7XG5cbiAgICAgICAgICBpZiAoZWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICByZXNpemluZ0VsZW1lbnQ6IGVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZS5lbGVtZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmhhbmRsZVR5cGUgPSBlbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUudHJhbnNmb3JtSGFuZGxlVHlwZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5yZXNpemUuaGFuZGxlVHlwZSA9IGdldFRyYW5zZm9ybUhhbmRsZVR5cGVGcm9tQ29vcmRzKGdldENvbW1vbkJvdW5kcyhzZWxlY3RlZEVsZW1lbnRzKSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSwgdGhpcy5zdGF0ZS56b29tLCBldmVudC5wb2ludGVyVHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5yZXNpemUuaGFuZGxlVHlwZSkge1xuICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmlzUmVzaXppbmcgPSB0cnVlO1xuICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLm9mZnNldCA9IHR1cGxlVG9Db29ycyhnZXRSZXNpemVPZmZzZXRYWShwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5oYW5kbGVUeXBlLCBzZWxlY3RlZEVsZW1lbnRzLCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55KSk7XG5cbiAgICAgICAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDEgJiYgaXNMaW5lYXJFbGVtZW50KHNlbGVjdGVkRWxlbWVudHNbMF0pICYmIHNlbGVjdGVkRWxlbWVudHNbMF0ucG9pbnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5yZXNpemUuYXJyb3dEaXJlY3Rpb24gPSBnZXRSZXNpemVBcnJvd0RpcmVjdGlvbihwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5oYW5kbGVUeXBlLCBzZWxlY3RlZEVsZW1lbnRzWzBdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgICBjb25zdCBsaW5lYXJFbGVtZW50RWRpdG9yID0gdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCB8fCB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudDtcbiAgICAgICAgICAgIGNvbnN0IHJldCA9IExpbmVhckVsZW1lbnRFZGl0b3IuaGFuZGxlUG9pbnRlckRvd24oZXZlbnQsIHRoaXMuc3RhdGUsIHRoaXMuaGlzdG9yeSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4sIGxpbmVhckVsZW1lbnRFZGl0b3IpO1xuXG4gICAgICAgICAgICBpZiAocmV0LmhpdEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudCA9IHJldC5oaXRFbGVtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocmV0LmxpbmVhckVsZW1lbnRFZGl0b3IpIHtcbiAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiByZXQubGluZWFyRWxlbWVudEVkaXRvclxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgZWRpdGluZ0xpbmVhckVsZW1lbnQ6IHJldC5saW5lYXJFbGVtZW50RWRpdG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJldC5kaWRBZGRQb2ludCkge1xuICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IC8vIGhpdEVsZW1lbnQgbWF5IGFscmVhZHkgYmUgc2V0IGFib3ZlLCBzbyBjaGVjayBmaXJzdFxuXG5cbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50ID0gKF9hID0gcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudCkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogdGhpcy5nZXRFbGVtZW50QXRQb3NpdGlvbihwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55KTtcblxuICAgICAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50KSB7XG4gICAgICAgICAgICAvLyBFYXJseSByZXR1cm4gaWYgcG9pbnRlciBpcyBoaXR0aW5nIGxpbmsgaWNvblxuICAgICAgICAgICAgY29uc3QgaGl0TGlua0VsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRMaW5rQXRQb3NpdGlvbih7XG4gICAgICAgICAgICAgIHg6IHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsXG4gICAgICAgICAgICAgIHk6IHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnlcbiAgICAgICAgICAgIH0sIHBvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQpO1xuXG4gICAgICAgICAgICBpZiAoaGl0TGlua0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gLy8gRm9yIG92ZXJsYXBwZWQgZWxlbWVudHMgb25lIHBvc2l0aW9uIG1heSBoaXRcbiAgICAgICAgICAvLyBtdWx0aXBsZSBlbGVtZW50c1xuXG5cbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmhpdC5hbGxIaXRFbGVtZW50cyA9IHRoaXMuZ2V0RWxlbWVudHNBdFBvc2l0aW9uKHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnkpO1xuICAgICAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50O1xuICAgICAgICAgIGNvbnN0IHNvbWVIaXRFbGVtZW50SXNTZWxlY3RlZCA9IHBvaW50ZXJEb3duU3RhdGUuaGl0LmFsbEhpdEVsZW1lbnRzLnNvbWUoZWxlbWVudCA9PiB0aGlzLmlzQVNlbGVjdGVkRWxlbWVudChlbGVtZW50KSk7XG5cbiAgICAgICAgICBpZiAoKGhpdEVsZW1lbnQgPT09IG51bGwgfHwgIXNvbWVIaXRFbGVtZW50SXNTZWxlY3RlZCkgJiYgIWV2ZW50LnNoaWZ0S2V5ICYmICFwb2ludGVyRG93blN0YXRlLmhpdC5oYXNIaXRDb21tb25Cb3VuZGluZ0JveE9mU2VsZWN0ZWRFbGVtZW50cykge1xuICAgICAgICAgICAgdGhpcy5jbGVhclNlbGVjdGlvbihoaXRFbGVtZW50KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe1xuICAgICAgICAgICAgICAgIFt0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZF06IHRydWVcbiAgICAgICAgICAgICAgfSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgICAgIH0pOyAvLyBJZiB3ZSBjbGljayBvbiBzb21ldGhpbmdcbiAgICAgICAgICB9IGVsc2UgaWYgKGhpdEVsZW1lbnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gb24gQ01EL0NUUkwsIGRyaWxsIGRvd24gdG8gaGl0IGVsZW1lbnQgcmVnYXJkbGVzcyBvZiBncm91cHMgZXRjLlxuICAgICAgICAgICAgaWYgKGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdKSB7XG4gICAgICAgICAgICAgIGlmICghdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbaGl0RWxlbWVudC5pZF0pIHtcbiAgICAgICAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmhpdC53YXNBZGRlZFRvU2VsZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZWRpdEdyb3VwRm9yU2VsZWN0ZWRFbGVtZW50KHByZXZTdGF0ZSwgaGl0RWxlbWVudCkpLCB7XG4gICAgICAgICAgICAgICAgcHJldmlvdXNTZWxlY3RlZEVsZW1lbnRJZHM6IHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgICAgICAgICAgIH0pKTsgLy8gbWFyayBhcyBub3QgY29tcGxldGVseSBoYW5kbGVkIHNvIGFzIHRvIGFsbG93IGRyYWdnaW5nIGV0Yy5cblxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9IC8vIGRlc2VsZWN0IGlmIGl0ZW0gaXMgc2VsZWN0ZWRcbiAgICAgICAgICAgIC8vIGlmIHNoaWZ0IGlzIG5vdCBjbGlja2VkLCB0aGlzIHdpbGwgYWx3YXlzIHJldHVybiB0cnVlXG4gICAgICAgICAgICAvLyBvdGhlcndpc2UsIGl0IHdpbGwgdHJpZ2dlciBzZWxlY3Rpb24gYmFzZWQgb24gY3VycmVudFxuICAgICAgICAgICAgLy8gc3RhdGUgb2YgdGhlIGJveFxuXG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbaGl0RWxlbWVudC5pZF0pIHtcbiAgICAgICAgICAgICAgLy8gaWYgd2UgYXJlIGN1cnJlbnRseSBlZGl0aW5nIGEgZ3JvdXAsIGV4aXRpbmcgZWRpdGluZyBtb2RlIGFuZCBkZXNlbGVjdCB0aGUgZ3JvdXAuXG4gICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdHcm91cElkICYmICFpc0VsZW1lbnRJbkdyb3VwKGhpdEVsZW1lbnQsIHRoaXMuc3RhdGUuZWRpdGluZ0dyb3VwSWQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IHt9LFxuICAgICAgICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0gLy8gQWRkIGhpdCBlbGVtZW50IHRvIHNlbGVjdGlvbi4gQXQgdGhpcyBwb2ludCBpZiB3ZSdyZSBub3QgaG9sZGluZ1xuICAgICAgICAgICAgICAvLyBTSElGVCB0aGUgcHJldmlvdXNseSBzZWxlY3RlZCBlbGVtZW50KHMpIHdlcmUgZGVzZWxlY3RlZCBhYm92ZVxuICAgICAgICAgICAgICAvLyAobWFrZSBzdXJlIHlvdSB1c2Ugc2V0U3RhdGUgdXBkYXRlciB0byB1c2UgbGF0ZXN0IHN0YXRlKVxuICAgICAgICAgICAgICAvLyBXaXRoIHNoaWZ0LXNlbGVjdGlvbiwgd2Ugd2FudCB0byBtYWtlIHN1cmUgdGhhdCBmcmFtZXMgYW5kIHRoZWlyIGNvbnRhaW5pbmdcbiAgICAgICAgICAgICAgLy8gZWxlbWVudHMgYXJlIG5vdCBzZWxlY3RlZCBhdCB0aGUgc2FtZSB0aW1lLlxuXG5cbiAgICAgICAgICAgICAgaWYgKCFzb21lSGl0RWxlbWVudElzU2VsZWN0ZWQgJiYgIXBvaW50ZXJEb3duU3RhdGUuaGl0Lmhhc0hpdENvbW1vbkJvdW5kaW5nQm94T2ZTZWxlY3RlZEVsZW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgbmV4dFNlbGVjdGVkRWxlbWVudElkcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyksIHtcbiAgICAgICAgICAgICAgICAgICAgW2hpdEVsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzbHlTZWxlY3RlZEVsZW1lbnRzID0gW107XG4gICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKS5mb3JFYWNoKGlkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuc2NlbmUuZ2V0RWxlbWVudChpZCk7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgJiYgcHJldmlvdXNseVNlbGVjdGVkRWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgIH0pOyAvLyBpZiBoaXRFbGVtZW50IGlzIGZyYW1lLCBkZXNlbGVjdCBhbGwgb2YgaXRzIGVsZW1lbnRzIGlmIHRoZXkgYXJlIHNlbGVjdGVkXG5cbiAgICAgICAgICAgICAgICAgIGlmIChoaXRFbGVtZW50LnR5cGUgPT09IFwiZnJhbWVcIikge1xuICAgICAgICAgICAgICAgICAgICBnZXRGcmFtZUVsZW1lbnRzKHByZXZpb3VzbHlTZWxlY3RlZEVsZW1lbnRzLCBoaXRFbGVtZW50LmlkKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2VsZW1lbnQuaWRdO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaGl0RWxlbWVudC5mcmFtZUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIGhpdEVsZW1lbnQgaXMgaW4gYSBmcmFtZSBhbmQgaXRzIGZyYW1lIGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIGRpc2FibGUgc2VsZWN0aW9uIGZvciB0aGUgZ2l2ZW4gZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICBpZiAobmV4dFNlbGVjdGVkRWxlbWVudElkc1toaXRFbGVtZW50LmZyYW1lSWRdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG5leHRTZWxlY3RlZEVsZW1lbnRJZHNbaGl0RWxlbWVudC5pZF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGhpdEVsZW1lbnQgaXMgbmVpdGhlciBhIGZyYW1lIG5vciBhbiBlbGVtZW50IGluIGEgZnJhbWVcbiAgICAgICAgICAgICAgICAgICAgLy8gYnV0IHNpbmNlIGhpdEVsZW1lbnQgY291bGQgYmUgaW4gYSBncm91cCB3aXRoIHNvbWUgZnJhbWVzXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgbWVhbnMgc2VsZWN0aW5nIGhpdEVsZW1lbnQgd2lsbCBoYXZlIHRoZSBmcmFtZXMgc2VsZWN0ZWQgYXMgd2VsbFxuICAgICAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHdlIHdhbnQgdG8ga2VlcCB0aGUgaW52YXJpYW50OlxuICAgICAgICAgICAgICAgICAgICAvLyAtIGZyYW1lcyBhbmQgdGhlaXIgZWxlbWVudHMgYXJlIG5vdCBzZWxlY3RlZCBhdCB0aGUgc2FtZSB0aW1lXG4gICAgICAgICAgICAgICAgICAgIC8vIHdlIGRlc2VsZWN0IGVsZW1lbnRzIGluIHRob3NlIGZyYW1lcyB0aGF0IHdlcmUgcHJldmlvdXNseSBzZWxlY3RlZFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBncm91cElkcyA9IGhpdEVsZW1lbnQuZ3JvdXBJZHM7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGZyYW1lc0luR3JvdXBzID0gbmV3IFNldChncm91cElkcy5mbGF0TWFwKGdpZCA9PiBnZXRFbGVtZW50c0luR3JvdXAodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZ2lkKSkuZmlsdGVyKGVsZW1lbnQgPT4gZWxlbWVudC50eXBlID09PSBcImZyYW1lXCIpLm1hcChmcmFtZSA9PiBmcmFtZS5pZCkpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChmcmFtZXNJbkdyb3Vwcy5zaXplID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzbHlTZWxlY3RlZEVsZW1lbnRzLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5mcmFtZUlkICYmIGZyYW1lc0luR3JvdXBzLmhhcyhlbGVtZW50LmZyYW1lSWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlc2VsZWN0IGVsZW1lbnQgYW5kIGdyb3VwcyBjb250YWluaW5nIHRoZSBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2VsZW1lbnQuaWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lmdyb3VwSWRzLmZsYXRNYXAoZ2lkID0+IGdldEVsZW1lbnRzSW5Hcm91cCh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBnaWQpKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2VsZW1lbnQuaWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IHByZXZTdGF0ZS5lZGl0aW5nR3JvdXBJZCxcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgICAgICAgICAgICAgICB9LCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBwcmV2U3RhdGUsIHRoaXMpKSwge1xuICAgICAgICAgICAgICAgICAgICBzaG93SHlwZXJsaW5rUG9wdXA6IGhpdEVsZW1lbnQubGluayB8fCBpc0VtYmVkZGFibGVFbGVtZW50KGhpdEVsZW1lbnQpID8gXCJpbmZvXCIgOiBmYWxzZVxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5oaXQud2FzQWRkZWRUb1NlbGVjdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHByZXZpb3VzU2VsZWN0ZWRFbGVtZW50SWRzOiB0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVUZXh0T25Qb2ludGVyRG93biA9IChldmVudCwgcG9pbnRlckRvd25TdGF0ZSkgPT4ge1xuICAgICAgLy8gaWYgd2UncmUgY3VycmVudGx5IHN0aWxsIGVkaXRpbmcgdGV4dCwgY2xpY2tpbmcgb3V0c2lkZVxuICAgICAgLy8gc2hvdWxkIG9ubHkgZmluYWxpemUgaXQsIG5vdCBjcmVhdGUgYW5vdGhlciAoaXJyZXNwZWN0aXZlXG4gICAgICAvLyBvZiBzdGF0ZS5hY3RpdmVUb29sLmxvY2tlZClcbiAgICAgIGlmIChpc1RleHRFbGVtZW50KHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IHNjZW5lWCA9IHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLng7XG4gICAgICBsZXQgc2NlbmVZID0gcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueTtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZLCB7XG4gICAgICAgIGluY2x1ZGVCb3VuZFRleHRFbGVtZW50OiB0cnVlXG4gICAgICB9KTsgLy8gRklYTUVcblxuICAgICAgbGV0IGNvbnRhaW5lciA9IGdldFRleHRCaW5kYWJsZUNvbnRhaW5lckF0UG9zaXRpb24odGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgdGhpcy5zdGF0ZSwgc2NlbmVYLCBzY2VuZVkpO1xuXG4gICAgICBpZiAoaGFzQm91bmRUZXh0RWxlbWVudChlbGVtZW50KSkge1xuICAgICAgICBjb250YWluZXIgPSBlbGVtZW50O1xuICAgICAgICBzY2VuZVggPSBlbGVtZW50LnggKyBlbGVtZW50LndpZHRoIC8gMjtcbiAgICAgICAgc2NlbmVZID0gZWxlbWVudC55ICsgZWxlbWVudC5oZWlnaHQgLyAyO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnN0YXJ0VGV4dEVkaXRpbmcoe1xuICAgICAgICBzY2VuZVgsXG4gICAgICAgIHNjZW5lWSxcbiAgICAgICAgaW5zZXJ0QXRQYXJlbnRDZW50ZXI6ICFldmVudC5hbHRLZXksXG4gICAgICAgIGNvbnRhaW5lclxuICAgICAgfSk7XG4gICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcblxuICAgICAgaWYgKCF0aGlzLnN0YXRlLmFjdGl2ZVRvb2wubG9ja2VkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGFjdGl2ZVRvb2w6IHVwZGF0ZUFjdGl2ZVRvb2wodGhpcy5zdGF0ZSwge1xuICAgICAgICAgICAgdHlwZTogXCJzZWxlY3Rpb25cIlxuICAgICAgICAgIH0pXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZUZyZWVEcmF3RWxlbWVudE9uUG9pbnRlckRvd24gPSAoZXZlbnQsIGVsZW1lbnRUeXBlLCBwb2ludGVyRG93blN0YXRlKSA9PiB7XG4gICAgICAvLyBCZWdpbiBhIG1hcmsgY2FwdHVyZS4gVGhpcyBkb2VzIG5vdCBoYXZlIHRvIHVwZGF0ZSBzdGF0ZSB5ZXQuXG4gICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55LCBudWxsKTtcbiAgICAgIGNvbnN0IHRvcExheWVyRnJhbWUgPSB0aGlzLmdldFRvcExheWVyRnJhbWVBdFNjZW5lQ29vcmRzKHtcbiAgICAgICAgeDogZ3JpZFgsXG4gICAgICAgIHk6IGdyaWRZXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBuZXdGcmVlRHJhd0VsZW1lbnQoe1xuICAgICAgICB0eXBlOiBlbGVtZW50VHlwZSxcbiAgICAgICAgeDogZ3JpZFgsXG4gICAgICAgIHk6IGdyaWRZLFxuICAgICAgICBzdHJva2VDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZUNvbG9yLFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1CYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgIGZpbGxTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZpbGxTdHlsZSxcbiAgICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VXaWR0aCxcbiAgICAgICAgc3Ryb2tlU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VTdHlsZSxcbiAgICAgICAgcm91Z2huZXNzOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91Z2huZXNzLFxuICAgICAgICBvcGFjaXR5OiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtT3BhY2l0eSxcbiAgICAgICAgcm91bmRuZXNzOiBudWxsLFxuICAgICAgICBzaW11bGF0ZVByZXNzdXJlOiBldmVudC5wcmVzc3VyZSA9PT0gMC41LFxuICAgICAgICBsb2NrZWQ6IGZhbHNlLFxuICAgICAgICBmcmFtZUlkOiB0b3BMYXllckZyYW1lID8gdG9wTGF5ZXJGcmFtZS5pZCA6IG51bGxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICBjb25zdCBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzID0gT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyk7XG4gICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2VsZW1lbnQuaWRdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMobmV4dFNlbGVjdGVkRWxlbWVudElkcywgcHJldlN0YXRlKVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICBjb25zdCBwcmVzc3VyZXMgPSBlbGVtZW50LnNpbXVsYXRlUHJlc3N1cmUgPyBlbGVtZW50LnByZXNzdXJlcyA6IFsuLi5lbGVtZW50LnByZXNzdXJlcywgZXZlbnQucHJlc3N1cmVdO1xuICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgIHBvaW50czogW1swLCAwXV0sXG4gICAgICAgIHByZXNzdXJlc1xuICAgICAgfSk7XG4gICAgICBjb25zdCBib3VuZEVsZW1lbnQgPSBnZXRIb3ZlcmVkRWxlbWVudEZvckJpbmRpbmcocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4sIHRoaXMuc2NlbmUpO1xuICAgICAgdGhpcy5zY2VuZS5hZGROZXdFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGRyYWdnaW5nRWxlbWVudDogZWxlbWVudCxcbiAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IGVsZW1lbnQsXG4gICAgICAgIHN0YXJ0Qm91bmRFbGVtZW50OiBib3VuZEVsZW1lbnQsXG4gICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgfSk7XG4gICAgfTsgLy9jcmVhdGUgcmVjdGFuZ2xlIGVsZW1lbnQgd2l0aCB5b3V0dWJlIHRvcCBsZWZ0IG9uIG5lYXJlc3QgZ3JpZCBwb2ludCB3aWR0aCAvIGhpZ2h0IDY0MC8zNjBcblxuXG4gICAgdGhpcy5pbnNlcnRFbWJlZGRhYmxlRWxlbWVudCA9ICh7XG4gICAgICBzY2VuZVgsXG4gICAgICBzY2VuZVksXG4gICAgICBsaW5rXG4gICAgfSkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChzY2VuZVgsIHNjZW5lWSwgKChfYSA9IHRoaXMubGFzdFBvaW50ZXJEb3duKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbS0VZUy5DVFJMX09SX0NNRF0pID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpO1xuICAgICAgY29uc3QgZW1iZWRMaW5rID0gZ2V0RW1iZWRMaW5rKGxpbmspO1xuXG4gICAgICBpZiAoIWVtYmVkTGluaykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChlbWJlZExpbmsud2FybmluZykge1xuICAgICAgICB0aGlzLnNldFRvYXN0KHtcbiAgICAgICAgICBtZXNzYWdlOiBlbWJlZExpbmsud2FybmluZyxcbiAgICAgICAgICBjbG9zYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZWxlbWVudCA9IG5ld0VtYmVkZGFibGVFbGVtZW50KHtcbiAgICAgICAgdHlwZTogXCJlbWJlZGRhYmxlXCIsXG4gICAgICAgIHg6IGdyaWRYLFxuICAgICAgICB5OiBncmlkWSxcbiAgICAgICAgc3Ryb2tlQ29sb3I6IFwidHJhbnNwYXJlbnRcIixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBcInRyYW5zcGFyZW50XCIsXG4gICAgICAgIGZpbGxTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZpbGxTdHlsZSxcbiAgICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VXaWR0aCxcbiAgICAgICAgc3Ryb2tlU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VTdHlsZSxcbiAgICAgICAgcm91Z2huZXNzOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91Z2huZXNzLFxuICAgICAgICByb3VuZG5lc3M6IHRoaXMuZ2V0Q3VycmVudEl0ZW1Sb3VuZG5lc3MoXCJlbWJlZGRhYmxlXCIpLFxuICAgICAgICBvcGFjaXR5OiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtT3BhY2l0eSxcbiAgICAgICAgbG9ja2VkOiBmYWxzZSxcbiAgICAgICAgd2lkdGg6IGVtYmVkTGluay5hc3BlY3RSYXRpby53LFxuICAgICAgICBoZWlnaHQ6IGVtYmVkTGluay5hc3BlY3RSYXRpby5oLFxuICAgICAgICBsaW5rLFxuICAgICAgICB2YWxpZGF0ZWQ6IG51bGxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoWy4uLnRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIGVsZW1lbnRdKTtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH07XG5cbiAgICB0aGlzLmNyZWF0ZUltYWdlRWxlbWVudCA9ICh7XG4gICAgICBzY2VuZVgsXG4gICAgICBzY2VuZVlcbiAgICB9KSA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIGNvbnN0IFtncmlkWCwgZ3JpZFldID0gZ2V0R3JpZFBvaW50KHNjZW5lWCwgc2NlbmVZLCAoKF9hID0gdGhpcy5sYXN0UG9pbnRlckRvd24pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYVtLRVlTLkNUUkxfT1JfQ01EXSkgPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICBjb25zdCB0b3BMYXllckZyYW1lID0gdGhpcy5nZXRUb3BMYXllckZyYW1lQXRTY2VuZUNvb3Jkcyh7XG4gICAgICAgIHg6IGdyaWRYLFxuICAgICAgICB5OiBncmlkWVxuICAgICAgfSk7XG4gICAgICBjb25zdCBlbGVtZW50ID0gbmV3SW1hZ2VFbGVtZW50KHtcbiAgICAgICAgdHlwZTogXCJpbWFnZVwiLFxuICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgeTogZ3JpZFksXG4gICAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlQ29sb3IsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUJhY2tncm91bmRDb2xvcixcbiAgICAgICAgZmlsbFN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtRmlsbFN0eWxlLFxuICAgICAgICBzdHJva2VXaWR0aDogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZVdpZHRoLFxuICAgICAgICBzdHJva2VTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZVN0eWxlLFxuICAgICAgICByb3VnaG5lc3M6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Sb3VnaG5lc3MsXG4gICAgICAgIHJvdW5kbmVzczogbnVsbCxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICAgIGxvY2tlZDogZmFsc2UsXG4gICAgICAgIGZyYW1lSWQ6IHRvcExheWVyRnJhbWUgPyB0b3BMYXllckZyYW1lLmlkIDogbnVsbFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVMaW5lYXJFbGVtZW50T25Qb2ludGVyRG93biA9IChldmVudCwgZWxlbWVudFR5cGUsIHBvaW50ZXJEb3duU3RhdGUpID0+IHtcbiAgICAgIGlmICh0aGlzLnN0YXRlLm11bHRpRWxlbWVudCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgbXVsdGlFbGVtZW50XG4gICAgICAgIH0gPSB0aGlzLnN0YXRlOyAvLyBmaW5hbGl6ZSBpZiBjb21wbGV0aW5nIGEgbG9vcFxuXG4gICAgICAgIGlmIChtdWx0aUVsZW1lbnQudHlwZSA9PT0gXCJsaW5lXCIgJiYgaXNQYXRoQUxvb3AobXVsdGlFbGVtZW50LnBvaW50cywgdGhpcy5zdGF0ZS56b29tLnZhbHVlKSkge1xuICAgICAgICAgIG11dGF0ZUVsZW1lbnQobXVsdGlFbGVtZW50LCB7XG4gICAgICAgICAgICBsYXN0Q29tbWl0dGVkUG9pbnQ6IG11bHRpRWxlbWVudC5wb2ludHNbbXVsdGlFbGVtZW50LnBvaW50cy5sZW5ndGggLSAxXVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeDogcngsXG4gICAgICAgICAgeTogcnksXG4gICAgICAgICAgbGFzdENvbW1pdHRlZFBvaW50XG4gICAgICAgIH0gPSBtdWx0aUVsZW1lbnQ7IC8vIGNsaWNraW5nIGluc2lkZSBjb21taXQgem9uZSDihpIgZmluYWxpemUgYXJyb3dcblxuICAgICAgICBpZiAobXVsdGlFbGVtZW50LnBvaW50cy5sZW5ndGggPiAxICYmIGxhc3RDb21taXR0ZWRQb2ludCAmJiBkaXN0YW5jZTJkKHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnggLSByeCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSAtIHJ5LCBsYXN0Q29tbWl0dGVkUG9pbnRbMF0sIGxhc3RDb21taXR0ZWRQb2ludFsxXSkgPCBMSU5FX0NPTkZJUk1fVEhSRVNIT0xEKSB7XG4gICAgICAgICAgdGhpcy5hY3Rpb25NYW5hZ2VyLmV4ZWN1dGVBY3Rpb24oYWN0aW9uRmluYWxpemUpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+ICh7XG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLCB7XG4gICAgICAgICAgICBbbXVsdGlFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgIH0pLCBwcmV2U3RhdGUpXG4gICAgICAgIH0pKTsgLy8gY2xpY2tpbmcgb3V0c2lkZSBjb21taXQgem9uZSDihpIgdXBkYXRlIHJlZmVyZW5jZSBmb3IgbGFzdCBjb21taXR0ZWRcbiAgICAgICAgLy8gcG9pbnRcblxuICAgICAgICBtdXRhdGVFbGVtZW50KG11bHRpRWxlbWVudCwge1xuICAgICAgICAgIGxhc3RDb21taXR0ZWRQb2ludDogbXVsdGlFbGVtZW50LnBvaW50c1ttdWx0aUVsZW1lbnQucG9pbnRzLmxlbmd0aCAtIDFdXG4gICAgICAgIH0pO1xuICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuUE9JTlRFUik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55LCBldmVudFtLRVlTLkNUUkxfT1JfQ01EXSA/IG51bGwgOiB0aGlzLnN0YXRlLmdyaWRTaXplKTtcbiAgICAgICAgY29uc3QgdG9wTGF5ZXJGcmFtZSA9IHRoaXMuZ2V0VG9wTGF5ZXJGcmFtZUF0U2NlbmVDb29yZHMoe1xuICAgICAgICAgIHg6IGdyaWRYLFxuICAgICAgICAgIHk6IGdyaWRZXG4gICAgICAgIH0pO1xuICAgICAgICAvKiBJZiBhcnJvdyBpcyBwcmUtYXJyb3doZWFkcywgaXQgd2lsbCBoYXZlIHVuZGVmaW5lZCBmb3IgYm90aCBzdGFydCBhbmQgZW5kIGFycm93aGVhZHMuXG4gICAgICAgIElmIHNvLCB3ZSB3YW50IGl0IHRvIGJlIG51bGwgZm9yIHN0YXJ0IGFuZCBcImFycm93XCIgZm9yIGVuZC4gSWYgdGhlIGxpbmVhciBpdGVtIGlzIG5vdFxuICAgICAgICBhbiBhcnJvdywgd2Ugd2FudCBpdCB0byBiZSBudWxsIGZvciBib3RoLiBPdGhlcndpc2UsIHdlIHdhbnQgaXQgdG8gdXNlIHRoZVxuICAgICAgICB2YWx1ZXMgZnJvbSBhcHBTdGF0ZS4gKi9cblxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgY3VycmVudEl0ZW1TdGFydEFycm93aGVhZCxcbiAgICAgICAgICBjdXJyZW50SXRlbUVuZEFycm93aGVhZFxuICAgICAgICB9ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgY29uc3QgW3N0YXJ0QXJyb3doZWFkLCBlbmRBcnJvd2hlYWRdID0gZWxlbWVudFR5cGUgPT09IFwiYXJyb3dcIiA/IFtjdXJyZW50SXRlbVN0YXJ0QXJyb3doZWFkLCBjdXJyZW50SXRlbUVuZEFycm93aGVhZF0gOiBbbnVsbCwgbnVsbF07XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBuZXdMaW5lYXJFbGVtZW50KHtcbiAgICAgICAgICB0eXBlOiBlbGVtZW50VHlwZSxcbiAgICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgICB5OiBncmlkWSxcbiAgICAgICAgICBzdHJva2VDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZUNvbG9yLFxuICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICBmaWxsU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1GaWxsU3R5bGUsXG4gICAgICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VXaWR0aCxcbiAgICAgICAgICBzdHJva2VTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZVN0eWxlLFxuICAgICAgICAgIHJvdWdobmVzczogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVJvdWdobmVzcyxcbiAgICAgICAgICBvcGFjaXR5OiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtT3BhY2l0eSxcbiAgICAgICAgICByb3VuZG5lc3M6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Sb3VuZG5lc3MgPT09IFwicm91bmRcIiA/IHtcbiAgICAgICAgICAgIHR5cGU6IFJPVU5ETkVTUy5QUk9QT1JUSU9OQUxfUkFESVVTXG4gICAgICAgICAgfSA6IG51bGwsXG4gICAgICAgICAgc3RhcnRBcnJvd2hlYWQsXG4gICAgICAgICAgZW5kQXJyb3doZWFkLFxuICAgICAgICAgIGxvY2tlZDogZmFsc2UsXG4gICAgICAgICAgZnJhbWVJZDogdG9wTGF5ZXJGcmFtZSA/IHRvcExheWVyRnJhbWUuaWQgOiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgY29uc3QgbmV4dFNlbGVjdGVkRWxlbWVudElkcyA9IE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpO1xuICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2VsZW1lbnQuaWRdO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKG5leHRTZWxlY3RlZEVsZW1lbnRJZHMsIHByZXZTdGF0ZSlcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgcG9pbnRzOiBbLi4uZWxlbWVudC5wb2ludHMsIFswLCAwXV1cbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGJvdW5kRWxlbWVudCA9IGdldEhvdmVyZWRFbGVtZW50Rm9yQmluZGluZyhwb2ludGVyRG93blN0YXRlLm9yaWdpbiwgdGhpcy5zY2VuZSk7XG4gICAgICAgIHRoaXMuc2NlbmUuYWRkTmV3RWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBlbGVtZW50LFxuICAgICAgICAgIGVkaXRpbmdFbGVtZW50OiBlbGVtZW50LFxuICAgICAgICAgIHN0YXJ0Qm91bmRFbGVtZW50OiBib3VuZEVsZW1lbnQsXG4gICAgICAgICAgc3VnZ2VzdGVkQmluZGluZ3M6IFtdXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmNyZWF0ZUdlbmVyaWNFbGVtZW50T25Qb2ludGVyRG93biA9IChlbGVtZW50VHlwZSwgcG9pbnRlckRvd25TdGF0ZSkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55LCAoKF9hID0gdGhpcy5sYXN0UG9pbnRlckRvd24pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYVtLRVlTLkNUUkxfT1JfQ01EXSkgPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICBjb25zdCB0b3BMYXllckZyYW1lID0gdGhpcy5nZXRUb3BMYXllckZyYW1lQXRTY2VuZUNvb3Jkcyh7XG4gICAgICAgIHg6IGdyaWRYLFxuICAgICAgICB5OiBncmlkWVxuICAgICAgfSk7XG4gICAgICBjb25zdCBiYXNlRWxlbWVudEF0dHJpYnV0ZXMgPSB7XG4gICAgICAgIHg6IGdyaWRYLFxuICAgICAgICB5OiBncmlkWSxcbiAgICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VDb2xvcixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtQmFja2dyb3VuZENvbG9yLFxuICAgICAgICBmaWxsU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1GaWxsU3R5bGUsXG4gICAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlV2lkdGgsXG4gICAgICAgIHN0cm9rZVN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlU3R5bGUsXG4gICAgICAgIHJvdWdobmVzczogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVJvdWdobmVzcyxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICAgIHJvdW5kbmVzczogdGhpcy5nZXRDdXJyZW50SXRlbVJvdW5kbmVzcyhlbGVtZW50VHlwZSksXG4gICAgICAgIGxvY2tlZDogZmFsc2UsXG4gICAgICAgIGZyYW1lSWQ6IHRvcExheWVyRnJhbWUgPyB0b3BMYXllckZyYW1lLmlkIDogbnVsbFxuICAgICAgfTtcbiAgICAgIGxldCBlbGVtZW50O1xuXG4gICAgICBpZiAoZWxlbWVudFR5cGUgPT09IFwiZW1iZWRkYWJsZVwiKSB7XG4gICAgICAgIGVsZW1lbnQgPSBuZXdFbWJlZGRhYmxlRWxlbWVudChPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICB0eXBlOiBcImVtYmVkZGFibGVcIixcbiAgICAgICAgICB2YWxpZGF0ZWQ6IG51bGxcbiAgICAgICAgfSwgYmFzZUVsZW1lbnRBdHRyaWJ1dGVzKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50ID0gbmV3RWxlbWVudChPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICB0eXBlOiBlbGVtZW50VHlwZVxuICAgICAgICB9LCBiYXNlRWxlbWVudEF0dHJpYnV0ZXMpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVsZW1lbnQudHlwZSA9PT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3Rpb25FbGVtZW50OiBlbGVtZW50LFxuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogZWxlbWVudFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2NlbmUuYWRkTmV3RWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgbXVsdGlFbGVtZW50OiBudWxsLFxuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogZWxlbWVudCxcbiAgICAgICAgICBlZGl0aW5nRWxlbWVudDogZWxlbWVudFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5jcmVhdGVGcmFtZUVsZW1lbnRPblBvaW50ZXJEb3duID0gcG9pbnRlckRvd25TdGF0ZSA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIGNvbnN0IFtncmlkWCwgZ3JpZFldID0gZ2V0R3JpZFBvaW50KHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnksICgoX2EgPSB0aGlzLmxhc3RQb2ludGVyRG93bikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hW0tFWVMuQ1RSTF9PUl9DTURdKSA/IG51bGwgOiB0aGlzLnN0YXRlLmdyaWRTaXplKTtcbiAgICAgIGNvbnN0IGZyYW1lID0gbmV3RnJhbWVFbGVtZW50KE9iamVjdC5hc3NpZ24oe1xuICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgeTogZ3JpZFksXG4gICAgICAgIG9wYWNpdHk6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1PcGFjaXR5LFxuICAgICAgICBsb2NrZWQ6IGZhbHNlXG4gICAgICB9LCBGUkFNRV9TVFlMRSkpO1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoWy4uLnRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIGZyYW1lXSk7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgbXVsdGlFbGVtZW50OiBudWxsLFxuICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IGZyYW1lLFxuICAgICAgICBlZGl0aW5nRWxlbWVudDogZnJhbWVcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLnJlc3RvcmVSZWFkeVRvRXJhc2VFbGVtZW50cyA9IHBvaW50ZXJEb3duU3RhdGUgPT4ge1xuICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLm1hcChlbGUgPT4ge1xuICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuaWRdICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmlkXS5lcmFzZSkge1xuICAgICAgICAgIHJldHVybiBuZXdFbGVtZW50V2l0aChlbGUsIHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmlkXS5vcGFjaXR5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNCb3VuZFRvQ29udGFpbmVyKGVsZSkgJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuY29udGFpbmVySWRdICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmNvbnRhaW5lcklkXS5lcmFzZSkge1xuICAgICAgICAgIHJldHVybiBuZXdFbGVtZW50V2l0aChlbGUsIHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmNvbnRhaW5lcklkXS5vcGFjaXR5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZWxlLmZyYW1lSWQgJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuZnJhbWVJZF0gJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuZnJhbWVJZF0uZXJhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICBvcGFjaXR5OiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5mcmFtZUlkXS5vcGFjaXR5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZWxlO1xuICAgICAgfSk7XG4gICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhlbGVtZW50cyk7XG4gICAgfTtcblxuICAgIHRoaXMuZXJhc2VFbGVtZW50cyA9IHBvaW50ZXJEb3duU3RhdGUgPT4ge1xuICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLm1hcChlbGUgPT4ge1xuICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuaWRdICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmlkXS5lcmFzZSkge1xuICAgICAgICAgIHJldHVybiBuZXdFbGVtZW50V2l0aChlbGUsIHtcbiAgICAgICAgICAgIGlzRGVsZXRlZDogdHJ1ZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQm91bmRUb0NvbnRhaW5lcihlbGUpICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmNvbnRhaW5lcklkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5jb250YWluZXJJZF0uZXJhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICBpc0RlbGV0ZWQ6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChlbGUuZnJhbWVJZCAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5mcmFtZUlkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5mcmFtZUlkXS5lcmFzZSkge1xuICAgICAgICAgIHJldHVybiBuZXdFbGVtZW50V2l0aChlbGUsIHtcbiAgICAgICAgICAgIGlzRGVsZXRlZDogdHJ1ZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoZWxlbWVudHMpO1xuICAgIH07XG5cbiAgICB0aGlzLmluaXRpYWxpemVJbWFnZSA9ICh7XG4gICAgICBpbWFnZUZpbGUsXG4gICAgICBpbWFnZUVsZW1lbnQ6IF9pbWFnZUVsZW1lbnQsXG4gICAgICBzaG93Q3Vyc29ySW1hZ2VQcmV2aWV3ID0gZmFsc2VcbiAgICB9KSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICB2YXIgX2YsIF9nLCBfaCwgX2o7IC8vIGF0IHRoaXMgcG9pbnQgdGhpcyBzaG91bGQgYmUgZ3VhcmFudGVlZCBpbWFnZSBmaWxlLCBidXQgd2UgZG8gdGhpcyBjaGVja1xuICAgICAgLy8gdG8gc2F0aXNmeSBUUyBkb3duIHRoZSBsaW5lXG5cblxuICAgICAgaWYgKCFpc1N1cHBvcnRlZEltYWdlRmlsZShpbWFnZUZpbGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih0KFwiZXJyb3JzLnVuc3VwcG9ydGVkRmlsZVR5cGVcIikpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtaW1lVHlwZSA9IGltYWdlRmlsZS50eXBlO1xuICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIFwid2FpdFwiKTtcblxuICAgICAgaWYgKG1pbWVUeXBlID09PSBNSU1FX1RZUEVTLnN2Zykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGltYWdlRmlsZSA9IFNWR1N0cmluZ1RvRmlsZSh5aWVsZCBub3JtYWxpemVTVkcoeWllbGQgaW1hZ2VGaWxlLnRleHQoKSksIGltYWdlRmlsZS5uYW1lKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oZXJyb3IpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0KFwiZXJyb3JzLnN2Z0ltYWdlSW5zZXJ0RXJyb3JcIikpO1xuICAgICAgICB9XG4gICAgICB9IC8vIGdlbmVyYXRlIGltYWdlIGlkIChieSBkZWZhdWx0IHRoZSBmaWxlIGRpZ2VzdCkgYmVmb3JlIGFueVxuICAgICAgLy8gcmVzaXppbmcvY29tcHJlc3Npb24gdGFrZXMgcGxhY2UgdG8ga2VlcCBpdCBtb3JlIHBvcnRhYmxlXG5cblxuICAgICAgY29uc3QgZmlsZUlkID0geWllbGQgKChfZyA9IChfZiA9IHRoaXMucHJvcHMpLmdlbmVyYXRlSWRGb3JGaWxlKSA9PT0gbnVsbCB8fCBfZyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2cuY2FsbChfZiwgaW1hZ2VGaWxlKSkgfHwgZ2VuZXJhdGVJZEZyb21GaWxlKGltYWdlRmlsZSk7XG5cbiAgICAgIGlmICghZmlsZUlkKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcIkNvdWxkbid0IGdlbmVyYXRlIGZpbGUgaWQgb3IgdGhlIHN1cHBsaWVkIGBnZW5lcmF0ZUlkRm9yRmlsZWAgZGlkbid0IHJlc29sdmUgdG8gb25lLlwiKTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHQoXCJlcnJvcnMuaW1hZ2VJbnNlcnRFcnJvclwiKSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV4aXN0aW5nRmlsZURhdGEgPSB0aGlzLmZpbGVzW2ZpbGVJZF07XG5cbiAgICAgIGlmICghKGV4aXN0aW5nRmlsZURhdGEgPT09IG51bGwgfHwgZXhpc3RpbmdGaWxlRGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogZXhpc3RpbmdGaWxlRGF0YS5kYXRhVVJMKSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGltYWdlRmlsZSA9IHlpZWxkIHJlc2l6ZUltYWdlRmlsZShpbWFnZUZpbGUsIHtcbiAgICAgICAgICAgIG1heFdpZHRoT3JIZWlnaHQ6IERFRkFVTFRfTUFYX0lNQUdFX1dJRFRIX09SX0hFSUdIVFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJlcnJvciB0cnlpbmcgdG8gcmVzaW5nIGltYWdlIGZpbGUgb24gaW5zZXJ0aW9uXCIsIGVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbWFnZUZpbGUuc2l6ZSA+IE1BWF9BTExPV0VEX0ZJTEVfQllURVMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodChcImVycm9ycy5maWxlVG9vQmlnXCIsIHtcbiAgICAgICAgICAgIG1heFNpemU6IGAke01hdGgudHJ1bmMoTUFYX0FMTE9XRURfRklMRV9CWVRFUyAvIDEwMjQgLyAxMDI0KX1NQmBcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHNob3dDdXJzb3JJbWFnZVByZXZpZXcpIHtcbiAgICAgICAgY29uc3QgZGF0YVVSTCA9IChfaCA9IHRoaXMuZmlsZXNbZmlsZUlkXSkgPT09IG51bGwgfHwgX2ggPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9oLmRhdGFVUkw7IC8vIG9wdGltaXphdGlvbiBzbyB0aGF0IHdlIGRvbid0IHVubmVjZXNzYXJpbHkgcmVzaXplIHRoZSBvcmlnaW5hbFxuICAgICAgICAvLyBmdWxsLXNpemUgZmlsZSBmb3IgY3Vyc29yIHByZXZpZXdcbiAgICAgICAgLy8gKGl0J3MgbXVjaCBmYXN0ZXIgdG8gY29udmVydCB0aGUgcmVzaXplZCBkYXRhVVJMIHRvIEZpbGUpXG5cbiAgICAgICAgY29uc3QgcmVzaXplZEZpbGUgPSBkYXRhVVJMICYmIGRhdGFVUkxUb0ZpbGUoZGF0YVVSTCk7XG4gICAgICAgIHRoaXMuc2V0SW1hZ2VQcmV2aWV3Q3Vyc29yKHJlc2l6ZWRGaWxlIHx8IGltYWdlRmlsZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRhdGFVUkwgPSAoKF9qID0gdGhpcy5maWxlc1tmaWxlSWRdKSA9PT0gbnVsbCB8fCBfaiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2ouZGF0YVVSTCkgfHwgKHlpZWxkIGdldERhdGFVUkwoaW1hZ2VGaWxlKSk7XG4gICAgICBjb25zdCBpbWFnZUVsZW1lbnQgPSBtdXRhdGVFbGVtZW50KF9pbWFnZUVsZW1lbnQsIHtcbiAgICAgICAgZmlsZUlkXG4gICAgICB9LCBmYWxzZSk7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICB2YXIgX2s7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGlzLmZpbGVzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLmZpbGVzKSwge1xuICAgICAgICAgICAgW2ZpbGVJZF06IHtcbiAgICAgICAgICAgICAgbWltZVR5cGUsXG4gICAgICAgICAgICAgIGlkOiBmaWxlSWQsXG4gICAgICAgICAgICAgIGRhdGFVUkwsXG4gICAgICAgICAgICAgIGNyZWF0ZWQ6IERhdGUubm93KCksXG4gICAgICAgICAgICAgIGxhc3RSZXRyaWV2ZWQ6IERhdGUubm93KClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zdCBjYWNoZWRJbWFnZURhdGEgPSB0aGlzLmltYWdlQ2FjaGUuZ2V0KGZpbGVJZCk7XG5cbiAgICAgICAgICBpZiAoIWNhY2hlZEltYWdlRGF0YSkge1xuICAgICAgICAgICAgdGhpcy5hZGROZXdJbWFnZXNUb0ltYWdlQ2FjaGUoKTtcbiAgICAgICAgICAgIHlpZWxkIHRoaXMudXBkYXRlSW1hZ2VDYWNoZShbaW1hZ2VFbGVtZW50XSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKChjYWNoZWRJbWFnZURhdGEgPT09IG51bGwgfHwgY2FjaGVkSW1hZ2VEYXRhID09PSB2b2lkIDAgPyB2b2lkIDAgOiBjYWNoZWRJbWFnZURhdGEuaW1hZ2UpIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgICAgICAgeWllbGQgY2FjaGVkSW1hZ2VEYXRhLmltYWdlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnBlbmRpbmdJbWFnZUVsZW1lbnRJZCAhPT0gaW1hZ2VFbGVtZW50LmlkICYmICgoX2sgPSB0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudCkgPT09IG51bGwgfHwgX2sgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9rLmlkKSAhPT0gaW1hZ2VFbGVtZW50LmlkKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVJbWFnZURpbWVuc2lvbnMoaW1hZ2VFbGVtZW50LCB0cnVlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXNvbHZlKGltYWdlRWxlbWVudCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0KFwiZXJyb3JzLmltYWdlSW5zZXJ0RXJyb3JcIikpKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBpZiAoIXNob3dDdXJzb3JJbWFnZVByZXZpZXcpIHtcbiAgICAgICAgICAgIHJlc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuICAgIH0pO1xuICAgIC8qKlxuICAgICAqIGluc2VydHMgaW1hZ2UgaW50byBlbGVtZW50cyBhcnJheSBhbmQgcmVyZW5kZXJzXG4gICAgICovXG5cblxuICAgIHRoaXMuaW5zZXJ0SW1hZ2VFbGVtZW50ID0gKGltYWdlRWxlbWVudCwgaW1hZ2VGaWxlLCBzaG93Q3Vyc29ySW1hZ2VQcmV2aWV3KSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICB0aGlzLnNjZW5lLmFkZE5ld0VsZW1lbnQoaW1hZ2VFbGVtZW50KTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgeWllbGQgdGhpcy5pbml0aWFsaXplSW1hZ2Uoe1xuICAgICAgICAgIGltYWdlRmlsZSxcbiAgICAgICAgICBpbWFnZUVsZW1lbnQsXG4gICAgICAgICAgc2hvd0N1cnNvckltYWdlUHJldmlld1xuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIG11dGF0ZUVsZW1lbnQoaW1hZ2VFbGVtZW50LCB7XG4gICAgICAgICAgaXNEZWxldGVkOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyb3IubWVzc2FnZSB8fCB0KFwiZXJyb3JzLmltYWdlSW5zZXJ0RXJyb3JcIilcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLnNldEltYWdlUHJldmlld0N1cnNvciA9IGltYWdlRmlsZSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICAvLyBtdXN0bid0IGJlIGxhcmdlciB0aGFuIDEyOCBweFxuICAgICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0NTU19CYXNpY19Vc2VyX0ludGVyZmFjZS9Vc2luZ19VUkxfdmFsdWVzX2Zvcl90aGVfY3Vyc29yX3Byb3BlcnR5XG4gICAgICBjb25zdCBjdXJzb3JJbWFnZVNpemVQeCA9IDk2O1xuICAgICAgY29uc3QgaW1hZ2VQcmV2aWV3ID0geWllbGQgcmVzaXplSW1hZ2VGaWxlKGltYWdlRmlsZSwge1xuICAgICAgICBtYXhXaWR0aE9ySGVpZ2h0OiBjdXJzb3JJbWFnZVNpemVQeFxuICAgICAgfSk7XG4gICAgICBsZXQgcHJldmlld0RhdGFVUkwgPSB5aWVsZCBnZXREYXRhVVJMKGltYWdlUHJldmlldyk7IC8vIFNWRyBjYW5ub3QgYmUgcmVzaXplZCB2aWEgYHJlc2l6ZUltYWdlRmlsZWAgc28gd2UgcmVzaXplIGJ5IHJlbmRlcmluZyB0b1xuICAgICAgLy8gYSBzbWFsbCBjYW52YXNcblxuICAgICAgaWYgKGltYWdlRmlsZS50eXBlID09PSBNSU1FX1RZUEVTLnN2Zykge1xuICAgICAgICBjb25zdCBpbWcgPSB5aWVsZCBsb2FkSFRNTEltYWdlRWxlbWVudChwcmV2aWV3RGF0YVVSTCk7XG4gICAgICAgIGxldCBoZWlnaHQgPSBNYXRoLm1pbihpbWcuaGVpZ2h0LCBjdXJzb3JJbWFnZVNpemVQeCk7XG4gICAgICAgIGxldCB3aWR0aCA9IGhlaWdodCAqIChpbWcud2lkdGggLyBpbWcuaGVpZ2h0KTtcblxuICAgICAgICBpZiAod2lkdGggPiBjdXJzb3JJbWFnZVNpemVQeCkge1xuICAgICAgICAgIHdpZHRoID0gY3Vyc29ySW1hZ2VTaXplUHg7XG4gICAgICAgICAgaGVpZ2h0ID0gd2lkdGggKiAoaW1nLmhlaWdodCAvIGltZy53aWR0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY29uc3QgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGltZywgMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIHByZXZpZXdEYXRhVVJMID0gY2FudmFzLnRvRGF0YVVSTChNSU1FX1RZUEVTLnN2Zyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLnBlbmRpbmdJbWFnZUVsZW1lbnRJZCkge1xuICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgYHVybCgke3ByZXZpZXdEYXRhVVJMfSkgNCA0LCBhdXRvYCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLm9uSW1hZ2VBY3Rpb24gPSAoe1xuICAgICAgaW5zZXJ0T25DYW52YXNEaXJlY3RseVxuICAgIH0gPSB7XG4gICAgICBpbnNlcnRPbkNhbnZhc0RpcmVjdGx5OiBmYWxzZVxuICAgIH0pID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGNsaWVudFggPSB0aGlzLnN0YXRlLndpZHRoIC8gMiArIHRoaXMuc3RhdGUub2Zmc2V0TGVmdDtcbiAgICAgICAgY29uc3QgY2xpZW50WSA9IHRoaXMuc3RhdGUuaGVpZ2h0IC8gMiArIHRoaXMuc3RhdGUub2Zmc2V0VG9wO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5XG4gICAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICAgIGNsaWVudFgsXG4gICAgICAgICAgY2xpZW50WVxuICAgICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgY29uc3QgaW1hZ2VGaWxlID0geWllbGQgZmlsZU9wZW4oe1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBcIkltYWdlXCIsXG4gICAgICAgICAgZXh0ZW5zaW9uczogT2JqZWN0LmtleXMoSU1BR0VfTUlNRV9UWVBFUylcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGltYWdlRWxlbWVudCA9IHRoaXMuY3JlYXRlSW1hZ2VFbGVtZW50KHtcbiAgICAgICAgICBzY2VuZVg6IHgsXG4gICAgICAgICAgc2NlbmVZOiB5XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChpbnNlcnRPbkNhbnZhc0RpcmVjdGx5KSB7XG4gICAgICAgICAgdGhpcy5pbnNlcnRJbWFnZUVsZW1lbnQoaW1hZ2VFbGVtZW50LCBpbWFnZUZpbGUpO1xuICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUltYWdlRGltZW5zaW9ucyhpbWFnZUVsZW1lbnQpO1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7XG4gICAgICAgICAgICAgIFtpbWFnZUVsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRlKVxuICAgICAgICAgIH0sICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHBlbmRpbmdJbWFnZUVsZW1lbnRJZDogaW1hZ2VFbGVtZW50LmlkXG4gICAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRJbWFnZUVsZW1lbnQoaW1hZ2VFbGVtZW50LCBpbWFnZUZpbGUsXG4gICAgICAgICAgICAvKiBzaG93Q3Vyc29ySW1hZ2VQcmV2aWV3ICovXG4gICAgICAgICAgICB0cnVlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGVycm9yLm5hbWUgIT09IFwiQWJvcnRFcnJvclwiKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKGVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHBlbmRpbmdJbWFnZUVsZW1lbnRJZDogbnVsbCxcbiAgICAgICAgICBlZGl0aW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgICBhY3RpdmVUb29sOiB1cGRhdGVBY3RpdmVUb29sKHRoaXMuc3RhdGUsIHtcbiAgICAgICAgICAgIHR5cGU6IFwic2VsZWN0aW9uXCJcbiAgICAgICAgICB9KVxuICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5hY3Rpb25NYW5hZ2VyLmV4ZWN1dGVBY3Rpb24oYWN0aW9uRmluYWxpemUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuaW5pdGlhbGl6ZUltYWdlRGltZW5zaW9ucyA9IChpbWFnZUVsZW1lbnQsIGZvcmNlTmF0dXJhbFNpemUgPSBmYWxzZSkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBpbWFnZSA9IGlzSW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnQoaW1hZ2VFbGVtZW50KSAmJiAoKF9hID0gdGhpcy5pbWFnZUNhY2hlLmdldChpbWFnZUVsZW1lbnQuZmlsZUlkKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmltYWdlKTtcblxuICAgICAgaWYgKCFpbWFnZSB8fCBpbWFnZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgaWYgKGltYWdlRWxlbWVudC53aWR0aCA8IERSQUdHSU5HX1RIUkVTSE9MRCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZSAmJiBpbWFnZUVsZW1lbnQuaGVpZ2h0IDwgRFJBR0dJTkdfVEhSRVNIT0xEIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlKSB7XG4gICAgICAgICAgY29uc3QgcGxhY2Vob2xkZXJTaXplID0gMTAwIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuICAgICAgICAgIG11dGF0ZUVsZW1lbnQoaW1hZ2VFbGVtZW50LCB7XG4gICAgICAgICAgICB4OiBpbWFnZUVsZW1lbnQueCAtIHBsYWNlaG9sZGVyU2l6ZSAvIDIsXG4gICAgICAgICAgICB5OiBpbWFnZUVsZW1lbnQueSAtIHBsYWNlaG9sZGVyU2l6ZSAvIDIsXG4gICAgICAgICAgICB3aWR0aDogcGxhY2Vob2xkZXJTaXplLFxuICAgICAgICAgICAgaGVpZ2h0OiBwbGFjZWhvbGRlclNpemVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGZvcmNlTmF0dXJhbFNpemUgfHwgLy8gaWYgdXNlci1jcmVhdGVkIGJvdW5kaW5nIGJveCBpcyBiZWxvdyB0aHJlc2hvbGQsIGFzc3VtZSB0aGVcbiAgICAgIC8vIGludGVudGlvbiB3YXMgdG8gY2xpY2sgaW5zdGVhZCBvZiBkcmFnLCBhbmQgdXNlIHRoZSBpbWFnZSdzXG4gICAgICAvLyBpbnRyaW5zaWMgc2l6ZVxuICAgICAgaW1hZ2VFbGVtZW50LndpZHRoIDwgRFJBR0dJTkdfVEhSRVNIT0xEIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlICYmIGltYWdlRWxlbWVudC5oZWlnaHQgPCBEUkFHR0lOR19USFJFU0hPTEQgLyB0aGlzLnN0YXRlLnpvb20udmFsdWUpIHtcbiAgICAgICAgY29uc3QgbWluSGVpZ2h0ID0gTWF0aC5tYXgodGhpcy5zdGF0ZS5oZWlnaHQgLSAxMjAsIDE2MCk7IC8vIG1heCA2NSUgb2YgY2FudmFzIGhlaWdodCwgY2xhbXBlZCB0byA8MzAwcHgsIHZoIC0gMTIwcHg+XG5cbiAgICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gTWF0aC5taW4obWluSGVpZ2h0LCBNYXRoLmZsb29yKHRoaXMuc3RhdGUuaGVpZ2h0ICogMC41KSAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZSk7XG4gICAgICAgIGNvbnN0IGhlaWdodCA9IE1hdGgubWluKGltYWdlLm5hdHVyYWxIZWlnaHQsIG1heEhlaWdodCk7XG4gICAgICAgIGNvbnN0IHdpZHRoID0gaGVpZ2h0ICogKGltYWdlLm5hdHVyYWxXaWR0aCAvIGltYWdlLm5hdHVyYWxIZWlnaHQpOyAvLyBhZGQgY3VycmVudCBpbWFnZUVsZW1lbnQgd2lkdGgvaGVpZ2h0IHRvIGFjY291bnQgZm9yIHByZXZpb3VzIGNlbnRlcmluZ1xuICAgICAgICAvLyBvZiB0aGUgcGxhY2Vob2xkZXIgaW1hZ2VcblxuICAgICAgICBjb25zdCB4ID0gaW1hZ2VFbGVtZW50LnggKyBpbWFnZUVsZW1lbnQud2lkdGggLyAyIC0gd2lkdGggLyAyO1xuICAgICAgICBjb25zdCB5ID0gaW1hZ2VFbGVtZW50LnkgKyBpbWFnZUVsZW1lbnQuaGVpZ2h0IC8gMiAtIGhlaWdodCAvIDI7XG4gICAgICAgIG11dGF0ZUVsZW1lbnQoaW1hZ2VFbGVtZW50LCB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5LFxuICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgIGhlaWdodFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIC8qKiB1cGRhdGVzIGltYWdlIGNhY2hlLCByZWZyZXNoaW5nIHVwZGF0ZWQgZWxlbWVudHMgYW5kL29yIHNldHRpbmcgc3RhdHVzXG4gICAgICAgIHRvIGVycm9yIGZvciBpbWFnZXMgdGhhdCBmYWlsIGR1cmluZyA8aW1nPiBlbGVtZW50IGNyZWF0aW9uICovXG5cblxuICAgIHRoaXMudXBkYXRlSW1hZ2VDYWNoZSA9IChlbGVtZW50cywgZmlsZXMgPSB0aGlzLmZpbGVzKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHVwZGF0ZWRGaWxlcyxcbiAgICAgICAgZXJyb3JlZEZpbGVzXG4gICAgICB9ID0geWllbGQgX3VwZGF0ZUltYWdlQ2FjaGUoe1xuICAgICAgICBpbWFnZUNhY2hlOiB0aGlzLmltYWdlQ2FjaGUsXG4gICAgICAgIGZpbGVJZHM6IGVsZW1lbnRzLm1hcChlbGVtZW50ID0+IGVsZW1lbnQuZmlsZUlkKSxcbiAgICAgICAgZmlsZXNcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodXBkYXRlZEZpbGVzLnNpemUgfHwgZXJyb3JlZEZpbGVzLnNpemUpIHtcbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7XG4gICAgICAgICAgaWYgKHVwZGF0ZWRGaWxlcy5oYXMoZWxlbWVudC5maWxlSWQpKSB7XG4gICAgICAgICAgICBTaGFwZUNhY2hlLmRlbGV0ZShlbGVtZW50KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGVycm9yZWRGaWxlcy5zaXplKSB7XG4gICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkubWFwKGVsZW1lbnQgPT4ge1xuICAgICAgICAgIGlmIChpc0luaXRpYWxpemVkSW1hZ2VFbGVtZW50KGVsZW1lbnQpICYmIGVycm9yZWRGaWxlcy5oYXMoZWxlbWVudC5maWxlSWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlbWVudCwge1xuICAgICAgICAgICAgICBzdGF0dXM6IFwiZXJyb3JcIlxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgICAgIH0pKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdXBkYXRlZEZpbGVzLFxuICAgICAgICBlcnJvcmVkRmlsZXNcbiAgICAgIH07XG4gICAgfSk7XG4gICAgLyoqIGFkZHMgbmV3IGltYWdlcyB0byBpbWFnZUNhY2hlIGFuZCByZS1yZW5kZXJzIGlmIG5lZWRlZCAqL1xuXG5cbiAgICB0aGlzLmFkZE5ld0ltYWdlc1RvSW1hZ2VDYWNoZSA9IChpbWFnZUVsZW1lbnRzID0gZ2V0SW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkpLCBmaWxlcyA9IHRoaXMuZmlsZXMpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIGNvbnN0IHVuY2FjaGVkSW1hZ2VFbGVtZW50cyA9IGltYWdlRWxlbWVudHMuZmlsdGVyKGVsZW1lbnQgPT4gIWVsZW1lbnQuaXNEZWxldGVkICYmICF0aGlzLmltYWdlQ2FjaGUuaGFzKGVsZW1lbnQuZmlsZUlkKSk7XG5cbiAgICAgIGlmICh1bmNhY2hlZEltYWdlRWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB1cGRhdGVkRmlsZXNcbiAgICAgICAgfSA9IHlpZWxkIHRoaXMudXBkYXRlSW1hZ2VDYWNoZSh1bmNhY2hlZEltYWdlRWxlbWVudHMsIGZpbGVzKTtcblxuICAgICAgICBpZiAodXBkYXRlZEZpbGVzLnNpemUpIHtcbiAgICAgICAgICB0aGlzLnNjZW5lLmluZm9ybU11dGF0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICAvKiogZ2VuZXJhbGx5IHlvdSBzaG91bGQgdXNlIGBhZGROZXdJbWFnZXNUb0ltYWdlQ2FjaGUoKWAgZGlyZWN0bHkgaWYgeW91IG5lZWRcbiAgICAgKiAgdG8gcmVuZGVyIG5ldyBpbWFnZXMuIFRoaXMgaXMganVzdCBhIGZhaWxzYWZlICAqL1xuXG5cbiAgICB0aGlzLnNjaGVkdWxlSW1hZ2VSZWZyZXNoID0gdGhyb3R0bGUoKCkgPT4ge1xuICAgICAgdGhpcy5hZGROZXdJbWFnZXNUb0ltYWdlQ2FjaGUoKTtcbiAgICB9LCBJTUFHRV9SRU5ERVJfVElNRU9VVCk7XG5cbiAgICB0aGlzLnVwZGF0ZUJpbmRpbmdFbmFibGVkT25Qb2ludGVyTW92ZSA9IGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IHNob3VsZEVuYWJsZUJpbmRpbmcgPSBzaG91bGRFbmFibGVCaW5kaW5nRm9yUG9pbnRlckV2ZW50KGV2ZW50KTtcblxuICAgICAgaWYgKHRoaXMuc3RhdGUuaXNCaW5kaW5nRW5hYmxlZCAhPT0gc2hvdWxkRW5hYmxlQmluZGluZykge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc0JpbmRpbmdFbmFibGVkOiBzaG91bGRFbmFibGVCaW5kaW5nXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdBdEN1cnNvciA9IHBvaW50ZXJDb29yZHMgPT4ge1xuICAgICAgY29uc3QgaG92ZXJlZEJpbmRhYmxlRWxlbWVudCA9IGdldEhvdmVyZWRFbGVtZW50Rm9yQmluZGluZyhwb2ludGVyQ29vcmRzLCB0aGlzLnNjZW5lKTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogaG92ZXJlZEJpbmRhYmxlRWxlbWVudCAhPSBudWxsID8gW2hvdmVyZWRCaW5kYWJsZUVsZW1lbnRdIDogW11cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdzRm9yTGluZWFyRWxlbWVudEF0Q29vcmRzID0gKGxpbmVhckVsZW1lbnQsXG4gICAgLyoqIHNjZW5lIGNvb3JkcyAqL1xuICAgIHBvaW50ZXJDb29yZHMsIC8vIER1cmluZyBsaW5lIGNyZWF0aW9uIHRoZSBzdGFydCBiaW5kaW5nIGhhc24ndCBiZWVuIHdyaXR0ZW4geWV0XG4gICAgLy8gaW50byBgbGluZWFyRWxlbWVudGBcbiAgICBvcHBvc2l0ZUJpbmRpbmdCb3VuZEVsZW1lbnQpID0+IHtcbiAgICAgIGlmICghcG9pbnRlckNvb3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdWdnZXN0ZWRCaW5kaW5ncyA9IHBvaW50ZXJDb29yZHMucmVkdWNlKChhY2MsIGNvb3JkcykgPT4ge1xuICAgICAgICBjb25zdCBob3ZlcmVkQmluZGFibGVFbGVtZW50ID0gZ2V0SG92ZXJlZEVsZW1lbnRGb3JCaW5kaW5nKGNvb3JkcywgdGhpcy5zY2VuZSk7XG5cbiAgICAgICAgaWYgKGhvdmVyZWRCaW5kYWJsZUVsZW1lbnQgIT0gbnVsbCAmJiAhaXNMaW5lYXJFbGVtZW50U2ltcGxlQW5kQWxyZWFkeUJvdW5kKGxpbmVhckVsZW1lbnQsIG9wcG9zaXRlQmluZGluZ0JvdW5kRWxlbWVudCA9PT0gbnVsbCB8fCBvcHBvc2l0ZUJpbmRpbmdCb3VuZEVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wcG9zaXRlQmluZGluZ0JvdW5kRWxlbWVudC5pZCwgaG92ZXJlZEJpbmRhYmxlRWxlbWVudCkpIHtcbiAgICAgICAgICBhY2MucHVzaChob3ZlcmVkQmluZGFibGVFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9LCBbXSk7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc3VnZ2VzdGVkQmluZGluZ3NcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZUludGVyYWN0aXZlQ2FudmFzUmVmID0gY2FudmFzID0+IHtcbiAgICAgIHZhciBfYSwgX2IsIF9jOyAvLyBjYW52YXMgaXMgbnVsbCB3aGVuIHVubW91bnRpbmdcblxuXG4gICAgICBpZiAoY2FudmFzICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuaW50ZXJhY3RpdmVDYW52YXMgPSBjYW52YXM7IC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIC8vIE5PVEUgd2hlZWwsIHRvdWNoc3RhcnQsIHRvdWNoZW5kIGV2ZW50cyBtdXN0IGJlIHJlZ2lzdGVyZWQgb3V0c2lkZVxuICAgICAgICAvLyBvZiByZWFjdCBiZWNhdXNlIHJlYWN0IGJpbmRzIHRoZW0gdGhlbSBwYXNzaXZlbHkgKHNvIHdlIGNhbid0IHByZXZlbnRcbiAgICAgICAgLy8gZGVmYXVsdCBvbiB0aGVtKVxuXG4gICAgICAgIHRoaXMuaW50ZXJhY3RpdmVDYW52YXMuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5XSEVFTCwgdGhpcy5oYW5kbGVXaGVlbCk7XG4gICAgICAgIHRoaXMuaW50ZXJhY3RpdmVDYW52YXMuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5UT1VDSF9TVEFSVCwgdGhpcy5vblRvdWNoU3RhcnQpO1xuICAgICAgICB0aGlzLmludGVyYWN0aXZlQ2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuVE9VQ0hfRU5ELCB0aGlzLm9uVG91Y2hFbmQpOyAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgKF9hID0gdGhpcy5pbnRlcmFjdGl2ZUNhbnZhcykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuV0hFRUwsIHRoaXMuaGFuZGxlV2hlZWwpO1xuICAgICAgICAoX2IgPSB0aGlzLmludGVyYWN0aXZlQ2FudmFzKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5UT1VDSF9TVEFSVCwgdGhpcy5vblRvdWNoU3RhcnQpO1xuICAgICAgICAoX2MgPSB0aGlzLmludGVyYWN0aXZlQ2FudmFzKSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5UT1VDSF9FTkQsIHRoaXMub25Ub3VjaEVuZCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuaGFuZGxlQXBwT25Ecm9wID0gZXZlbnQgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgdmFyIF9sLCBfbSwgX28sIF9wOyAvLyBtdXN0IGJlIHJldHJpZXZlZCBmaXJzdCwgaW4gdGhlIHNhbWUgZnJhbWVcblxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIGZpbGUsXG4gICAgICAgIGZpbGVIYW5kbGVcbiAgICAgIH0gPSB5aWVsZCBnZXRGaWxlRnJvbUV2ZW50KGV2ZW50KTtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgeDogc2NlbmVYLFxuICAgICAgICB5OiBzY2VuZVlcbiAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoZXZlbnQsIHRoaXMuc3RhdGUpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBpZiAoaXNTdXBwb3J0ZWRJbWFnZUZpbGUoZmlsZSkpIHtcbiAgICAgICAgICAvLyBmaXJzdCBhdHRlbXB0IHRvIGRlY29kZSBzY2VuZSBmcm9tIHRoZSBpbWFnZSBpZiBpdCdzIGVtYmVkZGVkXG4gICAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgICAgaWYgKChmaWxlID09PSBudWxsIHx8IGZpbGUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGZpbGUudHlwZSkgPT09IE1JTUVfVFlQRVMucG5nIHx8IChmaWxlID09PSBudWxsIHx8IGZpbGUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGZpbGUudHlwZSkgPT09IE1JTUVfVFlQRVMuc3ZnKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBzY2VuZSA9IHlpZWxkIGxvYWRGcm9tQmxvYihmaWxlLCB0aGlzLnN0YXRlLCB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCBmaWxlSGFuZGxlKTtcbiAgICAgICAgICAgICAgdGhpcy5zeW5jQWN0aW9uUmVzdWx0KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2NlbmUpLCB7XG4gICAgICAgICAgICAgICAgYXBwU3RhdGU6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2NlbmUuYXBwU3RhdGUgfHwgdGhpcy5zdGF0ZSksIHtcbiAgICAgICAgICAgICAgICAgIGlzTG9hZGluZzogZmFsc2VcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICByZXBsYWNlRmlsZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgY29tbWl0VG9IaXN0b3J5OiB0cnVlXG4gICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgaWYgKGVycm9yLm5hbWUgIT09IFwiRW5jb2RpbmdFcnJvclwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IC8vIGlmIG5vIHNjZW5lIGlzIGVtYmVkZGVkIG9yIHdlIGZhaWwgZm9yIHdoYXRldmVyIHJlYXNvbiwgZmFsbCBiYWNrXG4gICAgICAgICAgLy8gdG8gaW1wb3J0aW5nIGFzIHJlZ3VsYXIgaW1hZ2VcbiAgICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG4gICAgICAgICAgY29uc3QgaW1hZ2VFbGVtZW50ID0gdGhpcy5jcmVhdGVJbWFnZUVsZW1lbnQoe1xuICAgICAgICAgICAgc2NlbmVYLFxuICAgICAgICAgICAgc2NlbmVZXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy5pbnNlcnRJbWFnZUVsZW1lbnQoaW1hZ2VFbGVtZW50LCBmaWxlKTtcbiAgICAgICAgICB0aGlzLmluaXRpYWxpemVJbWFnZURpbWVuc2lvbnMoaW1hZ2VFbGVtZW50KTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe1xuICAgICAgICAgICAgICBbaW1hZ2VFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgfSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyb3IubWVzc2FnZVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbGlicmFyeUpTT04gPSBldmVudC5kYXRhVHJhbnNmZXIuZ2V0RGF0YShNSU1FX1RZUEVTLmV4Y2FsaWRyYXdsaWIpO1xuXG4gICAgICBpZiAobGlicmFyeUpTT04gJiYgdHlwZW9mIGxpYnJhcnlKU09OID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgbGlicmFyeUl0ZW1zID0gcGFyc2VMaWJyYXJ5SlNPTihsaWJyYXJ5SlNPTik7XG4gICAgICAgICAgdGhpcy5hZGRFbGVtZW50c0Zyb21QYXN0ZU9yTGlicmFyeSh7XG4gICAgICAgICAgICBlbGVtZW50czogZGlzdHJpYnV0ZUxpYnJhcnlJdGVtc09uU3F1YXJlR3JpZChsaWJyYXJ5SXRlbXMpLFxuICAgICAgICAgICAgcG9zaXRpb246IGV2ZW50LFxuICAgICAgICAgICAgZmlsZXM6IG51bGxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyb3IubWVzc2FnZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmlsZSkge1xuICAgICAgICAvLyBhdGV0bXB0IHRvIHBhcnNlIGFuIGV4Y2FsaWRyYXcvZXhjYWxpZHJhd2xpYiBmaWxlXG4gICAgICAgIHlpZWxkIHRoaXMubG9hZEZpbGVUb0NhbnZhcyhmaWxlLCBmaWxlSGFuZGxlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKChfbSA9IChfbCA9IGV2ZW50LmRhdGFUcmFuc2ZlcikgPT09IG51bGwgfHwgX2wgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9sLnR5cGVzKSA9PT0gbnVsbCB8fCBfbSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX20uaW5jbHVkZXMoXCJ0ZXh0L3BsYWluXCIpKSB7XG4gICAgICAgIGNvbnN0IHRleHQgPSAoX28gPSBldmVudC5kYXRhVHJhbnNmZXIpID09PSBudWxsIHx8IF9vID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfby5nZXREYXRhKFwidGV4dFwiKTtcblxuICAgICAgICBpZiAodGV4dCAmJiBlbWJlZGRhYmxlVVJMVmFsaWRhdG9yKHRleHQsIHRoaXMucHJvcHMudmFsaWRhdGVFbWJlZGRhYmxlKSAmJiAoL14oaHR0cHxodHRwcyk6XFwvXFwvW15cXHMvJC4/I10uW15cXHNdKiQvLnRlc3QodGV4dCkgfHwgKChfcCA9IGdldEVtYmVkTGluayh0ZXh0KSkgPT09IG51bGwgfHwgX3AgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9wLnR5cGUpID09PSBcInZpZGVvXCIpKSB7XG4gICAgICAgICAgY29uc3QgZW1iZWRkYWJsZSA9IHRoaXMuaW5zZXJ0RW1iZWRkYWJsZUVsZW1lbnQoe1xuICAgICAgICAgICAgc2NlbmVYLFxuICAgICAgICAgICAgc2NlbmVZLFxuICAgICAgICAgICAgbGluazogbm9ybWFsaXplTGluayh0ZXh0KVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGVtYmVkZGFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHtcbiAgICAgICAgICAgICAgICBbZW1iZWRkYWJsZS5pZF06IHRydWVcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmxvYWRGaWxlVG9DYW52YXMgPSAoZmlsZSwgZmlsZUhhbmRsZSkgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgZmlsZSA9IHlpZWxkIG5vcm1hbGl6ZUZpbGUoZmlsZSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJldCA9IHlpZWxkIGxvYWRTY2VuZU9yTGlicmFyeUZyb21CbG9iKGZpbGUsIHRoaXMuc3RhdGUsIHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIGZpbGVIYW5kbGUpO1xuXG4gICAgICAgIGlmIChyZXQudHlwZSA9PT0gTUlNRV9UWVBFUy5leGNhbGlkcmF3KSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBpc0xvYWRpbmc6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLnN5bmNBY3Rpb25SZXN1bHQoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCByZXQuZGF0YSksIHtcbiAgICAgICAgICAgIGFwcFN0YXRlOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHJldC5kYXRhLmFwcFN0YXRlIHx8IHRoaXMuc3RhdGUpLCB7XG4gICAgICAgICAgICAgIGlzTG9hZGluZzogZmFsc2VcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgcmVwbGFjZUZpbGVzOiB0cnVlLFxuICAgICAgICAgICAgY29tbWl0VG9IaXN0b3J5OiB0cnVlXG4gICAgICAgICAgfSkpO1xuICAgICAgICB9IGVsc2UgaWYgKHJldC50eXBlID09PSBNSU1FX1RZUEVTLmV4Y2FsaWRyYXdsaWIpIHtcbiAgICAgICAgICB5aWVsZCB0aGlzLmxpYnJhcnkudXBkYXRlTGlicmFyeSh7XG4gICAgICAgICAgICBsaWJyYXJ5SXRlbXM6IGZpbGUsXG4gICAgICAgICAgICBtZXJnZTogdHJ1ZSxcbiAgICAgICAgICAgIG9wZW5MaWJyYXJ5TWVudTogdHJ1ZVxuICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIGVycm9yTWVzc2FnZTogdChcImVycm9ycy5pbXBvcnRMaWJyYXJ5RXJyb3JcIilcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyb3IubWVzc2FnZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuaGFuZGxlQ2FudmFzQ29udGV4dE1lbnUgPSBldmVudCA9PiB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICBpZiAoKFwicG9pbnRlclR5cGVcIiBpbiBldmVudC5uYXRpdmVFdmVudCAmJiBldmVudC5uYXRpdmVFdmVudC5wb2ludGVyVHlwZSA9PT0gXCJ0b3VjaFwiIHx8IFwicG9pbnRlclR5cGVcIiBpbiBldmVudC5uYXRpdmVFdmVudCAmJiBldmVudC5uYXRpdmVFdmVudC5wb2ludGVyVHlwZSA9PT0gXCJwZW5cIiAmJiAvLyBhbHdheXMgYWxsb3cgaWYgdXNlciB1c2VzIGEgcGVuIHNlY29uZGFyeSBidXR0b25cbiAgICAgIGV2ZW50LmJ1dHRvbiAhPT0gUE9JTlRFUl9CVVRUT04uU0VDT05EQVJZKSAmJiB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgeCxcbiAgICAgICAgeVxuICAgICAgfSA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhldmVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50QXRQb3NpdGlvbih4LCB5LCB7XG4gICAgICAgIHByZWZlclNlbGVjdGVkOiB0cnVlLFxuICAgICAgICBpbmNsdWRlTG9ja2VkRWxlbWVudHM6IHRydWVcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IGlzSGl0dGlnbkNvbW1vbkJvdW5kQm94ID0gdGhpcy5pc0hpdHRpbmdDb21tb25Cb3VuZGluZ0JveE9mU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgIHgsXG4gICAgICAgIHlcbiAgICAgIH0sIHNlbGVjdGVkRWxlbWVudHMpO1xuICAgICAgY29uc3QgdHlwZSA9IGVsZW1lbnQgfHwgaXNIaXR0aWduQ29tbW9uQm91bmRCb3ggPyBcImVsZW1lbnRcIiA6IFwiY2FudmFzXCI7XG4gICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudDtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgdG9wOiBvZmZzZXRUb3AsXG4gICAgICAgIGxlZnQ6IG9mZnNldExlZnRcbiAgICAgIH0gPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCBsZWZ0ID0gZXZlbnQuY2xpZW50WCAtIG9mZnNldExlZnQ7XG4gICAgICBjb25zdCB0b3AgPSBldmVudC5jbGllbnRZIC0gb2Zmc2V0VG9wO1xuICAgICAgdHJhY2tFdmVudChcImNvbnRleHRNZW51XCIsIFwib3BlbkNvbnRleHRNZW51XCIsIHR5cGUpO1xuICAgICAgdGhpcy5zZXRTdGF0ZShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGVsZW1lbnQgJiYgIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2VsZW1lbnQuaWRdID8gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUpLCBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IHRoaXMuc3RhdGUuZWRpdGluZ0dyb3VwSWQsXG4gICAgICAgIHNlbGVjdGVkRWxlbWVudElkczoge1xuICAgICAgICAgIFtlbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICB9XG4gICAgICB9LCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCB0aGlzLnN0YXRlLCB0aGlzKSksIHtcbiAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBpc0xpbmVhckVsZW1lbnQoZWxlbWVudCkgPyBuZXcgTGluZWFyRWxlbWVudEVkaXRvcihlbGVtZW50LCB0aGlzLnNjZW5lKSA6IG51bGxcbiAgICAgIH0pIDogdGhpcy5zdGF0ZSksIHtcbiAgICAgICAgc2hvd0h5cGVybGlua1BvcHVwOiBmYWxzZVxuICAgICAgfSksICgpID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgY29udGV4dE1lbnU6IHtcbiAgICAgICAgICAgIHRvcCxcbiAgICAgICAgICAgIGxlZnQsXG4gICAgICAgICAgICBpdGVtczogdGhpcy5nZXRDb250ZXh0TWVudUl0ZW1zKHR5cGUpXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLm1heWJlRHJhZ05ld0dlbmVyaWNFbGVtZW50ID0gKHBvaW50ZXJEb3duU3RhdGUsIGV2ZW50KSA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIGNvbnN0IGRyYWdnaW5nRWxlbWVudCA9IHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50O1xuICAgICAgY29uc3QgcG9pbnRlckNvb3JkcyA9IHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3JkcztcblxuICAgICAgaWYgKCFkcmFnZ2luZ0VsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZHJhZ2dpbmdFbGVtZW50LnR5cGUgPT09IFwic2VsZWN0aW9uXCIgJiYgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwiZXJhc2VyXCIpIHtcbiAgICAgICAgZHJhZ05ld0VsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSwgcG9pbnRlckNvb3Jkcy54LCBwb2ludGVyQ29vcmRzLnksIGRpc3RhbmNlKHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJDb29yZHMueCksIGRpc3RhbmNlKHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnksIHBvaW50ZXJDb29yZHMueSksIHNob3VsZE1haW50YWluQXNwZWN0UmF0aW8oZXZlbnQpLCBzaG91bGRSZXNpemVGcm9tQ2VudGVyKGV2ZW50KSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChwb2ludGVyQ29vcmRzLngsIHBvaW50ZXJDb29yZHMueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICAgIGNvbnN0IGltYWdlID0gaXNJbml0aWFsaXplZEltYWdlRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQpICYmICgoX2EgPSB0aGlzLmltYWdlQ2FjaGUuZ2V0KGRyYWdnaW5nRWxlbWVudC5maWxlSWQpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuaW1hZ2UpO1xuICAgICAgICBjb25zdCBhc3BlY3RSYXRpbyA9IGltYWdlICYmICEoaW1hZ2UgaW5zdGFuY2VvZiBQcm9taXNlKSA/IGltYWdlLndpZHRoIC8gaW1hZ2UuaGVpZ2h0IDogbnVsbDtcbiAgICAgICAgZHJhZ05ld0VsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW5JbkdyaWQueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW5JbkdyaWQueSwgZ3JpZFgsIGdyaWRZLCBkaXN0YW5jZShwb2ludGVyRG93blN0YXRlLm9yaWdpbkluR3JpZC54LCBncmlkWCksIGRpc3RhbmNlKHBvaW50ZXJEb3duU3RhdGUub3JpZ2luSW5HcmlkLnksIGdyaWRZKSwgaXNJbWFnZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50KSA/ICFzaG91bGRNYWludGFpbkFzcGVjdFJhdGlvKGV2ZW50KSA6IHNob3VsZE1haW50YWluQXNwZWN0UmF0aW8oZXZlbnQpLCBzaG91bGRSZXNpemVGcm9tQ2VudGVyKGV2ZW50KSwgYXNwZWN0UmF0aW8pO1xuICAgICAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdGb3JBbGwoW2RyYWdnaW5nRWxlbWVudF0pOyAvLyBoaWdobGlnaHQgZWxlbWVudHMgdGhhdCBhcmUgdG8gYmUgYWRkZWQgdG8gZnJhbWVzIG9uIGZyYW1lcyBjcmVhdGlvblxuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJmcmFtZVwiKSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBlbGVtZW50c1RvSGlnaGxpZ2h0OiBnZXRFbGVtZW50c0luUmVzaXppbmdGcmFtZSh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBkcmFnZ2luZ0VsZW1lbnQsIHRoaXMuc3RhdGUpXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5tYXliZUhhbmRsZVJlc2l6ZSA9IChwb2ludGVyRG93blN0YXRlLCBldmVudCkgPT4ge1xuICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IHNlbGVjdGVkRnJhbWVzID0gc2VsZWN0ZWRFbGVtZW50cy5maWx0ZXIoZWxlbWVudCA9PiBlbGVtZW50LnR5cGUgPT09IFwiZnJhbWVcIik7XG4gICAgICBjb25zdCB0cmFuc2Zvcm1IYW5kbGVUeXBlID0gcG9pbnRlckRvd25TdGF0ZS5yZXNpemUuaGFuZGxlVHlwZTtcblxuICAgICAgaWYgKHNlbGVjdGVkRnJhbWVzLmxlbmd0aCA+IDAgJiYgdHJhbnNmb3JtSGFuZGxlVHlwZSA9PT0gXCJyb3RhdGlvblwiKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIC8vIFRPRE86IHJlbmFtZSB0aGlzIHN0YXRlIGZpZWxkIHRvIFwiaXNTY2FsaW5nXCIgdG8gZGlzdGluZ3Vpc2hcbiAgICAgICAgLy8gaXQgZnJvbSB0aGUgZ2VuZXJpYyBcImlzUmVzaXppbmdcIiB3aGljaCBpbmNsdWRlcyBzY2FsaW5nIGFuZFxuICAgICAgICAvLyByb3RhdGluZ1xuICAgICAgICBpc1Jlc2l6aW5nOiB0cmFuc2Zvcm1IYW5kbGVUeXBlICYmIHRyYW5zZm9ybUhhbmRsZVR5cGUgIT09IFwicm90YXRpb25cIixcbiAgICAgICAgaXNSb3RhdGluZzogdHJhbnNmb3JtSGFuZGxlVHlwZSA9PT0gXCJyb3RhdGlvblwiLFxuICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHBvaW50ZXJDb29yZHMgPSBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHM7XG4gICAgICBjb25zdCBbcmVzaXplWCwgcmVzaXplWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckNvb3Jkcy54IC0gcG9pbnRlckRvd25TdGF0ZS5yZXNpemUub2Zmc2V0LngsIHBvaW50ZXJDb29yZHMueSAtIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLm9mZnNldC55LCBldmVudFtLRVlTLkNUUkxfT1JfQ01EXSA/IG51bGwgOiB0aGlzLnN0YXRlLmdyaWRTaXplKTtcbiAgICAgIGNvbnN0IGZyYW1lRWxlbWVudHNPZmZzZXRzTWFwID0gbmV3IE1hcCgpO1xuICAgICAgc2VsZWN0ZWRGcmFtZXMuZm9yRWFjaChmcmFtZSA9PiB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzSW5GcmFtZSA9IGdldEZyYW1lRWxlbWVudHModGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZnJhbWUuaWQpO1xuICAgICAgICBlbGVtZW50c0luRnJhbWUuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICBmcmFtZUVsZW1lbnRzT2Zmc2V0c01hcC5zZXQoZnJhbWUuaWQgKyBlbGVtZW50LmlkLCB7XG4gICAgICAgICAgICB4OiBlbGVtZW50LnggLSBmcmFtZS54LFxuICAgICAgICAgICAgeTogZWxlbWVudC55IC0gZnJhbWUueVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodHJhbnNmb3JtRWxlbWVudHMocG9pbnRlckRvd25TdGF0ZSwgdHJhbnNmb3JtSGFuZGxlVHlwZSwgc2VsZWN0ZWRFbGVtZW50cywgcG9pbnRlckRvd25TdGF0ZS5yZXNpemUuYXJyb3dEaXJlY3Rpb24sIHNob3VsZFJvdGF0ZVdpdGhEaXNjcmV0ZUFuZ2xlKGV2ZW50KSwgc2hvdWxkUmVzaXplRnJvbUNlbnRlcihldmVudCksIHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxICYmIGlzSW1hZ2VFbGVtZW50KHNlbGVjdGVkRWxlbWVudHNbMF0pID8gIXNob3VsZE1haW50YWluQXNwZWN0UmF0aW8oZXZlbnQpIDogc2hvdWxkTWFpbnRhaW5Bc3BlY3RSYXRpbyhldmVudCksIHJlc2l6ZVgsIHJlc2l6ZVksIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmNlbnRlci54LCBwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5jZW50ZXIueSkpIHtcbiAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nRm9yQWxsKHNlbGVjdGVkRWxlbWVudHMpO1xuICAgICAgICBjb25zdCBlbGVtZW50c1RvSGlnaGxpZ2h0ID0gbmV3IFNldCgpO1xuICAgICAgICBzZWxlY3RlZEZyYW1lcy5mb3JFYWNoKGZyYW1lID0+IHtcbiAgICAgICAgICBjb25zdCBlbGVtZW50c0luRnJhbWUgPSBnZXRGcmFtZUVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIGZyYW1lLmlkKTsgLy8ga2VlcCBlbGVtZW50cycgcG9zaXRpb25zIHJlbGF0aXZlIHRvIHRoZWlyIGZyYW1lcyBvbiBmcmFtZXMgcmVzaXppbmdcblxuICAgICAgICAgIGlmICh0cmFuc2Zvcm1IYW5kbGVUeXBlKSB7XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtSGFuZGxlVHlwZS5pbmNsdWRlcyhcIndcIikpIHtcbiAgICAgICAgICAgICAgZWxlbWVudHNJbkZyYW1lLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIF9hLCBfYjtcblxuICAgICAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZWxlbWVudCwge1xuICAgICAgICAgICAgICAgICAgeDogZnJhbWUueCArICgoKF9hID0gZnJhbWVFbGVtZW50c09mZnNldHNNYXAuZ2V0KGZyYW1lLmlkICsgZWxlbWVudC5pZCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS54KSB8fCAwKSxcbiAgICAgICAgICAgICAgICAgIHk6IGZyYW1lLnkgKyAoKChfYiA9IGZyYW1lRWxlbWVudHNPZmZzZXRzTWFwLmdldChmcmFtZS5pZCArIGVsZW1lbnQuaWQpKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IueSkgfHwgMClcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0cmFuc2Zvcm1IYW5kbGVUeXBlLmluY2x1ZGVzKFwiblwiKSkge1xuICAgICAgICAgICAgICBlbGVtZW50c0luRnJhbWUuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICB2YXIgX2EsIF9iO1xuXG4gICAgICAgICAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgICAgICAgICB4OiBmcmFtZS54ICsgKCgoX2EgPSBmcmFtZUVsZW1lbnRzT2Zmc2V0c01hcC5nZXQoZnJhbWUuaWQgKyBlbGVtZW50LmlkKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLngpIHx8IDApLFxuICAgICAgICAgICAgICAgICAgeTogZnJhbWUueSArICgoKF9iID0gZnJhbWVFbGVtZW50c09mZnNldHNNYXAuZ2V0KGZyYW1lLmlkICsgZWxlbWVudC5pZCkpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi55KSB8fCAwKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBnZXRFbGVtZW50c0luUmVzaXppbmdGcmFtZSh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBmcmFtZSwgdGhpcy5zdGF0ZSkuZm9yRWFjaChlbGVtZW50ID0+IGVsZW1lbnRzVG9IaWdobGlnaHQuYWRkKGVsZW1lbnQpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGVsZW1lbnRzVG9IaWdobGlnaHQ6IFsuLi5lbGVtZW50c1RvSGlnaGxpZ2h0XVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgdGhpcy5nZXRDb250ZXh0TWVudUl0ZW1zID0gdHlwZSA9PiB7XG4gICAgICBjb25zdCBvcHRpb25zID0gW107XG4gICAgICBvcHRpb25zLnB1c2goYWN0aW9uQ29weUFzUG5nLCBhY3Rpb25Db3B5QXNTdmcpOyAvLyBjYW52YXMgY29udGV4dE1lbnVcbiAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAgICAgaWYgKHR5cGUgPT09IFwiY2FudmFzXCIpIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgICAgcmV0dXJuIFsuLi5vcHRpb25zLCBhY3Rpb25Ub2dnbGVHcmlkTW9kZSwgYWN0aW9uVG9nZ2xlWmVuTW9kZSwgYWN0aW9uVG9nZ2xlVmlld01vZGUsIGFjdGlvblRvZ2dsZVN0YXRzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbYWN0aW9uUGFzdGUsIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvbkNvcHlBc1BuZywgYWN0aW9uQ29weUFzU3ZnLCBjb3B5VGV4dCwgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgYWN0aW9uU2VsZWN0QWxsLCBhY3Rpb25VbmxvY2tBbGxFbGVtZW50cywgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgYWN0aW9uVG9nZ2xlR3JpZE1vZGUsIGFjdGlvblRvZ2dsZVplbk1vZGUsIGFjdGlvblRvZ2dsZVZpZXdNb2RlLCBhY3Rpb25Ub2dnbGVTdGF0c107XG4gICAgICB9IC8vIGVsZW1lbnQgY29udGV4dE1lbnVcbiAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG4gICAgICBvcHRpb25zLnB1c2goY29weVRleHQpO1xuXG4gICAgICBpZiAodGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuIFthY3Rpb25Db3B5LCAuLi5vcHRpb25zXTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFthY3Rpb25DdXQsIGFjdGlvbkNvcHksIGFjdGlvblBhc3RlLCBhY3Rpb25TZWxlY3RBbGxFbGVtZW50c0luRnJhbWUsIGFjdGlvblJlbW92ZUFsbEVsZW1lbnRzRnJvbUZyYW1lLCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCAuLi5vcHRpb25zLCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCBhY3Rpb25Db3B5U3R5bGVzLCBhY3Rpb25QYXN0ZVN0eWxlcywgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgYWN0aW9uR3JvdXAsIGFjdGlvblVuYmluZFRleHQsIGFjdGlvbkJpbmRUZXh0LCBhY3Rpb25XcmFwVGV4dEluQ29udGFpbmVyLCBhY3Rpb25Vbmdyb3VwLCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCBhY3Rpb25BZGRUb0xpYnJhcnksIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvblNlbmRCYWNrd2FyZCwgYWN0aW9uQnJpbmdGb3J3YXJkLCBhY3Rpb25TZW5kVG9CYWNrLCBhY3Rpb25CcmluZ1RvRnJvbnQsIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvbkZsaXBIb3Jpem9udGFsLCBhY3Rpb25GbGlwVmVydGljYWwsIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvblRvZ2dsZUxpbmVhckVkaXRvciwgYWN0aW9uTGluaywgYWN0aW9uRHVwbGljYXRlU2VsZWN0aW9uLCBhY3Rpb25Ub2dnbGVFbGVtZW50TG9jaywgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgYWN0aW9uRGVsZXRlU2VsZWN0ZWRdO1xuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZVdoZWVsID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIGlmIChpc1Bhbm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIGRlbHRhWCxcbiAgICAgICAgZGVsdGFZXG4gICAgICB9ID0gZXZlbnQ7IC8vIG5vdGUgdGhhdCBldmVudC5jdHJsS2V5IGlzIG5lY2Vzc2FyeSB0byBoYW5kbGUgcGluY2ggem9vbWluZ1xuXG4gICAgICBpZiAoZXZlbnQubWV0YUtleSB8fCBldmVudC5jdHJsS2V5KSB7XG4gICAgICAgIGNvbnN0IHNpZ24gPSBNYXRoLnNpZ24oZGVsdGFZKTtcbiAgICAgICAgY29uc3QgTUFYX1NURVAgPSBaT09NX1NURVAgKiAxMDA7XG4gICAgICAgIGNvbnN0IGFic0RlbHRhID0gTWF0aC5hYnMoZGVsdGFZKTtcbiAgICAgICAgbGV0IGRlbHRhID0gZGVsdGFZO1xuXG4gICAgICAgIGlmIChhYnNEZWx0YSA+IE1BWF9TVEVQKSB7XG4gICAgICAgICAgZGVsdGEgPSBNQVhfU1RFUCAqIHNpZ247XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbmV3Wm9vbSA9IHRoaXMuc3RhdGUuem9vbS52YWx1ZSAtIGRlbHRhIC8gMTAwOyAvLyBpbmNyZWFzZSB6b29tIHN0ZXBzIHRoZSBtb3JlIHpvb21lZC1pbiB3ZSBhcmUgKGFwcGxpZXMgdG8gPjEwMCUgb25seSlcblxuICAgICAgICBuZXdab29tICs9IE1hdGgubG9nMTAoTWF0aC5tYXgoMSwgdGhpcy5zdGF0ZS56b29tLnZhbHVlKSkgKiAtc2lnbiAqIC8vIHJlZHVjZWQgYW1wbGlmaWNhdGlvbiBmb3Igc21hbGwgZGVsdGFzIChzbWFsbCBtb3ZlbWVudHMgb24gYSB0cmFja3BhZClcbiAgICAgICAgTWF0aC5taW4oMSwgYWJzRGVsdGEgLyAyMCk7XG4gICAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHN0YXRlID0+IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZ2V0U3RhdGVGb3Jab29tKHtcbiAgICAgICAgICB2aWV3cG9ydFg6IHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueCxcbiAgICAgICAgICB2aWV3cG9ydFk6IHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueSxcbiAgICAgICAgICBuZXh0Wm9vbTogZ2V0Tm9ybWFsaXplZFpvb20obmV3Wm9vbSlcbiAgICAgICAgfSwgc3RhdGUpKSwge1xuICAgICAgICAgIHNob3VsZENhY2hlSWdub3JlWm9vbTogdHJ1ZVxuICAgICAgICB9KSk7XG4gICAgICAgIHRoaXMucmVzZXRTaG91bGRDYWNoZUlnbm9yZVpvb21EZWJvdW5jZWQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBzY3JvbGwgaG9yaXpvbnRhbGx5IHdoZW4gc2hpZnQgcHJlc3NlZFxuXG5cbiAgICAgIGlmIChldmVudC5zaGlmdEtleSkge1xuICAgICAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcygoe1xuICAgICAgICAgIHpvb20sXG4gICAgICAgICAgc2Nyb2xsWFxuICAgICAgICB9KSA9PiAoe1xuICAgICAgICAgIC8vIG9uIE1hYywgc2hpZnQrd2hlZWwgdGVuZHMgdG8gcmVzdWx0IGluIGRlbHRhWFxuICAgICAgICAgIHNjcm9sbFg6IHNjcm9sbFggLSAoZGVsdGFZIHx8IGRlbHRhWCkgLyB6b29tLnZhbHVlXG4gICAgICAgIH0pKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcygoe1xuICAgICAgICB6b29tLFxuICAgICAgICBzY3JvbGxYLFxuICAgICAgICBzY3JvbGxZXG4gICAgICB9KSA9PiAoe1xuICAgICAgICBzY3JvbGxYOiBzY3JvbGxYIC0gZGVsdGFYIC8gem9vbS52YWx1ZSxcbiAgICAgICAgc2Nyb2xsWTogc2Nyb2xsWSAtIGRlbHRhWSAvIHpvb20udmFsdWVcbiAgICAgIH0pKTtcbiAgICB9KTtcblxuICAgIHRoaXMuc2F2ZVBvaW50ZXIgPSAoeCwgeSwgYnV0dG9uKSA9PiB7XG4gICAgICB2YXIgX2EsIF9iO1xuXG4gICAgICBpZiAoIXggfHwgIXkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwb2ludGVyID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKHtcbiAgICAgICAgY2xpZW50WDogeCxcbiAgICAgICAgY2xpZW50WTogeVxuICAgICAgfSwgdGhpcy5zdGF0ZSk7XG5cbiAgICAgIGlmIChpc05hTihwb2ludGVyLngpIHx8IGlzTmFOKHBvaW50ZXIueSkpIHsvLyBzb21ldGltZXMgdGhlIHBvaW50ZXIgZ29lcyBvZmYgc2NyZWVuXG4gICAgICB9XG5cbiAgICAgIChfYiA9IChfYSA9IHRoaXMucHJvcHMpLm9uUG9pbnRlclVwZGF0ZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmNhbGwoX2EsIHtcbiAgICAgICAgcG9pbnRlcixcbiAgICAgICAgYnV0dG9uLFxuICAgICAgICBwb2ludGVyc01hcDogZ2VzdHVyZS5wb2ludGVyc1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMucmVzZXRTaG91bGRDYWNoZUlnbm9yZVpvb21EZWJvdW5jZWQgPSBkZWJvdW5jZSgoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMudW5tb3VudGVkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNob3VsZENhY2hlSWdub3JlWm9vbTogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSwgMzAwKTtcblxuICAgIHRoaXMudXBkYXRlRE9NUmVjdCA9IGNiID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgaWYgKChfYSA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmN1cnJlbnQpIHtcbiAgICAgICAgY29uc3QgZXhjYWxpZHJhd0NvbnRhaW5lciA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50O1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0LFxuICAgICAgICAgIGxlZnQ6IG9mZnNldExlZnQsXG4gICAgICAgICAgdG9wOiBvZmZzZXRUb3BcbiAgICAgICAgfSA9IGV4Y2FsaWRyYXdDb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB3aWR0aDogY3VycmVudFdpZHRoLFxuICAgICAgICAgIGhlaWdodDogY3VycmVudEhlaWdodCxcbiAgICAgICAgICBvZmZzZXRUb3A6IGN1cnJlbnRPZmZzZXRUb3AsXG4gICAgICAgICAgb2Zmc2V0TGVmdDogY3VycmVudE9mZnNldExlZnRcbiAgICAgICAgfSA9IHRoaXMuc3RhdGU7XG5cbiAgICAgICAgaWYgKHdpZHRoID09PSBjdXJyZW50V2lkdGggJiYgaGVpZ2h0ID09PSBjdXJyZW50SGVpZ2h0ICYmIG9mZnNldExlZnQgPT09IGN1cnJlbnRPZmZzZXRMZWZ0ICYmIG9mZnNldFRvcCA9PT0gY3VycmVudE9mZnNldFRvcCkge1xuICAgICAgICAgIGlmIChjYikge1xuICAgICAgICAgICAgY2IoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgb2Zmc2V0TGVmdCxcbiAgICAgICAgICBvZmZzZXRUb3BcbiAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgIGNiICYmIGNiKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLnJlZnJlc2ggPSAoKSA9PiB7XG4gICAgICB0aGlzLnNldFN0YXRlKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZ2V0Q2FudmFzT2Zmc2V0cygpKSk7XG4gICAgfTtcblxuICAgIGNvbnN0IGRlZmF1bHRBcHBTdGF0ZSA9IGdldERlZmF1bHRBcHBTdGF0ZSgpO1xuICAgIGNvbnN0IHtcbiAgICAgIGV4Y2FsaWRyYXdSZWYsXG4gICAgICB2aWV3TW9kZUVuYWJsZWQgPSBmYWxzZSxcbiAgICAgIHplbk1vZGVFbmFibGVkID0gZmFsc2UsXG4gICAgICBncmlkTW9kZUVuYWJsZWQgPSBmYWxzZSxcbiAgICAgIHRoZW1lID0gZGVmYXVsdEFwcFN0YXRlLnRoZW1lLFxuICAgICAgbmFtZSA9IGRlZmF1bHRBcHBTdGF0ZS5uYW1lXG4gICAgfSA9IHByb3BzO1xuICAgIHRoaXMuc3RhdGUgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0QXBwU3RhdGUpLCB7XG4gICAgICB0aGVtZSxcbiAgICAgIGlzTG9hZGluZzogdHJ1ZVxuICAgIH0pLCB0aGlzLmdldENhbnZhc09mZnNldHMoKSksIHtcbiAgICAgIHZpZXdNb2RlRW5hYmxlZCxcbiAgICAgIHplbk1vZGVFbmFibGVkLFxuICAgICAgZ3JpZFNpemU6IGdyaWRNb2RlRW5hYmxlZCA/IEdSSURfU0laRSA6IG51bGwsXG4gICAgICBuYW1lLFxuICAgICAgd2lkdGg6IHdpbmRvdy5pbm5lcldpZHRoLFxuICAgICAgaGVpZ2h0OiB3aW5kb3cuaW5uZXJIZWlnaHRcbiAgICB9KTtcbiAgICB0aGlzLmlkID0gbmFub2lkKCk7XG4gICAgdGhpcy5saWJyYXJ5ID0gbmV3IExpYnJhcnkodGhpcyk7XG4gICAgdGhpcy5zY2VuZSA9IG5ldyBTY2VuZSgpO1xuICAgIHRoaXMuY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICB0aGlzLnJjID0gcm91Z2guY2FudmFzKHRoaXMuY2FudmFzKTtcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFJlbmRlcmVyKHRoaXMuc2NlbmUpO1xuXG4gICAgaWYgKGV4Y2FsaWRyYXdSZWYpIHtcbiAgICAgIGNvbnN0IHJlYWR5UHJvbWlzZSA9IFwiY3VycmVudFwiIGluIGV4Y2FsaWRyYXdSZWYgJiYgKChfYSA9IGV4Y2FsaWRyYXdSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnJlYWR5UHJvbWlzZSkgfHwgcmVzb2x2YWJsZVByb21pc2UoKTtcbiAgICAgIGNvbnN0IGFwaSA9IHtcbiAgICAgICAgcmVhZHk6IHRydWUsXG4gICAgICAgIHJlYWR5UHJvbWlzZSxcbiAgICAgICAgdXBkYXRlU2NlbmU6IHRoaXMudXBkYXRlU2NlbmUsXG4gICAgICAgIHVwZGF0ZUxpYnJhcnk6IHRoaXMubGlicmFyeS51cGRhdGVMaWJyYXJ5LFxuICAgICAgICBhZGRGaWxlczogdGhpcy5hZGRGaWxlcyxcbiAgICAgICAgcmVzZXRTY2VuZTogdGhpcy5yZXNldFNjZW5lLFxuICAgICAgICBnZXRTY2VuZUVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZDogdGhpcy5nZXRTY2VuZUVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCxcbiAgICAgICAgaGlzdG9yeToge1xuICAgICAgICAgIGNsZWFyOiB0aGlzLnJlc2V0SGlzdG9yeVxuICAgICAgICB9LFxuICAgICAgICBzY3JvbGxUb0NvbnRlbnQ6IHRoaXMuc2Nyb2xsVG9Db250ZW50LFxuICAgICAgICBnZXRTY2VuZUVsZW1lbnRzOiB0aGlzLmdldFNjZW5lRWxlbWVudHMsXG4gICAgICAgIGdldEFwcFN0YXRlOiAoKSA9PiB0aGlzLnN0YXRlLFxuICAgICAgICBnZXRGaWxlczogKCkgPT4gdGhpcy5maWxlcyxcbiAgICAgICAgcmVmcmVzaDogdGhpcy5yZWZyZXNoLFxuICAgICAgICBzZXRUb2FzdDogdGhpcy5zZXRUb2FzdCxcbiAgICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICAgIHNldEFjdGl2ZVRvb2w6IHRoaXMuc2V0QWN0aXZlVG9vbCxcbiAgICAgICAgc2V0Q3Vyc29yOiB0aGlzLnNldEN1cnNvcixcbiAgICAgICAgcmVzZXRDdXJzb3I6IHRoaXMucmVzZXRDdXJzb3IsXG4gICAgICAgIHVwZGF0ZUZyYW1lUmVuZGVyaW5nOiB0aGlzLnVwZGF0ZUZyYW1lUmVuZGVyaW5nLFxuICAgICAgICB0b2dnbGVTaWRlYmFyOiB0aGlzLnRvZ2dsZVNpZGViYXJcbiAgICAgIH07XG5cbiAgICAgIGlmICh0eXBlb2YgZXhjYWxpZHJhd1JlZiA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIGV4Y2FsaWRyYXdSZWYoYXBpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4Y2FsaWRyYXdSZWYuY3VycmVudCA9IGFwaTtcbiAgICAgIH1cblxuICAgICAgcmVhZHlQcm9taXNlLnJlc29sdmUoYXBpKTtcbiAgICB9XG5cbiAgICB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJWYWx1ZSA9IHtcbiAgICAgIGNvbnRhaW5lcjogdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQsXG4gICAgICBpZDogdGhpcy5pZFxuICAgIH07XG4gICAgdGhpcy5mb250cyA9IG5ldyBGb250cyh7XG4gICAgICBzY2VuZTogdGhpcy5zY2VuZSxcbiAgICAgIG9uU2NlbmVVcGRhdGVkOiB0aGlzLm9uU2NlbmVVcGRhdGVkXG4gICAgfSk7XG4gICAgdGhpcy5oaXN0b3J5ID0gbmV3IEhpc3RvcnkoKTtcbiAgICB0aGlzLmFjdGlvbk1hbmFnZXIgPSBuZXcgQWN0aW9uTWFuYWdlcih0aGlzLnN5bmNBY3Rpb25SZXN1bHQsICgpID0+IHRoaXMuc3RhdGUsICgpID0+IHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIHRoaXMpO1xuICAgIHRoaXMuYWN0aW9uTWFuYWdlci5yZWdpc3RlckFsbChhY3Rpb25zKTtcbiAgICB0aGlzLmFjdGlvbk1hbmFnZXIucmVnaXN0ZXJBY3Rpb24oY3JlYXRlVW5kb0FjdGlvbih0aGlzLmhpc3RvcnkpKTtcbiAgICB0aGlzLmFjdGlvbk1hbmFnZXIucmVnaXN0ZXJBY3Rpb24oY3JlYXRlUmVkb0FjdGlvbih0aGlzLmhpc3RvcnkpKTtcbiAgfVxuXG4gIG9uV2luZG93TWVzc2FnZShldmVudCkge1xuICAgIGlmIChldmVudC5vcmlnaW4gIT09IFwiaHR0cHM6Ly9wbGF5ZXIudmltZW8uY29tXCIgJiYgZXZlbnQub3JpZ2luICE9PSBcImh0dHBzOi8vd3d3LnlvdXR1YmUuY29tXCIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZGF0YSA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZXZlbnQuZGF0YSk7XG4gICAgfSBjYXRjaCAoZSkge31cblxuICAgIGlmICghZGF0YSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZXZlbnQub3JpZ2luKSB7XG4gICAgICBjYXNlIFwiaHR0cHM6Ly9wbGF5ZXIudmltZW8uY29tXCI6XG4gICAgICAgIC8vQWxsb3dpbmcgZm9yIG11bHRpcGxlIGluc3RhbmNlcyBvZiBFeGNhbGlkcmF3IHJ1bm5pbmcgaW4gdGhlIHdpbmRvd1xuICAgICAgICBpZiAoZGF0YS5tZXRob2QgPT09IFwicGF1c2VkXCIpIHtcbiAgICAgICAgICBsZXQgc291cmNlID0gbnVsbDtcbiAgICAgICAgICBjb25zdCBpZnJhbWVzID0gZG9jdW1lbnQuYm9keS5xdWVyeVNlbGVjdG9yQWxsKFwiaWZyYW1lLmV4Y2FsaWRyYXdfX2VtYmVkZGFibGVcIik7XG5cbiAgICAgICAgICBpZiAoIWlmcmFtZXMpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAoY29uc3QgaWZyYW1lIG9mIGlmcmFtZXMpIHtcbiAgICAgICAgICAgIGlmIChpZnJhbWUuY29udGVudFdpbmRvdyA9PT0gZXZlbnQuc291cmNlKSB7XG4gICAgICAgICAgICAgIHNvdXJjZSA9IGlmcmFtZS5jb250ZW50V2luZG93O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHNvdXJjZSA9PT0gbnVsbCB8fCBzb3VyY2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHNvdXJjZS5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBtZXRob2Q6IGRhdGEudmFsdWUgPyBcInBsYXlcIiA6IFwicGF1c2VcIixcbiAgICAgICAgICAgIHZhbHVlOiB0cnVlXG4gICAgICAgICAgfSksIFwiKlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiaHR0cHM6Ly93d3cueW91dHViZS5jb21cIjpcbiAgICAgICAgaWYgKGRhdGEuZXZlbnQgPT09IFwiaW5mb0RlbGl2ZXJ5XCIgJiYgZGF0YS5pbmZvICYmIGRhdGEuaWQgJiYgdHlwZW9mIGRhdGEuaW5mby5wbGF5ZXJTdGF0ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgIGNvbnN0IGlkID0gZGF0YS5pZDtcbiAgICAgICAgICBjb25zdCBwbGF5ZXJTdGF0ZSA9IGRhdGEuaW5mby5wbGF5ZXJTdGF0ZTtcblxuICAgICAgICAgIGlmIChPYmplY3QudmFsdWVzKFlPVVRVQkVfU1RBVEVTKS5pbmNsdWRlcyhwbGF5ZXJTdGF0ZSkpIHtcbiAgICAgICAgICAgIFlPVVRVQkVfVklERU9fU1RBVEVTLnNldChpZCwgcGxheWVyU3RhdGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZUVtYmVkZGFibGVSZWYoaWQsIHJlZikge1xuICAgIGlmIChyZWYpIHtcbiAgICAgIHRoaXMuaUZyYW1lUmVmcy5zZXQoaWQsIHJlZik7XG4gICAgfVxuICB9XG5cbiAgZ2V0SFRNTElGcmFtZUVsZW1lbnQoaWQpIHtcbiAgICByZXR1cm4gdGhpcy5pRnJhbWVSZWZzLmdldChpZCk7XG4gIH1cblxuICBoYW5kbGVFbWJlZGRhYmxlQ2VudGVyQ2xpY2soZWxlbWVudCkge1xuICAgIHZhciBfYSwgX2IsIF9jLCBfZDtcblxuICAgIGlmICgoKF9hID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZWxlbWVudCkgPT09IGVsZW1lbnQgJiYgKChfYiA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnN0YXRlKSA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gVGhlIGRlbGF5IHNlcnZlcyB0d28gcHVycG9zZXNcbiAgICAvLyAxLiBUbyBwcmV2ZW50IGZpcnN0IGNsaWNrIHByb3BhZ2F0aW5nIHRvIGlmcmFtZSBvbiBtb2JpbGUsXG4gICAgLy8gICAgZWxzZSB0aGUgY2xpY2sgd2lsbCBpbW1lZGlhdGVseSBzdGFydCBhbmQgc3RvcCB0aGUgdmlkZW9cbiAgICAvLyAyLiBJZiB0aGUgdXNlciBkb3VibGUgY2xpY2tzIHRoZSBmcmFtZSBjZW50ZXIgdG8gYWN0aXZhdGUgaXRcbiAgICAvLyAgICB3aXRob3V0IHRoZSBkZWxheSB5b3V0dWJlIHdpbGwgaW1tZWRpYXRlbHkgb3BlbiB0aGUgdmlkZW9cbiAgICAvLyAgICBpbiBmdWxsc2NyZWVuIG1vZGVcblxuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgYWN0aXZlRW1iZWRkYWJsZToge1xuICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgc3RhdGU6IFwiYWN0aXZlXCJcbiAgICAgICAgfSxcbiAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiB7XG4gICAgICAgICAgW2VsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgc2VsZWN0aW9uRWxlbWVudDogbnVsbFxuICAgICAgfSk7XG4gICAgfSwgMTAwKTtcbiAgICBjb25zdCBpZnJhbWUgPSB0aGlzLmdldEhUTUxJRnJhbWVFbGVtZW50KGVsZW1lbnQuaWQpO1xuXG4gICAgaWYgKCEoaWZyYW1lID09PSBudWxsIHx8IGlmcmFtZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogaWZyYW1lLmNvbnRlbnRXaW5kb3cpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGlmcmFtZS5zcmMuaW5jbHVkZXMoXCJ5b3V0dWJlXCIpKSB7XG4gICAgICBjb25zdCBzdGF0ZSA9IFlPVVRVQkVfVklERU9fU1RBVEVTLmdldChlbGVtZW50LmlkKTtcblxuICAgICAgaWYgKCFzdGF0ZSkge1xuICAgICAgICBZT1VUVUJFX1ZJREVPX1NUQVRFUy5zZXQoZWxlbWVudC5pZCwgWU9VVFVCRV9TVEFURVMuVU5TVEFSVEVEKTtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIGV2ZW50OiBcImxpc3RlbmluZ1wiLFxuICAgICAgICAgIGlkOiBlbGVtZW50LmlkXG4gICAgICAgIH0pLCBcIipcIik7XG4gICAgICB9XG5cbiAgICAgIHN3aXRjaCAoc3RhdGUpIHtcbiAgICAgICAgY2FzZSBZT1VUVUJFX1NUQVRFUy5QTEFZSU5HOlxuICAgICAgICBjYXNlIFlPVVRVQkVfU1RBVEVTLkJVRkZFUklORzpcbiAgICAgICAgICAoX2MgPSBpZnJhbWUuY29udGVudFdpbmRvdykgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIGV2ZW50OiBcImNvbW1hbmRcIixcbiAgICAgICAgICAgIGZ1bmM6IFwicGF1c2VWaWRlb1wiLFxuICAgICAgICAgICAgYXJnczogXCJcIlxuICAgICAgICAgIH0pLCBcIipcIik7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAoX2QgPSBpZnJhbWUuY29udGVudFdpbmRvdykgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIGV2ZW50OiBcImNvbW1hbmRcIixcbiAgICAgICAgICAgIGZ1bmM6IFwicGxheVZpZGVvXCIsXG4gICAgICAgICAgICBhcmdzOiBcIlwiXG4gICAgICAgICAgfSksIFwiKlwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaWZyYW1lLnNyYy5pbmNsdWRlcyhcInBsYXllci52aW1lby5jb21cIikpIHtcbiAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgbWV0aG9kOiBcInBhdXNlZFwiIC8vdmlkZW8gcGxheS9wYXVzZSBpbiBvbldpbmRvd01lc3NhZ2UgaGFuZGxlclxuXG4gICAgICB9KSwgXCIqXCIpO1xuICAgIH1cbiAgfVxuXG4gIGlzRW1iZWRkYWJsZUNlbnRlcihlbCwgZXZlbnQsIHNjZW5lWCwgc2NlbmVZKSB7XG4gICAgdmFyIF9hLCBfYjtcblxuICAgIHJldHVybiBlbCAmJiAhZXZlbnQuYWx0S2V5ICYmICFldmVudC5zaGlmdEtleSAmJiAhZXZlbnQubWV0YUtleSAmJiAhZXZlbnQuY3RybEtleSAmJiAoKChfYSA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmVsZW1lbnQpICE9PSBlbCB8fCAoKF9iID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iuc3RhdGUpID09PSBcImhvdmVyXCIgfHwgIXRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgJiYgc2NlbmVYID49IGVsLnggKyBlbC53aWR0aCAvIDMgJiYgc2NlbmVYIDw9IGVsLnggKyAyICogZWwud2lkdGggLyAzICYmIHNjZW5lWSA+PSBlbC55ICsgZWwuaGVpZ2h0IC8gMyAmJiBzY2VuZVkgPD0gZWwueSArIDIgKiBlbC5oZWlnaHQgLyAzO1xuICB9XG5cbiAgcmVuZGVyRW1iZWRkYWJsZXMoKSB7XG4gICAgY29uc3Qgc2NhbGUgPSB0aGlzLnN0YXRlLnpvb20udmFsdWU7XG4gICAgY29uc3Qgbm9ybWFsaXplZFdpZHRoID0gdGhpcy5zdGF0ZS53aWR0aDtcbiAgICBjb25zdCBub3JtYWxpemVkSGVpZ2h0ID0gdGhpcy5zdGF0ZS5oZWlnaHQ7XG4gICAgY29uc3QgZW1iZWRkYWJsZUVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKS5maWx0ZXIoZWwgPT4gaXNFbWJlZGRhYmxlRWxlbWVudChlbCkgJiYgISFlbC52YWxpZGF0ZWQpO1xuICAgIHJldHVybiBfanN4KF9GcmFnbWVudCwge1xuICAgICAgY2hpbGRyZW46IGVtYmVkZGFibGVFbGVtZW50cy5tYXAoZWwgPT4ge1xuICAgICAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lLCBfZiwgX2csIF9oO1xuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB4LFxuICAgICAgICAgIHlcbiAgICAgICAgfSA9IHNjZW5lQ29vcmRzVG9WaWV3cG9ydENvb3Jkcyh7XG4gICAgICAgICAgc2NlbmVYOiBlbC54LFxuICAgICAgICAgIHNjZW5lWTogZWwueVxuICAgICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgY29uc3QgZW1iZWRMaW5rID0gZ2V0RW1iZWRMaW5rKHRvVmFsaWRVUkwoZWwubGluayB8fCBcIlwiKSk7XG4gICAgICAgIGNvbnN0IGlzVmlzaWJsZSA9IGlzRWxlbWVudEluVmlld3BvcnQoZWwsIG5vcm1hbGl6ZWRXaWR0aCwgbm9ybWFsaXplZEhlaWdodCwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIGNvbnN0IGlzQWN0aXZlID0gKChfYSA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmVsZW1lbnQpID09PSBlbCAmJiAoKF9iID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iuc3RhdGUpID09PSBcImFjdGl2ZVwiO1xuICAgICAgICBjb25zdCBpc0hvdmVyZWQgPSAoKF9jID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MuZWxlbWVudCkgPT09IGVsICYmICgoX2QgPSB0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5zdGF0ZSkgPT09IFwiaG92ZXJcIjtcbiAgICAgICAgcmV0dXJuIF9qc3goXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgY2xhc3NOYW1lOiBjbHN4KFwiZXhjYWxpZHJhd19fZW1iZWRkYWJsZS1jb250YWluZXJcIiwge1xuICAgICAgICAgICAgXCJpcy1ob3ZlcmVkXCI6IGlzSG92ZXJlZFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGlzVmlzaWJsZSA/IGB0cmFuc2xhdGUoJHt4IC0gdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0fXB4LCAke3kgLSB0aGlzLnN0YXRlLm9mZnNldFRvcH1weCkgc2NhbGUoJHtzY2FsZX0pYCA6IFwibm9uZVwiLFxuICAgICAgICAgICAgZGlzcGxheTogaXNWaXNpYmxlID8gXCJibG9ja1wiIDogXCJub25lXCIsXG4gICAgICAgICAgICBvcGFjaXR5OiBlbC5vcGFjaXR5IC8gMTAwLFxuICAgICAgICAgICAgW1wiLS1lbWJlZGRhYmxlLXJhZGl1c1wiXTogYCR7Z2V0Q29ybmVyUmFkaXVzKE1hdGgubWluKGVsLndpZHRoLCBlbC5oZWlnaHQpLCBlbCl9cHhgXG4gICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IF9qc3hzKFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgLy90aGlzIGlzIGEgaGFjayB0aGF0IGFkZHJlc3NlcyBpc3NlIHdpdGggZW1iZWRkZWQgZXhjYWxpZHJhdy5jb20gZW1iZWRkYWJsZVxuICAgICAgICAgICAgLy9odHRwczovL2dpdGh1Yi5jb20vZXhjYWxpZHJhdy9leGNhbGlkcmF3L3B1bGwvNjY5MSNpc3N1ZWNvbW1lbnQtMTYwNzM4MzkzOFxuXG4gICAgICAgICAgICAvKnJlZj17KHJlZikgPT4ge1xuICAgICAgICAgICAgICBpZiAoIXRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50O1xuICAgICAgICAgICAgICBjb25zdCBzaCA9IGNvbnRhaW5lci5zY3JvbGxIZWlnaHQ7XG4gICAgICAgICAgICAgIGNvbnN0IGNoID0gY29udGFpbmVyLmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgICAgaWYgKHNoICE9PSBjaCkge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSBgJHtzaH1weGA7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gYDEwMCVgO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9fSovXG4gICAgICAgICAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhd19fZW1iZWRkYWJsZS1jb250YWluZXJfX2lubmVyXCIsXG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICB3aWR0aDogaXNWaXNpYmxlID8gYCR7ZWwud2lkdGh9cHhgIDogMCxcbiAgICAgICAgICAgICAgaGVpZ2h0OiBpc1Zpc2libGUgPyBgJHtlbC5oZWlnaHR9cHhgIDogMCxcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiBpc1Zpc2libGUgPyBgcm90YXRlKCR7ZWwuYW5nbGV9cmFkKWAgOiBcIm5vbmVcIixcbiAgICAgICAgICAgICAgcG9pbnRlckV2ZW50czogaXNBY3RpdmUgPyBQT0lOVEVSX0VWRU5UUy5lbmFibGVkIDogUE9JTlRFUl9FVkVOVFMuZGlzYWJsZWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LCB7XG4gICAgICAgICAgICBjaGlsZHJlbjogW2lzSG92ZXJlZCAmJiBfanN4KFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhd19fZW1iZWRkYWJsZS1oaW50XCJcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgY2hpbGRyZW46IHQoXCJidXR0b25zLmVtYmVkZGFibGVJbnRlcmFjdGlvbkJ1dHRvblwiKVxuICAgICAgICAgICAgfSkpLCBfanN4KFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhd19fZW1iZWRkYWJsZV9fb3V0ZXJcIixcbiAgICAgICAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nOiBgJHtlbC5zdHJva2VXaWR0aH1weGBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICBjaGlsZHJlbjogKF9nID0gKF9mID0gKF9lID0gdGhpcy5wcm9wcykucmVuZGVyRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2YgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9mLmNhbGwoX2UsIGVsLCB0aGlzLnN0YXRlKSkgIT09IG51bGwgJiYgX2cgIT09IHZvaWQgMCA/IF9nIDogX2pzeChcImlmcmFtZVwiLCB7XG4gICAgICAgICAgICAgICAgcmVmOiByZWYgPT4gdGhpcy51cGRhdGVFbWJlZGRhYmxlUmVmKGVsLmlkLCByZWYpLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogXCJleGNhbGlkcmF3X19lbWJlZGRhYmxlXCIsXG4gICAgICAgICAgICAgICAgc3JjRG9jOiAoZW1iZWRMaW5rID09PSBudWxsIHx8IGVtYmVkTGluayA9PT0gdm9pZCAwID8gdm9pZCAwIDogZW1iZWRMaW5rLnR5cGUpID09PSBcImRvY3VtZW50XCIgPyBlbWJlZExpbmsuc3JjZG9jKHRoaXMuc3RhdGUudGhlbWUpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIHNyYzogKGVtYmVkTGluayA9PT0gbnVsbCB8fCBlbWJlZExpbmsgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGVtYmVkTGluay50eXBlKSAhPT0gXCJkb2N1bWVudFwiID8gKF9oID0gZW1iZWRMaW5rID09PSBudWxsIHx8IGVtYmVkTGluayA9PT0gdm9pZCAwID8gdm9pZCAwIDogZW1iZWRMaW5rLmxpbmspICE9PSBudWxsICYmIF9oICE9PSB2b2lkIDAgPyBfaCA6IFwiXCIgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xLzE4NDcwMDE1XG4gICAgICAgICAgICAgICAgc2Nyb2xsaW5nOiBcIm5vXCIsXG4gICAgICAgICAgICAgICAgcmVmZXJyZXJQb2xpY3k6IFwibm8tcmVmZXJyZXItd2hlbi1kb3duZ3JhZGVcIixcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJFeGNhbGlkcmF3IEVtYmVkZGVkIENvbnRlbnRcIixcbiAgICAgICAgICAgICAgICBhbGxvdzogXCJhY2NlbGVyb21ldGVyOyBhdXRvcGxheTsgY2xpcGJvYXJkLXdyaXRlOyBlbmNyeXB0ZWQtbWVkaWE7IGd5cm9zY29wZTsgcGljdHVyZS1pbi1waWN0dXJlXCIsXG4gICAgICAgICAgICAgICAgYWxsb3dGdWxsU2NyZWVuOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNhbmRib3g6IFwiYWxsb3ctc2FtZS1vcmlnaW4gYWxsb3ctc2NyaXB0cyBhbGxvdy1mb3JtcyBhbGxvdy1wb3B1cHMgYWxsb3ctcG9wdXBzLXRvLWVzY2FwZS1zYW5kYm94IGFsbG93LXByZXNlbnRhdGlvbiBhbGxvdy1kb3dubG9hZHNcIlxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkpXVxuICAgICAgICAgIH0pKVxuICAgICAgICB9KSwgZWwuaWQpO1xuICAgICAgfSlcbiAgICB9KTtcbiAgfVxuXG4gIHJlbmRlcigpIHtcbiAgICB2YXIgX2EsIF9iLCBfYztcblxuICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG4gICAgY29uc3Qge1xuICAgICAgcmVuZGVyVG9wUmlnaHRVSSxcbiAgICAgIHJlbmRlckN1c3RvbVN0YXRzXG4gICAgfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3QgdmVyc2lvbk5vbmNlID0gdGhpcy5zY2VuZS5nZXRWZXJzaW9uTm9uY2UoKTtcbiAgICBjb25zdCB7XG4gICAgICBjYW52YXNFbGVtZW50cyxcbiAgICAgIHZpc2libGVFbGVtZW50c1xuICAgIH0gPSB0aGlzLnJlbmRlcmVyLmdldFJlbmRlcmFibGVFbGVtZW50cyh7XG4gICAgICB2ZXJzaW9uTm9uY2UsXG4gICAgICB6b29tOiB0aGlzLnN0YXRlLnpvb20sXG4gICAgICBvZmZzZXRMZWZ0OiB0aGlzLnN0YXRlLm9mZnNldExlZnQsXG4gICAgICBvZmZzZXRUb3A6IHRoaXMuc3RhdGUub2Zmc2V0VG9wLFxuICAgICAgc2Nyb2xsWDogdGhpcy5zdGF0ZS5zY3JvbGxYLFxuICAgICAgc2Nyb2xsWTogdGhpcy5zdGF0ZS5zY3JvbGxZLFxuICAgICAgaGVpZ2h0OiB0aGlzLnN0YXRlLmhlaWdodCxcbiAgICAgIHdpZHRoOiB0aGlzLnN0YXRlLndpZHRoLFxuICAgICAgZWRpdGluZ0VsZW1lbnQ6IHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQsXG4gICAgICBwZW5kaW5nSW1hZ2VFbGVtZW50SWQ6IHRoaXMuc3RhdGUucGVuZGluZ0ltYWdlRWxlbWVudElkXG4gICAgfSk7XG4gICAgcmV0dXJuIF9qc3goXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICBjbGFzc05hbWU6IGNsc3goXCJleGNhbGlkcmF3IGV4Y2FsaWRyYXctY29udGFpbmVyXCIsIHtcbiAgICAgICAgXCJleGNhbGlkcmF3LS12aWV3LW1vZGVcIjogdGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQsXG4gICAgICAgIFwiZXhjYWxpZHJhdy0tbW9iaWxlXCI6IHRoaXMuZGV2aWNlLmlzTW9iaWxlXG4gICAgICB9KSxcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIFtcIi0tdWktcG9pbnRlckV2ZW50c1wiXTogdGhpcy5zdGF0ZS5zZWxlY3Rpb25FbGVtZW50IHx8IHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50IHx8IHRoaXMuc3RhdGUucmVzaXppbmdFbGVtZW50IHx8IHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQgJiYgIWlzVGV4dEVsZW1lbnQodGhpcy5zdGF0ZS5lZGl0aW5nRWxlbWVudCkgPyBQT0lOVEVSX0VWRU5UUy5kaXNhYmxlZCA6IFBPSU5URVJfRVZFTlRTLmVuYWJsZWRcbiAgICAgIH0sXG4gICAgICByZWY6IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZixcbiAgICAgIG9uRHJvcDogdGhpcy5oYW5kbGVBcHBPbkRyb3AsXG4gICAgICB0YWJJbmRleDogMCxcbiAgICAgIG9uS2V5RG93bjogdGhpcy5wcm9wcy5oYW5kbGVLZXlib2FyZEdsb2JhbGx5ID8gdW5kZWZpbmVkIDogdGhpcy5vbktleURvd25cbiAgICB9LCB7XG4gICAgICBjaGlsZHJlbjogX2pzeChBcHBDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgdmFsdWU6IHRoaXNcbiAgICAgIH0sIHtcbiAgICAgICAgY2hpbGRyZW46IF9qc3goQXBwUHJvcHNDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICB2YWx1ZTogdGhpcy5wcm9wc1xuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IF9qc3goRXhjYWxpZHJhd0NvbnRhaW5lckNvbnRleHQuUHJvdmlkZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgdmFsdWU6IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclZhbHVlXG4gICAgICAgICAgfSwge1xuICAgICAgICAgICAgY2hpbGRyZW46IF9qc3goRGV2aWNlQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgIHZhbHVlOiB0aGlzLmRldmljZVxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICBjaGlsZHJlbjogX2pzeChFeGNhbGlkcmF3U2V0QXBwU3RhdGVDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5zZXRBcHBTdGF0ZVxuICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgY2hpbGRyZW46IF9qc3goRXhjYWxpZHJhd0FwcFN0YXRlQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5zdGF0ZVxuICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4cyhFeGNhbGlkcmF3RWxlbWVudHNDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKClcbiAgICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtfanN4cyhFeGNhbGlkcmF3QWN0aW9uTWFuYWdlckNvbnRleHQuUHJvdmlkZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLmFjdGlvbk1hbmFnZXJcbiAgICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBbX2pzeChMYXllclVJLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhczogdGhpcy5jYW52YXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGl2ZUNhbnZhczogdGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcFN0YXRlOiB0aGlzLnN0YXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZXM6IHRoaXMuZmlsZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRBcHBTdGF0ZTogdGhpcy5zZXRBcHBTdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbk1hbmFnZXI6IHRoaXMuYWN0aW9uTWFuYWdlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRzOiB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25Mb2NrVG9nZ2xlOiB0aGlzLnRvZ2dsZUxvY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICBvblBlbk1vZGVUb2dnbGU6IHRoaXMudG9nZ2xlUGVuTW9kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uSGFuZFRvb2xUb2dnbGU6IHRoaXMub25IYW5kVG9vbFRvZ2dsZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhbmdDb2RlOiBnZXRMYW5ndWFnZSgpLmNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJUb3BSaWdodFVJOiByZW5kZXJUb3BSaWdodFVJLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyQ3VzdG9tU3RhdHM6IHJlbmRlckN1c3RvbVN0YXRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvd0V4aXRaZW5Nb2RlQnRuOiB0eXBlb2YgKChfYSA9IHRoaXMucHJvcHMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS56ZW5Nb2RlRW5hYmxlZCkgPT09IFwidW5kZWZpbmVkXCIgJiYgdGhpcy5zdGF0ZS56ZW5Nb2RlRW5hYmxlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIFVJT3B0aW9uczogdGhpcy5wcm9wcy5VSU9wdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkltYWdlQWN0aW9uOiB0aGlzLm9uSW1hZ2VBY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkV4cG9ydEltYWdlOiB0aGlzLm9uRXhwb3J0SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJXZWxjb21lU2NyZWVuOiAhdGhpcy5zdGF0ZS5pc0xvYWRpbmcgJiYgdGhpcy5zdGF0ZS5zaG93V2VsY29tZVNjcmVlbiAmJiB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJzZWxlY3Rpb25cIiAmJiAhdGhpcy5zdGF0ZS56ZW5Nb2RlRW5hYmxlZCAmJiAhdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcHA6IHRoaXNcbiAgICAgICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogdGhpcy5wcm9wcy5jaGlsZHJlblxuICAgICAgICAgICAgICAgICAgICAgIH0pKSwgX2pzeChcImRpdlwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhdy10ZXh0RWRpdG9yQ29udGFpbmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChcImRpdlwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhdy1jb250ZXh0TWVudUNvbnRhaW5lclwiXG4gICAgICAgICAgICAgICAgICAgICAgfSksIF9qc3goXCJkaXZcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXctZXllLWRyb3BwZXItY29udGFpbmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICB9KSwgc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDEgJiYgIXRoaXMuc3RhdGUuY29udGV4dE1lbnUgJiYgdGhpcy5zdGF0ZS5zaG93SHlwZXJsaW5rUG9wdXAgJiYgX2pzeChIeXBlcmxpbmssIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHNlbGVjdGVkRWxlbWVudHNbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRBcHBTdGF0ZTogdGhpcy5zZXRBcHBTdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uTGlua09wZW46IHRoaXMucHJvcHMub25MaW5rT3BlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRvYXN0OiB0aGlzLnNldFRvYXN0XG4gICAgICAgICAgICAgICAgICAgICAgfSwgc2VsZWN0ZWRFbGVtZW50c1swXS5pZCksIHRoaXMuc3RhdGUudG9hc3QgIT09IG51bGwgJiYgX2pzeChUb2FzdCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogdGhpcy5zdGF0ZS50b2FzdC5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbG9zZTogKCkgPT4gdGhpcy5zZXRUb2FzdChudWxsKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLnN0YXRlLnRvYXN0LmR1cmF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2FibGU6IHRoaXMuc3RhdGUudG9hc3QuY2xvc2FibGVcbiAgICAgICAgICAgICAgICAgICAgICB9KSwgdGhpcy5zdGF0ZS5jb250ZXh0TWVudSAmJiBfanN4KENvbnRleHRNZW51LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtczogdGhpcy5zdGF0ZS5jb250ZXh0TWVudS5pdGVtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcDogdGhpcy5zdGF0ZS5jb250ZXh0TWVudS50b3AsXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0OiB0aGlzLnN0YXRlLmNvbnRleHRNZW51LmxlZnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb25NYW5hZ2VyOiB0aGlzLmFjdGlvbk1hbmFnZXJcbiAgICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChTdGF0aWNDYW52YXMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhczogdGhpcy5jYW52YXMsXG4gICAgICAgICAgICAgICAgICAgICAgICByYzogdGhpcy5yYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRzOiBjYW52YXNFbGVtZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpc2libGVFbGVtZW50czogdmlzaWJsZUVsZW1lbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmVyc2lvbk5vbmNlOiB2ZXJzaW9uTm9uY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb25Ob25jZTogKF9iID0gdGhpcy5zdGF0ZS5zZWxlY3Rpb25FbGVtZW50KSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IudmVyc2lvbk5vbmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU6IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwU3RhdGU6IHRoaXMuc3RhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJDb25maWc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1hZ2VDYWNoZTogdGhpcy5pbWFnZUNhY2hlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBpc0V4cG9ydGluZzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckdyaWQ6IHRydWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChJbnRlcmFjdGl2ZUNhbnZhcywge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyUmVmOiB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYsXG4gICAgICAgICAgICAgICAgICAgICAgICBjYW52YXM6IHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50czogY2FudmFzRWxlbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmxlRWxlbWVudHM6IHZpc2libGVFbGVtZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudHM6IHNlbGVjdGVkRWxlbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uTm9uY2U6IHZlcnNpb25Ob25jZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbk5vbmNlOiAoX2MgPSB0aGlzLnN0YXRlLnNlbGVjdGlvbkVsZW1lbnQpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy52ZXJzaW9uTm9uY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZTogd2luZG93LmRldmljZVBpeGVsUmF0aW8sXG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBTdGF0ZTogdGhpcy5zdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckludGVyYWN0aXZlU2NlbmVDYWxsYmFjazogdGhpcy5yZW5kZXJJbnRlcmFjdGl2ZVNjZW5lQ2FsbGJhY2ssXG4gICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVDYW52YXNSZWY6IHRoaXMuaGFuZGxlSW50ZXJhY3RpdmVDYW52YXNSZWYsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNvbnRleHRNZW51OiB0aGlzLmhhbmRsZUNhbnZhc0NvbnRleHRNZW51LFxuICAgICAgICAgICAgICAgICAgICAgICAgb25Qb2ludGVyTW92ZTogdGhpcy5oYW5kbGVDYW52YXNQb2ludGVyTW92ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uUG9pbnRlclVwOiB0aGlzLmhhbmRsZUNhbnZhc1BvaW50ZXJVcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uUG9pbnRlckNhbmNlbDogdGhpcy5yZW1vdmVQb2ludGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25Ub3VjaE1vdmU6IHRoaXMuaGFuZGxlVG91Y2hNb3ZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25Qb2ludGVyRG93bjogdGhpcy5oYW5kbGVDYW52YXNQb2ludGVyRG93bixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uRG91YmxlQ2xpY2s6IHRoaXMuaGFuZGxlQ2FudmFzRG91YmxlQ2xpY2tcbiAgICAgICAgICAgICAgICAgICAgICB9KSwgdGhpcy5yZW5kZXJGcmFtZU5hbWVzKCldXG4gICAgICAgICAgICAgICAgICAgIH0pKSwgdGhpcy5yZW5kZXJFbWJlZGRhYmxlcygpXVxuICAgICAgICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgfSkpXG4gICAgICAgICAgfSkpXG4gICAgICAgIH0pKVxuICAgICAgfSkpXG4gICAgfSkpO1xuICB9XG5cbiAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgdmFyIF9hLCBfYjtcblxuICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICB0aGlzLnVubW91bnRlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyVmFsdWUuY29udGFpbmVyID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQ7XG5cbiAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gRU5WLlRFU1QgfHwgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09IFwicHJvZHVjdGlvblwiKSB7XG4gICAgICAgIGNvbnN0IHNldFN0YXRlID0gdGhpcy5zZXRTdGF0ZS5iaW5kKHRoaXMpO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh3aW5kb3cuaCwge1xuICAgICAgICAgIHN0YXRlOiB7XG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBzZXRTdGF0ZToge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6ICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLnNldFN0YXRlKC4uLmFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgYXBwOiB7XG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgICB2YWx1ZTogdGhpc1xuICAgICAgICAgIH0sXG4gICAgICAgICAgaGlzdG9yeToge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IHRoaXMuaGlzdG9yeVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2NlbmUuYWRkQ2FsbGJhY2sodGhpcy5vblNjZW5lVXBkYXRlZCk7XG4gICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXJzKCk7XG5cbiAgICAgIGlmICh0aGlzLnByb3BzLmF1dG9Gb2N1cyAmJiB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkge1xuICAgICAgICB0aGlzLmZvY3VzQ29udGFpbmVyKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCAmJiAvLyBib3VuZGluZyByZWN0cyBkb24ndCB3b3JrIGluIHRlc3RzIHNvIHVwZGF0aW5nXG4gICAgICAvLyB0aGUgc3RhdGUgb24gaW5pdCB3b3VsZCByZXN1bHQgaW4gbWFraW5nIHRoZSB0ZXN0IGVudmlybyBydW5cbiAgICAgIC8vIGluIG1vYmlsZSBicmVha3BvaW50ICgwIHdpZHRoL2hlaWdodCksIG1ha2luZyBldmVyeXRoaW5nIGZhaWxcbiAgICAgICFpc1Rlc3RFbnYoKSkge1xuICAgICAgICB0aGlzLnJlZnJlc2hEZXZpY2VTdGF0ZSh0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChcIlJlc2l6ZU9ic2VydmVyXCIgaW4gd2luZG93ICYmICgoX2EgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jdXJyZW50KSkge1xuICAgICAgICB0aGlzLnJlc2l6ZU9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKCgpID0+IHtcbiAgICAgICAgICAvLyByZWNvbXB1dGUgZGV2aWNlIGRpbWVuc2lvbnMgc3RhdGVcbiAgICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgICB0aGlzLnJlZnJlc2hEZXZpY2VTdGF0ZSh0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCk7IC8vIHJlZnJlc2ggb2Zmc2V0c1xuICAgICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgICAgICAgdGhpcy51cGRhdGVET01SZWN0KCk7XG4gICAgICAgIH0pO1xuICAgICAgICAoX2IgPSB0aGlzLnJlc2l6ZU9ic2VydmVyKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iub2JzZXJ2ZSh0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCk7XG4gICAgICB9IGVsc2UgaWYgKHdpbmRvdy5tYXRjaE1lZGlhKSB7XG4gICAgICAgIGNvbnN0IG1kU2NyZWVuUXVlcnkgPSB3aW5kb3cubWF0Y2hNZWRpYShgKG1heC13aWR0aDogJHtNUV9NQVhfV0lEVEhfUE9SVFJBSVR9cHgpLCAobWF4LWhlaWdodDogJHtNUV9NQVhfSEVJR0hUX0xBTkRTQ0FQRX1weCkgYW5kIChtYXgtd2lkdGg6ICR7TVFfTUFYX1dJRFRIX0xBTkRTQ0FQRX1weClgKTtcbiAgICAgICAgY29uc3Qgc21TY3JlZW5RdWVyeSA9IHdpbmRvdy5tYXRjaE1lZGlhKGAobWF4LXdpZHRoOiAke01RX1NNX01BWF9XSURUSH1weClgKTtcbiAgICAgICAgY29uc3QgY2FuRGV2aWNlRml0U2lkZWJhck1lZGlhUXVlcnkgPSB3aW5kb3cubWF0Y2hNZWRpYShgKG1pbi13aWR0aDogJHsvLyBOT1RFIHRoaXMgd29uJ3QgdXBkYXRlIGlmIGEgZGlmZmVyZW50IGJyZWFrcG9pbnQgaXMgc3VwcGxpZWRcbiAgICAgICAgLy8gYWZ0ZXIgbW91bnRcbiAgICAgICAgdGhpcy5wcm9wcy5VSU9wdGlvbnMuZG9ja2VkU2lkZWJhckJyZWFrcG9pbnQgIT0gbnVsbCA/IHRoaXMucHJvcHMuVUlPcHRpb25zLmRvY2tlZFNpZGViYXJCcmVha3BvaW50IDogTVFfUklHSFRfU0lERUJBUl9NSU5fV0lEVEh9cHgpYCk7XG5cbiAgICAgICAgY29uc3QgaGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICB0aGlzLmRldmljZSA9IHVwZGF0ZU9iamVjdCh0aGlzLmRldmljZSwge1xuICAgICAgICAgICAgaXNTbVNjcmVlbjogc21TY3JlZW5RdWVyeS5tYXRjaGVzLFxuICAgICAgICAgICAgaXNNb2JpbGU6IG1kU2NyZWVuUXVlcnkubWF0Y2hlcyxcbiAgICAgICAgICAgIGNhbkRldmljZUZpdFNpZGViYXI6IGNhbkRldmljZUZpdFNpZGViYXJNZWRpYVF1ZXJ5Lm1hdGNoZXNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBtZFNjcmVlblF1ZXJ5LmFkZExpc3RlbmVyKGhhbmRsZXIpO1xuXG4gICAgICAgIHRoaXMuZGV0YWNoSXNNb2JpbGVNcUhhbmRsZXIgPSAoKSA9PiBtZFNjcmVlblF1ZXJ5LnJlbW92ZUxpc3RlbmVyKGhhbmRsZXIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzZWFyY2hQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc2xpY2UoMSkpO1xuXG4gICAgICBpZiAoc2VhcmNoUGFyYW1zLmhhcyhcIndlYi1zaGFyZS10YXJnZXRcIikpIHtcbiAgICAgICAgLy8gT2J0YWluIGEgZmlsZSB0aGF0IHdhcyBzaGFyZWQgdmlhIHRoZSBXZWIgU2hhcmUgVGFyZ2V0IEFQSS5cbiAgICAgICAgdGhpcy5yZXN0b3JlRmlsZUZyb21TaGFyZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy51cGRhdGVET01SZWN0KHRoaXMuaW5pdGlhbGl6ZVNjZW5lKTtcbiAgICAgIH0gLy8gbm90ZSB0aGF0IHRoaXMgY2hlY2sgc2VlbXMgdG8gYWx3YXlzIHBhc3MgaW4gbG9jYWxob3N0XG5cblxuICAgICAgaWYgKGlzQnJhdmUoKSAmJiAhaXNNZWFzdXJlVGV4dFN1cHBvcnRlZCgpKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGVycm9yTWVzc2FnZTogX2pzeChCcmF2ZU1lYXN1cmVUZXh0RXJyb3IsIHt9KVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgIHZhciBfYTtcblxuICAgIHRoaXMucmVuZGVyZXIuZGVzdHJveSgpO1xuICAgIHRoaXMuc2NlbmUgPSBuZXcgU2NlbmUoKTtcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFJlbmRlcmVyKHRoaXMuc2NlbmUpO1xuICAgIHRoaXMuZmlsZXMgPSB7fTtcbiAgICB0aGlzLmltYWdlQ2FjaGUuY2xlYXIoKTtcbiAgICAoX2EgPSB0aGlzLnJlc2l6ZU9ic2VydmVyKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZGlzY29ubmVjdCgpO1xuICAgIHRoaXMudW5tb3VudGVkID0gdHJ1ZTtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XG4gICAgdGhpcy5zY2VuZS5kZXN0cm95KCk7XG4gICAgdGhpcy5saWJyYXJ5LmRlc3Ryb3koKTtcbiAgICBTaGFwZUNhY2hlLmRlc3Ryb3koKTtcbiAgICBjbGVhclRpbWVvdXQodG91Y2hUaW1lb3V0KTtcbiAgICBpc1NvbWVFbGVtZW50U2VsZWN0ZWQuY2xlYXJDYWNoZSgpO1xuICAgIHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMuY2xlYXJDYWNoZSgpO1xuICAgIHRvdWNoVGltZW91dCA9IDA7XG4gIH1cblxuICByZW1vdmVFdmVudExpc3RlbmVycygpIHtcbiAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lO1xuXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCB0aGlzLnJlbW92ZVBvaW50ZXIpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuQ09QWSwgdGhpcy5vbkNvcHkpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUEFTVEUsIHRoaXMucGFzdGVGcm9tQ2xpcGJvYXJkKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkNVVCwgdGhpcy5vbkN1dCk7XG4gICAgKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULldIRUVMLCB0aGlzLm9uV2hlZWwpO1xuICAgIChfYiA9IHRoaXMubmVhcmVzdFNjcm9sbGFibGVDb250YWluZXIpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlNDUk9MTCwgdGhpcy5vblNjcm9sbCk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5LRVlET1dOLCB0aGlzLm9uS2V5RG93biwgZmFsc2UpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuTU9VU0VfTU9WRSwgdGhpcy51cGRhdGVDdXJyZW50Q3Vyc29yUG9zaXRpb24sIGZhbHNlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULktFWVVQLCB0aGlzLm9uS2V5VXApO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlJFU0laRSwgdGhpcy5vblJlc2l6ZSwgZmFsc2UpO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlVOTE9BRCwgdGhpcy5vblVubG9hZCwgZmFsc2UpO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkJMVVIsIHRoaXMub25CbHVyLCBmYWxzZSk7XG4gICAgKF9jID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkRSQUdfT1ZFUiwgdGhpcy5kaXNhYmxlRXZlbnQsIGZhbHNlKTtcbiAgICAoX2QgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuRFJPUCwgdGhpcy5kaXNhYmxlRXZlbnQsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkdFU1RVUkVfU1RBUlQsIHRoaXMub25HZXN0dXJlU3RhcnQsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkdFU1RVUkVfQ0hBTkdFLCB0aGlzLm9uR2VzdHVyZUNoYW5nZSwgZmFsc2UpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuR0VTVFVSRV9FTkQsIHRoaXMub25HZXN0dXJlRW5kLCBmYWxzZSk7XG4gICAgKF9lID0gdGhpcy5kZXRhY2hJc01vYmlsZU1xSGFuZGxlcikgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLmNhbGwodGhpcyk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuTUVTU0FHRSwgdGhpcy5vbldpbmRvd01lc3NhZ2UsIGZhbHNlKTtcbiAgfVxuXG4gIGFkZEV2ZW50TGlzdGVuZXJzKCkge1xuICAgIHZhciBfYSwgX2IsIF9jLCBfZCwgX2U7XG5cbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuTUVTU0FHRSwgdGhpcy5vbldpbmRvd01lc3NhZ2UsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIHRoaXMucmVtb3ZlUG9pbnRlcik7IC8vICMzNTUzXG5cbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULkNPUFksIHRoaXMub25Db3B5KTtcbiAgICAoX2EgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuV0hFRUwsIHRoaXMub25XaGVlbCwge1xuICAgICAgcGFzc2l2ZTogZmFsc2VcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLnByb3BzLmhhbmRsZUtleWJvYXJkR2xvYmFsbHkpIHtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZRE9XTiwgdGhpcy5vbktleURvd24sIGZhbHNlKTtcbiAgICB9XG5cbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULktFWVVQLCB0aGlzLm9uS2V5VXAsIHtcbiAgICAgIHBhc3NpdmU6IHRydWVcbiAgICB9KTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULk1PVVNFX01PVkUsIHRoaXMudXBkYXRlQ3VycmVudEN1cnNvclBvc2l0aW9uKTsgLy8gcmVyZW5kZXIgdGV4dCBlbGVtZW50cyBvbiBmb250IGxvYWQgdG8gZml4ICM2MzcgJiYgIzE1NTNcblxuICAgIChfYyA9IChfYiA9IGRvY3VtZW50LmZvbnRzKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuYWRkRXZlbnRMaXN0ZW5lcikgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLmNhbGwoX2IsIFwibG9hZGluZ2RvbmVcIiwgZXZlbnQgPT4ge1xuICAgICAgY29uc3QgbG9hZGVkRm9udEZhY2VzID0gZXZlbnQuZm9udGZhY2VzO1xuICAgICAgdGhpcy5mb250cy5vbkZvbnRzTG9hZGVkKGxvYWRlZEZvbnRGYWNlcyk7XG4gICAgfSk7IC8vIFNhZmFyaS1vbmx5IGRlc2t0b3AgcGluY2ggem9vbVxuXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5HRVNUVVJFX1NUQVJULCB0aGlzLm9uR2VzdHVyZVN0YXJ0LCBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5HRVNUVVJFX0NIQU5HRSwgdGhpcy5vbkdlc3R1cmVDaGFuZ2UsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULkdFU1RVUkVfRU5ELCB0aGlzLm9uR2VzdHVyZUVuZCwgZmFsc2UpO1xuXG4gICAgaWYgKHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5QQVNURSwgdGhpcy5wYXN0ZUZyb21DbGlwYm9hcmQpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuQ1VULCB0aGlzLm9uQ3V0KTtcblxuICAgIGlmICh0aGlzLnByb3BzLmRldGVjdFNjcm9sbCkge1xuICAgICAgdGhpcy5uZWFyZXN0U2Nyb2xsYWJsZUNvbnRhaW5lciA9IGdldE5lYXJlc3RTY3JvbGxhYmxlQ29udGFpbmVyKHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KTtcbiAgICAgIHRoaXMubmVhcmVzdFNjcm9sbGFibGVDb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5TQ1JPTEwsIHRoaXMub25TY3JvbGwpO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlJFU0laRSwgdGhpcy5vblJlc2l6ZSwgZmFsc2UpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlVOTE9BRCwgdGhpcy5vblVubG9hZCwgZmFsc2UpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULkJMVVIsIHRoaXMub25CbHVyLCBmYWxzZSk7XG4gICAgKF9kID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULkRSQUdfT1ZFUiwgdGhpcy5kaXNhYmxlRXZlbnQsIGZhbHNlKTtcbiAgICAoX2UgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuRFJPUCwgdGhpcy5kaXNhYmxlRXZlbnQsIGZhbHNlKTtcbiAgfVxuXG4gIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHMsIHByZXZTdGF0ZSkge1xuICAgIHZhciBfYSwgX2IsIF9jLCBfZCwgX2UsIF9mO1xuXG4gICAgdGhpcy51cGRhdGVFbWJlZGRhYmxlcygpO1xuXG4gICAgaWYgKCF0aGlzLnN0YXRlLnNob3dXZWxjb21lU2NyZWVuICYmICF0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLmxlbmd0aCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHNob3dXZWxjb21lU2NyZWVuOiB0cnVlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQgJiYgcHJldlByb3BzLlVJT3B0aW9ucy5kb2NrZWRTaWRlYmFyQnJlYWtwb2ludCAhPT0gdGhpcy5wcm9wcy5VSU9wdGlvbnMuZG9ja2VkU2lkZWJhckJyZWFrcG9pbnQpIHtcbiAgICAgIHRoaXMucmVmcmVzaERldmljZVN0YXRlKHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KTtcbiAgICB9XG5cbiAgICBpZiAocHJldlN0YXRlLnNjcm9sbFggIT09IHRoaXMuc3RhdGUuc2Nyb2xsWCB8fCBwcmV2U3RhdGUuc2Nyb2xsWSAhPT0gdGhpcy5zdGF0ZS5zY3JvbGxZKSB7XG4gICAgICAoX2IgPSAoX2EgPSB0aGlzLnByb3BzKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Eub25TY3JvbGxDaGFuZ2UpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCB0aGlzLnN0YXRlLnNjcm9sbFgsIHRoaXMuc3RhdGUuc2Nyb2xsWSk7XG4gICAgfVxuXG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKS5sZW5ndGggJiYgaXNFcmFzZXJBY3RpdmUodGhpcy5zdGF0ZSkpIHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBhY3RpdmVUb29sOiB1cGRhdGVBY3RpdmVUb29sKHRoaXMuc3RhdGUsIHtcbiAgICAgICAgICB0eXBlOiBcInNlbGVjdGlvblwiXG4gICAgICAgIH0pXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiZXJhc2VyXCIgJiYgcHJldlN0YXRlLnRoZW1lICE9PSB0aGlzLnN0YXRlLnRoZW1lKSB7XG4gICAgICBzZXRFcmFzZXJDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZS50aGVtZSk7XG4gICAgfSAvLyBIaWRlIGh5cGVybGluayBwb3B1cCBpZiBzaG93biB3aGVuIGVsZW1lbnQgdHlwZSBpcyBub3Qgc2VsZWN0aW9uXG5cblxuICAgIGlmIChwcmV2U3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInNlbGVjdGlvblwiICYmIHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcInNlbGVjdGlvblwiICYmIHRoaXMuc3RhdGUuc2hvd0h5cGVybGlua1BvcHVwKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc2hvd0h5cGVybGlua1BvcHVwOiBmYWxzZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHByZXZQcm9wcy5sYW5nQ29kZSAhPT0gdGhpcy5wcm9wcy5sYW5nQ29kZSkge1xuICAgICAgdGhpcy51cGRhdGVMYW5ndWFnZSgpO1xuICAgIH1cblxuICAgIGlmIChwcmV2UHJvcHMudmlld01vZGVFbmFibGVkICE9PSB0aGlzLnByb3BzLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHZpZXdNb2RlRW5hYmxlZDogISF0aGlzLnByb3BzLnZpZXdNb2RlRW5hYmxlZFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHByZXZTdGF0ZS52aWV3TW9kZUVuYWJsZWQgIT09IHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICB0aGlzLmRlc2VsZWN0RWxlbWVudHMoKTtcbiAgICB9XG5cbiAgICBpZiAocHJldlByb3BzLnplbk1vZGVFbmFibGVkICE9PSB0aGlzLnByb3BzLnplbk1vZGVFbmFibGVkKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgemVuTW9kZUVuYWJsZWQ6ICEhdGhpcy5wcm9wcy56ZW5Nb2RlRW5hYmxlZFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHByZXZQcm9wcy50aGVtZSAhPT0gdGhpcy5wcm9wcy50aGVtZSAmJiB0aGlzLnByb3BzLnRoZW1lKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgdGhlbWU6IHRoaXMucHJvcHMudGhlbWVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChwcmV2UHJvcHMuZ3JpZE1vZGVFbmFibGVkICE9PSB0aGlzLnByb3BzLmdyaWRNb2RlRW5hYmxlZCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGdyaWRTaXplOiB0aGlzLnByb3BzLmdyaWRNb2RlRW5hYmxlZCA/IEdSSURfU0laRSA6IG51bGxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnByb3BzLm5hbWUgJiYgcHJldlByb3BzLm5hbWUgIT09IHRoaXMucHJvcHMubmFtZSkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIG5hbWU6IHRoaXMucHJvcHMubmFtZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgKF9jID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5jbGFzc0xpc3QudG9nZ2xlKFwidGhlbWUtLWRhcmtcIiwgdGhpcy5zdGF0ZS50aGVtZSA9PT0gXCJkYXJrXCIpO1xuXG4gICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgJiYgIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW3RoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQuZWxlbWVudElkXSkge1xuICAgICAgLy8gZGVmZXIgc28gdGhhdCB0aGUgY29tbWl0VG9IaXN0b3J5IGZsYWcgaXNuJ3QgcmVzZXQgdmlhIGN1cnJlbnQgdXBkYXRlXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgLy8gZXhlY3V0ZSBvbmx5IGlmIHRoZSBjb25kaXRpb24gc3RpbGwgaG9sZHMgd2hlbiB0aGUgZGVmZXJyZWQgY2FsbGJhY2tcbiAgICAgICAgLy8gZXhlY3V0ZXMgKGl0IGNhbiBiZSBzY2hlZHVsZWQgbXVsdGlwbGUgdGltZXMgZGVwZW5kaW5nIG9uIGhvd1xuICAgICAgICAvLyBtYW55IHRpbWVzIHRoZSBjb21wb25lbnQgcmVuZGVycylcbiAgICAgICAgdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCAmJiB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICB9KTtcbiAgICB9IC8vIGZhaWxzYWZlIGluIGNhc2UgdGhlIHN0YXRlIGlzIGJlaW5nIHVwZGF0ZWQgaW4gaW5jb3JyZWN0IG9yZGVyIHJlc3VsdGluZ1xuICAgIC8vIGluIHRoZSBlZGl0aW5nRWxlbWVudCBiZWluZyBub3cgYSBkZWxldGVkIGVsZW1lbnRcblxuXG4gICAgaWYgKChfZCA9IHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5pc0RlbGV0ZWQpIHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBlZGl0aW5nRWxlbWVudDogbnVsbFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50ICYmICF0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1t0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudC5lbGVtZW50SWRdKSB7XG4gICAgICAvLyBUbyBtYWtlIHN1cmUgYHNlbGVjdGVkTGluZWFyRWxlbWVudGAgaXMgaW4gc3luYyB3aXRoIGBzZWxlY3RlZEVsZW1lbnRJZHNgLCBob3dldmVyIHRoaXMgc2hvdWxkbid0IGJlIG5lZWRlZCBvbmNlXG4gICAgICAvLyB3ZSBoYXZlIGEgc2luZ2xlIEFQSSB0byB1cGRhdGUgYHNlbGVjdGVkRWxlbWVudElkc2BcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IG51bGxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHtcbiAgICAgIG11bHRpRWxlbWVudFxuICAgIH0gPSBwcmV2U3RhdGU7XG5cbiAgICBpZiAocHJldlN0YXRlLmFjdGl2ZVRvb2wgIT09IHRoaXMuc3RhdGUuYWN0aXZlVG9vbCAmJiBtdWx0aUVsZW1lbnQgIT0gbnVsbCAmJiBpc0JpbmRpbmdFbmFibGVkKHRoaXMuc3RhdGUpICYmIGlzQmluZGluZ0VsZW1lbnQobXVsdGlFbGVtZW50LCBmYWxzZSkpIHtcbiAgICAgIG1heWJlQmluZExpbmVhckVsZW1lbnQobXVsdGlFbGVtZW50LCB0aGlzLnN0YXRlLCB0aGlzLnNjZW5lLCB0dXBsZVRvQ29vcnMoTGluZWFyRWxlbWVudEVkaXRvci5nZXRQb2ludEF0SW5kZXhHbG9iYWxDb29yZGluYXRlcyhtdWx0aUVsZW1lbnQsIC0xKSkpO1xuICAgIH1cblxuICAgIHRoaXMuaGlzdG9yeS5yZWNvcmQodGhpcy5zdGF0ZSwgdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSk7IC8vIERvIG5vdCBub3RpZnkgY29uc3VtZXJzIGlmIHdlJ3JlIHN0aWxsIGxvYWRpbmcgdGhlIHNjZW5lLiBBbW9uZyBvdGhlclxuICAgIC8vIHBvdGVudGlhbCBpc3N1ZXMsIHRoaXMgZml4ZXMgYSBjYXNlIHdoZXJlIHRoZSB0YWIgaXNuJ3QgZm9jdXNlZCBkdXJpbmdcbiAgICAvLyBpbml0LCB3aGljaCB3b3VsZCB0cmlnZ2VyIG9uQ2hhbmdlIHdpdGggZW1wdHkgZWxlbWVudHMsIHdoaWNoIHdvdWxkIHRoZW5cbiAgICAvLyBvdmVycmlkZSB3aGF0ZXZlciBpcyBpbiBsb2NhbFN0b3JhZ2UgY3VycmVudGx5LlxuXG4gICAgaWYgKCF0aGlzLnN0YXRlLmlzTG9hZGluZykge1xuICAgICAgKF9mID0gKF9lID0gdGhpcy5wcm9wcykub25DaGFuZ2UpID09PSBudWxsIHx8IF9mID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZi5jYWxsKF9lLCB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCB0aGlzLnN0YXRlLCB0aGlzLmZpbGVzKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgcmVzZXRUYXBUd2ljZSgpIHtcbiAgICBkaWRUYXBUd2ljZSA9IGZhbHNlO1xuICB9XG5cbiAgYWRkVGV4dEZyb21QYXN0ZSh0ZXh0LCBpc1BsYWluUGFzdGUgPSBmYWxzZSkge1xuICAgIGNvbnN0IHtcbiAgICAgIHgsXG4gICAgICB5XG4gICAgfSA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICBjbGllbnRYOiB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLngsXG4gICAgICBjbGllbnRZOiB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLnlcbiAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICBjb25zdCB0ZXh0RWxlbWVudFByb3BzID0ge1xuICAgICAgeCxcbiAgICAgIHksXG4gICAgICBzdHJva2VDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZUNvbG9yLFxuICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtQmFja2dyb3VuZENvbG9yLFxuICAgICAgZmlsbFN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtRmlsbFN0eWxlLFxuICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VXaWR0aCxcbiAgICAgIHN0cm9rZVN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlU3R5bGUsXG4gICAgICByb3VuZG5lc3M6IG51bGwsXG4gICAgICByb3VnaG5lc3M6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Sb3VnaG5lc3MsXG4gICAgICBvcGFjaXR5OiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtT3BhY2l0eSxcbiAgICAgIHRleHQsXG4gICAgICBmb250U2l6ZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZvbnRTaXplLFxuICAgICAgZm9udEZhbWlseTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZvbnRGYW1pbHksXG4gICAgICB0ZXh0QWxpZ246IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1UZXh0QWxpZ24sXG4gICAgICB2ZXJ0aWNhbEFsaWduOiBERUZBVUxUX1ZFUlRJQ0FMX0FMSUdOLFxuICAgICAgbG9ja2VkOiBmYWxzZVxuICAgIH07XG4gICAgY29uc3QgTElORV9HQVAgPSAxMDtcbiAgICBsZXQgY3VycmVudFkgPSB5O1xuICAgIGNvbnN0IGxpbmVzID0gaXNQbGFpblBhc3RlID8gW3RleHRdIDogdGV4dC5zcGxpdChcIlxcblwiKTtcbiAgICBjb25zdCB0ZXh0RWxlbWVudHMgPSBsaW5lcy5yZWR1Y2UoKGFjYywgbGluZSwgaWR4KSA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIGNvbnN0IHRleHQgPSBsaW5lLnRyaW0oKTtcbiAgICAgIGNvbnN0IGxpbmVIZWlnaHQgPSBnZXREZWZhdWx0TGluZUhlaWdodCh0ZXh0RWxlbWVudFByb3BzLmZvbnRGYW1pbHkpO1xuXG4gICAgICBpZiAodGV4dC5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgdG9wTGF5ZXJGcmFtZSA9IHRoaXMuZ2V0VG9wTGF5ZXJGcmFtZUF0U2NlbmVDb29yZHMoe1xuICAgICAgICAgIHgsXG4gICAgICAgICAgeTogY3VycmVudFlcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBuZXdUZXh0RWxlbWVudChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRleHRFbGVtZW50UHJvcHMpLCB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5OiBjdXJyZW50WSxcbiAgICAgICAgICB0ZXh0LFxuICAgICAgICAgIGxpbmVIZWlnaHQsXG4gICAgICAgICAgZnJhbWVJZDogdG9wTGF5ZXJGcmFtZSA/IHRvcExheWVyRnJhbWUuaWQgOiBudWxsXG4gICAgICAgIH0pKTtcbiAgICAgICAgYWNjLnB1c2goZWxlbWVudCk7XG4gICAgICAgIGN1cnJlbnRZICs9IGVsZW1lbnQuaGVpZ2h0ICsgTElORV9HQVA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwcmV2TGluZSA9IChfYSA9IGxpbmVzW2lkeCAtIDFdKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudHJpbSgpOyAvLyBhZGQgcGFyYWdyYXBoIG9ubHkgaWYgcHJldmlvdXMgbGluZSB3YXMgbm90IGVtcHR5LCBJT1cgZG9uJ3QgYWRkXG4gICAgICAgIC8vIG1vcmUgdGhhbiBvbmUgZW1wdHkgbGluZVxuXG4gICAgICAgIGlmIChwcmV2TGluZSkge1xuICAgICAgICAgIGN1cnJlbnRZICs9IGdldExpbmVIZWlnaHRJblB4KHRleHRFbGVtZW50UHJvcHMuZm9udFNpemUsIGxpbmVIZWlnaHQpICsgTElORV9HQVA7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCBbXSk7XG5cbiAgICBpZiAodGV4dEVsZW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGZyYW1lSWQgPSB0ZXh0RWxlbWVudHNbMF0uZnJhbWVJZDtcblxuICAgIGlmIChmcmFtZUlkKSB7XG4gICAgICB0aGlzLnNjZW5lLmluc2VydEVsZW1lbnRzQXRJbmRleCh0ZXh0RWxlbWVudHMsIHRoaXMuc2NlbmUuZ2V0RWxlbWVudEluZGV4KGZyYW1lSWQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoWy4uLnRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIC4uLnRleHRFbGVtZW50c10pO1xuICAgIH1cblxuICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyhPYmplY3QuZnJvbUVudHJpZXModGV4dEVsZW1lbnRzLm1hcChlbCA9PiBbZWwuaWQsIHRydWVdKSksIHRoaXMuc3RhdGUpXG4gICAgfSk7XG5cbiAgICBpZiAoIWlzUGxhaW5QYXN0ZSAmJiB0ZXh0RWxlbWVudHMubGVuZ3RoID4gMSAmJiBQTEFJTl9QQVNURV9UT0FTVF9TSE9XTiA9PT0gZmFsc2UgJiYgIXRoaXMuZGV2aWNlLmlzTW9iaWxlKSB7XG4gICAgICB0aGlzLnNldFRvYXN0KHtcbiAgICAgICAgbWVzc2FnZTogdChcInRvYXN0LnBhc3RlQXNTaW5nbGVFbGVtZW50XCIsIHtcbiAgICAgICAgICBzaG9ydGN1dDogZ2V0U2hvcnRjdXRLZXkoXCJDdHJsT3JDbWQrU2hpZnQrVlwiKVxuICAgICAgICB9KSxcbiAgICAgICAgZHVyYXRpb246IDUwMDBcbiAgICAgIH0pO1xuICAgICAgUExBSU5fUEFTVEVfVE9BU1RfU0hPV04gPSB0cnVlO1xuICAgIH1cblxuICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgfVxuXG4gIGhhbmRsZVRleHRXeXNpd3lnKGVsZW1lbnQsIHtcbiAgICBpc0V4aXN0aW5nRWxlbWVudCA9IGZhbHNlXG4gIH0pIHtcbiAgICBjb25zdCB1cGRhdGVFbGVtZW50ID0gKHRleHQsIG9yaWdpbmFsVGV4dCwgaXNEZWxldGVkKSA9PiB7XG4gICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhbLi4udGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5tYXAoX2VsZW1lbnQgPT4ge1xuICAgICAgICBpZiAoX2VsZW1lbnQuaWQgPT09IGVsZW1lbnQuaWQgJiYgaXNUZXh0RWxlbWVudChfZWxlbWVudCkpIHtcbiAgICAgICAgICByZXR1cm4gdXBkYXRlVGV4dEVsZW1lbnQoX2VsZW1lbnQsIHtcbiAgICAgICAgICAgIHRleHQsXG4gICAgICAgICAgICBpc0RlbGV0ZWQsXG4gICAgICAgICAgICBvcmlnaW5hbFRleHRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBfZWxlbWVudDtcbiAgICAgIH0pXSk7XG4gICAgfTtcblxuICAgIHRleHRXeXNpd3lnKHtcbiAgICAgIGlkOiBlbGVtZW50LmlkLFxuICAgICAgY2FudmFzOiB0aGlzLmNhbnZhcyxcbiAgICAgIGdldFZpZXdwb3J0Q29vcmRzOiAoeCwgeSkgPT4ge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeDogdmlld3BvcnRYLFxuICAgICAgICAgIHk6IHZpZXdwb3J0WVxuICAgICAgICB9ID0gc2NlbmVDb29yZHNUb1ZpZXdwb3J0Q29vcmRzKHtcbiAgICAgICAgICBzY2VuZVg6IHgsXG4gICAgICAgICAgc2NlbmVZOiB5XG4gICAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgICByZXR1cm4gW3ZpZXdwb3J0WCAtIHRoaXMuc3RhdGUub2Zmc2V0TGVmdCwgdmlld3BvcnRZIC0gdGhpcy5zdGF0ZS5vZmZzZXRUb3BdO1xuICAgICAgfSxcbiAgICAgIG9uQ2hhbmdlOiB3aXRoQmF0Y2hlZFVwZGF0ZXModGV4dCA9PiB7XG4gICAgICAgIHVwZGF0ZUVsZW1lbnQodGV4dCwgdGV4dCwgZmFsc2UpO1xuXG4gICAgICAgIGlmIChpc05vbkRlbGV0ZWRFbGVtZW50KGVsZW1lbnQpKSB7XG4gICAgICAgICAgdXBkYXRlQm91bmRFbGVtZW50cyhlbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfSksXG4gICAgICBvblN1Ym1pdDogd2l0aEJhdGNoZWRVcGRhdGVzKCh7XG4gICAgICAgIHRleHQsXG4gICAgICAgIHZpYUtleWJvYXJkLFxuICAgICAgICBvcmlnaW5hbFRleHRcbiAgICAgIH0pID0+IHtcbiAgICAgICAgY29uc3QgaXNEZWxldGVkID0gIXRleHQudHJpbSgpO1xuICAgICAgICB1cGRhdGVFbGVtZW50KHRleHQsIG9yaWdpbmFsVGV4dCwgaXNEZWxldGVkKTsgLy8gc2VsZWN0IHRoZSBjcmVhdGVkIHRleHQgZWxlbWVudCBvbmx5IGlmIHN1Ym1pdHRpbmcgdmlhIGtleWJvYXJkXG4gICAgICAgIC8vICh3aGVuIHN1Ym1pdHRpbmcgdmlhIGNsaWNrIGl0IHNob3VsZCBhY3QgYXMgc2lnbmFsIHRvIGRlc2VsZWN0KVxuXG4gICAgICAgIGlmICghaXNEZWxldGVkICYmIHZpYUtleWJvYXJkKSB7XG4gICAgICAgICAgY29uc3QgZWxlbWVudElkVG9TZWxlY3QgPSBlbGVtZW50LmNvbnRhaW5lcklkID8gZWxlbWVudC5jb250YWluZXJJZCA6IGVsZW1lbnQuaWQ7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4gKHtcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKSwge1xuICAgICAgICAgICAgICBbZWxlbWVudElkVG9TZWxlY3RdOiB0cnVlXG4gICAgICAgICAgICB9KSwgcHJldlN0YXRlKVxuICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0RlbGV0ZWQpIHtcbiAgICAgICAgICBmaXhCaW5kaW5nc0FmdGVyRGVsZXRpb24odGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgW2VsZW1lbnRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNEZWxldGVkIHx8IGlzRXhpc3RpbmdFbGVtZW50KSB7XG4gICAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBudWxsLFxuICAgICAgICAgIGVkaXRpbmdFbGVtZW50OiBudWxsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wubG9ja2VkKSB7XG4gICAgICAgICAgc2V0Q3Vyc29yRm9yU2hhcGUodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZvY3VzQ29udGFpbmVyKCk7XG4gICAgICB9KSxcbiAgICAgIGVsZW1lbnQsXG4gICAgICBleGNhbGlkcmF3Q29udGFpbmVyOiB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCxcbiAgICAgIGFwcDogdGhpc1xuICAgIH0pOyAvLyBkZXNlbGVjdCBhbGwgb3RoZXIgZWxlbWVudHMgd2hlbiBpbnNlcnRpbmcgdGV4dFxuXG4gICAgdGhpcy5kZXNlbGVjdEVsZW1lbnRzKCk7IC8vIGRvIGFuIGluaXRpYWwgdXBkYXRlIHRvIHJlLWluaXRpYWxpemUgZWxlbWVudCBwb3NpdGlvbiBzaW5jZSB3ZSB3ZXJlXG4gICAgLy8gbW9kaWZ5aW5nIGVsZW1lbnQncyB4L3kgZm9yIHNha2Ugb2YgZWRpdG9yIChjYXNlOiBzeW5jaW5nIHRvIHJlbW90ZSlcblxuICAgIHVwZGF0ZUVsZW1lbnQoZWxlbWVudC50ZXh0LCBlbGVtZW50Lm9yaWdpbmFsVGV4dCwgZmFsc2UpO1xuICB9XG5cbiAgZGVzZWxlY3RFbGVtZW50cygpIHtcbiAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe30sIHRoaXMuc3RhdGUpLFxuICAgICAgc2VsZWN0ZWRHcm91cElkczoge30sXG4gICAgICBlZGl0aW5nR3JvdXBJZDogbnVsbCxcbiAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICB9KTtcbiAgfVxuXG4gIGdldFRleHRFbGVtZW50QXRQb3NpdGlvbih4LCB5KSB7XG4gICAgY29uc3QgZWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oeCwgeSwge1xuICAgICAgaW5jbHVkZUJvdW5kVGV4dEVsZW1lbnQ6IHRydWVcbiAgICB9KTtcblxuICAgIGlmIChlbGVtZW50ICYmIGlzVGV4dEVsZW1lbnQoZWxlbWVudCkgJiYgIWVsZW1lbnQuaXNEZWxldGVkKSB7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGdldEVsZW1lbnRBdFBvc2l0aW9uKHgsIHksIG9wdHMpIHtcbiAgICBjb25zdCBhbGxIaXRFbGVtZW50cyA9IHRoaXMuZ2V0RWxlbWVudHNBdFBvc2l0aW9uKHgsIHksIG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5pbmNsdWRlQm91bmRUZXh0RWxlbWVudCwgb3B0cyA9PT0gbnVsbCB8fCBvcHRzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRzLmluY2x1ZGVMb2NrZWRFbGVtZW50cyk7XG5cbiAgICBpZiAoYWxsSGl0RWxlbWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgaWYgKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5wcmVmZXJTZWxlY3RlZCkge1xuICAgICAgICBmb3IgKGxldCBpbmRleCA9IGFsbEhpdEVsZW1lbnRzLmxlbmd0aCAtIDE7IGluZGV4ID4gLTE7IGluZGV4LS0pIHtcbiAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbYWxsSGl0RWxlbWVudHNbaW5kZXhdLmlkXSkge1xuICAgICAgICAgICAgcmV0dXJuIGFsbEhpdEVsZW1lbnRzW2luZGV4XTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgZWxlbWVudFdpdGhIaWdoZXN0WkluZGV4ID0gYWxsSGl0RWxlbWVudHNbYWxsSGl0RWxlbWVudHMubGVuZ3RoIC0gMV07IC8vIElmIHdlJ3JlIGhpdHRpbmcgZWxlbWVudCB3aXRoIGhpZ2hlc3Qgei1pbmRleCBvbmx5IG9uIGl0cyBib3VuZGluZyBib3hcbiAgICAgIC8vIHdoaWxlIGFsc28gaGl0dGluZyBvdGhlciBlbGVtZW50IGZpZ3VyZSwgdGhlIGxhdHRlciBzaG91bGQgYmUgY29uc2lkZXJlZC5cblxuICAgICAgcmV0dXJuIGlzSGl0dGluZ0VsZW1lbnRCb3VuZGluZ0JveFdpdGhvdXRIaXR0aW5nRWxlbWVudChlbGVtZW50V2l0aEhpZ2hlc3RaSW5kZXgsIHRoaXMuc3RhdGUsIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUsIHgsIHkpID8gYWxsSGl0RWxlbWVudHNbYWxsSGl0RWxlbWVudHMubGVuZ3RoIC0gMl0gOiBlbGVtZW50V2l0aEhpZ2hlc3RaSW5kZXg7XG4gICAgfVxuXG4gICAgaWYgKGFsbEhpdEVsZW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIGFsbEhpdEVsZW1lbnRzWzBdO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZ2V0RWxlbWVudHNBdFBvc2l0aW9uKHgsIHksIGluY2x1ZGVCb3VuZFRleHRFbGVtZW50ID0gZmFsc2UsIGluY2x1ZGVMb2NrZWRFbGVtZW50cyA9IGZhbHNlKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBpbmNsdWRlQm91bmRUZXh0RWxlbWVudCAmJiBpbmNsdWRlTG9ja2VkRWxlbWVudHMgPyB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpIDogdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKS5maWx0ZXIoZWxlbWVudCA9PiAoaW5jbHVkZUxvY2tlZEVsZW1lbnRzIHx8ICFlbGVtZW50LmxvY2tlZCkgJiYgKGluY2x1ZGVCb3VuZFRleHRFbGVtZW50IHx8ICEoaXNUZXh0RWxlbWVudChlbGVtZW50KSAmJiBlbGVtZW50LmNvbnRhaW5lcklkKSkpO1xuICAgIHJldHVybiBnZXRFbGVtZW50c0F0UG9zaXRpb24oZWxlbWVudHMsIGVsZW1lbnQgPT4gaGl0VGVzdChlbGVtZW50LCB0aGlzLnN0YXRlLCB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLCB4LCB5KSkuZmlsdGVyKGVsZW1lbnQgPT4ge1xuICAgICAgLy8gaGl0dGluZyBhIGZyYW1lJ3MgZWxlbWVudCBmcm9tIG91dHNpZGUgdGhlIGZyYW1lIGlzIG5vdCBjb25zaWRlcmVkIGEgaGl0XG4gICAgICBjb25zdCBjb250YWluaW5nRnJhbWUgPSBnZXRDb250YWluaW5nRnJhbWUoZWxlbWVudCk7XG4gICAgICByZXR1cm4gY29udGFpbmluZ0ZyYW1lICYmIHRoaXMuc3RhdGUuZnJhbWVSZW5kZXJpbmcuZW5hYmxlZCAmJiB0aGlzLnN0YXRlLmZyYW1lUmVuZGVyaW5nLmNsaXAgPyBpc0N1cnNvckluRnJhbWUoe1xuICAgICAgICB4LFxuICAgICAgICB5XG4gICAgICB9LCBjb250YWluaW5nRnJhbWUpIDogdHJ1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZUhvdmVyU2VsZWN0ZWRMaW5lYXJFbGVtZW50KGxpbmVhckVsZW1lbnRFZGl0b3IsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclkpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gTGluZWFyRWxlbWVudEVkaXRvci5nZXRFbGVtZW50KGxpbmVhckVsZW1lbnRFZGl0b3IuZWxlbWVudElkKTtcbiAgICBjb25zdCBib3VuZFRleHRFbGVtZW50ID0gZ2V0Qm91bmRUZXh0RWxlbWVudChlbGVtZW50KTtcblxuICAgIGlmICghZWxlbWVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkge1xuICAgICAgbGV0IGhvdmVyUG9pbnRJbmRleCA9IC0xO1xuICAgICAgbGV0IHNlZ21lbnRNaWRQb2ludEhvdmVyZWRDb29yZHMgPSBudWxsO1xuXG4gICAgICBpZiAoaXNIaXR0aW5nRWxlbWVudE5vdENvbnNpZGVyaW5nQm91bmRpbmdCb3goZWxlbWVudCwgdGhpcy5zdGF0ZSwgdGhpcy5mcmFtZU5hbWVCb3VuZHNDYWNoZSwgW3NjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclldKSkge1xuICAgICAgICBob3ZlclBvaW50SW5kZXggPSBMaW5lYXJFbGVtZW50RWRpdG9yLmdldFBvaW50SW5kZXhVbmRlckN1cnNvcihlbGVtZW50LCB0aGlzLnN0YXRlLnpvb20sIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclkpO1xuICAgICAgICBzZWdtZW50TWlkUG9pbnRIb3ZlcmVkQ29vcmRzID0gTGluZWFyRWxlbWVudEVkaXRvci5nZXRTZWdtZW50TWlkcG9pbnRIaXRDb29yZHMobGluZWFyRWxlbWVudEVkaXRvciwge1xuICAgICAgICAgIHg6IHNjZW5lUG9pbnRlclgsXG4gICAgICAgICAgeTogc2NlbmVQb2ludGVyWVxuICAgICAgICB9LCB0aGlzLnN0YXRlKTtcblxuICAgICAgICBpZiAoaG92ZXJQb2ludEluZGV4ID49IDAgfHwgc2VnbWVudE1pZFBvaW50SG92ZXJlZENvb3Jkcykge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5QT0lOVEVSKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuTU9WRSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc2hvdWxkU2hvd0JvdW5kaW5nQm94KFtlbGVtZW50XSwgdGhpcy5zdGF0ZSkgJiYgaXNIaXR0aW5nRWxlbWVudEJvdW5kaW5nQm94V2l0aG91dEhpdHRpbmdFbGVtZW50KGVsZW1lbnQsIHRoaXMuc3RhdGUsIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclkpKSB7XG4gICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5NT1ZFKTtcbiAgICAgIH0gZWxzZSBpZiAoYm91bmRUZXh0RWxlbWVudCAmJiBoaXRUZXN0KGJvdW5kVGV4dEVsZW1lbnQsIHRoaXMuc3RhdGUsIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclkpKSB7XG4gICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5NT1ZFKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50LmhvdmVyUG9pbnRJbmRleCAhPT0gaG92ZXJQb2ludEluZGV4KSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCksIHtcbiAgICAgICAgICAgIGhvdmVyUG9pbnRJbmRleFxuICAgICAgICAgIH0pXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoIUxpbmVhckVsZW1lbnRFZGl0b3IuYXJlUG9pbnRzRXF1YWwodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQuc2VnbWVudE1pZFBvaW50SG92ZXJlZENvb3Jkcywgc2VnbWVudE1pZFBvaW50SG92ZXJlZENvb3JkcykpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSwge1xuICAgICAgICAgICAgc2VnbWVudE1pZFBvaW50SG92ZXJlZENvb3Jkc1xuICAgICAgICAgIH0pXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuQVVUTyk7XG4gICAgfVxuICB9XG5cbiAgbWF5YmVDbGVhbnVwQWZ0ZXJNaXNzaW5nUG9pbnRlclVwKGV2ZW50KSB7XG4gICAgaWYgKGxhc3RQb2ludGVyVXAgIT09IG51bGwpIHtcbiAgICAgIC8vIFVuZm9ydHVuYXRlbHksIHNvbWV0aW1lcyB3ZSBkb24ndCBnZXQgYSBwb2ludGVydXAgYWZ0ZXIgYSBwb2ludGVyZG93bixcbiAgICAgIC8vIHRoaXMgY2FuIGhhcHBlbiB3aGVuIGEgY29udGV4dHVhbCBtZW51IG9yIGFsZXJ0IGlzIHRyaWdnZXJlZC4gSW4gb3JkZXIgdG8gYXZvaWRcbiAgICAgIC8vIGJlaW5nIGluIGEgd2VpcmQgc3RhdGUsIHdlIGNsZWFuIHVwIG9uIHRoZSBuZXh0IHBvaW50ZXJkb3duXG4gICAgICBsYXN0UG9pbnRlclVwKGV2ZW50KTtcbiAgICB9XG4gIH1cblxuICB1cGRhdGVHZXN0dXJlT25Qb2ludGVyRG93bihldmVudCkge1xuICAgIGdlc3R1cmUucG9pbnRlcnMuc2V0KGV2ZW50LnBvaW50ZXJJZCwge1xuICAgICAgeDogZXZlbnQuY2xpZW50WCxcbiAgICAgIHk6IGV2ZW50LmNsaWVudFlcbiAgICB9KTtcblxuICAgIGlmIChnZXN0dXJlLnBvaW50ZXJzLnNpemUgPT09IDIpIHtcbiAgICAgIGdlc3R1cmUubGFzdENlbnRlciA9IGdldENlbnRlcihnZXN0dXJlLnBvaW50ZXJzKTtcbiAgICAgIGdlc3R1cmUuaW5pdGlhbFNjYWxlID0gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuICAgICAgZ2VzdHVyZS5pbml0aWFsRGlzdGFuY2UgPSBnZXREaXN0YW5jZShBcnJheS5mcm9tKGdlc3R1cmUucG9pbnRlcnMudmFsdWVzKCkpKTtcbiAgICB9XG4gIH1cblxuICBpbml0aWFsUG9pbnRlckRvd25TdGF0ZShldmVudCkge1xuICAgIGNvbnN0IG9yaWdpbiA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhldmVudCwgdGhpcy5zdGF0ZSk7XG4gICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcbiAgICBjb25zdCBbbWluWCwgbWluWSwgbWF4WCwgbWF4WV0gPSBnZXRDb21tb25Cb3VuZHMoc2VsZWN0ZWRFbGVtZW50cyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIG9yaWdpbixcbiAgICAgIHdpdGhDbWRPckN0cmw6IGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdLFxuICAgICAgb3JpZ2luSW5HcmlkOiB0dXBsZVRvQ29vcnMoZ2V0R3JpZFBvaW50KG9yaWdpbi54LCBvcmlnaW4ueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSkpLFxuICAgICAgc2Nyb2xsYmFyczogaXNPdmVyU2Nyb2xsQmFycyhjdXJyZW50U2Nyb2xsQmFycywgZXZlbnQuY2xpZW50WCAtIHRoaXMuc3RhdGUub2Zmc2V0TGVmdCwgZXZlbnQuY2xpZW50WSAtIHRoaXMuc3RhdGUub2Zmc2V0VG9wKSxcbiAgICAgIC8vIHdlIG5lZWQgdG8gZHVwbGljYXRlIGJlY2F1c2Ugd2UnbGwgYmUgdXBkYXRpbmcgdGhpcyBzdGF0ZVxuICAgICAgbGFzdENvb3JkczogT2JqZWN0LmFzc2lnbih7fSwgb3JpZ2luKSxcbiAgICAgIG9yaWdpbmFsRWxlbWVudHM6IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkucmVkdWNlKChhY2MsIGVsZW1lbnQpID0+IHtcbiAgICAgICAgYWNjLnNldChlbGVtZW50LmlkLCBkZWVwQ29weUVsZW1lbnQoZWxlbWVudCkpO1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwgbmV3IE1hcCgpKSxcbiAgICAgIHJlc2l6ZToge1xuICAgICAgICBoYW5kbGVUeXBlOiBmYWxzZSxcbiAgICAgICAgaXNSZXNpemluZzogZmFsc2UsXG4gICAgICAgIG9mZnNldDoge1xuICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgeTogMFxuICAgICAgICB9LFxuICAgICAgICBhcnJvd0RpcmVjdGlvbjogXCJvcmlnaW5cIixcbiAgICAgICAgY2VudGVyOiB7XG4gICAgICAgICAgeDogKG1heFggKyBtaW5YKSAvIDIsXG4gICAgICAgICAgeTogKG1heFkgKyBtaW5ZKSAvIDJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGhpdDoge1xuICAgICAgICBlbGVtZW50OiBudWxsLFxuICAgICAgICBhbGxIaXRFbGVtZW50czogW10sXG4gICAgICAgIHdhc0FkZGVkVG9TZWxlY3Rpb246IGZhbHNlLFxuICAgICAgICBoYXNCZWVuRHVwbGljYXRlZDogZmFsc2UsXG4gICAgICAgIGhhc0hpdENvbW1vbkJvdW5kaW5nQm94T2ZTZWxlY3RlZEVsZW1lbnRzOiB0aGlzLmlzSGl0dGluZ0NvbW1vbkJvdW5kaW5nQm94T2ZTZWxlY3RlZEVsZW1lbnRzKG9yaWdpbiwgc2VsZWN0ZWRFbGVtZW50cylcbiAgICAgIH0sXG4gICAgICBkcmFnOiB7XG4gICAgICAgIGhhc09jY3VycmVkOiBmYWxzZSxcbiAgICAgICAgb2Zmc2V0OiBudWxsXG4gICAgICB9LFxuICAgICAgZXZlbnRMaXN0ZW5lcnM6IHtcbiAgICAgICAgb25Nb3ZlOiBudWxsLFxuICAgICAgICBvblVwOiBudWxsLFxuICAgICAgICBvbktleVVwOiBudWxsLFxuICAgICAgICBvbktleURvd246IG51bGxcbiAgICAgIH0sXG4gICAgICBib3hTZWxlY3Rpb246IHtcbiAgICAgICAgaGFzT2NjdXJyZWQ6IGZhbHNlXG4gICAgICB9LFxuICAgICAgZWxlbWVudElkc1RvRXJhc2U6IHt9XG4gICAgfTtcbiAgfSAvLyBSZXR1cm5zIHdoZXRoZXIgdGhlIGV2ZW50IGlzIGEgZHJhZ2dpbmcgYSBzY3JvbGxiYXJcblxuXG4gIGhhbmRsZURyYWdnaW5nU2Nyb2xsQmFyKGV2ZW50LCBwb2ludGVyRG93blN0YXRlKSB7XG4gICAgaWYgKCEocG9pbnRlckRvd25TdGF0ZS5zY3JvbGxiYXJzLmlzT3ZlckVpdGhlciAmJiAhdGhpcy5zdGF0ZS5tdWx0aUVsZW1lbnQpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaXNEcmFnZ2luZ1Njcm9sbEJhciA9IHRydWU7XG4gICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnggPSBldmVudC5jbGllbnRYO1xuICAgIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy55ID0gZXZlbnQuY2xpZW50WTtcbiAgICBjb25zdCBvblBvaW50ZXJNb3ZlID0gd2l0aEJhdGNoZWRVcGRhdGVzVGhyb3R0bGVkKGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcblxuICAgICAgaWYgKCEodGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5oYW5kbGVQb2ludGVyTW92ZU92ZXJTY3JvbGxiYXJzKGV2ZW50LCBwb2ludGVyRG93blN0YXRlKTtcbiAgICB9KTtcbiAgICBjb25zdCBvblBvaW50ZXJVcCA9IHdpdGhCYXRjaGVkVXBkYXRlcygoKSA9PiB7XG4gICAgICBpc0RyYWdnaW5nU2Nyb2xsQmFyID0gZmFsc2U7XG4gICAgICBzZXRDdXJzb3JGb3JTaGFwZSh0aGlzLmludGVyYWN0aXZlQ2FudmFzLCB0aGlzLnN0YXRlKTtcbiAgICAgIGxhc3RQb2ludGVyVXAgPSBudWxsO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGN1cnNvckJ1dHRvbjogXCJ1cFwiXG4gICAgICB9KTtcbiAgICAgIHRoaXMuc2F2ZVBvaW50ZXIoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgXCJ1cFwiKTtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfTU9WRSwgb25Qb2ludGVyTW92ZSk7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCBvblBvaW50ZXJVcCk7XG4gICAgICBvblBvaW50ZXJNb3ZlLmZsdXNoKCk7XG4gICAgfSk7XG4gICAgbGFzdFBvaW50ZXJVcCA9IG9uUG9pbnRlclVwO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfTU9WRSwgb25Qb2ludGVyTW92ZSk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgb25Qb2ludGVyVXApO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaXNBU2VsZWN0ZWRFbGVtZW50KGhpdEVsZW1lbnQpIHtcbiAgICByZXR1cm4gaGl0RWxlbWVudCAhPSBudWxsICYmIHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdO1xuICB9XG5cbiAgaXNIaXR0aW5nQ29tbW9uQm91bmRpbmdCb3hPZlNlbGVjdGVkRWxlbWVudHMocG9pbnQsIHNlbGVjdGVkRWxlbWVudHMpIHtcbiAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSAvLyBIb3cgbWFueSBwaXhlbHMgb2ZmIHRoZSBzaGFwZSBib3VuZGFyeSB3ZSBzdGlsbCBjb25zaWRlciBhIGhpdFxuXG5cbiAgICBjb25zdCB0aHJlc2hvbGQgPSAxMCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcbiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gZ2V0Q29tbW9uQm91bmRzKHNlbGVjdGVkRWxlbWVudHMpO1xuICAgIHJldHVybiBwb2ludC54ID4geDEgLSB0aHJlc2hvbGQgJiYgcG9pbnQueCA8IHgyICsgdGhyZXNob2xkICYmIHBvaW50LnkgPiB5MSAtIHRocmVzaG9sZCAmJiBwb2ludC55IDwgeTIgKyB0aHJlc2hvbGQ7XG4gIH1cblxuICBnZXRDdXJyZW50SXRlbVJvdW5kbmVzcyhlbGVtZW50VHlwZSkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91bmRuZXNzID09PSBcInJvdW5kXCIgPyB7XG4gICAgICB0eXBlOiBpc1VzaW5nQWRhcHRpdmVSYWRpdXMoZWxlbWVudFR5cGUpID8gUk9VTkRORVNTLkFEQVBUSVZFX1JBRElVUyA6IFJPVU5ETkVTUy5QUk9QT1JUSU9OQUxfUkFESVVTXG4gICAgfSA6IG51bGw7XG4gIH1cblxuICBvbktleURvd25Gcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpIHtcbiAgICByZXR1cm4gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIGlmICh0aGlzLm1heWJlSGFuZGxlUmVzaXplKHBvaW50ZXJEb3duU3RhdGUsIGV2ZW50KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMubWF5YmVEcmFnTmV3R2VuZXJpY0VsZW1lbnQocG9pbnRlckRvd25TdGF0ZSwgZXZlbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgb25LZXlVcEZyb21Qb2ludGVyRG93bkhhbmRsZXIocG9pbnRlckRvd25TdGF0ZSkge1xuICAgIHJldHVybiB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgLy8gUHJldmVudHMgZm9jdXMgZnJvbSBlc2NhcGluZyBleGNhbGlkcmF3IHRhYlxuICAgICAgZXZlbnQua2V5ID09PSBLRVlTLkFMVCAmJiBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICBpZiAodGhpcy5tYXliZUhhbmRsZVJlc2l6ZShwb2ludGVyRG93blN0YXRlLCBldmVudCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm1heWJlRHJhZ05ld0dlbmVyaWNFbGVtZW50KHBvaW50ZXJEb3duU3RhdGUsIGV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIG9uUG9pbnRlck1vdmVGcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpIHtcbiAgICByZXR1cm4gd2l0aEJhdGNoZWRVcGRhdGVzVGhyb3R0bGVkKGV2ZW50ID0+IHtcbiAgICAgIHZhciBfYSwgX2I7IC8vIFdlIG5lZWQgdG8gaW5pdGlhbGl6ZSBkcmFnT2Zmc2V0WFkgb25seSBhZnRlciB3ZSd2ZSB1cGRhdGVkXG4gICAgICAvLyBgc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzYCBvbiBwb2ludGVyRG93bi4gRG9pbmcgaXQgaGVyZSBpbiBwb2ludGVyTW92ZVxuICAgICAgLy8gZXZlbnQgaGFuZGxlciBzaG91bGQgaG9wZWZ1bGx5IGVuc3VyZSB3ZSdyZSBhbHJlYWR5IHdvcmtpbmcgd2l0aFxuICAgICAgLy8gdGhlIHVwZGF0ZWQgc3RhdGUuXG5cblxuICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZHJhZy5vZmZzZXQgPT09IG51bGwpIHtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5kcmFnLm9mZnNldCA9IHR1cGxlVG9Db29ycyhnZXREcmFnT2Zmc2V0WFkodGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpLCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55KSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcblxuICAgICAgaWYgKCEodGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuaGFuZGxlUG9pbnRlck1vdmVPdmVyU2Nyb2xsYmFycyhldmVudCwgcG9pbnRlckRvd25TdGF0ZSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwb2ludGVyQ29vcmRzID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKGV2ZW50LCB0aGlzLnN0YXRlKTtcblxuICAgICAgaWYgKGlzRXJhc2VyQWN0aXZlKHRoaXMuc3RhdGUpKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlRXJhc2VyKGV2ZW50LCBwb2ludGVyRG93blN0YXRlLCBwb2ludGVyQ29vcmRzKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChwb2ludGVyQ29vcmRzLngsIHBvaW50ZXJDb29yZHMueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7IC8vIGZvciBhcnJvd3MvbGluZXMsIGRvbid0IHN0YXJ0IGRyYWdnaW5nIHVudGlsIGEgZ2l2ZW4gdGhyZXNob2xkXG4gICAgICAvLyB0byBlbnN1cmUgd2UgZG9uJ3QgY3JlYXRlIGEgMi1wb2ludCBhcnJvdyBieSBtaXN0YWtlIHdoZW5cbiAgICAgIC8vIHVzZXIgY2xpY2tzIG1vdXNlIGluIGEgd2F5IHRoYXQgaXQgbW92ZXMgYSB0aW55IGJpdCAodGh1c1xuICAgICAgLy8gdHJpZ2dlcmluZyBwb2ludGVybW92ZSlcblxuICAgICAgaWYgKCFwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgJiYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImFycm93XCIgfHwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwibGluZVwiKSkge1xuICAgICAgICBpZiAoZGlzdGFuY2UyZChwb2ludGVyQ29vcmRzLngsIHBvaW50ZXJDb29yZHMueSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSkgPCBEUkFHR0lOR19USFJFU0hPTEQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmlzUmVzaXppbmcpIHtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnggPSBwb2ludGVyQ29vcmRzLng7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy55ID0gcG9pbnRlckNvb3Jkcy55O1xuXG4gICAgICAgIGlmICh0aGlzLm1heWJlSGFuZGxlUmVzaXplKHBvaW50ZXJEb3duU3RhdGUsIGV2ZW50KSkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkge1xuICAgICAgICBjb25zdCBsaW5lYXJFbGVtZW50RWRpdG9yID0gdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCB8fCB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudDtcblxuICAgICAgICBpZiAoTGluZWFyRWxlbWVudEVkaXRvci5zaG91bGRBZGRNaWRwb2ludCh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCwgcG9pbnRlckNvb3JkcywgdGhpcy5zdGF0ZSkpIHtcbiAgICAgICAgICBjb25zdCByZXQgPSBMaW5lYXJFbGVtZW50RWRpdG9yLmFkZE1pZHBvaW50KHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50LCBwb2ludGVyQ29vcmRzLCB0aGlzLnN0YXRlLCAhZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0pO1xuXG4gICAgICAgICAgaWYgKCFyZXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9IC8vIFNpbmNlIHdlIGFyZSByZWFkaW5nIGZyb20gcHJldmlvdXMgc3RhdGUgd2hpY2ggaXMgbm90IHBvc3NpYmxlIHdpdGhcbiAgICAgICAgICAvLyBhdXRvbWF0aWMgYmF0Y2hpbmcgaW4gUmVhY3QgMTggaGVuY2UgdXNpbmcgZmx1c2ggc3luYyB0byBzeW5jaHJvbm91c2x5XG4gICAgICAgICAgLy8gdXBkYXRlIHRoZSBzdGF0ZS4gQ2hlY2sgaHR0cHM6Ly9naXRodWIuY29tL2V4Y2FsaWRyYXcvZXhjYWxpZHJhdy9wdWxsLzU1MDggZm9yIG1vcmUgZGV0YWlscy5cblxuXG4gICAgICAgICAgZmx1c2hTeW5jKCgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQpLCB7XG4gICAgICAgICAgICAgICAgICBwb2ludGVyRG93blN0YXRlOiByZXQucG9pbnRlckRvd25TdGF0ZSxcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkUG9pbnRzSW5kaWNlczogcmV0LnNlbGVjdGVkUG9pbnRzSW5kaWNlc1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBlZGl0aW5nTGluZWFyRWxlbWVudDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSwge1xuICAgICAgICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZTogcmV0LnBvaW50ZXJEb3duU3RhdGUsXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZFBvaW50c0luZGljZXM6IHJldC5zZWxlY3RlZFBvaW50c0luZGljZXNcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAobGluZWFyRWxlbWVudEVkaXRvci5wb2ludGVyRG93blN0YXRlLnNlZ21lbnRNaWRwb2ludC52YWx1ZSAhPT0gbnVsbCAmJiAhbGluZWFyRWxlbWVudEVkaXRvci5wb2ludGVyRG93blN0YXRlLnNlZ21lbnRNaWRwb2ludC5hZGRlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGRpZERyYWcgPSBMaW5lYXJFbGVtZW50RWRpdG9yLmhhbmRsZVBvaW50RHJhZ2dpbmcoZXZlbnQsIHRoaXMuc3RhdGUsIHBvaW50ZXJDb29yZHMueCwgcG9pbnRlckNvb3Jkcy55LCAoZWxlbWVudCwgcG9pbnRzU2NlbmVDb29yZHMpID0+IHtcbiAgICAgICAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdzRm9yTGluZWFyRWxlbWVudEF0Q29vcmRzKGVsZW1lbnQsIHBvaW50c1NjZW5lQ29vcmRzKTtcbiAgICAgICAgfSwgbGluZWFyRWxlbWVudEVkaXRvcik7XG5cbiAgICAgICAgaWYgKGRpZERyYWcpIHtcbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueCA9IHBvaW50ZXJDb29yZHMueDtcbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueSA9IHBvaW50ZXJDb29yZHMueTtcbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgPSB0cnVlO1xuXG4gICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgJiYgIXRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIGVkaXRpbmdMaW5lYXJFbGVtZW50OiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpLCB7XG4gICAgICAgICAgICAgICAgaXNEcmFnZ2luZzogdHJ1ZVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudC5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSwge1xuICAgICAgICAgICAgICAgIGlzRHJhZ2dpbmc6IHRydWVcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBoYXNIaXRBU2VsZWN0ZWRFbGVtZW50ID0gcG9pbnRlckRvd25TdGF0ZS5oaXQuYWxsSGl0RWxlbWVudHMuc29tZShlbGVtZW50ID0+IHRoaXMuaXNBU2VsZWN0ZWRFbGVtZW50KGVsZW1lbnQpKTtcbiAgICAgIGNvbnN0IGlzU2VsZWN0aW5nUG9pbnRzSW5MaW5lRWRpdG9yID0gdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCAmJiBldmVudC5zaGlmdEtleSAmJiB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZCA9PT0gKChfYSA9IHBvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pZCk7XG5cbiAgICAgIGlmICgoaGFzSGl0QVNlbGVjdGVkRWxlbWVudCB8fCBwb2ludGVyRG93blN0YXRlLmhpdC5oYXNIaXRDb21tb25Cb3VuZGluZ0JveE9mU2VsZWN0ZWRFbGVtZW50cykgJiYgIWlzU2VsZWN0aW5nUG9pbnRzSW5MaW5lRWRpdG9yKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMuZXZlcnkoZWxlbWVudCA9PiBlbGVtZW50LmxvY2tlZCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzSGFzQUZyYW1lID0gc2VsZWN0ZWRFbGVtZW50cy5maW5kKGUgPT4gaXNGcmFtZUVsZW1lbnQoZSkpO1xuICAgICAgICBjb25zdCB0b3BMYXllckZyYW1lID0gdGhpcy5nZXRUb3BMYXllckZyYW1lQXRTY2VuZUNvb3Jkcyhwb2ludGVyQ29vcmRzKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZnJhbWVUb0hpZ2hsaWdodDogdG9wTGF5ZXJGcmFtZSAmJiAhc2VsZWN0ZWRFbGVtZW50c0hhc0FGcmFtZSA/IHRvcExheWVyRnJhbWUgOiBudWxsXG4gICAgICAgIH0pOyAvLyBNYXJraW5nIHRoYXQgY2xpY2sgd2FzIHVzZWQgZm9yIGRyYWdnaW5nIHRvIGNoZWNrXG4gICAgICAgIC8vIGlmIGVsZW1lbnRzIHNob3VsZCBiZSBkZXNlbGVjdGVkIG9uIHBvaW50ZXJ1cFxuXG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZHJhZy5oYXNPY2N1cnJlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudHNBcmVCZWluZ0RyYWdnZWQ6IHRydWVcbiAgICAgICAgfSk7IC8vIHByZXZlbnQgZHJhZ2dpbmcgZXZlbiBpZiB3ZSdyZSBubyBsb25nZXIgaG9sZGluZyBjbWQvY3RybCBvdGhlcndpc2VcbiAgICAgICAgLy8gaXQgd291bGQgaGF2ZSB3ZWlyZCByZXN1bHRzIChzdHVmZiBqdW1waW5nIGFsbCBvdmVyIHRoZSBzY3JlZW4pXG4gICAgICAgIC8vIENoZWNraW5nIGZvciBlZGl0aW5nRWxlbWVudCB0byBhdm9pZCBqdW1wIHdoaWxlIGVkaXRpbmcgb24gbW9iaWxlICM2NTAzXG5cbiAgICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID4gMCAmJiAhcG9pbnRlckRvd25TdGF0ZS53aXRoQ21kT3JDdHJsICYmICF0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50ICYmICgoX2IgPSB0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5zdGF0ZSkgIT09IFwiYWN0aXZlXCIpIHtcbiAgICAgICAgICBjb25zdCBbZHJhZ1gsIGRyYWdZXSA9IGdldEdyaWRQb2ludChwb2ludGVyQ29vcmRzLnggLSBwb2ludGVyRG93blN0YXRlLmRyYWcub2Zmc2V0LngsIHBvaW50ZXJDb29yZHMueSAtIHBvaW50ZXJEb3duU3RhdGUuZHJhZy5vZmZzZXQueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICAgICAgY29uc3QgW2RyYWdEaXN0YW5jZVgsIGRyYWdEaXN0YW5jZVldID0gW01hdGguYWJzKHBvaW50ZXJDb29yZHMueCAtIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngpLCBNYXRoLmFicyhwb2ludGVyQ29vcmRzLnkgLSBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55KV07IC8vIFdlIG9ubHkgZHJhZyBpbiBvbmUgZGlyZWN0aW9uIGlmIHNoaWZ0IGlzIHByZXNzZWRcblxuICAgICAgICAgIGNvbnN0IGxvY2tEaXJlY3Rpb24gPSBldmVudC5zaGlmdEtleTsgLy8gd2hlbiB3ZSdyZSBlZGl0aW5nIHRoZSBuYW1lIG9mIGEgZnJhbWUsIHdlIHdhbnQgdGhlIHVzZXIgdG8gYmVcbiAgICAgICAgICAvLyBhYmxlIHRvIHNlbGVjdCBhbmQgaW50ZXJhY3Qgd2l0aCB0aGUgdGV4dCBpbnB1dFxuXG4gICAgICAgICAgIXRoaXMuc3RhdGUuZWRpdGluZ0ZyYW1lICYmIGRyYWdTZWxlY3RlZEVsZW1lbnRzKHBvaW50ZXJEb3duU3RhdGUsIHNlbGVjdGVkRWxlbWVudHMsIGRyYWdYLCBkcmFnWSwgbG9ja0RpcmVjdGlvbiwgZHJhZ0Rpc3RhbmNlWCwgZHJhZ0Rpc3RhbmNlWSwgdGhpcy5zdGF0ZSwgdGhpcy5zY2VuZSk7XG4gICAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nRm9yQWxsKHNlbGVjdGVkRWxlbWVudHMpOyAvLyBXZSBkdXBsaWNhdGUgdGhlIHNlbGVjdGVkIGVsZW1lbnQgaWYgYWx0IGlzIHByZXNzZWQgb24gcG9pbnRlciBtb3ZlXG5cbiAgICAgICAgICBpZiAoZXZlbnQuYWx0S2V5ICYmICFwb2ludGVyRG93blN0YXRlLmhpdC5oYXNCZWVuRHVwbGljYXRlZCkge1xuICAgICAgICAgICAgLy8gTW92ZSB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGVsZW1lbnRzIHRvIHRoZSB0b3Agb2YgdGhlIHogaW5kZXggc3RhY2ssIGFuZFxuICAgICAgICAgICAgLy8gcHV0IHRoZSBkdXBsaWNhdGVzIHdoZXJlIHRoZSBzZWxlY3RlZCBlbGVtZW50cyB1c2VkIHRvIGJlLlxuICAgICAgICAgICAgLy8gKHRoZSBvcmlnaW4gcG9pbnQgd2hlcmUgdGhlIGRyYWdnaW5nIHN0YXJ0ZWQpXG4gICAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmhpdC5oYXNCZWVuRHVwbGljYXRlZCA9IHRydWU7XG4gICAgICAgICAgICBjb25zdCBuZXh0RWxlbWVudHMgPSBbXTtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzVG9BcHBlbmQgPSBbXTtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwSWRNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBjb25zdCBvbGRJZFRvRHVwbGljYXRlZElkID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgY29uc3QgaGl0RWxlbWVudCA9IHBvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQ7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRJZHMgPSBuZXcgU2V0KHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMsXG4gICAgICAgICAgICAgIGluY2x1ZGVCb3VuZFRleHRFbGVtZW50OiB0cnVlLFxuICAgICAgICAgICAgICBpbmNsdWRlRWxlbWVudHNJbkZyYW1lczogdHJ1ZVxuICAgICAgICAgICAgfSkubWFwKGVsZW1lbnQgPT4gZWxlbWVudC5pZCkpO1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcbiAgICAgICAgICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudElkcy5oYXMoZWxlbWVudC5pZCkgfHwgLy8gY2FzZTogdGhlIHN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyBtaWdodCBub3QgaGF2ZSBiZWVuXG4gICAgICAgICAgICAgIC8vIHVwZGF0ZWQgeWV0IGJ5IHRoZSB0aW1lIHRoaXMgbW91c2Vtb3ZlIGV2ZW50IGlzIGZpcmVkXG4gICAgICAgICAgICAgIGVsZW1lbnQuaWQgPT09IChoaXRFbGVtZW50ID09PSBudWxsIHx8IGhpdEVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGhpdEVsZW1lbnQuaWQpICYmIHBvaW50ZXJEb3duU3RhdGUuaGl0Lndhc0FkZGVkVG9TZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkdXBsaWNhdGVkRWxlbWVudCA9IGR1cGxpY2F0ZUVsZW1lbnQodGhpcy5zdGF0ZS5lZGl0aW5nR3JvdXBJZCwgZ3JvdXBJZE1hcCwgZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgY29uc3QgW29yaWdpbkRyYWdYLCBvcmlnaW5EcmFnWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCAtIHBvaW50ZXJEb3duU3RhdGUuZHJhZy5vZmZzZXQueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSAtIHBvaW50ZXJEb3duU3RhdGUuZHJhZy5vZmZzZXQueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICAgICAgICAgICAgbXV0YXRlRWxlbWVudChkdXBsaWNhdGVkRWxlbWVudCwge1xuICAgICAgICAgICAgICAgICAgeDogZHVwbGljYXRlZEVsZW1lbnQueCArIChvcmlnaW5EcmFnWCAtIGRyYWdYKSxcbiAgICAgICAgICAgICAgICAgIHk6IGR1cGxpY2F0ZWRFbGVtZW50LnkgKyAob3JpZ2luRHJhZ1kgLSBkcmFnWSlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBuZXh0RWxlbWVudHMucHVzaChkdXBsaWNhdGVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgZWxlbWVudHNUb0FwcGVuZC5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIG9sZElkVG9EdXBsaWNhdGVkSWQuc2V0KGVsZW1lbnQuaWQsIGR1cGxpY2F0ZWRFbGVtZW50LmlkKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZXh0RWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBuZXh0U2NlbmVFbGVtZW50cyA9IFsuLi5uZXh0RWxlbWVudHMsIC4uLmVsZW1lbnRzVG9BcHBlbmRdO1xuICAgICAgICAgICAgYmluZFRleHRUb1NoYXBlQWZ0ZXJEdXBsaWNhdGlvbihuZXh0RWxlbWVudHMsIGVsZW1lbnRzVG9BcHBlbmQsIG9sZElkVG9EdXBsaWNhdGVkSWQpO1xuICAgICAgICAgICAgZml4QmluZGluZ3NBZnRlckR1cGxpY2F0aW9uKG5leHRTY2VuZUVsZW1lbnRzLCBlbGVtZW50c1RvQXBwZW5kLCBvbGRJZFRvRHVwbGljYXRlZElkLCBcImR1cGxpY2F0ZXNTZXJ2ZUFzT2xkXCIpO1xuICAgICAgICAgICAgYmluZEVsZW1lbnRzVG9GcmFtZXNBZnRlckR1cGxpY2F0aW9uKG5leHRTY2VuZUVsZW1lbnRzLCBlbGVtZW50c1RvQXBwZW5kLCBvbGRJZFRvRHVwbGljYXRlZElkKTtcbiAgICAgICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKG5leHRTY2VuZUVsZW1lbnRzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gLy8gSXQgaXMgdmVyeSBpbXBvcnRhbnQgdG8gcmVhZCB0aGlzLnN0YXRlIHdpdGhpbiBlYWNoIG1vdmUgZXZlbnQsXG4gICAgICAvLyBvdGhlcndpc2Ugd2Ugd291bGQgcmVhZCBhIHN0YWxlIG9uZSFcblxuXG4gICAgICBjb25zdCBkcmFnZ2luZ0VsZW1lbnQgPSB0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudDtcblxuICAgICAgaWYgKCFkcmFnZ2luZ0VsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZHJhZ2dpbmdFbGVtZW50LnR5cGUgPT09IFwiZnJlZWRyYXdcIikge1xuICAgICAgICBjb25zdCBwb2ludHMgPSBkcmFnZ2luZ0VsZW1lbnQucG9pbnRzO1xuICAgICAgICBjb25zdCBkeCA9IHBvaW50ZXJDb29yZHMueCAtIGRyYWdnaW5nRWxlbWVudC54O1xuICAgICAgICBjb25zdCBkeSA9IHBvaW50ZXJDb29yZHMueSAtIGRyYWdnaW5nRWxlbWVudC55O1xuICAgICAgICBjb25zdCBsYXN0UG9pbnQgPSBwb2ludHMubGVuZ3RoID4gMCAmJiBwb2ludHNbcG9pbnRzLmxlbmd0aCAtIDFdO1xuICAgICAgICBjb25zdCBkaXNjYXJkUG9pbnQgPSBsYXN0UG9pbnQgJiYgbGFzdFBvaW50WzBdID09PSBkeCAmJiBsYXN0UG9pbnRbMV0gPT09IGR5O1xuXG4gICAgICAgIGlmICghZGlzY2FyZFBvaW50KSB7XG4gICAgICAgICAgY29uc3QgcHJlc3N1cmVzID0gZHJhZ2dpbmdFbGVtZW50LnNpbXVsYXRlUHJlc3N1cmUgPyBkcmFnZ2luZ0VsZW1lbnQucHJlc3N1cmVzIDogWy4uLmRyYWdnaW5nRWxlbWVudC5wcmVzc3VyZXMsIGV2ZW50LnByZXNzdXJlXTtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwge1xuICAgICAgICAgICAgcG9pbnRzOiBbLi4ucG9pbnRzLCBbZHgsIGR5XV0sXG4gICAgICAgICAgICBwcmVzc3VyZXNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpc0xpbmVhckVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50KSkge1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRzQXJlQmVpbmdEcmFnZ2VkOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBwb2ludHMgPSBkcmFnZ2luZ0VsZW1lbnQucG9pbnRzO1xuICAgICAgICBsZXQgZHggPSBncmlkWCAtIGRyYWdnaW5nRWxlbWVudC54O1xuICAgICAgICBsZXQgZHkgPSBncmlkWSAtIGRyYWdnaW5nRWxlbWVudC55O1xuXG4gICAgICAgIGlmIChzaG91bGRSb3RhdGVXaXRoRGlzY3JldGVBbmdsZShldmVudCkgJiYgcG9pbnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICh7XG4gICAgICAgICAgICB3aWR0aDogZHgsXG4gICAgICAgICAgICBoZWlnaHQ6IGR5XG4gICAgICAgICAgfSA9IGdldExvY2tlZExpbmVhckN1cnNvckFsaWduU2l6ZShkcmFnZ2luZ0VsZW1lbnQueCwgZHJhZ2dpbmdFbGVtZW50LnksIHBvaW50ZXJDb29yZHMueCwgcG9pbnRlckNvb3Jkcy55KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocG9pbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCB7XG4gICAgICAgICAgICBwb2ludHM6IFsuLi5wb2ludHMsIFtkeCwgZHldXVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKHBvaW50cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwge1xuICAgICAgICAgICAgcG9pbnRzOiBbLi4ucG9pbnRzLnNsaWNlKDAsIC0xKSwgW2R4LCBkeV1dXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNCaW5kaW5nRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQsIGZhbHNlKSkge1xuICAgICAgICAgIC8vIFdoZW4gY3JlYXRpbmcgYSBsaW5lYXIgZWxlbWVudCBieSBkcmFnZ2luZ1xuICAgICAgICAgIHRoaXMubWF5YmVTdWdnZXN0QmluZGluZ3NGb3JMaW5lYXJFbGVtZW50QXRDb29yZHMoZHJhZ2dpbmdFbGVtZW50LCBbcG9pbnRlckNvb3Jkc10sIHRoaXMuc3RhdGUuc3RhcnRCb3VuZEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueCA9IHBvaW50ZXJDb29yZHMueDtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnkgPSBwb2ludGVyQ29vcmRzLnk7XG4gICAgICAgIHRoaXMubWF5YmVEcmFnTmV3R2VuZXJpY0VsZW1lbnQocG9pbnRlckRvd25TdGF0ZSwgZXZlbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5ib3hTZWxlY3Rpb24uaGFzT2NjdXJyZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCBlbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCk7IC8vIGJveC1zZWxlY3QgbGluZSBlZGl0b3IgcG9pbnRzXG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICBMaW5lYXJFbGVtZW50RWRpdG9yLmhhbmRsZUJveFNlbGVjdGlvbihldmVudCwgdGhpcy5zdGF0ZSwgdGhpcy5zZXRTdGF0ZS5iaW5kKHRoaXMpKTsgLy8gcmVndWxhciBib3gtc2VsZWN0XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbGV0IHNob3VsZFJldXNlU2VsZWN0aW9uID0gdHJ1ZTtcblxuICAgICAgICAgIGlmICghZXZlbnQuc2hpZnRLZXkgJiYgaXNTb21lRWxlbWVudFNlbGVjdGVkKGVsZW1lbnRzLCB0aGlzLnN0YXRlKSkge1xuICAgICAgICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUud2l0aENtZE9yQ3RybCAmJiBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50KSB7XG4gICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUpLCB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiB7XG4gICAgICAgICAgICAgICAgICBbcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pLCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBwcmV2U3RhdGUsIHRoaXMpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNob3VsZFJldXNlU2VsZWN0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZWxlbWVudHNXaXRoaW5TZWxlY3Rpb24gPSBnZXRFbGVtZW50c1dpdGhpblNlbGVjdGlvbihlbGVtZW50cywgZHJhZ2dpbmdFbGVtZW50KTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgICBjb25zdCBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzaG91bGRSZXVzZVNlbGVjdGlvbiAmJiBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKSwgZWxlbWVudHNXaXRoaW5TZWxlY3Rpb24ucmVkdWNlKChhY2MsIGVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgYWNjW2VsZW1lbnQuaWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgICAgIH0sIHt9KSk7XG5cbiAgICAgICAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50KSB7XG4gICAgICAgICAgICAgIC8vIGlmIHVzaW5nIGN0cmwvY21kLCBzZWxlY3QgdGhlIGhpdEVsZW1lbnQgb25seSBpZiB3ZVxuICAgICAgICAgICAgICAvLyBoYXZlbid0IGJveC1zZWxlY3RlZCBhbnl0aGluZyBlbHNlXG4gICAgICAgICAgICAgIGlmICghZWxlbWVudHNXaXRoaW5TZWxlY3Rpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbmV4dFNlbGVjdGVkRWxlbWVudElkc1twb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50LmlkXSA9IHRydWU7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG5leHRTZWxlY3RlZEVsZW1lbnRJZHNbcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudC5pZF07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHJldlN0YXRlID0gIXNob3VsZFJldXNlU2VsZWN0aW9uID8gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUpLCB7XG4gICAgICAgICAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IHt9LFxuICAgICAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogbnVsbFxuICAgICAgICAgICAgfSkgOiBwcmV2U3RhdGU7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IHByZXZTdGF0ZS5lZGl0aW5nR3JvdXBJZCxcbiAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgICAgICAgICB9LCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBwcmV2U3RhdGUsIHRoaXMpKSwge1xuICAgICAgICAgICAgICAvLyBzZWxlY3QgbGluZWFyIGVsZW1lbnQgb25seSB3aGVuIHdlIGhhdmVuJ3QgYm94LXNlbGVjdGVkIGFueXRoaW5nIGVsc2VcbiAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBlbGVtZW50c1dpdGhpblNlbGVjdGlvbi5sZW5ndGggPT09IDEgJiYgaXNMaW5lYXJFbGVtZW50KGVsZW1lbnRzV2l0aGluU2VsZWN0aW9uWzBdKSA/IG5ldyBMaW5lYXJFbGVtZW50RWRpdG9yKGVsZW1lbnRzV2l0aGluU2VsZWN0aW9uWzBdLCB0aGlzLnNjZW5lKSA6IG51bGwsXG4gICAgICAgICAgICAgIHNob3dIeXBlcmxpbmtQb3B1cDogZWxlbWVudHNXaXRoaW5TZWxlY3Rpb24ubGVuZ3RoID09PSAxICYmIChlbGVtZW50c1dpdGhpblNlbGVjdGlvblswXS5saW5rIHx8IGlzRW1iZWRkYWJsZUVsZW1lbnQoZWxlbWVudHNXaXRoaW5TZWxlY3Rpb25bMF0pKSA/IFwiaW5mb1wiIDogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0gLy8gUmV0dXJucyB3aGV0aGVyIHRoZSBwb2ludGVyIG1vdmUgaGFwcGVuZWQgb3ZlciBlaXRoZXIgc2Nyb2xsYmFyXG5cblxuICBoYW5kbGVQb2ludGVyTW92ZU92ZXJTY3JvbGxiYXJzKGV2ZW50LCBwb2ludGVyRG93blN0YXRlKSB7XG4gICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuc2Nyb2xsYmFycy5pc092ZXJIb3Jpem9udGFsKSB7XG4gICAgICBjb25zdCB4ID0gZXZlbnQuY2xpZW50WDtcbiAgICAgIGNvbnN0IGR4ID0geCAtIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy54O1xuICAgICAgdGhpcy50cmFuc2xhdGVDYW52YXMoe1xuICAgICAgICBzY3JvbGxYOiB0aGlzLnN0YXRlLnNjcm9sbFggLSBkeCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZVxuICAgICAgfSk7XG4gICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueCA9IHg7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5zY3JvbGxiYXJzLmlzT3ZlclZlcnRpY2FsKSB7XG4gICAgICBjb25zdCB5ID0gZXZlbnQuY2xpZW50WTtcbiAgICAgIGNvbnN0IGR5ID0geSAtIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy55O1xuICAgICAgdGhpcy50cmFuc2xhdGVDYW52YXMoe1xuICAgICAgICBzY3JvbGxZOiB0aGlzLnN0YXRlLnNjcm9sbFkgLSBkeSAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZVxuICAgICAgfSk7XG4gICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueSA9IHk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBvblBvaW50ZXJVcEZyb21Qb2ludGVyRG93bkhhbmRsZXIocG9pbnRlckRvd25TdGF0ZSkge1xuICAgIHJldHVybiB3aXRoQmF0Y2hlZFVwZGF0ZXMoY2hpbGRFdmVudCA9PiB7XG4gICAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lLCBfZjtcblxuICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25Nb3ZlKSB7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25Nb3ZlLmZsdXNoKCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgZHJhZ2dpbmdFbGVtZW50LFxuICAgICAgICByZXNpemluZ0VsZW1lbnQsXG4gICAgICAgIG11bHRpRWxlbWVudCxcbiAgICAgICAgYWN0aXZlVG9vbCxcbiAgICAgICAgaXNSZXNpemluZyxcbiAgICAgICAgaXNSb3RhdGluZ1xuICAgICAgfSA9IHRoaXMuc3RhdGU7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgaXNSZXNpemluZzogZmFsc2UsXG4gICAgICAgIGlzUm90YXRpbmc6IGZhbHNlLFxuICAgICAgICByZXNpemluZ0VsZW1lbnQ6IG51bGwsXG4gICAgICAgIHNlbGVjdGlvbkVsZW1lbnQ6IG51bGwsXG4gICAgICAgIGZyYW1lVG9IaWdobGlnaHQ6IG51bGwsXG4gICAgICAgIGVsZW1lbnRzVG9IaWdobGlnaHQ6IG51bGwsXG4gICAgICAgIGN1cnNvckJ1dHRvbjogXCJ1cFwiLFxuICAgICAgICAvLyB0ZXh0IGVsZW1lbnRzIGFyZSByZXNldCBvbiBmaW5hbGl6ZSwgYW5kIHJlc2V0dGluZyBvbiBwb2ludGVydXBcbiAgICAgICAgLy8gbWF5IGNhdXNlIGlzc3VlcyB3aXRoIGRvdWJsZSB0YXBzXG4gICAgICAgIGVkaXRpbmdFbGVtZW50OiBtdWx0aUVsZW1lbnQgfHwgaXNUZXh0RWxlbWVudCh0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50KSA/IHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQgOiBudWxsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuc2F2ZVBvaW50ZXIoY2hpbGRFdmVudC5jbGllbnRYLCBjaGlsZEV2ZW50LmNsaWVudFksIFwidXBcIik7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc2VsZWN0ZWRFbGVtZW50c0FyZUJlaW5nRHJhZ2dlZDogZmFsc2VcbiAgICAgIH0pOyAvLyBIYW5kbGUgZW5kIG9mIGRyYWdnaW5nIGEgcG9pbnQgb2YgYSBsaW5lYXIgZWxlbWVudCwgbWlnaHQgY2xvc2UgYSBsb29wXG4gICAgICAvLyBhbmQgc2V0cyBiaW5kaW5nIGVsZW1lbnRcblxuICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFwb2ludGVyRG93blN0YXRlLmJveFNlbGVjdGlvbi5oYXNPY2N1cnJlZCAmJiAoKF9iID0gKF9hID0gcG9pbnRlckRvd25TdGF0ZS5oaXQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5lbGVtZW50KSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuaWQpICE9PSB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZCkge1xuICAgICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBlZGl0aW5nTGluZWFyRWxlbWVudCA9IExpbmVhckVsZW1lbnRFZGl0b3IuaGFuZGxlUG9pbnRlclVwKGNoaWxkRXZlbnQsIHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQsIHRoaXMuc3RhdGUpO1xuXG4gICAgICAgICAgaWYgKGVkaXRpbmdMaW5lYXJFbGVtZW50ICE9PSB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgZWRpdGluZ0xpbmVhckVsZW1lbnQsXG4gICAgICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgIGlmICgoKF9kID0gKF9jID0gcG9pbnRlckRvd25TdGF0ZS5oaXQpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5lbGVtZW50KSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QuaWQpICE9PSB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudC5lbGVtZW50SWQpIHtcbiAgICAgICAgICBjb25zdCBzZWxlY3RlZEVMZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpOyAvLyBzZXQgc2VsZWN0ZWRMaW5lYXJFbGVtZW50IHRvIG51bGwgaWYgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSBlbGVtZW50IHNlbGVjdGVkIHNpbmNlIHdlIGRvbid0IHdhbnQgdG8gc2hvdyBsaW5lYXIgZWxlbWVudCBoYW5kbGVzXG5cbiAgICAgICAgICBpZiAoc2VsZWN0ZWRFTGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBudWxsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgbGluZWFyRWxlbWVudEVkaXRvciA9IExpbmVhckVsZW1lbnRFZGl0b3IuaGFuZGxlUG9pbnRlclVwKGNoaWxkRXZlbnQsIHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBzdGFydEJpbmRpbmdFbGVtZW50LFxuICAgICAgICAgICAgZW5kQmluZGluZ0VsZW1lbnRcbiAgICAgICAgICB9ID0gbGluZWFyRWxlbWVudEVkaXRvcjtcbiAgICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50KGxpbmVhckVsZW1lbnRFZGl0b3IuZWxlbWVudElkKTtcblxuICAgICAgICAgIGlmIChpc0JpbmRpbmdFbGVtZW50KGVsZW1lbnQpKSB7XG4gICAgICAgICAgICBiaW5kT3JVbmJpbmRMaW5lYXJFbGVtZW50KGVsZW1lbnQsIHN0YXJ0QmluZGluZ0VsZW1lbnQsIGVuZEJpbmRpbmdFbGVtZW50KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobGluZWFyRWxlbWVudEVkaXRvciAhPT0gdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgbGluZWFyRWxlbWVudEVkaXRvciksIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZFBvaW50c0luZGljZXM6IG51bGxcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxhc3RQb2ludGVyVXAgPSBudWxsO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9NT1ZFLCBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uTW92ZSk7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uVXApO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZRE9XTiwgcG9pbnRlckRvd25TdGF0ZS5ldmVudExpc3RlbmVycy5vbktleURvd24pO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZVVAsIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25LZXlVcCk7XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLnBlbmRpbmdJbWFnZUVsZW1lbnRJZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBwZW5kaW5nSW1hZ2VFbGVtZW50SWQ6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmICgoZHJhZ2dpbmdFbGVtZW50ID09PSBudWxsIHx8IGRyYWdnaW5nRWxlbWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogZHJhZ2dpbmdFbGVtZW50LnR5cGUpID09PSBcImZyZWVkcmF3XCIpIHtcbiAgICAgICAgY29uc3QgcG9pbnRlckNvb3JkcyA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhjaGlsZEV2ZW50LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gZHJhZ2dpbmdFbGVtZW50LnBvaW50cztcbiAgICAgICAgbGV0IGR4ID0gcG9pbnRlckNvb3Jkcy54IC0gZHJhZ2dpbmdFbGVtZW50Lng7XG4gICAgICAgIGxldCBkeSA9IHBvaW50ZXJDb29yZHMueSAtIGRyYWdnaW5nRWxlbWVudC55OyAvLyBBbGxvd3MgZG90cyB0byBhdm9pZCBiZWluZyBmbGFnZ2VkIGFzIGluZmluaXRlbHkgc21hbGxcblxuICAgICAgICBpZiAoZHggPT09IHBvaW50c1swXVswXSAmJiBkeSA9PT0gcG9pbnRzWzBdWzFdKSB7XG4gICAgICAgICAgZHkgKz0gMC4wMDAxO1xuICAgICAgICAgIGR4ICs9IDAuMDAwMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByZXNzdXJlcyA9IGRyYWdnaW5nRWxlbWVudC5zaW11bGF0ZVByZXNzdXJlID8gW10gOiBbLi4uZHJhZ2dpbmdFbGVtZW50LnByZXNzdXJlcywgY2hpbGRFdmVudC5wcmVzc3VyZV07XG4gICAgICAgIG11dGF0ZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCB7XG4gICAgICAgICAgcG9pbnRzOiBbLi4ucG9pbnRzLCBbZHgsIGR5XV0sXG4gICAgICAgICAgcHJlc3N1cmVzLFxuICAgICAgICAgIGxhc3RDb21taXR0ZWRQb2ludDogW2R4LCBkeV1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNJbWFnZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50KSkge1xuICAgICAgICBjb25zdCBpbWFnZUVsZW1lbnQgPSBkcmFnZ2luZ0VsZW1lbnQ7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGlzLmluaXRpYWxpemVJbWFnZURpbWVuc2lvbnMoaW1hZ2VFbGVtZW50KTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe1xuICAgICAgICAgICAgICBbaW1hZ2VFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgfSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHModGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5maWx0ZXIoZWwgPT4gZWwuaWQgIT09IGltYWdlRWxlbWVudC5pZCkpO1xuICAgICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzTGluZWFyRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQpKSB7XG4gICAgICAgIGlmIChkcmFnZ2luZ0VsZW1lbnQucG9pbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB0aGlzLmhpc3RvcnkucmVzdW1lUmVjb3JkaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwb2ludGVyQ29vcmRzID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKGNoaWxkRXZlbnQsIHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmICghcG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkICYmIGRyYWdnaW5nRWxlbWVudCAmJiAhbXVsdGlFbGVtZW50KSB7XG4gICAgICAgICAgbXV0YXRlRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQsIHtcbiAgICAgICAgICAgIHBvaW50czogWy4uLmRyYWdnaW5nRWxlbWVudC5wb2ludHMsIFtwb2ludGVyQ29vcmRzLnggLSBkcmFnZ2luZ0VsZW1lbnQueCwgcG9pbnRlckNvb3Jkcy55IC0gZHJhZ2dpbmdFbGVtZW50LnldXVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgbXVsdGlFbGVtZW50OiBkcmFnZ2luZ0VsZW1lbnQsXG4gICAgICAgICAgICBlZGl0aW5nRWxlbWVudDogdGhpcy5zdGF0ZS5kcmFnZ2luZ0VsZW1lbnRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgJiYgIW11bHRpRWxlbWVudCkge1xuICAgICAgICAgIGlmIChpc0JpbmRpbmdFbmFibGVkKHRoaXMuc3RhdGUpICYmIGlzQmluZGluZ0VsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCBmYWxzZSkpIHtcbiAgICAgICAgICAgIG1heWJlQmluZExpbmVhckVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCB0aGlzLnN0YXRlLCB0aGlzLnNjZW5lLCBwb2ludGVyQ29vcmRzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXSxcbiAgICAgICAgICAgIHN0YXJ0Qm91bmRFbGVtZW50OiBudWxsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoIWFjdGl2ZVRvb2wubG9ja2VkKSB7XG4gICAgICAgICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+ICh7XG4gICAgICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgICAgICAgYWN0aXZlVG9vbDogdXBkYXRlQWN0aXZlVG9vbCh0aGlzLnN0YXRlLCB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzZWxlY3Rpb25cIlxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLCB7XG4gICAgICAgICAgICAgICAgW2RyYWdnaW5nRWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgICAgfSksIHByZXZTdGF0ZSksXG4gICAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogbmV3IExpbmVhckVsZW1lbnRFZGl0b3IoZHJhZ2dpbmdFbGVtZW50LCB0aGlzLnNjZW5lKVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiAoe1xuICAgICAgICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IG51bGxcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChhY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIgJiYgZHJhZ2dpbmdFbGVtZW50ICYmIGlzSW52aXNpYmx5U21hbGxFbGVtZW50KGRyYWdnaW5nRWxlbWVudCkpIHtcbiAgICAgICAgLy8gcmVtb3ZlIGludmlzaWJsZSBlbGVtZW50IHdoaWNoIHdhcyBhZGRlZCBpbiBvblBvaW50ZXJEb3duXG4gICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkuc2xpY2UoMCwgLTEpKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChkcmFnZ2luZ0VsZW1lbnQpIHtcbiAgICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZHJhZy5oYXNPY2N1cnJlZCkge1xuICAgICAgICAgIGNvbnN0IHNjZW5lQ29vcmRzID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKGNoaWxkRXZlbnQsIHRoaXMuc3RhdGUpOyAvLyB3aGVuIGVkaXRpbmcgdGhlIHBvaW50cyBvZiBhIGxpbmVhciBlbGVtZW50LCB3ZSBjaGVjayBpZiB0aGVcbiAgICAgICAgICAvLyBsaW5lYXIgZWxlbWVudCBzdGlsbCBpcyBpbiB0aGUgZnJhbWUgYWZ0ZXJ3YXJkc1xuICAgICAgICAgIC8vIGlmIG5vdCwgdGhlIGxpbmVhciBlbGVtZW50IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIGl0cyBmcmFtZSAoaWYgYW55KVxuXG4gICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50ICYmIHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50LmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIGNvbnN0IGxpbmVhckVsZW1lbnQgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnQodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQuZWxlbWVudElkKTtcblxuICAgICAgICAgICAgaWYgKGxpbmVhckVsZW1lbnQgPT09IG51bGwgfHwgbGluZWFyRWxlbWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogbGluZWFyRWxlbWVudC5mcmFtZUlkKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGZyYW1lID0gZ2V0Q29udGFpbmluZ0ZyYW1lKGxpbmVhckVsZW1lbnQpO1xuXG4gICAgICAgICAgICAgIGlmIChmcmFtZSAmJiBsaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFlbGVtZW50T3ZlcmxhcHNXaXRoRnJhbWUobGluZWFyRWxlbWVudCwgZnJhbWUpKSB7XG4gICAgICAgICAgICAgICAgICAvLyByZW1vdmUgdGhlIGxpbmVhciBlbGVtZW50IGZyb20gYWxsIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgLy8gYmVmb3JlIHJlbW92aW5nIGl0IGZyb20gdGhlIGZyYW1lIGFzIHdlbGxcbiAgICAgICAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQobGluZWFyRWxlbWVudCwge1xuICAgICAgICAgICAgICAgICAgICBncm91cElkczogW11cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMocmVtb3ZlRWxlbWVudHNGcm9tRnJhbWUodGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgW2xpbmVhckVsZW1lbnRdLCB0aGlzLnN0YXRlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHNlbGVjdGVkIGVsZW1lbnRzIGFuZCBmcmFtZXNcbiAgICAgICAgICAgIGNvbnN0IHRvcExheWVyRnJhbWUgPSB0aGlzLmdldFRvcExheWVyRnJhbWVBdFNjZW5lQ29vcmRzKHNjZW5lQ29vcmRzKTtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG4gICAgICAgICAgICBsZXQgbmV4dEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKTtcblxuICAgICAgICAgICAgY29uc3QgdXBkYXRlR3JvdXBJZHNBZnRlckVkaXRpbmdHcm91cCA9IGVsZW1lbnRzID0+IHtcbiAgICAgICAgICAgICAgaWYgKGVsZW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gZWxlbWVudC5ncm91cElkcy5pbmRleE9mKHRoaXMuc3RhdGUuZWRpdGluZ0dyb3VwSWQpO1xuICAgICAgICAgICAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwSWRzOiBlbGVtZW50Lmdyb3VwSWRzLnNsaWNlKDAsIGluZGV4KVxuICAgICAgICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG5leHRFbGVtZW50cy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuZ3JvdXBJZHMubGVuZ3RoICYmIGdldEVsZW1lbnRzSW5Hcm91cChuZXh0RWxlbWVudHMsIGVsZW1lbnQuZ3JvdXBJZHNbZWxlbWVudC5ncm91cElkcy5sZW5ndGggLSAxXSkubGVuZ3RoIDwgMikge1xuICAgICAgICAgICAgICAgICAgICBtdXRhdGVFbGVtZW50KGVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgICAgICAgICBncm91cElkczogW11cbiAgICAgICAgICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRvcExheWVyRnJhbWUgJiYgIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW3RvcExheWVyRnJhbWUuaWRdKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzVG9BZGQgPSBzZWxlY3RlZEVsZW1lbnRzLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQuZnJhbWVJZCAhPT0gdG9wTGF5ZXJGcmFtZS5pZCAmJiBpc0VsZW1lbnRJbkZyYW1lKGVsZW1lbnQsIG5leHRFbGVtZW50cywgdGhpcy5zdGF0ZSkpO1xuXG4gICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdHcm91cElkKSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlR3JvdXBJZHNBZnRlckVkaXRpbmdHcm91cChlbGVtZW50c1RvQWRkKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIG5leHRFbGVtZW50cyA9IGFkZEVsZW1lbnRzVG9GcmFtZShuZXh0RWxlbWVudHMsIGVsZW1lbnRzVG9BZGQsIHRvcExheWVyRnJhbWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghdG9wTGF5ZXJGcmFtZSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nR3JvdXBJZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzVG9SZW1vdmUgPSBzZWxlY3RlZEVsZW1lbnRzLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQuZnJhbWVJZCAmJiAhaXNFbGVtZW50SW5GcmFtZShlbGVtZW50LCBuZXh0RWxlbWVudHMsIHRoaXMuc3RhdGUpKTtcbiAgICAgICAgICAgICAgICB1cGRhdGVHcm91cElkc0FmdGVyRWRpdGluZ0dyb3VwKGVsZW1lbnRzVG9SZW1vdmUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5leHRFbGVtZW50cyA9IHVwZGF0ZUZyYW1lTWVtYmVyc2hpcE9mU2VsZWN0ZWRFbGVtZW50cyhuZXh0RWxlbWVudHMsIHRoaXMuc3RhdGUsIHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMobmV4dEVsZW1lbnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZHJhZ2dpbmdFbGVtZW50LnR5cGUgPT09IFwiZnJhbWVcIikge1xuICAgICAgICAgIGNvbnN0IGVsZW1lbnRzSW5zaWRlRnJhbWUgPSBnZXRFbGVtZW50c0luTmV3RnJhbWUodGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgZHJhZ2dpbmdFbGVtZW50KTtcbiAgICAgICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhhZGRFbGVtZW50c1RvRnJhbWUodGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgZWxlbWVudHNJbnNpZGVGcmFtZSwgZHJhZ2dpbmdFbGVtZW50KSk7XG4gICAgICAgIH1cblxuICAgICAgICBtdXRhdGVFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwgZ2V0Tm9ybWFsaXplZERpbWVuc2lvbnMoZHJhZ2dpbmdFbGVtZW50KSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXNpemluZ0VsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzaXppbmdFbGVtZW50ICYmIGlzSW52aXNpYmx5U21hbGxFbGVtZW50KHJlc2l6aW5nRWxlbWVudCkpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHModGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5maWx0ZXIoZWwgPT4gZWwuaWQgIT09IHJlc2l6aW5nRWxlbWVudC5pZCkpO1xuICAgICAgfSAvLyBoYW5kbGUgZnJhbWUgbWVtYmVyc2hpcCBmb3IgcmVzaXppbmcgZnJhbWVzIGFuZC9vciBzZWxlY3RlZCBlbGVtZW50c1xuXG5cbiAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5pc1Jlc2l6aW5nKSB7XG4gICAgICAgIGxldCBuZXh0RWxlbWVudHMgPSB1cGRhdGVGcmFtZU1lbWJlcnNoaXBPZlNlbGVjdGVkRWxlbWVudHModGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgdGhpcy5zdGF0ZSwgdGhpcyk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRnJhbWVzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQudHlwZSA9PT0gXCJmcmFtZVwiKTtcblxuICAgICAgICBmb3IgKGNvbnN0IGZyYW1lIG9mIHNlbGVjdGVkRnJhbWVzKSB7XG4gICAgICAgICAgbmV4dEVsZW1lbnRzID0gcmVwbGFjZUFsbEVsZW1lbnRzSW5GcmFtZShuZXh0RWxlbWVudHMsIGdldEVsZW1lbnRzSW5SZXNpemluZ0ZyYW1lKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIGZyYW1lLCB0aGlzLnN0YXRlKSwgZnJhbWUsIHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMobmV4dEVsZW1lbnRzKTtcbiAgICAgIH0gLy8gQ29kZSBiZWxvdyBoYW5kbGVzIHNlbGVjdGlvbiB3aGVuIGVsZW1lbnQocykgd2VyZW4ndFxuICAgICAgLy8gZHJhZyBvciBhZGRlZCB0byBzZWxlY3Rpb24gb24gcG9pbnRlciBkb3duIHBoYXNlLlxuXG5cbiAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50O1xuXG4gICAgICBpZiAoKChfZSA9IHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSA9PT0gbnVsbCB8fCBfZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2UuZWxlbWVudElkKSAhPT0gKGhpdEVsZW1lbnQgPT09IG51bGwgfHwgaGl0RWxlbWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogaGl0RWxlbWVudC5pZCkgJiYgaXNMaW5lYXJFbGVtZW50KGhpdEVsZW1lbnQpKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRUxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7IC8vIHNldCBzZWxlY3RlZExpbmVhckVsZW1lbnQgd2hlbiBubyBvdGhlciBlbGVtZW50IHNlbGVjdGVkIGV4Y2VwdFxuICAgICAgICAvLyB0aGUgb25lIHdlJ3ZlIGhpdFxuXG4gICAgICAgIGlmIChzZWxlY3RlZEVMZW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBuZXcgTGluZWFyRWxlbWVudEVkaXRvcihoaXRFbGVtZW50LCB0aGlzLnNjZW5lKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0VyYXNlckFjdGl2ZSh0aGlzLnN0YXRlKSkge1xuICAgICAgICBjb25zdCBkcmFnZ2VkRGlzdGFuY2UgPSBkaXN0YW5jZTJkKHRoaXMubGFzdFBvaW50ZXJEb3duLmNsaWVudFgsIHRoaXMubGFzdFBvaW50ZXJEb3duLmNsaWVudFksIHRoaXMubGFzdFBvaW50ZXJVcC5jbGllbnRYLCB0aGlzLmxhc3RQb2ludGVyVXAuY2xpZW50WSk7XG5cbiAgICAgICAgaWYgKGRyYWdnZWREaXN0YW5jZSA9PT0gMCkge1xuICAgICAgICAgIGNvbnN0IHNjZW5lUG9pbnRlciA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICAgICAgICBjbGllbnRYOiB0aGlzLmxhc3RQb2ludGVyVXAuY2xpZW50WCxcbiAgICAgICAgICAgIGNsaWVudFk6IHRoaXMubGFzdFBvaW50ZXJVcC5jbGllbnRZXG4gICAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgICAgICAgY29uc3QgaGl0RWxlbWVudHMgPSB0aGlzLmdldEVsZW1lbnRzQXRQb3NpdGlvbihzY2VuZVBvaW50ZXIueCwgc2NlbmVQb2ludGVyLnkpO1xuICAgICAgICAgIGhpdEVsZW1lbnRzLmZvckVhY2goaGl0RWxlbWVudCA9PiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2hpdEVsZW1lbnQuaWRdID0ge1xuICAgICAgICAgICAgZXJhc2U6IHRydWUsXG4gICAgICAgICAgICBvcGFjaXR5OiBoaXRFbGVtZW50Lm9wYWNpdHlcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZXJhc2VFbGVtZW50cyhwb2ludGVyRG93blN0YXRlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIGlmIChPYmplY3Qua2V5cyhwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlKS5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy5yZXN0b3JlUmVhZHlUb0VyYXNlRWxlbWVudHMocG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChoaXRFbGVtZW50ICYmICFwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgJiYgIXBvaW50ZXJEb3duU3RhdGUuaGl0Lndhc0FkZGVkVG9TZWxlY3Rpb24gJiYgKCAvLyBpZiB3ZSdyZSBlZGl0aW5nIGEgbGluZSwgcG9pbnRlcnVwIHNob3VsZG4ndCBzd2l0Y2ggc2VsZWN0aW9uIGlmXG4gICAgICAvLyBib3ggc2VsZWN0ZWRcbiAgICAgICF0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50IHx8ICFwb2ludGVyRG93blN0YXRlLmJveFNlbGVjdGlvbi5oYXNPY2N1cnJlZCkpIHtcbiAgICAgICAgLy8gd2hlbiBpbnNpZGUgbGluZSBlZGl0b3IsIHNoaWZ0IHNlbGVjdHMgcG9pbnRzIGluc3RlYWRcbiAgICAgICAgaWYgKGNoaWxkRXZlbnQuc2hpZnRLZXkgJiYgIXRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbaGl0RWxlbWVudC5pZF0pIHtcbiAgICAgICAgICAgIGlmIChpc1NlbGVjdGVkVmlhR3JvdXAodGhpcy5zdGF0ZSwgaGl0RWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShfcHJldlN0YXRlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzID0gT2JqZWN0LmFzc2lnbih7fSwgX3ByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpOyAvLyBXZSB3YW50IHRvIHVuc2VsZWN0IGFsbCBncm91cHMgaGl0RWxlbWVudCBpcyBwYXJ0IG9mXG4gICAgICAgICAgICAgICAgLy8gYXMgd2VsbCBhcyBhbGwgZWxlbWVudHMgdGhhdCBhcmUgcGFydCBvZiB0aGUgZ3JvdXBzXG4gICAgICAgICAgICAgICAgLy8gaGl0RWxlbWVudCBpcyBwYXJ0IG9mXG5cbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGdyb3VwZWRFbGVtZW50IG9mIGhpdEVsZW1lbnQuZ3JvdXBJZHMuZmxhdE1hcChncm91cElkID0+IGdldEVsZW1lbnRzSW5Hcm91cCh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBncm91cElkKSkpIHtcbiAgICAgICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2dyb3VwZWRFbGVtZW50LmlkXTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRHcm91cElkczogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBfcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyksIGhpdEVsZW1lbnQuZ3JvdXBJZHMubWFwKGdJZCA9PiAoe1xuICAgICAgICAgICAgICAgICAgICBbZ0lkXTogZmFsc2VcbiAgICAgICAgICAgICAgICAgIH0pKS5yZWR1Y2UoKHByZXYsIGFjYykgPT4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2KSwgYWNjKSwge30pKSxcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMobmV4dFNlbGVjdGVkRWxlbWVudElkcywgX3ByZXZTdGF0ZSlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB9KTsgLy8gaWYgbm90IGdyYWdnaW5nIGEgbGluZWFyIGVsZW1lbnQgcG9pbnQgKG91dHNpZGUgZWRpdG9yKVxuICAgICAgICAgICAgfSBlbHNlIGlmICghKChfZiA9IHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSA9PT0gbnVsbCB8fCBfZiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2YuaXNEcmFnZ2luZykpIHtcbiAgICAgICAgICAgICAgLy8gcmVtb3ZlIGVsZW1lbnQgZnJvbSBzZWxlY3Rpb24gd2hpbGVcbiAgICAgICAgICAgICAgLy8ga2VlcGluZyBwcmV2IGVsZW1lbnRzIHNlbGVjdGVkXG4gICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdTZWxlY3RlZEVsZW1lbnRJZHMgPSBPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgbmV3U2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1NlbGVjdGVkRWxlbWVudHMgPSBnZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIHtcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbmV3U2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgICAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogcHJldlN0YXRlLmVkaXRpbmdHcm91cElkLFxuICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBuZXdTZWxlY3RlZEVsZW1lbnRJZHNcbiAgICAgICAgICAgICAgICB9LCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBwcmV2U3RhdGUsIHRoaXMpKSwge1xuICAgICAgICAgICAgICAgICAgLy8gc2V0IHNlbGVjdGVkTGluZWFyRWxlbWVudCBvbmx5IGlmIHRoYXRzIHRoZSBvbmx5IGVsZW1lbnQgc2VsZWN0ZWRcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogbmV3U2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDEgJiYgaXNMaW5lYXJFbGVtZW50KG5ld1NlbGVjdGVkRWxlbWVudHNbMF0pID8gbmV3IExpbmVhckVsZW1lbnRFZGl0b3IobmV3U2VsZWN0ZWRFbGVtZW50c1swXSwgdGhpcy5zY2VuZSkgOiBwcmV2U3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoaGl0RWxlbWVudC5mcmFtZUlkICYmIHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuZnJhbWVJZF0pIHtcbiAgICAgICAgICAgIC8vIHdoZW4gaGl0RWxlbWVudCBpcyBwYXJ0IG9mIGEgc2VsZWN0ZWQgZnJhbWUsIGRlc2VsZWN0IHRoZSBmcmFtZVxuICAgICAgICAgICAgLy8gdG8gYXZvaWQgZnJhbWUgYW5kIGNvbnRhaW5pbmcgZWxlbWVudHMgc2VsZWN0ZWQgc2ltdWx0YW5lb3VzbHlcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgICAgICAgdmFyIF9hLCBfYjtcblxuICAgICAgICAgICAgICBjb25zdCBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKSwge1xuICAgICAgICAgICAgICAgIFtoaXRFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgICB9KTsgLy8gZGVzZWxlY3QgdGhlIGZyYW1lXG5cbiAgICAgICAgICAgICAgZGVsZXRlIG5leHRTZWxlY3RlZEVsZW1lbnRJZHNbaGl0RWxlbWVudC5mcmFtZUlkXTsgLy8gZGVzZWxlY3QgZ3JvdXBzIGNvbnRhaW5pbmcgdGhlIGZyYW1lXG5cbiAgICAgICAgICAgICAgKChfYiA9IChfYSA9IHRoaXMuc2NlbmUuZ2V0RWxlbWVudChoaXRFbGVtZW50LmZyYW1lSWQpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ3JvdXBJZHMpICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IFtdKS5mbGF0TWFwKGdpZCA9PiBnZXRFbGVtZW50c0luR3JvdXAodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZ2lkKSkuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBwcmV2U3RhdGUuZWRpdGluZ0dyb3VwSWQsXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgICAgICAgICAgIH0sIHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIHByZXZTdGF0ZSwgdGhpcykpLCB7XG4gICAgICAgICAgICAgICAgc2hvd0h5cGVybGlua1BvcHVwOiBoaXRFbGVtZW50LmxpbmsgfHwgaXNFbWJlZGRhYmxlRWxlbWVudChoaXRFbGVtZW50KSA/IFwiaW5mb1wiIDogZmFsc2VcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gYWRkIGVsZW1lbnQgdG8gc2VsZWN0aW9uIHdoaWxlIGtlZXBpbmcgcHJldiBlbGVtZW50cyBzZWxlY3RlZFxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShfcHJldlN0YXRlID0+ICh7XG4gICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBfcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyksIHtcbiAgICAgICAgICAgICAgICBbaGl0RWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgICAgfSksIF9wcmV2U3RhdGUpXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgICAgIHZhciBfYTtcblxuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBwcmV2U3RhdGUuZWRpdGluZ0dyb3VwSWQsXG4gICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczoge1xuICAgICAgICAgICAgICAgIFtoaXRFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBwcmV2U3RhdGUsIHRoaXMpKSwge1xuICAgICAgICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IGlzTGluZWFyRWxlbWVudChoaXRFbGVtZW50KSAmJiAvLyBEb24ndCBzZXQgYHNlbGVjdGVkTGluZWFyRWxlbWVudGAgaWYgaXRzIHNhbWUgYXMgdGhlIGhpdEVsZW1lbnQsIHRoaXMgaXMgbWFpbmx5IHRvIHByZXZlbnQgcmVzZXR0aW5nIHRoZSBgaG92ZXJQb2ludEluZGV4YCB0byAtMS5cbiAgICAgICAgICAgICAgLy8gRnV0dXJlIHdlIHNob3VsZCB1cGRhdGUgdGhlIEFQSSB0byB0YWtlIGNhcmUgb2Ygc2V0dGluZyB0aGUgY29ycmVjdCBgaG92ZXJQb2ludEluZGV4YCB3aGVuIGluaXRpYWxpemVkXG4gICAgICAgICAgICAgICgoX2EgPSBwcmV2U3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZWxlbWVudElkKSAhPT0gaGl0RWxlbWVudC5pZCA/IG5ldyBMaW5lYXJFbGVtZW50RWRpdG9yKGhpdEVsZW1lbnQsIHRoaXMuc2NlbmUpIDogcHJldlN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKCFwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgJiYgIXRoaXMuc3RhdGUuaXNSZXNpemluZyAmJiAoaGl0RWxlbWVudCAmJiBpc0hpdHRpbmdFbGVtZW50Qm91bmRpbmdCb3hXaXRob3V0SGl0dGluZ0VsZW1lbnQoaGl0RWxlbWVudCwgdGhpcy5zdGF0ZSwgdGhpcy5mcmFtZU5hbWVCb3VuZHNDYWNoZSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSkgfHwgIWhpdEVsZW1lbnQgJiYgcG9pbnRlckRvd25TdGF0ZS5oaXQuaGFzSGl0Q29tbW9uQm91bmRpbmdCb3hPZlNlbGVjdGVkRWxlbWVudHMpKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBlZGl0aW5nTGluZWFyRWxlbWVudDogbnVsbFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIERlc2VsZWN0IHNlbGVjdGVkIGVsZW1lbnRzXG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgICAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IHt9LFxuICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGwsXG4gICAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghYWN0aXZlVG9vbC5sb2NrZWQgJiYgYWN0aXZlVG9vbC50eXBlICE9PSBcImZyZWVkcmF3XCIgJiYgZHJhZ2dpbmdFbGVtZW50ICYmIGRyYWdnaW5nRWxlbWVudC50eXBlICE9PSBcInNlbGVjdGlvblwiKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+ICh7XG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyhPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLCB7XG4gICAgICAgICAgICBbZHJhZ2dpbmdFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgIH0pLCBwcmV2U3RhdGUpLFxuICAgICAgICAgIHNob3dIeXBlcmxpbmtQb3B1cDogaXNFbWJlZGRhYmxlRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQpICYmICFkcmFnZ2luZ0VsZW1lbnQubGluayA/IFwiZWRpdG9yXCIgOiBwcmV2U3RhdGUuc2hvd0h5cGVybGlua1BvcHVwXG4gICAgICAgIH0pKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIiB8fCBpc1NvbWVFbGVtZW50U2VsZWN0ZWQodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgdGhpcy5zdGF0ZSkpIHtcbiAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkIHx8IGlzUmVzaXppbmcgfHwgaXNSb3RhdGluZykge1xuICAgICAgICAoaXNCaW5kaW5nRW5hYmxlZCh0aGlzLnN0YXRlKSA/IGJpbmRPclVuYmluZFNlbGVjdGVkRWxlbWVudHMgOiB1bmJpbmRMaW5lYXJFbGVtZW50cykodGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFhY3RpdmVUb29sLmxvY2tlZCAmJiBhY3RpdmVUb29sLnR5cGUgIT09IFwiZnJlZWRyYXdcIikge1xuICAgICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBudWxsLFxuICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXSxcbiAgICAgICAgICBhY3RpdmVUb29sOiB1cGRhdGVBY3RpdmVUb29sKHRoaXMuc3RhdGUsIHtcbiAgICAgICAgICAgIHR5cGU6IFwic2VsZWN0aW9uXCJcbiAgICAgICAgICB9KVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW11cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChoaXRFbGVtZW50ICYmIHRoaXMubGFzdFBvaW50ZXJVcCAmJiB0aGlzLmxhc3RQb2ludGVyRG93biAmJiB0aGlzLmxhc3RQb2ludGVyVXAudGltZVN0YW1wIC0gdGhpcy5sYXN0UG9pbnRlckRvd24udGltZVN0YW1wIDwgMzAwICYmIGdlc3R1cmUucG9pbnRlcnMuc2l6ZSA8PSAxICYmIGlzRW1iZWRkYWJsZUVsZW1lbnQoaGl0RWxlbWVudCkgJiYgdGhpcy5pc0VtYmVkZGFibGVDZW50ZXIoaGl0RWxlbWVudCwgdGhpcy5sYXN0UG9pbnRlclVwLCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55KSkge1xuICAgICAgICB0aGlzLmhhbmRsZUVtYmVkZGFibGVDZW50ZXJDbGljayhoaXRFbGVtZW50KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIG1heWJlU3VnZ2VzdEJpbmRpbmdGb3JBbGwoc2VsZWN0ZWRFbGVtZW50cykge1xuICAgIGlmIChzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA+IDUwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3VnZ2VzdGVkQmluZGluZ3MgPSBnZXRFbGlnaWJsZUVsZW1lbnRzRm9yQmluZGluZyhzZWxlY3RlZEVsZW1lbnRzKTtcbiAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzXG4gICAgfSk7XG4gIH1cblxuICBjbGVhclNlbGVjdGlvbihoaXRFbGVtZW50KSB7XG4gICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4gKHtcbiAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe30sIHByZXZTdGF0ZSksXG4gICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsLFxuICAgICAgc2VsZWN0ZWRHcm91cElkczoge30sXG4gICAgICAvLyBDb250aW51ZSBlZGl0aW5nIHRoZSBzYW1lIGdyb3VwIGlmIHRoZSB1c2VyIHNlbGVjdGVkIGEgZGlmZmVyZW50XG4gICAgICAvLyBlbGVtZW50IGZyb20gaXRcbiAgICAgIGVkaXRpbmdHcm91cElkOiBwcmV2U3RhdGUuZWRpdGluZ0dyb3VwSWQgJiYgaGl0RWxlbWVudCAhPSBudWxsICYmIGlzRWxlbWVudEluR3JvdXAoaGl0RWxlbWVudCwgcHJldlN0YXRlLmVkaXRpbmdHcm91cElkKSA/IHByZXZTdGF0ZS5lZGl0aW5nR3JvdXBJZCA6IG51bGxcbiAgICB9KSk7XG4gICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGwsXG4gICAgICBwcmV2aW91c1NlbGVjdGVkRWxlbWVudElkczogdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNcbiAgICB9KTtcbiAgfVxuXG4gIGdldFRleHRXeXNpd3lnU25hcHBlZFRvQ2VudGVyUG9zaXRpb24oeCwgeSwgYXBwU3RhdGUsIGNvbnRhaW5lcikge1xuICAgIGlmIChjb250YWluZXIpIHtcbiAgICAgIGxldCBlbGVtZW50Q2VudGVyWCA9IGNvbnRhaW5lci54ICsgY29udGFpbmVyLndpZHRoIC8gMjtcbiAgICAgIGxldCBlbGVtZW50Q2VudGVyWSA9IGNvbnRhaW5lci55ICsgY29udGFpbmVyLmhlaWdodCAvIDI7XG4gICAgICBjb25zdCBlbGVtZW50Q2VudGVyID0gZ2V0Q29udGFpbmVyQ2VudGVyKGNvbnRhaW5lciwgYXBwU3RhdGUpO1xuXG4gICAgICBpZiAoZWxlbWVudENlbnRlcikge1xuICAgICAgICBlbGVtZW50Q2VudGVyWCA9IGVsZW1lbnRDZW50ZXIueDtcbiAgICAgICAgZWxlbWVudENlbnRlclkgPSBlbGVtZW50Q2VudGVyLnk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRpc3RhbmNlVG9DZW50ZXIgPSBNYXRoLmh5cG90KHggLSBlbGVtZW50Q2VudGVyWCwgeSAtIGVsZW1lbnRDZW50ZXJZKTtcbiAgICAgIGNvbnN0IGlzU25hcHBlZFRvQ2VudGVyID0gZGlzdGFuY2VUb0NlbnRlciA8IFRFWFRfVE9fQ0VOVEVSX1NOQVBfVEhSRVNIT0xEO1xuXG4gICAgICBpZiAoaXNTbmFwcGVkVG9DZW50ZXIpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHg6IHZpZXdwb3J0WCxcbiAgICAgICAgICB5OiB2aWV3cG9ydFlcbiAgICAgICAgfSA9IHNjZW5lQ29vcmRzVG9WaWV3cG9ydENvb3Jkcyh7XG4gICAgICAgICAgc2NlbmVYOiBlbGVtZW50Q2VudGVyWCxcbiAgICAgICAgICBzY2VuZVk6IGVsZW1lbnRDZW50ZXJZXG4gICAgICAgIH0sIGFwcFN0YXRlKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2aWV3cG9ydFgsXG4gICAgICAgICAgdmlld3BvcnRZLFxuICAgICAgICAgIGVsZW1lbnRDZW50ZXJYLFxuICAgICAgICAgIGVsZW1lbnRDZW50ZXJZXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZ2V0Q2FudmFzT2Zmc2V0cygpIHtcbiAgICB2YXIgX2E7XG5cbiAgICBpZiAoKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY3VycmVudCkge1xuICAgICAgY29uc3QgZXhjYWxpZHJhd0NvbnRhaW5lciA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50O1xuICAgICAgY29uc3Qge1xuICAgICAgICBsZWZ0LFxuICAgICAgICB0b3BcbiAgICAgIH0gPSBleGNhbGlkcmF3Q29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb2Zmc2V0TGVmdDogbGVmdCxcbiAgICAgICAgb2Zmc2V0VG9wOiB0b3BcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIG9mZnNldExlZnQ6IDAsXG4gICAgICBvZmZzZXRUb3A6IDBcbiAgICB9O1xuICB9XG5cbiAgdXBkYXRlTGFuZ3VhZ2UoKSB7XG4gICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRMYW5nID0gbGFuZ3VhZ2VzLmZpbmQobGFuZyA9PiBsYW5nLmNvZGUgPT09IHRoaXMucHJvcHMubGFuZ0NvZGUpIHx8IGRlZmF1bHRMYW5nO1xuICAgICAgeWllbGQgc2V0TGFuZ3VhZ2UoY3VycmVudExhbmcpO1xuICAgICAgdGhpcy5zZXRBcHBTdGF0ZSh7fSk7XG4gICAgfSk7XG4gIH1cblxufVxuXG5BcHAuZGVmYXVsdFByb3BzID0ge1xuICAvLyBuZWVkZWQgZm9yIHRlc3RzIHRvIHBhc3Mgc2luY2Ugd2UgZGlyZWN0bHkgcmVuZGVyIEFwcCBpbiBtYW55IHRlc3RzXG4gIFVJT3B0aW9uczogREVGQVVMVF9VSV9PUFRJT05TXG59O1xuXG5pZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IEVOVi5URVNUIHx8IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBcInByb2R1Y3Rpb25cIikge1xuICB3aW5kb3cuaCA9IHdpbmRvdy5oIHx8IHt9O1xuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh3aW5kb3cuaCwge1xuICAgIGVsZW1lbnRzOiB7XG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG5cbiAgICAgIGdldCgpIHtcbiAgICAgICAgdmFyIF9hO1xuXG4gICAgICAgIHJldHVybiAoX2EgPSB0aGlzLmFwcCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpO1xuICAgICAgfSxcblxuICAgICAgc2V0KGVsZW1lbnRzKSB7XG4gICAgICAgIHZhciBfYTtcblxuICAgICAgICByZXR1cm4gKF9hID0gdGhpcy5hcHApID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoZWxlbWVudHMpO1xuICAgICAgfVxuXG4gICAgfVxuICB9KTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgQXBwOyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///../../components/App.tsx\n");
2466
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ExcalidrawContainerContext\": () => (/* binding */ ExcalidrawContainerContext),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ \"useApp\": () => (/* binding */ useApp),\n/* harmony export */ \"useAppProps\": () => (/* binding */ useAppProps),\n/* harmony export */ \"useDevice\": () => (/* binding */ useDevice),\n/* harmony export */ \"useExcalidrawActionManager\": () => (/* binding */ useExcalidrawActionManager),\n/* harmony export */ \"useExcalidrawAppState\": () => (/* binding */ useExcalidrawAppState),\n/* harmony export */ \"useExcalidrawContainer\": () => (/* binding */ useExcalidrawContainer),\n/* harmony export */ \"useExcalidrawElements\": () => (/* binding */ useExcalidrawElements),\n/* harmony export */ \"useExcalidrawSetAppState\": () => (/* binding */ useExcalidrawSetAppState)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var nanoid__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! nanoid */ \"../../../node_modules/nanoid/index.browser.js\");\n/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../actions */ \"../../actions/index.ts\");\n/* harmony import */ var _actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../actions/actionHistory */ \"../../actions/actionHistory.tsx\");\n/* harmony import */ var _actions_manager__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../actions/manager */ \"../../actions/manager.tsx\");\n/* harmony import */ var _actions_register__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../actions/register */ \"../../actions/register.ts\");\n/* harmony import */ var _analytics__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../analytics */ \"../../analytics.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../appState */ \"../../appState.ts\");\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../clipboard */ \"../../clipboard.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../data */ \"../../data/index.ts\");\n/* harmony import */ var _data_library__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../data/library */ \"../../data/library.ts\");\n/* harmony import */ var _data_restore__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../data/restore */ \"../../data/restore.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../element */ \"../../element/index.ts\");\n/* harmony import */ var _element_binding__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../element/binding */ \"../../element/binding.ts\");\n/* harmony import */ var _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../element/linearElementEditor */ \"../../element/linearElementEditor.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../element/mutateElement */ \"../../element/mutateElement.ts\");\n/* harmony import */ var _element_newElement__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../element/newElement */ \"../../element/newElement.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../element/typeChecks */ \"../../element/typeChecks.ts\");\n/* harmony import */ var _gesture__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../gesture */ \"../../gesture.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../groups */ \"../../groups.ts\");\n/* harmony import */ var _history__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../history */ \"../../history.ts\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../i18n */ \"../../i18n.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../keys */ \"../../keys.ts\");\n/* harmony import */ var _element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../element/sizeHelpers */ \"../../element/sizeHelpers.ts\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../math */ \"../../math.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../scene */ \"../../scene/index.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../scene/Scene */ \"../../scene/Scene.ts\");\n/* harmony import */ var _scene_zoom__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../scene/zoom */ \"../../scene/zoom.ts\");\n/* harmony import */ var _shapes__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../shapes */ \"../../shapes.tsx\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../utils */ \"../../utils.ts\");\n/* harmony import */ var _element_embeddable__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ../element/embeddable */ \"../../element/embeddable.ts\");\n/* harmony import */ var _ContextMenu__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./ContextMenu */ \"../../components/ContextMenu.tsx\");\n/* harmony import */ var _LayerUI__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./LayerUI */ \"../../components/LayerUI.tsx\");\n/* harmony import */ var _Toast__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./Toast */ \"../../components/Toast.tsx\");\n/* harmony import */ var _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../actions/actionToggleViewMode */ \"../../actions/actionToggleViewMode.tsx\");\n/* harmony import */ var _data_blob__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../data/blob */ \"../../data/blob.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../element/image */ \"../../element/image.ts\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! lodash.throttle */ \"../../../node_modules/lodash.throttle/index.js\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_41___default = /*#__PURE__*/__webpack_require__.n(lodash_throttle__WEBPACK_IMPORTED_MODULE_41__);\n/* harmony import */ var _data_filesystem__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ../data/filesystem */ \"../../data/filesystem.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ../element/textElement */ \"../../element/textElement.ts\");\n/* harmony import */ var _element_collision__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ../element/collision */ \"../../element/collision.ts\");\n/* harmony import */ var _element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ../element/Hyperlink */ \"../../element/Hyperlink.tsx\");\n/* harmony import */ var _data_url__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ../data/url */ \"../../data/url.ts\");\n/* harmony import */ var _element_transformHandles__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ../element/transformHandles */ \"../../element/transformHandles.ts\");\n/* harmony import */ var _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ../actions/actionElementLock */ \"../../actions/actionElementLock.ts\");\n/* harmony import */ var _scene_Fonts__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ../scene/Fonts */ \"../../scene/Fonts.ts\");\n/* harmony import */ var _frame__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ../frame */ \"../../frame.ts\");\n/* harmony import */ var _scene_selection__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ../scene/selection */ \"../../scene/selection.ts\");\n/* harmony import */ var _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ../actions/actionClipboard */ \"../../actions/actionClipboard.tsx\");\n/* harmony import */ var _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ../actions/actionFrame */ \"../../actions/actionFrame.ts\");\n/* harmony import */ var _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ../actions/actionCanvas */ \"../../actions/actionCanvas.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ../jotai */ \"../../jotai.ts\");\n/* harmony import */ var _ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./ActiveConfirmDialog */ \"../../components/ActiveConfirmDialog.tsx\");\n/* harmony import */ var _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ../actions/actionBoundText */ \"../../actions/actionBoundText.tsx\");\n/* harmony import */ var _BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ./BraveMeasureTextError */ \"../../components/BraveMeasureTextError.tsx\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ./EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var _data_transform__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ../data/transform */ \"../../data/transform.ts\");\n/* harmony import */ var _Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./Sidebar/Sidebar */ \"../../components/Sidebar/Sidebar.tsx\");\n/* harmony import */ var _canvases__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ./canvases */ \"../../components/canvases/index.tsx\");\n/* harmony import */ var _scene_Renderer__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ../scene/Renderer */ \"../../scene/Renderer.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ../scene/ShapeCache */ \"../../scene/ShapeCache.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst AppContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst AppPropsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst deviceContextInitialValue = {\n isSmScreen: false,\n isMobile: false,\n isTouchScreen: false,\n canDeviceFitSidebar: false,\n isLandscape: false\n};\nconst DeviceContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(deviceContextInitialValue);\nDeviceContext.displayName = \"DeviceContext\";\nconst ExcalidrawContainerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext({\n container: null,\n id: null\n});\nExcalidrawContainerContext.displayName = \"ExcalidrawContainerContext\";\nconst ExcalidrawElementsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext([]);\nExcalidrawElementsContext.displayName = \"ExcalidrawElementsContext\";\nconst ExcalidrawAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n width: 0,\n height: 0,\n offsetLeft: 0,\n offsetTop: 0\n}));\nExcalidrawAppStateContext.displayName = \"ExcalidrawAppStateContext\";\nconst ExcalidrawSetAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(() => {\n console.warn(\"unitialized ExcalidrawSetAppStateContext context!\");\n});\nExcalidrawSetAppStateContext.displayName = \"ExcalidrawSetAppStateContext\";\nconst ExcalidrawActionManagerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nExcalidrawActionManagerContext.displayName = \"ExcalidrawActionManagerContext\";\nconst useApp = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppContext);\nconst useAppProps = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppPropsContext);\nconst useDevice = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(DeviceContext);\nconst useExcalidrawContainer = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawContainerContext);\nconst useExcalidrawElements = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawElementsContext);\nconst useExcalidrawAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawAppStateContext);\nconst useExcalidrawSetAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawSetAppStateContext);\nconst useExcalidrawActionManager = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawActionManagerContext);\nlet didTapTwice = false;\nlet tappedTwiceTimer = 0;\nlet isHoldingSpace = false;\nlet isPanning = false;\nlet isDraggingScrollBar = false;\nlet currentScrollBars = {\n horizontal: null,\n vertical: null\n};\nlet touchTimeout = 0;\nlet invalidateContextMenu = false;\n/**\n * Map of youtube embed video states\n */\n\nconst YOUTUBE_VIDEO_STATES = new Map();\nlet IS_PLAIN_PASTE = false;\nlet IS_PLAIN_PASTE_TIMER = 0;\nlet PLAIN_PASTE_TOAST_SHOWN = false;\nlet lastPointerUp = null;\nconst gesture = {\n pointers: new Map(),\n lastCenter: null,\n initialDistance: null,\n initialScale: null\n};\n\nclass App extends (react__WEBPACK_IMPORTED_MODULE_1___default().Component) {\n constructor(props) {\n var _a;\n\n super(props);\n this.interactiveCanvas = null;\n this.unmounted = false;\n this.device = deviceContextInitialValue;\n this.excalidrawContainerRef = react__WEBPACK_IMPORTED_MODULE_1___default().createRef();\n this.files = {};\n this.imageCache = new Map();\n this.iFrameRefs = new Map();\n this.lastPointerDown = null;\n this.lastPointerUp = null;\n this.lastViewportPosition = {\n x: 0,\n y: 0\n };\n\n this.updateEmbeddables = () => {\n const embeddableElements = new Map();\n let updated = false;\n this.scene.getNonDeletedElements().filter(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(element)) {\n embeddableElements.set(element.id, true);\n\n if (element.validated == null) {\n updated = true;\n const validated = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.embeddableURLValidator)(element.link, this.props.validateEmbeddable);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n validated\n }, false);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element);\n }\n }\n\n return false;\n });\n\n if (updated) {\n this.scene.informMutation();\n } // GC\n\n\n this.iFrameRefs.forEach((ref, id) => {\n if (!embeddableElements.has(id)) {\n this.iFrameRefs.delete(id);\n }\n });\n };\n\n this.getFrameNameDOMId = frameElement => {\n return `${this.id}-frame-name-${frameElement.id}`;\n };\n\n this.frameNameBoundsCache = {\n get: frameElement => {\n let bounds = this.frameNameBoundsCache._cache.get(frameElement.id);\n\n if (!bounds || bounds.zoom !== this.state.zoom.value || bounds.versionNonce !== frameElement.versionNonce) {\n const frameNameDiv = document.getElementById(this.getFrameNameDOMId(frameElement));\n\n if (frameNameDiv) {\n const box = frameNameDiv.getBoundingClientRect();\n const boxSceneTopLeft = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: box.x,\n clientY: box.y\n }, this.state);\n const boxSceneBottomRight = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: box.right,\n clientY: box.bottom\n }, this.state);\n bounds = {\n x: boxSceneTopLeft.x,\n y: boxSceneTopLeft.y,\n width: boxSceneBottomRight.x - boxSceneTopLeft.x,\n height: boxSceneBottomRight.y - boxSceneTopLeft.y,\n angle: 0,\n zoom: this.state.zoom.value,\n versionNonce: frameElement.versionNonce\n };\n\n this.frameNameBoundsCache._cache.set(frameElement.id, bounds);\n\n return bounds;\n }\n\n return null;\n }\n\n return bounds;\n },\n\n /**\n * @private\n */\n _cache: new Map()\n };\n\n this.renderFrameNames = () => {\n if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {\n return null;\n }\n\n const isDarkTheme = this.state.theme === \"dark\";\n return this.scene.getNonDeletedFrames().map((f, index) => {\n if (!(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(f, this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n })) {\n // if frame not visible, don't render its name\n return null;\n }\n\n const {\n x: x1,\n y: y1\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: f.x,\n sceneY: f.y\n }, this.state);\n const {\n x: x2\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: f.x + f.width,\n sceneY: f.y + f.height\n }, this.state);\n const FRAME_NAME_GAP = 20;\n const FRAME_NAME_EDIT_PADDING = 6;\n\n const reset = () => {\n var _a;\n\n if (((_a = f.name) === null || _a === void 0 ? void 0 : _a.trim()) === \"\") {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: null\n });\n }\n\n this.setState({\n editingFrame: null\n });\n };\n\n let frameNameJSX;\n\n if (f.id === this.state.editingFrame) {\n const frameNameInEdit = f.name == null ? `Frame ${index + 1}` : f.name;\n frameNameJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"input\", {\n autoFocus: true,\n value: frameNameInEdit,\n onChange: e => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: e.target.value\n });\n },\n onBlur: () => reset(),\n onKeyDown: event => {\n // for some inexplicable reason, `onBlur` triggered on ESC\n // does not reset `state.editingFrame` despite being called,\n // and we need to reset it here as well\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n reset();\n }\n },\n style: {\n background: this.state.viewBackgroundColor,\n filter: isDarkTheme ? _constants__WEBPACK_IMPORTED_MODULE_12__.THEME_FILTER : \"none\",\n zIndex: 2,\n border: \"none\",\n display: \"block\",\n padding: `${FRAME_NAME_EDIT_PADDING}px`,\n borderRadius: 4,\n boxShadow: \"inset 0 0 0 1px var(--color-primary)\",\n fontFamily: \"Assistant\",\n fontSize: \"14px\",\n transform: `translateY(-${FRAME_NAME_EDIT_PADDING}px)`,\n color: \"var(--color-gray-80)\",\n overflow: \"hidden\",\n maxWidth: `${Math.min(x2 - x1 - FRAME_NAME_EDIT_PADDING, document.body.clientWidth - x1 - FRAME_NAME_EDIT_PADDING)}px`\n },\n size: frameNameInEdit.length + 1 || 1,\n dir: \"auto\",\n autoComplete: \"off\",\n autoCapitalize: \"off\",\n autoCorrect: \"off\"\n });\n } else {\n frameNameJSX = f.name == null || f.name.trim() === \"\" ? `Frame ${index + 1}` : f.name.trim();\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n id: this.getFrameNameDOMId(f),\n style: {\n position: \"absolute\",\n top: `${y1 - FRAME_NAME_GAP - this.state.offsetTop}px`,\n left: `${x1 - this.state.offsetLeft - (this.state.editingFrame === f.id ? FRAME_NAME_EDIT_PADDING : 0)}px`,\n zIndex: 2,\n fontSize: \"14px\",\n color: isDarkTheme ? \"var(--color-gray-60)\" : \"var(--color-gray-50)\",\n width: \"max-content\",\n maxWidth: `${x2 - x1 + FRAME_NAME_EDIT_PADDING * 2}px`,\n overflow: f.id === this.state.editingFrame ? \"visible\" : \"hidden\",\n whiteSpace: \"nowrap\",\n textOverflow: \"ellipsis\",\n cursor: _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE,\n pointerEvents: this.state.viewModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.inheritFromUI\n },\n onPointerDown: event => this.handleCanvasPointerDown(event),\n onWheel: event => this.handleWheel(event),\n onContextMenu: this.handleCanvasContextMenu,\n onDoubleClick: () => {\n this.setState({\n editingFrame: f.id\n });\n }\n }, {\n children: frameNameJSX\n }), f.id);\n });\n };\n\n this.focusContainer = () => {\n var _a;\n\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.focus();\n };\n\n this.getSceneElementsIncludingDeleted = () => {\n return this.scene.getElementsIncludingDeleted();\n };\n\n this.getSceneElements = () => {\n return this.scene.getNonDeletedElements();\n };\n\n this.onInsertElements = elements => {\n this.addElementsFromPasteOrLibrary({\n elements,\n position: \"center\",\n files: null\n });\n };\n\n this.onExportImage = (type, elements) => __awaiter(this, void 0, void 0, function* () {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"export\", type, \"ui\");\n const fileHandle = yield (0,_data__WEBPACK_IMPORTED_MODULE_13__.exportCanvas)(type, elements, this.state, this.files, {\n exportBackground: this.state.exportBackground,\n name: this.state.name,\n viewBackgroundColor: this.state.viewBackgroundColor\n }).catch(_utils__WEBPACK_IMPORTED_MODULE_33__.muteFSAbortError).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: error.message\n });\n });\n\n if (this.state.exportEmbedScene && fileHandle && (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isImageFileHandle)(fileHandle)) {\n this.setState({\n fileHandle\n });\n }\n });\n\n this.openEyeDropper = ({\n type\n }) => {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_EyeDropper__WEBPACK_IMPORTED_MODULE_59__.activeEyeDropperAtom, {\n swapPreviewOnAlt: true,\n colorPickerType: type === \"stroke\" ? \"elementStroke\" : \"elementBackground\",\n onSelect: (color, event) => {\n const shouldUpdateStrokeColor = type === \"background\" && event.altKey || type === \"stroke\" && !event.altKey;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (!selectedElements.length || this.state.activeTool.type !== \"selection\") {\n if (shouldUpdateStrokeColor) {\n this.syncActionResult({\n appState: Object.assign(Object.assign({}, this.state), {\n currentItemStrokeColor: color\n }),\n commitToHistory: true\n });\n } else {\n this.syncActionResult({\n appState: Object.assign(Object.assign({}, this.state), {\n currentItemBackgroundColor: color\n }),\n commitToHistory: true\n });\n }\n } else {\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().map(el => {\n if (this.state.selectedElementIds[el.id]) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(el, {\n [shouldUpdateStrokeColor ? \"strokeColor\" : \"backgroundColor\"]: color\n });\n }\n\n return el;\n })\n });\n }\n },\n keepOpenOnAlt: false\n });\n };\n\n this.syncActionResult = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(actionResult => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j;\n\n if (this.unmounted || actionResult === false) {\n return;\n }\n\n let editingElement = null;\n\n if (actionResult.elements) {\n actionResult.elements.forEach(element => {\n var _a;\n\n if (((_a = this.state.editingElement) === null || _a === void 0 ? void 0 : _a.id) === element.id && this.state.editingElement !== element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element)) {\n editingElement = element;\n }\n });\n this.scene.replaceAllElements(actionResult.elements);\n\n if (actionResult.commitToHistory) {\n this.history.resumeRecording();\n }\n }\n\n if (actionResult.files) {\n this.files = actionResult.replaceFiles ? actionResult.files : Object.assign(Object.assign({}, this.files), actionResult.files);\n this.addNewImagesToImageCache();\n }\n\n if (actionResult.appState || editingElement || this.state.contextMenu) {\n if (actionResult.commitToHistory) {\n this.history.resumeRecording();\n }\n\n let viewModeEnabled = ((_a = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _a === void 0 ? void 0 : _a.viewModeEnabled) || false;\n let zenModeEnabled = ((_b = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _b === void 0 ? void 0 : _b.zenModeEnabled) || false;\n let gridSize = ((_c = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _c === void 0 ? void 0 : _c.gridSize) || null;\n const theme = ((_d = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _d === void 0 ? void 0 : _d.theme) || this.props.theme || _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.LIGHT;\n let name = (_f = (_e = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : this.state.name;\n const errorMessage = (_h = (_g = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _g === void 0 ? void 0 : _g.errorMessage) !== null && _h !== void 0 ? _h : this.state.errorMessage;\n\n if (typeof this.props.viewModeEnabled !== \"undefined\") {\n viewModeEnabled = this.props.viewModeEnabled;\n }\n\n if (typeof this.props.zenModeEnabled !== \"undefined\") {\n zenModeEnabled = this.props.zenModeEnabled;\n }\n\n if (typeof this.props.gridModeEnabled !== \"undefined\") {\n gridSize = this.props.gridModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.GRID_SIZE : null;\n }\n\n if (typeof this.props.name !== \"undefined\") {\n name = this.props.name;\n }\n\n editingElement = editingElement || ((_j = actionResult.appState) === null || _j === void 0 ? void 0 : _j.editingElement) || null;\n\n if (editingElement === null || editingElement === void 0 ? void 0 : editingElement.isDeleted) {\n editingElement = null;\n }\n\n this.setState(state => {\n // using Object.assign instead of spread to fool TS 4.2.2+ into\n // regarding the resulting type as not containing undefined\n // (which the following expression will never contain)\n return Object.assign(actionResult.appState || {}, {\n // NOTE this will prevent opening context menu using an action\n // or programmatically from the host, so it will need to be\n // rewritten later\n contextMenu: null,\n editingElement,\n viewModeEnabled,\n zenModeEnabled,\n gridSize,\n theme,\n name,\n errorMessage\n });\n }, () => {\n if (actionResult.syncHistory) {\n this.history.setCurrentState(this.state, this.scene.getElementsIncludingDeleted());\n }\n });\n }\n }); // Lifecycle\n\n this.onBlur = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(() => {\n isHoldingSpace = false;\n this.setState({\n isBindingEnabled: true\n });\n });\n\n this.onUnload = () => {\n this.onBlur();\n };\n\n this.disableEvent = event => {\n event.preventDefault();\n };\n\n this.resetHistory = () => {\n this.history.clear();\n };\n /**\n * Resets scene & history.\n * ! Do not use to clear scene user action !\n */\n\n\n this.resetScene = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(opts => {\n this.scene.replaceAllElements([]);\n this.setState(state => Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n isLoading: (opts === null || opts === void 0 ? void 0 : opts.resetLoadingState) ? false : state.isLoading,\n theme: this.state.theme\n }));\n this.resetHistory();\n });\n\n this.initializeScene = () => __awaiter(this, void 0, void 0, function* () {\n var _b;\n\n if (\"launchQueue\" in window && \"LaunchParams\" in window) {\n window.launchQueue.setConsumer(launchParams => __awaiter(this, void 0, void 0, function* () {\n if (!launchParams.files.length) {\n return;\n }\n\n const fileHandle = launchParams.files[0];\n const blob = yield fileHandle.getFile();\n this.loadFileToCanvas(new File([blob], blob.name || \"\", {\n type: blob.type\n }), fileHandle);\n }));\n }\n\n if (this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n if (!this.state.isLoading) {\n this.setState({\n isLoading: true\n });\n }\n\n let initialData = null;\n\n try {\n initialData = (yield this.props.initialData) || null;\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.libraryItems) {\n this.library.updateLibrary({\n libraryItems: initialData.libraryItems,\n merge: true\n }).catch(error => {\n console.error(error);\n });\n }\n } catch (error) {\n console.error(error);\n initialData = {\n appState: {\n errorMessage: error.message || \"Encountered an error during importing or restoring scene data\"\n }\n };\n }\n\n const scene = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restore)(initialData, null, null, {\n repairBindings: true\n });\n scene.appState = Object.assign(Object.assign({}, scene.appState), {\n theme: this.props.theme || scene.appState.theme,\n // we're falling back to current (pre-init) state when deciding\n // whether to open the library, to handle a case where we\n // update the state outside of initialData (e.g. when loading the app\n // with a library install link, which should auto-open the library)\n openSidebar: ((_b = scene.appState) === null || _b === void 0 ? void 0 : _b.openSidebar) || this.state.openSidebar,\n activeTool: scene.appState.activeTool.type === \"image\" ? Object.assign(Object.assign({}, scene.appState.activeTool), {\n type: \"selection\"\n }) : scene.appState.activeTool,\n isLoading: false,\n toast: this.state.toast\n });\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.scrollToContent) {\n scene.appState = Object.assign(Object.assign({}, scene.appState), (0,_scene__WEBPACK_IMPORTED_MODULE_29__.calculateScrollCenter)(scene.elements, Object.assign(Object.assign({}, scene.appState), {\n width: this.state.width,\n height: this.state.height,\n offsetTop: this.state.offsetTop,\n offsetLeft: this.state.offsetLeft\n })));\n } // FontFaceSet loadingdone event we listen on may not always fire\n // (looking at you Safari), so on init we manually load fonts for current\n // text elements on canvas, and rerender them once done. This also\n // seems faster even in browsers that do fire the loadingdone event.\n\n\n this.fonts.loadFontsForElements(scene.elements);\n this.resetHistory();\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n commitToHistory: true\n }));\n });\n\n this.refreshDeviceState = container => {\n const {\n width,\n height\n } = container.getBoundingClientRect();\n const sidebarBreakpoint = this.props.UIOptions.dockedSidebarBreakpoint != null ? this.props.UIOptions.dockedSidebarBreakpoint : _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_RIGHT_SIDEBAR_MIN_WIDTH;\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateObject)(this.device, {\n isLandscape: width > height,\n isSmScreen: width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_SM_MAX_WIDTH,\n isMobile: width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_PORTRAIT || height < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_HEIGHT_LANDSCAPE && width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_LANDSCAPE,\n canDeviceFitSidebar: width > sidebarBreakpoint\n });\n };\n\n this.onResize = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(() => {\n this.scene.getElementsIncludingDeleted().forEach(element => _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element));\n this.setState({});\n });\n\n this.renderInteractiveSceneCallback = ({\n atLeastOneVisibleElement,\n scrollBars,\n elements\n }) => {\n if (scrollBars) {\n currentScrollBars = scrollBars;\n }\n\n const scrolledOutside = // hide when editing text\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement) ? false : !atLeastOneVisibleElement && elements.length > 0;\n\n if (this.state.scrolledOutside !== scrolledOutside) {\n this.setState({\n scrolledOutside\n });\n }\n\n this.scheduleImageRefresh();\n };\n\n this.onScroll = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.debounce)(() => {\n const {\n offsetTop,\n offsetLeft\n } = this.getCanvasOffsets();\n this.setState(state => {\n if (state.offsetLeft === offsetLeft && state.offsetTop === offsetTop) {\n return null;\n }\n\n return {\n offsetTop,\n offsetLeft\n };\n });\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.SCROLL_TIMEOUT); // Copy/paste\n\n this.onCut = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target)) {\n return;\n }\n\n this.cutAll();\n event.preventDefault();\n event.stopPropagation();\n });\n this.onCopy = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target)) {\n return;\n }\n\n this.copyAll();\n event.preventDefault();\n event.stopPropagation();\n });\n\n this.cutAll = () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, \"keyboard\");\n };\n\n this.copyAll = () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, \"keyboard\");\n };\n\n this.onTouchStart = event => {\n // fix for Apple Pencil Scribble\n // On Android, preventing the event would disable contextMenu on tap-hold\n if (!_constants__WEBPACK_IMPORTED_MODULE_12__.isAndroid) {\n event.preventDefault();\n }\n\n if (!didTapTwice) {\n didTapTwice = true;\n clearTimeout(tappedTwiceTimer);\n tappedTwiceTimer = window.setTimeout(App.resetTapTwice, _constants__WEBPACK_IMPORTED_MODULE_12__.TAP_TWICE_TIMEOUT);\n return;\n } // insert text only if we tapped twice with a single finger\n // event.touches.length === 1 will also prevent inserting text when user's zooming\n\n\n if (didTapTwice && event.touches.length === 1) {\n const touch = event.touches[0]; // @ts-ignore\n\n this.handleCanvasDoubleClick({\n clientX: touch.clientX,\n clientY: touch.clientY\n });\n didTapTwice = false;\n clearTimeout(tappedTwiceTimer);\n }\n\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.isAndroid) {\n event.preventDefault();\n }\n\n if (event.touches.length === 2) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n };\n\n this.onTouchEnd = event => {\n this.resetContextMenuTimer();\n\n if (event.touches.length > 0) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n } else {\n gesture.pointers.clear();\n }\n };\n\n this.pasteFromClipboard = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => __awaiter(this, void 0, void 0, function* () {\n var _c, _d, _e;\n\n const isPlainPaste = !!(IS_PLAIN_PASTE && event); // #686\n\n const target = document.activeElement;\n const isExcalidrawActive = (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.contains(target);\n\n if (event && !isExcalidrawActive) {\n return;\n }\n\n const elementUnderCursor = document.elementFromPoint(this.lastViewportPosition.x, this.lastViewportPosition.y);\n\n if (event && (!(elementUnderCursor instanceof HTMLCanvasElement) || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(target))) {\n return;\n } // must be called in the same frame (thus before any awaits) as the paste\n // event else some browsers (FF...) will clear the clipboardData\n // (something something security)\n\n\n let file = (_d = event === null || event === void 0 ? void 0 : event.clipboardData) === null || _d === void 0 ? void 0 : _d.files[0];\n const data = yield (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.parseClipboard)(event, isPlainPaste);\n\n if (!file && data.text && !isPlainPaste) {\n const string = data.text.trim();\n\n if (string.startsWith(\"<svg\") && string.endsWith(\"</svg>\")) {\n // ignore SVG validation/normalization which will be done during image\n // initialization\n file = (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.SVGStringToFile)(string);\n }\n }\n\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state); // prefer spreadsheet data over image file (MS Office/Libre Office)\n\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isSupportedImageFile)(file) && !data.spreadsheet) {\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n\n if (this.props.onPaste) {\n try {\n if ((yield this.props.onPaste(data, event)) === false) {\n return;\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n if (data.errorMessage) {\n this.setState({\n errorMessage: data.errorMessage\n });\n } else if (data.spreadsheet && !isPlainPaste) {\n this.setState({\n pasteDialog: {\n data: data.spreadsheet,\n shown: true\n }\n });\n } else if (data.elements) {\n const elements = data.programmaticAPI ? (0,_data_transform__WEBPACK_IMPORTED_MODULE_60__.convertToExcalidrawElements)(data.elements) : data.elements; // TODO remove formatting from elements if isPlainPaste\n\n this.addElementsFromPasteOrLibrary({\n elements,\n files: data.files || null,\n position: \"cursor\",\n retainSeed: isPlainPaste\n });\n } else if (data.text) {\n const maybeUrl = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.extractSrc)(data.text);\n\n if (!isPlainPaste && (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.embeddableURLValidator)(maybeUrl, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(maybeUrl) || ((_e = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)(maybeUrl)) === null || _e === void 0 ? void 0 : _e.type) === \"video\")) {\n const embeddable = this.insertEmbeddableElement({\n sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(maybeUrl)\n });\n\n if (embeddable) {\n this.setState({\n selectedElementIds: {\n [embeddable.id]: true\n }\n });\n }\n\n return;\n }\n\n this.addTextFromPaste(data.text, isPlainPaste);\n }\n\n this.setActiveTool({\n type: \"selection\"\n });\n event === null || event === void 0 ? void 0 : event.preventDefault();\n }));\n\n this.addElementsFromPasteOrLibrary = opts => {\n const elements = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restoreElements)(opts.elements, null, undefined);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(elements);\n const elementsCenterX = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(minX, maxX) / 2;\n const elementsCenterY = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(minY, maxY) / 2;\n const clientX = typeof opts.position === \"object\" ? opts.position.clientX : opts.position === \"cursor\" ? this.lastViewportPosition.x : this.state.width / 2 + this.state.offsetLeft;\n const clientY = typeof opts.position === \"object\" ? opts.position.clientY : opts.position === \"cursor\" ? this.lastViewportPosition.y : this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const dx = x - elementsCenterX;\n const dy = y - elementsCenterY;\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(dx, dy, this.state.gridSize);\n const newElements = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.duplicateElements)(elements.map(element => {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n x: element.x + gridX - minX,\n y: element.y + gridY - minY\n });\n }), {\n randomizeSeed: !opts.retainSeed\n });\n const nextElements = [...this.scene.getElementsIncludingDeleted(), ...newElements];\n this.scene.replaceAllElements(nextElements);\n newElements.forEach(newElement => {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(newElement) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(newElement)) {\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerElement)(newElement);\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.redrawTextBoundingBox)(newElement, container);\n }\n });\n\n if (opts.files) {\n this.files = Object.assign(Object.assign({}, this.files), opts.files);\n }\n\n this.history.resumeRecording();\n const nextElementsToSelect = (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.excludeElementsInFramesFromSelection)(newElements);\n this.setState(Object.assign(Object.assign(Object.assign({}, this.state), {\n // keep sidebar (presumably the library) open if it's docked and\n // can fit.\n //\n // Note, we should close the sidebar only if we're dropping items\n // from library, not when pasting from clipboard. Alas.\n openSidebar: this.state.openSidebar && this.device.canDeviceFitSidebar && _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.get(_Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_61__.isSidebarDockedAtom) ? this.state.openSidebar : null\n }), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: null,\n selectedElementIds: nextElementsToSelect.reduce((acc, element) => {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(element)) {\n acc[element.id] = true;\n }\n\n return acc;\n }, {})\n }, this.scene.getNonDeletedElements(), this.state, this)), () => {\n if (opts.files) {\n this.addNewImagesToImageCache();\n }\n });\n this.setActiveTool({\n type: \"selection\"\n });\n };\n\n this.setAppState = (state, callback) => {\n this.setState(state, callback);\n };\n\n this.removePointer = event => {\n if (touchTimeout) {\n this.resetContextMenuTimer();\n }\n\n gesture.pointers.delete(event.pointerId);\n };\n\n this.toggleLock = (source = \"ui\") => {\n if (!this.state.activeTool.locked) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", \"toggleLock\", `${source} (${this.device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n this.setState(prevState => {\n return {\n activeTool: Object.assign(Object.assign(Object.assign({}, prevState.activeTool), (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, prevState.activeTool.locked ? {\n type: \"selection\"\n } : prevState.activeTool)), {\n locked: !prevState.activeTool.locked\n })\n };\n });\n };\n\n this.updateFrameRendering = opts => {\n this.setState(prevState => {\n var _a, _b, _c, _d;\n\n const next = typeof opts === \"function\" ? opts(prevState.frameRendering) : opts;\n return {\n frameRendering: {\n enabled: (_a = next === null || next === void 0 ? void 0 : next.enabled) !== null && _a !== void 0 ? _a : prevState.frameRendering.enabled,\n clip: (_b = next === null || next === void 0 ? void 0 : next.clip) !== null && _b !== void 0 ? _b : prevState.frameRendering.clip,\n name: (_c = next === null || next === void 0 ? void 0 : next.name) !== null && _c !== void 0 ? _c : prevState.frameRendering.name,\n outline: (_d = next === null || next === void 0 ? void 0 : next.outline) !== null && _d !== void 0 ? _d : prevState.frameRendering.outline\n }\n };\n });\n };\n\n this.togglePenMode = () => {\n this.setState(prevState => {\n return {\n penMode: !prevState.penMode\n };\n });\n };\n\n this.onHandToolToggle = () => {\n this.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleHandTool);\n };\n /**\n * Zooms on canvas viewport center\n */\n\n\n this.zoomCanvas = (\n /** decimal fraction between 0.1 (10% zoom) and 30 (3000% zoom) */\n value) => {\n this.setState(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: this.state.width / 2 + this.state.offsetLeft,\n viewportY: this.state.height / 2 + this.state.offsetTop,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(value)\n }, this.state)));\n };\n\n this.cancelInProgresAnimation = null;\n\n this.scrollToContent = (target = this.scene.getNonDeletedElements(), opts) => {\n var _a, _b;\n\n (_a = this.cancelInProgresAnimation) === null || _a === void 0 ? void 0 : _a.call(this); // convert provided target into ExcalidrawElement[] if necessary\n\n const targetElements = Array.isArray(target) ? target : [target];\n let zoom = this.state.zoom;\n let scrollX = this.state.scrollX;\n let scrollY = this.state.scrollY;\n\n if ((opts === null || opts === void 0 ? void 0 : opts.fitToContent) || (opts === null || opts === void 0 ? void 0 : opts.fitToViewport)) {\n const {\n appState\n } = (0,_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.zoomToFit)({\n targetElements,\n appState: this.state,\n fitToViewport: !!(opts === null || opts === void 0 ? void 0 : opts.fitToViewport),\n viewportZoomFactor: opts === null || opts === void 0 ? void 0 : opts.viewportZoomFactor\n });\n zoom = appState.zoom;\n scrollX = appState.scrollX;\n scrollY = appState.scrollY;\n } else {\n // compute only the viewport location, without any zoom adjustment\n const scroll = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.calculateScrollCenter)(targetElements, this.state);\n scrollX = scroll.scrollX;\n scrollY = scroll.scrollY;\n } // when animating, we use RequestAnimationFrame to prevent the animation\n // from slowing down other processes\n\n\n if (opts === null || opts === void 0 ? void 0 : opts.animate) {\n const origScrollX = this.state.scrollX;\n const origScrollY = this.state.scrollY;\n const origZoom = this.state.zoom.value;\n const cancel = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.easeToValuesRAF)({\n fromValues: {\n scrollX: origScrollX,\n scrollY: origScrollY,\n zoom: origZoom\n },\n toValues: {\n scrollX,\n scrollY,\n zoom: zoom.value\n },\n interpolateValue: (from, to, progress, key) => {\n // for zoom, use different easing\n if (key === \"zoom\") {\n return from * Math.pow(to / from, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.easeOut)(progress));\n } // handle using default\n\n\n return undefined;\n },\n onStep: ({\n scrollX,\n scrollY,\n zoom\n }) => {\n this.setState({\n scrollX,\n scrollY,\n zoom: {\n value: zoom\n }\n });\n },\n onStart: () => {\n this.setState({\n shouldCacheIgnoreZoom: true\n });\n },\n onEnd: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n onCancel: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n duration: (_b = opts === null || opts === void 0 ? void 0 : opts.duration) !== null && _b !== void 0 ? _b : 500\n });\n\n this.cancelInProgresAnimation = () => {\n cancel();\n this.cancelInProgresAnimation = null;\n };\n } else {\n this.setState({\n scrollX,\n scrollY,\n zoom\n });\n }\n };\n /** use when changing scrollX/scrollY/zoom based on user interaction */\n\n\n this.translateCanvas = state => {\n var _a;\n\n (_a = this.cancelInProgresAnimation) === null || _a === void 0 ? void 0 : _a.call(this);\n this.setState(state);\n };\n\n this.setToast = toast => {\n this.setState({\n toast\n });\n };\n\n this.restoreFileFromShare = () => __awaiter(this, void 0, void 0, function* () {\n try {\n const webShareTargetCache = yield caches.open(\"web-share-target\");\n const response = yield webShareTargetCache.match(\"shared-file\");\n\n if (response) {\n const blob = yield response.blob();\n const file = new File([blob], blob.name || \"\", {\n type: blob.type\n });\n this.loadFileToCanvas(file, null);\n yield webShareTargetCache.delete(\"shared-file\");\n window.history.replaceState(null, _constants__WEBPACK_IMPORTED_MODULE_12__.APP_NAME, window.location.pathname);\n }\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n });\n /** adds supplied files to existing files in the appState */\n\n\n this.addFiles = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(files => {\n const filesMap = files.reduce((acc, fileData) => {\n acc.set(fileData.id, fileData);\n return acc;\n }, new Map());\n this.files = Object.assign(Object.assign({}, this.files), Object.fromEntries(filesMap));\n this.scene.getNonDeletedElements().forEach(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && filesMap.has(element.fileId)) {\n this.imageCache.delete(element.fileId);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element);\n }\n });\n this.scene.informMutation();\n this.addNewImagesToImageCache();\n });\n this.updateScene = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(sceneData => {\n if (sceneData.commitToHistory) {\n this.history.resumeRecording();\n }\n\n if (sceneData.appState) {\n this.setState(sceneData.appState);\n }\n\n if (sceneData.elements) {\n this.scene.replaceAllElements(sceneData.elements);\n }\n\n if (sceneData.collaborators) {\n this.setState({\n collaborators: sceneData.collaborators\n });\n }\n });\n\n this.onSceneUpdated = () => {\n this.setState({});\n };\n /**\n * @returns whether the menu was toggled on or off\n */\n\n\n this.toggleSidebar = ({\n name,\n tab,\n force\n }) => {\n var _a;\n\n let nextName;\n\n if (force === undefined) {\n nextName = ((_a = this.state.openSidebar) === null || _a === void 0 ? void 0 : _a.name) === name ? null : name;\n } else {\n nextName = force ? name : null;\n }\n\n this.setState({\n openSidebar: nextName ? {\n name: nextName,\n tab\n } : null\n });\n return !!nextName;\n };\n\n this.updateCurrentCursorPosition = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n this.lastViewportPosition.x = event.clientX;\n this.lastViewportPosition.y = event.clientY;\n }); // Input handling\n\n this.onKeyDown = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n // normalize `event.key` when CapsLock is pressed #2372\n if (\"Proxy\" in window && (!event.shiftKey && /^[A-Z]$/.test(event.key) || event.shiftKey && /^[a-z]$/.test(event.key))) {\n event = new Proxy(event, {\n get(ev, prop) {\n const value = ev[prop];\n\n if (typeof value === \"function\") {\n // fix for Proxies hijacking `this`\n return value.bind(ev);\n }\n\n return prop === \"key\" ? // CapsLock inverts capitalization based on ShiftKey, so invert\n // it back\n event.shiftKey ? ev.key.toUpperCase() : ev.key.toLowerCase() : value;\n }\n\n });\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.V) {\n IS_PLAIN_PASTE = event.shiftKey;\n clearTimeout(IS_PLAIN_PASTE_TIMER); // reset (100ms to be safe that we it runs after the ensuing\n // paste event). Though, technically unnecessary to reset since we\n // (re)set the flag before each paste event.\n\n IS_PLAIN_PASTE_TIMER = window.setTimeout(() => {\n IS_PLAIN_PASTE = false;\n }, 100);\n } // prevent browser zoom in input fields\n\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target)) {\n if (event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.MINUS || event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.EQUAL) {\n event.preventDefault();\n return;\n }\n } // bail if\n\n\n if ( // inside an input\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isWritableElement)(event.target) && // unless pressing escape (finalize action)\n event.key !== _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || // or unless using arrows (to move between buttons)\n (0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key) && (0,_utils__WEBPACK_IMPORTED_MODULE_33__.isInputLike)(event.target)) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.QUESTION_MARK) {\n this.setState({\n openDialog: \"help\"\n });\n return;\n } else if (event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.E && event.shiftKey && event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n this.setState({\n openDialog: \"imageExport\"\n });\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_UP || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n let offset = (event.shiftKey ? this.state.width : this.state.height) / this.state.zoom.value;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n offset = -offset;\n }\n\n if (event.shiftKey) {\n this.translateCanvas(state => ({\n scrollX: state.scrollX + offset\n }));\n } else {\n this.translateCanvas(state => ({\n scrollY: state.scrollY + offset\n }));\n }\n }\n\n if (this.actionManager.handleKeyDown(event)) {\n return;\n }\n\n if (this.state.viewModeEnabled) {\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: false\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n const step = this.state.gridSize && (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT : this.state.gridSize) || (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_SHIFT_TRANSLATE_AMOUNT : _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT);\n let offsetX = 0;\n let offsetY = 0;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_LEFT) {\n offsetX = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_RIGHT) {\n offsetX = step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_UP) {\n offsetY = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_DOWN) {\n offsetY = step;\n }\n\n const selectedElements = this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n });\n selectedElements.forEach(element => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: element.x + offsetX,\n y: element.y + offsetY\n });\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element, {\n simultaneouslyUpdated: selectedElements\n });\n });\n this.maybeSuggestBindingForAll(selectedElements);\n event.preventDefault();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n const selectedElement = selectedElements[0];\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElement)) {\n if (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id) {\n this.history.resumeRecording();\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElement, this.scene)\n });\n }\n }\n } else if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.isValidTextContainer)(selectedElement)) {\n let container;\n\n if (!(0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement)) {\n container = selectedElement;\n }\n\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerCenter)(selectedElement, this.state);\n const sceneX = midPoint.x;\n const sceneY = midPoint.y;\n this.startTextEditing({\n sceneX,\n sceneY,\n container\n });\n event.preventDefault();\n return;\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameElement)(selectedElement)) {\n this.setState({\n editingFrame: selectedElement.id\n });\n }\n }\n } else if (!event.ctrlKey && !event.altKey && !event.metaKey && this.state.draggingElement === null) {\n const shape = (0,_shapes__WEBPACK_IMPORTED_MODULE_32__.findShapeByKey)(event.key);\n\n if (shape) {\n if (this.state.activeTool.type !== shape) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", shape, `keyboard (${this.device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n this.setActiveTool({\n type: shape\n });\n event.stopPropagation();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.Q) {\n this.toggleLock(\"keyboard\");\n event.stopPropagation();\n }\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE && gesture.pointers.size === 0) {\n isHoldingSpace = true;\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n event.preventDefault();\n }\n\n if ((event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (this.state.activeTool.type === \"selection\" && !selectedElements.length) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && ((0,_scene__WEBPACK_IMPORTED_MODULE_29__.hasBackground)(this.state.activeTool.type) || selectedElements.some(element => (0,_scene__WEBPACK_IMPORTED_MODULE_29__.hasBackground)(element.type)))) {\n this.setState({\n openPopup: \"elementBackground\"\n });\n event.stopPropagation();\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) {\n this.setState({\n openPopup: \"elementStroke\"\n });\n event.stopPropagation();\n }\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.BACKSPACE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.DELETE)) {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__.activeConfirmDialogAtom, \"clearCanvas\");\n } // eye dropper\n // -----------------------------------------------------------------------\n\n\n const lowerCased = event.key.toLocaleLowerCase();\n const isPickingStroke = lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S && event.shiftKey;\n const isPickingBackground = event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.I || lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && event.shiftKey;\n\n if (isPickingStroke || isPickingBackground) {\n this.openEyeDropper({\n type: isPickingStroke ? \"stroke\" : \"background\"\n });\n } // -----------------------------------------------------------------------\n\n });\n this.onWheel = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n // prevent browser pinch zoom on DOM elements\n if (!(event.target instanceof HTMLCanvasElement) && event.ctrlKey) {\n event.preventDefault();\n }\n });\n this.onKeyUp = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE) {\n if (this.state.viewModeEnabled) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (this.state.activeTool.type === \"selection\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n isHoldingSpace = false;\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: true\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) ? (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindSelectedElements)(selectedElements) : (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.unbindLinearElements)(selectedElements);\n this.setState({\n suggestedBindings: []\n });\n }\n });\n\n this.setActiveTool = tool => {\n const nextActiveTool = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, tool);\n\n if (nextActiveTool.type === \"hand\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (!isHoldingSpace) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_33__.isToolIcon)(document.activeElement)) {\n this.focusContainer();\n }\n\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElementType)(nextActiveTool.type)) {\n this.setState({\n suggestedBindings: []\n });\n }\n\n if (nextActiveTool.type === \"image\") {\n this.onImageAction();\n }\n\n if (nextActiveTool.type !== \"selection\") {\n this.setState({\n activeTool: nextActiveTool,\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } else {\n this.setState({\n activeTool: nextActiveTool,\n activeEmbeddable: null\n });\n }\n };\n\n this.setCursor = cursor => {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, cursor);\n };\n\n this.resetCursor = () => {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n };\n /**\n * returns whether user is making a gesture with >= 2 fingers (points)\n * on o touch screen (not on a trackpad). Currently only relates to Darwin\n * (iOS/iPadOS,MacOS), but may work on other devices in the future if\n * GestureEvent is standardized.\n */\n\n\n this.isTouchScreenMultiTouchGesture = () => {\n // we don't want to deselect when using trackpad, and multi-point gestures\n // only work on touch screens, so checking for >= pointers means we're on a\n // touchscreen\n return gesture.pointers.size >= 2;\n }; // fires only on Safari\n\n\n this.onGestureStart = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault(); // we only want to deselect on touch screens because user may have selected\n // elements by mistake while zooming\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n\n gesture.initialScale = this.state.zoom.value;\n }); // fires only on Safari\n\n this.onGestureChange = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault(); // onGestureChange only has zoom factor but not the center.\n // If we're on iPad or iPhone, then we recognize multi-touch and will\n // zoom in at the right location in the touchmove handler\n // (handleCanvasPointerMove).\n //\n // On Macbook trackpad, we don't have those events so will zoom in at the\n // current location instead.\n //\n // As such, bail from this handler on touch devices.\n\n if (this.isTouchScreenMultiTouchGesture()) {\n return;\n }\n\n const initialScale = gesture.initialScale;\n\n if (initialScale) {\n this.setState(state => Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(initialScale * event.scale)\n }, state)));\n }\n }); // fires only on Safari\n\n this.onGestureEnd = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault(); // reselect elements only on touch screens (see onGestureStart)\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n }\n\n gesture.initialScale = null;\n });\n\n this.startTextEditing = ({\n sceneX,\n sceneY,\n insertAtParentCenter = true,\n container\n }) => {\n var _a, _b;\n\n let shouldBindToContainer = false;\n let parentCenterPosition = insertAtParentCenter && this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n\n if (container && parentCenterPosition) {\n const boundTextElementToContainer = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getBoundTextElement)(container);\n\n if (!boundTextElementToContainer) {\n shouldBindToContainer = true;\n }\n }\n\n let existingTextElement = null;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElements[0])) {\n existingTextElement = selectedElements[0];\n } else if (container) {\n existingTextElement = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getBoundTextElement)(selectedElements[0]);\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n\n const fontFamily = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.fontFamily) || this.state.currentItemFontFamily;\n const lineHeight = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.lineHeight) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getDefaultLineHeight)(fontFamily);\n const fontSize = this.state.currentItemFontSize;\n\n if (!existingTextElement && shouldBindToContainer && container && !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(container)) {\n const fontString = {\n fontSize,\n fontFamily\n };\n const minWidth = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getApproxMinLineWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_33__.getFontString)(fontString), lineHeight);\n const minHeight = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getApproxMinLineHeight)(fontSize, lineHeight);\n const newHeight = Math.max(container.height, minHeight);\n const newWidth = Math.max(container.width, minWidth);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n height: newHeight,\n width: newWidth\n });\n sceneX = container.x + newWidth / 2;\n sceneY = container.y + newHeight / 2;\n\n if (parentCenterPosition) {\n parentCenterPosition = this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n }\n }\n\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: sceneX,\n y: sceneY\n });\n const element = existingTextElement ? existingTextElement : (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)({\n x: parentCenterPosition ? parentCenterPosition.elementCenterX : sceneX,\n y: parentCenterPosition ? parentCenterPosition.elementCenterY : sceneY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text: \"\",\n fontSize,\n fontFamily,\n textAlign: parentCenterPosition ? \"center\" : this.state.currentItemTextAlign,\n verticalAlign: parentCenterPosition ? _constants__WEBPACK_IMPORTED_MODULE_12__.VERTICAL_ALIGN.MIDDLE : _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n containerId: shouldBindToContainer ? container === null || container === void 0 ? void 0 : container.id : undefined,\n groupIds: (_a = container === null || container === void 0 ? void 0 : container.groupIds) !== null && _a !== void 0 ? _a : [],\n lineHeight,\n angle: (_b = container === null || container === void 0 ? void 0 : container.angle) !== null && _b !== void 0 ? _b : 0,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n\n if (!existingTextElement && shouldBindToContainer && container) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: element.id\n })\n });\n }\n\n this.setState({\n editingElement: element\n });\n\n if (!existingTextElement) {\n if (container && shouldBindToContainer) {\n const containerIndex = this.scene.getElementIndex(container.id);\n this.scene.insertElementAtIndex(element, containerIndex + 1);\n } else {\n this.scene.addNewElement(element);\n }\n }\n\n this.setState({\n editingElement: element\n });\n this.handleTextWysiwyg(element, {\n isExistingElement: !!existingTextElement\n });\n };\n\n this.handleCanvasDoubleClick = event => {\n // case: double-clicking with arrow/line tool selected would both create\n // text and enter multiElement mode\n if (this.state.multiElement) {\n return;\n } // we should only be able to double click when mode is selection\n\n\n if (this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0])) {\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id)) {\n this.history.resumeRecording();\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElements[0], this.scene)\n });\n return;\n } else if (this.state.editingLinearElement && this.state.editingLinearElement.elementId === selectedElements[0].id) {\n return;\n }\n }\n\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n let {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedGroupIds = (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIds)(this.state);\n\n if (selectedGroupIds.length > 0) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n const selectedGroupId = hitElement && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIdForElement)(hitElement, this.state.selectedGroupIds);\n\n if (selectedGroupId) {\n this.setState(prevState => Object.assign(Object.assign({}, prevState), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: selectedGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)));\n return;\n }\n }\n\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.viewModeEnabled) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement)) {\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"active\"\n }\n });\n return;\n }\n\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getTextBindableContainerAtPosition)(this.scene.getNonDeletedElements(), this.state, sceneX, sceneY);\n\n if (container) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(container) || !(0,_utils__WEBPACK_IMPORTED_MODULE_33__.isTransparent)(container.backgroundColor) || (0,_element_collision__WEBPACK_IMPORTED_MODULE_44__.isHittingElementNotConsideringBoundingBox)(container, this.state, this.frameNameBoundsCache, [sceneX, sceneY])) {\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerCenter)(container, this.state);\n sceneX = midPoint.x;\n sceneY = midPoint.y;\n }\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container\n });\n }\n };\n\n this.getElementLinkAtPosition = (scenePointer, hitElement) => {\n // Reversing so we traverse the elements in decreasing order\n // of z-index\n const elements = this.scene.getNonDeletedElements().slice().reverse();\n let hitElementIndex = Infinity;\n return elements.find((element, index) => {\n if (hitElement && element.id === hitElement.id) {\n hitElementIndex = index;\n }\n\n return element.link && index <= hitElementIndex && (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLink)(element, this.state, [scenePointer.x, scenePointer.y], this.device.isMobile);\n });\n };\n\n this.redirectToLink = (event, isTouchScreen) => {\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(this.lastPointerDown.clientX, this.lastPointerDown.clientY, this.lastPointerUp.clientX, this.lastPointerUp.clientY);\n\n if (!this.hitLinkElement || // For touch screen allow dragging threshold else strict check\n isTouchScreen && draggedDistance > _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD || !isTouchScreen && draggedDistance !== 0) {\n return;\n }\n\n const lastPointerDownCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(this.lastPointerDown, this.state);\n const lastPointerDownHittingLinkIcon = (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLink)(this.hitLinkElement, this.state, [lastPointerDownCoords.x, lastPointerDownCoords.y], this.device.isMobile);\n const lastPointerUpCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(this.lastPointerUp, this.state);\n const lastPointerUpHittingLinkIcon = (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLink)(this.hitLinkElement, this.state, [lastPointerUpCoords.x, lastPointerUpCoords.y], this.device.isMobile);\n\n if (lastPointerDownHittingLinkIcon && lastPointerUpHittingLinkIcon) {\n let url = this.hitLinkElement.link;\n\n if (url) {\n url = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(url);\n let customEvent;\n\n if (this.props.onLinkOpen) {\n customEvent = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.wrapEvent)(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.EXCALIDRAW_LINK, event.nativeEvent);\n this.props.onLinkOpen(Object.assign(Object.assign({}, this.hitLinkElement), {\n link: url\n }), customEvent);\n }\n\n if (!(customEvent === null || customEvent === void 0 ? void 0 : customEvent.defaultPrevented)) {\n const target = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.isLocalLink)(url) ? \"_self\" : \"_blank\";\n const newWindow = window.open(undefined, target); // https://mathiasbynens.github.io/rel-noopener/\n\n if (newWindow) {\n newWindow.opener = null;\n newWindow.location = url;\n }\n }\n }\n }\n };\n\n this.getTopLayerFrameAtSceneCoords = sceneCoords => {\n const frames = this.scene.getNonDeletedFrames().filter(frame => (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)(sceneCoords, frame));\n return frames.length ? frames[frames.length - 1] : null;\n };\n\n this.handleCanvasPointerMove = event => {\n var _a, _b;\n\n this.savePointer(event.clientX, event.clientY, this.state.cursorButton);\n\n if (gesture.pointers.has(event.pointerId)) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n }\n\n const initialScale = gesture.initialScale;\n\n if (gesture.pointers.size === 2 && gesture.lastCenter && initialScale && gesture.initialDistance) {\n const center = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n const deltaX = center.x - gesture.lastCenter.x;\n const deltaY = center.y - gesture.lastCenter.y;\n gesture.lastCenter = center;\n const distance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n const scaleFactor = this.state.activeTool.type === \"freedraw\" && this.state.penMode ? 1 : distance / gesture.initialDistance;\n const nextZoom = scaleFactor ? (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(initialScale * scaleFactor) : this.state.zoom.value;\n this.setState(state => {\n const zoomState = (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: center.x,\n viewportY: center.y,\n nextZoom\n }, state);\n this.translateCanvas({\n zoom: zoomState.zoom,\n scrollX: zoomState.scrollX + deltaX / nextZoom,\n scrollY: zoomState.scrollY + deltaY / nextZoom,\n shouldCacheIgnoreZoom: true\n });\n });\n this.resetShouldCacheIgnoreZoomDebounced();\n } else {\n gesture.lastCenter = gesture.initialDistance = gesture.initialScale = null;\n }\n\n if (isHoldingSpace || isPanning || isDraggingScrollBar || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state)) {\n return;\n }\n\n const isPointerOverScrollBars = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop);\n const isOverScrollBar = isPointerOverScrollBars.isOverEither;\n\n if (!this.state.draggingElement && !this.state.multiElement) {\n if (isOverScrollBar) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const {\n x: scenePointerX,\n y: scenePointerY\n } = scenePointer;\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerMove(event, scenePointerX, scenePointerY, this.state);\n\n if (editingLinearElement && editingLinearElement !== this.state.editingLinearElement) {\n // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n editingLinearElement\n });\n });\n }\n\n if ((editingLinearElement === null || editingLinearElement === void 0 ? void 0 : editingLinearElement.lastUncommittedPoint) != null) {\n this.maybeSuggestBindingAtCursor(scenePointer);\n } else {\n // causes stack overflow if not sync\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n suggestedBindings: []\n });\n });\n }\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElementType)(this.state.activeTool.type)) {\n // Hovering with a selected tool or creating new linear element via click\n // and point\n const {\n draggingElement\n } = this.state;\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(draggingElement, false)) {\n this.maybeSuggestBindingsForLinearElementAtCoords(draggingElement, [scenePointer], this.state.startBoundElement);\n } else {\n this.maybeSuggestBindingAtCursor(scenePointer);\n }\n }\n\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state;\n const {\n x: rx,\n y: ry\n } = multiElement;\n const {\n points,\n lastCommittedPoint\n } = multiElement;\n const lastPoint = points[points.length - 1];\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n\n if (lastPoint === lastCommittedPoint) {\n // if we haven't yet created a temp point and we're beyond commit-zone\n // threshold, add a point\n if ((0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(scenePointerX - rx, scenePointerY - ry, lastPoint[0], lastPoint[1]) >= _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points, [scenePointerX - rx, scenePointerY - ry]]\n });\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER); // in this branch, we're inside the commit zone, and no uncommitted\n // point exists. Thus do nothing (don't add/remove points).\n }\n } else if (points.length > 2 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(scenePointerX - rx, scenePointerY - ry, lastCommittedPoint[0], lastCommittedPoint[1]) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: points.slice(0, -1)\n });\n } else {\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(scenePointerX, scenePointerY, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const [lastCommittedX, lastCommittedY] = (_a = multiElement === null || multiElement === void 0 ? void 0 : multiElement.lastCommittedPoint) !== null && _a !== void 0 ? _a : [0, 0];\n let dxFromLastCommitted = gridX - rx - lastCommittedX;\n let dyFromLastCommitted = gridY - ry - lastCommittedY;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event)) {\n ({\n width: dxFromLastCommitted,\n height: dyFromLastCommitted\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)( // actual coordinate of the last committed point\n lastCommittedX + rx, lastCommittedY + ry, // cursor-grid coordinate\n gridX, gridY));\n }\n\n if ((0,_math__WEBPACK_IMPORTED_MODULE_28__.isPathALoop)(points, this.state.zoom.value)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } // update last uncommitted point\n\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points.slice(0, -1), [lastCommittedX + dxFromLastCommitted, lastCommittedY + dyFromLastCommitted]]\n });\n }\n\n return;\n }\n\n const hasDeselectedButton = Boolean(event.buttons);\n\n if (hasDeselectedButton || this.state.activeTool.type !== \"selection\" && this.state.activeTool.type !== \"text\" && this.state.activeTool.type !== \"eraser\") {\n return;\n }\n\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !isOverScrollBar && !this.state.editingLinearElement) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType);\n\n if (elementWithTransformHandleType && elementWithTransformHandleType.transformHandleType) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)(elementWithTransformHandleType));\n return;\n }\n } else if (selectedElements.length > 1 && !isOverScrollBar) {\n const transformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType);\n\n if (transformHandleType) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)({\n transformHandleType\n }));\n return;\n }\n }\n\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n return;\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.showHyperlinkTooltip)(this.hitLinkElement, this.state);\n } else {\n (0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.hideHyperlinkToolip)();\n\n if (hitElement && (hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement)) && this.state.selectedElementIds[hitElement.id] && !this.state.contextMenu && !this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: \"info\"\n });\n } else if (this.state.activeTool.type === \"text\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(hitElement) ? _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.TEXT : _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR);\n } else if (this.state.viewModeEnabled) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (isOverScrollBar) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n } else if (this.state.selectedLinearElement) {\n this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);\n } else if ( // if using cmd/ctrl, we're not dragging\n !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((hitElement || this.isHittingCommonBoundingBoxOfSelectedElements(scenePointer, selectedElements)) && !(hitElement === null || hitElement === void 0 ? void 0 : hitElement.locked)) {\n if (hitElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) && this.isEmbeddableCenter(hitElement, event, scenePointerX, scenePointerY)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"hover\"\n }\n });\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n\n if (((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\") {\n this.setState({\n activeEmbeddable: null\n });\n }\n }\n }\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n };\n\n this.handleEraser = (event, pointerDownState, scenePointer) => {\n const updateElementIds = elements => {\n elements.forEach(element => {\n if (element.locked) {\n return;\n }\n\n idsToUpdate.push(element.id);\n\n if (event.altKey) {\n if (pointerDownState.elementIdsToErase[element.id] && pointerDownState.elementIdsToErase[element.id].erase) {\n pointerDownState.elementIdsToErase[element.id].erase = false;\n }\n } else if (!pointerDownState.elementIdsToErase[element.id]) {\n pointerDownState.elementIdsToErase[element.id] = {\n erase: true,\n opacity: element.opacity\n };\n }\n });\n };\n\n const idsToUpdate = [];\n const distance = (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y, scenePointer.x, scenePointer.y);\n const threshold = 10 / this.state.zoom.value;\n const point = Object.assign({}, pointerDownState.lastCoords);\n let samplingInterval = 0;\n\n while (samplingInterval <= distance) {\n const hitElements = this.getElementsAtPosition(point.x, point.y);\n updateElementIds(hitElements); // Exit since we reached current point\n\n if (samplingInterval === distance) {\n break;\n } // Calculate next point in the line at a distance of sampling interval\n\n\n samplingInterval = Math.min(samplingInterval + threshold, distance);\n const distanceRatio = samplingInterval / distance;\n const nextX = (1 - distanceRatio) * point.x + distanceRatio * scenePointer.x;\n const nextY = (1 - distanceRatio) * point.y + distanceRatio * scenePointer.y;\n point.x = nextX;\n point.y = nextY;\n }\n\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n const id = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && idsToUpdate.includes(ele.containerId) ? ele.containerId : ele.id;\n\n if (idsToUpdate.includes(id)) {\n if (event.altKey) {\n if (pointerDownState.elementIdsToErase[id] && pointerDownState.elementIdsToErase[id].erase === false) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[id].opacity\n });\n }\n } else {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_READY_TO_ERASE_OPACITY\n });\n }\n }\n\n return ele;\n });\n this.scene.replaceAllElements(elements);\n pointerDownState.lastCoords.x = scenePointer.x;\n pointerDownState.lastCoords.y = scenePointer.y;\n }; // set touch moving for mobile context menu\n\n\n this.handleTouchMove = event => {\n invalidateContextMenu = true;\n };\n\n this.handleCanvasPointerDown = event => {\n var _a, _b; // since contextMenu options are potentially evaluated on each render,\n // and an contextMenu action may depend on selection state, we must\n // close the contextMenu before we update the selection on pointerDown\n // (e.g. resetting selection)\n\n\n if (this.state.contextMenu) {\n this.setState({\n contextMenu: null\n });\n }\n\n this.updateGestureOnPointerDown(event); // if dragging element is freedraw and another pointerdown event occurs\n // a second finger is on the screen\n // discard the freedraw element if it is very short because it is likely\n // just a spike, otherwise finalize the freedraw element when the second\n // finger is lifted\n\n if (event.pointerType === \"touch\" && this.state.draggingElement && this.state.draggingElement.type === \"freedraw\") {\n const element = this.state.draggingElement;\n this.updateScene(Object.assign(Object.assign({}, element.points.length < 10 ? {\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== element.id)\n } : {}), {\n appState: {\n draggingElement: null,\n editingElement: null,\n startBoundElement: null,\n suggestedBindings: [],\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.keys(this.state.selectedElementIds).filter(key => key !== element.id).reduce((obj, key) => {\n obj[key] = this.state.selectedElementIds[key];\n return obj;\n }, {}), this.state)\n }\n }));\n return;\n } // remove any active selection when we start to interact with canvas\n // (mainly, we care about removing selection outside the component which\n // would prevent our copy handling otherwise)\n\n\n const selection = document.getSelection();\n\n if (selection === null || selection === void 0 ? void 0 : selection.anchorNode) {\n selection.removeAllRanges();\n }\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices(event);\n this.maybeCleanupAfterMissingPointerUp(event); //fires only once, if pen is detected, penMode is enabled\n //the user can disable this by toggling the penMode button\n\n if (!this.state.penDetected && event.pointerType === \"pen\") {\n this.setState(prevState => {\n return {\n penMode: true,\n penDetected: true\n };\n });\n }\n\n if (!this.device.isTouchScreen && [\"pen\", \"touch\"].includes(event.pointerType)) {\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateObject)(this.device, {\n isTouchScreen: true\n });\n }\n\n if (isPanning) {\n return;\n }\n\n this.lastPointerDown = event;\n this.setState({\n lastPointerDownWith: event.pointerType,\n cursorButton: \"down\"\n });\n this.savePointer(event.clientX, event.clientY, \"down\");\n\n if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {\n return;\n } // only handle left mouse button or touch\n\n\n if (event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.TOUCH) {\n return;\n } // don't select while panning\n\n\n if (gesture.pointers.size > 1) {\n return;\n } // State for the duration of a pointer interaction, which starts with a\n // pointerDown event, ends with a pointerUp event (or another pointerDown)\n\n\n const pointerDownState = this.initialPointerDownState(event);\n this.setState({\n selectedElementsAreBeingDragged: false\n });\n\n if (this.handleDraggingScrollBar(event, pointerDownState)) {\n return;\n }\n\n this.clearSelectionIfNotUsingSelection();\n this.updateBindingEnabledOnPointerMove(event);\n\n if (this.handleSelectionOnPointerDown(event, pointerDownState)) {\n return;\n }\n\n const allowOnPointerDown = !this.state.penMode || event.pointerType !== \"touch\" || this.state.activeTool.type === \"selection\" || this.state.activeTool.type === \"text\" || this.state.activeTool.type === \"image\";\n\n if (!allowOnPointerDown) {\n return;\n }\n\n if (this.state.activeTool.type === \"text\") {\n this.handleTextOnPointerDown(event, pointerDownState);\n return;\n } else if (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\") {\n this.handleLinearElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"image\") {\n // reset image preview on pointerdown\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR); // retrieve the latest element as the state may be stale\n\n const pendingImageElement = this.state.pendingImageElementId && this.scene.getElement(this.state.pendingImageElementId);\n\n if (!pendingImageElement) {\n return;\n }\n\n this.setState({\n draggingElement: pendingImageElement,\n editingElement: pendingImageElement,\n pendingImageElementId: null,\n multiElement: null\n });\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(pendingImageElement, {\n x,\n y\n });\n } else if (this.state.activeTool.type === \"freedraw\") {\n this.handleFreeDrawElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"custom\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n } else if (this.state.activeTool.type === \"frame\") {\n this.createFrameElementOnPointerDown(pointerDownState);\n } else if (this.state.activeTool.type !== \"eraser\" && this.state.activeTool.type !== \"hand\") {\n this.createGenericElementOnPointerDown(this.state.activeTool.type, pointerDownState);\n }\n\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onPointerDown) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.activeTool, pointerDownState);\n const onPointerMove = this.onPointerMoveFromPointerDownHandler(pointerDownState);\n const onPointerUp = this.onPointerUpFromPointerDownHandler(pointerDownState);\n const onKeyDown = this.onKeyDownFromPointerDownHandler(pointerDownState);\n const onKeyUp = this.onKeyUpFromPointerDownHandler(pointerDownState);\n lastPointerUp = onPointerUp;\n\n if (!this.state.viewModeEnabled) {\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, onKeyDown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, onKeyUp);\n pointerDownState.eventListeners.onMove = onPointerMove;\n pointerDownState.eventListeners.onUp = onPointerUp;\n pointerDownState.eventListeners.onKeyUp = onKeyUp;\n pointerDownState.eventListeners.onKeyDown = onKeyDown;\n }\n };\n\n this.handleCanvasPointerUp = event => {\n var _a, _b;\n\n this.removePointer(event);\n this.lastPointerUp = event;\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: event.clientX,\n clientY: event.clientY\n }, this.state);\n const clicklength = event.timeStamp - ((_b = (_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a.timeStamp) !== null && _b !== void 0 ? _b : 0);\n\n if (this.device.isMobile && clicklength < 300) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) && this.isEmbeddableCenter(hitElement, event, scenePointer.x, scenePointer.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n return;\n }\n }\n\n if (this.device.isTouchScreen) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n if (clicklength < 300 && this.hitLinkElement.type === \"embeddable\" && !(0,_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.isPointHittingLinkIcon)(this.hitLinkElement, this.state, [scenePointer.x, scenePointer.y])) {\n this.handleEmbeddableCenterClick(this.hitLinkElement);\n } else {\n this.redirectToLink(event, this.device.isTouchScreen);\n }\n } else if (this.state.viewModeEnabled) {\n this.setState({\n activeEmbeddable: null,\n selectedElementIds: {}\n });\n }\n };\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices = event => {\n // deal with opening context menu on touch devices\n if (event.pointerType === \"touch\") {\n invalidateContextMenu = false;\n\n if (touchTimeout) {\n // If there's already a touchTimeout, this means that there's another\n // touch down and we are doing another touch, so we shouldn't open the\n // context menu.\n invalidateContextMenu = true;\n } else {\n // open the context menu with the first touch's clientX and clientY\n // if the touch is not moving\n touchTimeout = window.setTimeout(() => {\n touchTimeout = 0;\n\n if (!invalidateContextMenu) {\n this.handleCanvasContextMenu(event);\n }\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.TOUCH_CTX_MENU_TIMEOUT);\n }\n }\n };\n\n this.resetContextMenuTimer = () => {\n clearTimeout(touchTimeout);\n touchTimeout = 0;\n invalidateContextMenu = false;\n }; // Returns whether the event is a panning\n\n\n this.handleCanvasPanUsingWheelOrSpaceDrag = event => {\n if (!(gesture.pointers.size <= 1 && (event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.WHEEL || event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && isHoldingSpace || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state) || this.state.viewModeEnabled)) || (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement)) {\n return false;\n }\n\n isPanning = true;\n event.preventDefault();\n let nextPastePrevented = false;\n const isLinux = /Linux/.test(window.navigator.platform);\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRABBING);\n let {\n clientX: lastX,\n clientY: lastY\n } = event;\n const onPointerMove = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdatesThrottled)(event => {\n const deltaX = lastX - event.clientX;\n const deltaY = lastY - event.clientY;\n lastX = event.clientX;\n lastY = event.clientY;\n /*\n * Prevent paste event if we move while middle clicking on Linux.\n * See issue #1383.\n */\n\n if (isLinux && !nextPastePrevented && (Math.abs(deltaX) > 1 || Math.abs(deltaY) > 1)) {\n nextPastePrevented = true;\n /* Prevent the next paste event */\n\n const preventNextPaste = event => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n event.stopPropagation();\n };\n /*\n * Reenable next paste in case of disabled middle click paste for\n * any reason:\n * - right click paste\n * - empty clipboard\n */\n\n\n const enableNextPaste = () => {\n setTimeout(() => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }, 100);\n };\n\n document.body.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }\n\n this.translateCanvas({\n scrollX: this.state.scrollX - deltaX / this.state.zoom.value,\n scrollY: this.state.scrollY - deltaY / this.state.zoom.value\n });\n });\n const teardown = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(lastPointerUp = () => {\n lastPointerUp = null;\n isPanning = false;\n\n if (!isHoldingSpace) {\n if (this.state.viewModeEnabled) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n onPointerMove.flush();\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove, {\n passive: true\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n return true;\n };\n\n this.clearSelectionIfNotUsingSelection = () => {\n if (this.state.activeTool.type !== \"selection\") {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n };\n /**\n * @returns whether the pointer event has been completely handled\n */\n\n\n this.handleSelectionOnPointerDown = (event, pointerDownState) => {\n var _a;\n\n if (this.state.activeTool.type === \"selection\") {\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !this.state.editingLinearElement) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);\n\n if (elementWithTransformHandleType != null) {\n this.setState({\n resizingElement: elementWithTransformHandleType.element\n });\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n }\n } else if (selectedElements.length > 1) {\n pointerDownState.resize.handleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);\n }\n\n if (pointerDownState.resize.handleType) {\n pointerDownState.resize.isResizing = true;\n pointerDownState.resize.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeOffsetXY)(pointerDownState.resize.handleType, selectedElements, pointerDownState.origin.x, pointerDownState.origin.y));\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0]) && selectedElements[0].points.length === 2) {\n pointerDownState.resize.arrowDirection = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeArrowDirection)(pointerDownState.resize.handleType, selectedElements[0]);\n }\n } else {\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerDown(event, this.state, this.history, pointerDownState.origin, linearElementEditor);\n\n if (ret.hitElement) {\n pointerDownState.hit.element = ret.hitElement;\n }\n\n if (ret.linearElementEditor) {\n this.setState({\n selectedLinearElement: ret.linearElementEditor\n });\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: ret.linearElementEditor\n });\n }\n }\n\n if (ret.didAddPoint) {\n return true;\n }\n } // hitElement may already be set above, so check first\n\n\n pointerDownState.hit.element = (_a = pointerDownState.hit.element) !== null && _a !== void 0 ? _a : this.getElementAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n\n if (pointerDownState.hit.element) {\n // Early return if pointer is hitting link icon\n const hitLinkElement = this.getElementLinkAtPosition({\n x: pointerDownState.origin.x,\n y: pointerDownState.origin.y\n }, pointerDownState.hit.element);\n\n if (hitLinkElement) {\n return false;\n }\n } // For overlapped elements one position may hit\n // multiple elements\n\n\n pointerDownState.hit.allHitElements = this.getElementsAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n const hitElement = pointerDownState.hit.element;\n const someHitElementIsSelected = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n\n if ((hitElement === null || !someHitElementIsSelected) && !event.shiftKey && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.clearSelection(hitElement);\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [this.state.editingLinearElement.elementId]: true\n }, this.state)\n }); // If we click on something\n } else if (hitElement != null) {\n // on CMD/CTRL, drill down to hit element regardless of groups etc.\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (!this.state.selectedElementIds[hitElement.id]) {\n pointerDownState.hit.wasAddedToSelection = true;\n }\n\n this.setState(prevState => Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.editGroupForSelectedElement)(prevState, hitElement)), {\n previousSelectedElementIds: this.state.selectedElementIds\n })); // mark as not completely handled so as to allow dragging etc.\n\n return false;\n } // deselect if item is selected\n // if shift is not clicked, this will always return true\n // otherwise, it will trigger selection based on current\n // state of the box\n\n\n if (!this.state.selectedElementIds[hitElement.id]) {\n // if we are currently editing a group, exiting editing mode and deselect the group.\n if (this.state.editingGroupId && !(0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, this.state.editingGroupId)) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } // Add hit element to selection. At this point if we're not holding\n // SHIFT the previously selected element(s) were deselected above\n // (make sure you use setState updater to use latest state)\n // With shift-selection, we want to make sure that frames and their containing\n // elements are not selected at the same time.\n\n\n if (!someHitElementIsSelected && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n });\n const previouslySelectedElements = [];\n Object.keys(prevState.selectedElementIds).forEach(id => {\n const element = this.scene.getElement(id);\n element && previouslySelectedElements.push(element);\n }); // if hitElement is frame, deselect all of its elements if they are selected\n\n if (hitElement.type === \"frame\") {\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameElements)(previouslySelectedElements, hitElement.id).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n } else if (hitElement.frameId) {\n // if hitElement is in a frame and its frame has been selected\n // disable selection for the given element\n if (nextSelectedElementIds[hitElement.frameId]) {\n delete nextSelectedElementIds[hitElement.id];\n }\n } else {\n // hitElement is neither a frame nor an element in a frame\n // but since hitElement could be in a group with some frames\n // this means selecting hitElement will have the frames selected as well\n // because we want to keep the invariant:\n // - frames and their elements are not selected at the same time\n // we deselect elements in those frames that were previously selected\n const groupIds = hitElement.groupIds;\n const framesInGroups = new Set(groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).filter(element => element.type === \"frame\").map(frame => frame.id));\n\n if (framesInGroups.size > 0) {\n previouslySelectedElements.forEach(element => {\n if (element.frameId && framesInGroups.has(element.frameId)) {\n // deselect element and groups containing the element\n delete nextSelectedElementIds[element.id];\n element.groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n }\n });\n }\n }\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n pointerDownState.hit.wasAddedToSelection = true;\n }\n }\n }\n\n this.setState({\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n }\n\n return false;\n };\n\n this.handleTextOnPointerDown = (event, pointerDownState) => {\n // if we're currently still editing text, clicking outside\n // should only finalize it, not create another (irrespective\n // of state.activeTool.locked)\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement)) {\n return;\n }\n\n let sceneX = pointerDownState.origin.x;\n let sceneY = pointerDownState.origin.y;\n const element = this.getElementAtPosition(sceneX, sceneY, {\n includeBoundTextElement: true\n }); // FIXME\n\n let container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getTextBindableContainerAtPosition)(this.scene.getNonDeletedElements(), this.state, sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(element)) {\n container = element;\n sceneX = element.x + element.width / 2;\n sceneY = element.y + element.height / 2;\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container\n });\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n\n if (!this.state.activeTool.locked) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n };\n\n this.handleFreeDrawElementOnPointerDown = (event, elementType, pointerDownState) => {\n // Begin a mark capture. This does not have to update state yet.\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, null);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFreeDrawElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: null,\n simulatePressure: event.pressure === 0.5,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n const pressures = element.simulatePressure ? element.pressures : [...element.pressures, event.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n points: [[0, 0]],\n pressures\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene);\n this.scene.addNewElement(element);\n this.setState({\n draggingElement: element,\n editingElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n }; //create rectangle element with youtube top left on nearest grid point width / hight 640/360\n\n\n this.insertEmbeddableElement = ({\n sceneX,\n sceneY,\n link\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)(link);\n\n if (!embedLink) {\n return;\n }\n\n if (embedLink.warning) {\n this.setToast({\n message: embedLink.warning,\n closable: true\n });\n }\n\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)({\n type: \"embeddable\",\n x: gridX,\n y: gridY,\n strokeColor: \"transparent\",\n backgroundColor: \"transparent\",\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: this.getCurrentItemRoundness(\"embeddable\"),\n opacity: this.state.currentItemOpacity,\n locked: false,\n width: embedLink.aspectRatio.w,\n height: embedLink.aspectRatio.h,\n link,\n validated: null\n });\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted(), element]);\n return element;\n };\n\n this.createImageElement = ({\n sceneX,\n sceneY\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newImageElement)({\n type: \"image\",\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: null,\n opacity: this.state.currentItemOpacity,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n return element;\n };\n\n this.handleLinearElementOnPointerDown = (event, elementType, pointerDownState) => {\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state; // finalize if completing a loop\n\n if (multiElement.type === \"line\" && (0,_math__WEBPACK_IMPORTED_MODULE_28__.isPathALoop)(multiElement.points, this.state.zoom.value)) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n const {\n x: rx,\n y: ry,\n lastCommittedPoint\n } = multiElement; // clicking inside commit zone → finalize arrow\n\n if (multiElement.points.length > 1 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(pointerDownState.origin.x - rx, pointerDownState.origin.y - ry, lastCommittedPoint[0], lastCommittedPoint[1]) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [multiElement.id]: true\n }), prevState)\n })); // clicking outside commit zone → update reference for last committed\n // point\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else {\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n /* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.\n If so, we want it to be null for start and \"arrow\" for end. If the linear item is not\n an arrow, we want it to be null for both. Otherwise, we want it to use the\n values from appState. */\n\n const {\n currentItemStartArrowhead,\n currentItemEndArrowhead\n } = this.state;\n const [startArrowhead, endArrowhead] = elementType === \"arrow\" ? [currentItemStartArrowhead, currentItemEndArrowhead] : [null, null];\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newLinearElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.state.currentItemRoundness === \"round\" ? {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null,\n startArrowhead,\n endArrowhead,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n points: [...element.points, [0, 0]]\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene);\n this.scene.addNewElement(element);\n this.setState({\n draggingElement: element,\n editingElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n }\n };\n\n this.createGenericElementOnPointerDown = (elementType, pointerDownState) => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const baseElementAttributes = {\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.getCurrentItemRoundness(elementType),\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n };\n let element;\n\n if (elementType === \"embeddable\") {\n element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)(Object.assign({\n type: \"embeddable\",\n validated: null\n }, baseElementAttributes));\n } else {\n element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newElement)(Object.assign({\n type: elementType\n }, baseElementAttributes));\n }\n\n if (element.type === \"selection\") {\n this.setState({\n selectionElement: element,\n draggingElement: element\n });\n } else {\n this.scene.addNewElement(element);\n this.setState({\n multiElement: null,\n draggingElement: element,\n editingElement: element\n });\n }\n };\n\n this.createFrameElementOnPointerDown = pointerDownState => {\n var _a;\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDown) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.state.gridSize);\n const frame = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFrameElement)(Object.assign({\n x: gridX,\n y: gridY,\n opacity: this.state.currentItemOpacity,\n locked: false\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE));\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted(), frame]);\n this.setState({\n multiElement: null,\n draggingElement: frame,\n editingElement: frame\n });\n };\n\n this.restoreReadyToEraseElements = pointerDownState => {\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n if (pointerDownState.elementIdsToErase[ele.id] && pointerDownState.elementIdsToErase[ele.id].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[ele.id].opacity\n });\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && pointerDownState.elementIdsToErase[ele.containerId] && pointerDownState.elementIdsToErase[ele.containerId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[ele.containerId].opacity\n });\n } else if (ele.frameId && pointerDownState.elementIdsToErase[ele.frameId] && pointerDownState.elementIdsToErase[ele.frameId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n opacity: pointerDownState.elementIdsToErase[ele.frameId].opacity\n });\n }\n\n return ele;\n });\n this.scene.replaceAllElements(elements);\n };\n\n this.eraseElements = pointerDownState => {\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n if (pointerDownState.elementIdsToErase[ele.id] && pointerDownState.elementIdsToErase[ele.id].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && pointerDownState.elementIdsToErase[ele.containerId] && pointerDownState.elementIdsToErase[ele.containerId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n } else if (ele.frameId && pointerDownState.elementIdsToErase[ele.frameId] && pointerDownState.elementIdsToErase[ele.frameId].erase) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n }\n\n return ele;\n });\n this.history.resumeRecording();\n this.scene.replaceAllElements(elements);\n };\n\n this.initializeImage = ({\n imageFile,\n imageElement: _imageElement,\n showCursorImagePreview = false\n }) => __awaiter(this, void 0, void 0, function* () {\n var _f, _g, _h, _j; // at this point this should be guaranteed image file, but we do this check\n // to satisfy TS down the line\n\n\n if (!(0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isSupportedImageFile)(imageFile)) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\"));\n }\n\n const mimeType = imageFile.type;\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, \"wait\");\n\n if (mimeType === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n imageFile = (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.SVGStringToFile)(yield (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.normalizeSVG)(yield imageFile.text()), imageFile.name);\n } catch (error) {\n console.warn(error);\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.svgImageInsertError\"));\n }\n } // generate image id (by default the file digest) before any\n // resizing/compression takes place to keep it more portable\n\n\n const fileId = yield ((_g = (_f = this.props).generateIdForFile) === null || _g === void 0 ? void 0 : _g.call(_f, imageFile)) || (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.generateIdFromFile)(imageFile);\n\n if (!fileId) {\n console.warn(\"Couldn't generate file id or the supplied `generateIdForFile` didn't resolve to one.\");\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\"));\n }\n\n const existingFileData = this.files[fileId];\n\n if (!(existingFileData === null || existingFileData === void 0 ? void 0 : existingFileData.dataURL)) {\n try {\n imageFile = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT\n });\n } catch (error) {\n console.error(\"error trying to resing image file on insertion\", error);\n }\n\n if (imageFile.size > _constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.fileTooBig\", {\n maxSize: `${Math.trunc(_constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES / 1024 / 1024)}MB`\n }));\n }\n }\n\n if (showCursorImagePreview) {\n const dataURL = (_h = this.files[fileId]) === null || _h === void 0 ? void 0 : _h.dataURL; // optimization so that we don't unnecessarily resize the original\n // full-size file for cursor preview\n // (it's much faster to convert the resized dataURL to File)\n\n const resizedFile = dataURL && (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.dataURLToFile)(dataURL);\n this.setImagePreviewCursor(resizedFile || imageFile);\n }\n\n const dataURL = ((_j = this.files[fileId]) === null || _j === void 0 ? void 0 : _j.dataURL) || (yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.getDataURL)(imageFile));\n const imageElement = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(_imageElement, {\n fileId\n }, false);\n return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {\n var _k;\n\n try {\n this.files = Object.assign(Object.assign({}, this.files), {\n [fileId]: {\n mimeType,\n id: fileId,\n dataURL,\n created: Date.now(),\n lastRetrieved: Date.now()\n }\n });\n const cachedImageData = this.imageCache.get(fileId);\n\n if (!cachedImageData) {\n this.addNewImagesToImageCache();\n yield this.updateImageCache([imageElement]);\n }\n\n if ((cachedImageData === null || cachedImageData === void 0 ? void 0 : cachedImageData.image) instanceof Promise) {\n yield cachedImageData.image;\n }\n\n if (this.state.pendingImageElementId !== imageElement.id && ((_k = this.state.draggingElement) === null || _k === void 0 ? void 0 : _k.id) !== imageElement.id) {\n this.initializeImageDimensions(imageElement, true);\n }\n\n resolve(imageElement);\n } catch (error) {\n console.error(error);\n reject(new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")));\n } finally {\n if (!showCursorImagePreview) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n }\n }\n }));\n });\n /**\n * inserts image into elements array and rerenders\n */\n\n\n this.insertImageElement = (imageElement, imageFile, showCursorImagePreview) => __awaiter(this, void 0, void 0, function* () {\n this.scene.addNewElement(imageElement);\n\n try {\n yield this.initializeImage({\n imageFile,\n imageElement,\n showCursorImagePreview\n });\n } catch (error) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n isDeleted: true\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n this.setState({\n errorMessage: error.message || (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")\n });\n }\n });\n\n this.setImagePreviewCursor = imageFile => __awaiter(this, void 0, void 0, function* () {\n // mustn't be larger than 128 px\n // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Basic_User_Interface/Using_URL_values_for_the_cursor_property\n const cursorImageSizePx = 96;\n const imagePreview = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: cursorImageSizePx\n });\n let previewDataURL = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.getDataURL)(imagePreview); // SVG cannot be resized via `resizeImageFile` so we resize by rendering to\n // a small canvas\n\n if (imageFile.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n const img = yield (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.loadHTMLImageElement)(previewDataURL);\n let height = Math.min(img.height, cursorImageSizePx);\n let width = height * (img.width / img.height);\n\n if (width > cursorImageSizePx) {\n width = cursorImageSizePx;\n height = width * (img.height / img.width);\n }\n\n const canvas = document.createElement(\"canvas\");\n canvas.height = height;\n canvas.width = width;\n const context = canvas.getContext(\"2d\");\n context.drawImage(img, 0, 0, width, height);\n previewDataURL = canvas.toDataURL(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg);\n }\n\n if (this.state.pendingImageElementId) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, `url(${previewDataURL}) 4 4, auto`);\n }\n });\n\n this.onImageAction = ({\n insertOnCanvasDirectly\n } = {\n insertOnCanvasDirectly: false\n }) => __awaiter(this, void 0, void 0, function* () {\n try {\n const clientX = this.state.width / 2 + this.state.offsetLeft;\n const clientY = this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const imageFile = yield (0,_data_filesystem__WEBPACK_IMPORTED_MODULE_42__.fileOpen)({\n description: \"Image\",\n extensions: Object.keys(_constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_MIME_TYPES)\n });\n const imageElement = this.createImageElement({\n sceneX: x,\n sceneY: y\n });\n\n if (insertOnCanvasDirectly) {\n this.insertImageElement(imageElement, imageFile);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } else {\n this.setState({\n pendingImageElementId: imageElement.id\n }, () => {\n this.insertImageElement(imageElement, imageFile,\n /* showCursorImagePreview */\n true);\n });\n }\n } catch (error) {\n if (error.name !== \"AbortError\") {\n console.error(error);\n } else {\n console.warn(error);\n }\n\n this.setState({\n pendingImageElementId: null,\n editingElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n }\n });\n\n this.initializeImageDimensions = (imageElement, forceNaturalSize = false) => {\n var _a;\n\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(imageElement) && ((_a = this.imageCache.get(imageElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n\n if (!image || image instanceof Promise) {\n if (imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const placeholderSize = 100 / this.state.zoom.value;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x: imageElement.x - placeholderSize / 2,\n y: imageElement.y - placeholderSize / 2,\n width: placeholderSize,\n height: placeholderSize\n });\n }\n\n return;\n }\n\n if (forceNaturalSize || // if user-created bounding box is below threshold, assume the\n // intention was to click instead of drag, and use the image's\n // intrinsic size\n imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const minHeight = Math.max(this.state.height - 120, 160); // max 65% of canvas height, clamped to <300px, vh - 120px>\n\n const maxHeight = Math.min(minHeight, Math.floor(this.state.height * 0.5) / this.state.zoom.value);\n const height = Math.min(image.naturalHeight, maxHeight);\n const width = height * (image.naturalWidth / image.naturalHeight); // add current imageElement width/height to account for previous centering\n // of the placeholder image\n\n const x = imageElement.x + imageElement.width / 2 - width / 2;\n const y = imageElement.y + imageElement.height / 2 - height / 2;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x,\n y,\n width,\n height\n });\n }\n };\n /** updates image cache, refreshing updated elements and/or setting status\n to error for images that fail during <img> element creation */\n\n\n this.updateImageCache = (elements, files = this.files) => __awaiter(this, void 0, void 0, function* () {\n const {\n updatedFiles,\n erroredFiles\n } = yield (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.updateImageCache)({\n imageCache: this.imageCache,\n fileIds: elements.map(element => element.fileId),\n files\n });\n\n if (updatedFiles.size || erroredFiles.size) {\n for (const element of elements) {\n if (updatedFiles.has(element.fileId)) {\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache[\"delete\"](element);\n }\n }\n }\n\n if (erroredFiles.size) {\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().map(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && erroredFiles.has(element.fileId)) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n status: \"error\"\n });\n }\n\n return element;\n }));\n }\n\n return {\n updatedFiles,\n erroredFiles\n };\n });\n /** adds new images to imageCache and re-renders if needed */\n\n\n this.addNewImagesToImageCache = (imageElements = (0,_element_image__WEBPACK_IMPORTED_MODULE_40__.getInitializedImageElements)(this.scene.getNonDeletedElements()), files = this.files) => __awaiter(this, void 0, void 0, function* () {\n const uncachedImageElements = imageElements.filter(element => !element.isDeleted && !this.imageCache.has(element.fileId));\n\n if (uncachedImageElements.length) {\n const {\n updatedFiles\n } = yield this.updateImageCache(uncachedImageElements, files);\n\n if (updatedFiles.size) {\n this.scene.informMutation();\n }\n }\n });\n /** generally you should use `addNewImagesToImageCache()` directly if you need\n * to render new images. This is just a failsafe */\n\n\n this.scheduleImageRefresh = lodash_throttle__WEBPACK_IMPORTED_MODULE_41___default()(() => {\n this.addNewImagesToImageCache();\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_RENDER_TIMEOUT);\n\n this.updateBindingEnabledOnPointerMove = event => {\n const shouldEnableBinding = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.shouldEnableBindingForPointerEvent)(event);\n\n if (this.state.isBindingEnabled !== shouldEnableBinding) {\n this.setState({\n isBindingEnabled: shouldEnableBinding\n });\n }\n };\n\n this.maybeSuggestBindingAtCursor = pointerCoords => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerCoords, this.scene);\n this.setState({\n suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : []\n });\n };\n\n this.maybeSuggestBindingsForLinearElementAtCoords = (linearElement,\n /** scene coords */\n pointerCoords, // During line creation the start binding hasn't been written yet\n // into `linearElement`\n oppositeBindingBoundElement) => {\n if (!pointerCoords.length) {\n return;\n }\n\n const suggestedBindings = pointerCoords.reduce((acc, coords) => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(coords, this.scene);\n\n if (hoveredBindableElement != null && !(0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isLinearElementSimpleAndAlreadyBound)(linearElement, oppositeBindingBoundElement === null || oppositeBindingBoundElement === void 0 ? void 0 : oppositeBindingBoundElement.id, hoveredBindableElement)) {\n acc.push(hoveredBindableElement);\n }\n\n return acc;\n }, []);\n this.setState({\n suggestedBindings\n });\n };\n\n this.handleInteractiveCanvasRef = canvas => {\n var _a, _b, _c; // canvas is null when unmounting\n\n\n if (canvas !== null) {\n this.interactiveCanvas = canvas; // -----------------------------------------------------------------------\n // NOTE wheel, touchstart, touchend events must be registered outside\n // of react because react binds them them passively (so we can't prevent\n // default on them)\n\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel);\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd); // -----------------------------------------------------------------------\n } else {\n (_a = this.interactiveCanvas) === null || _a === void 0 ? void 0 : _a.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel);\n (_b = this.interactiveCanvas) === null || _b === void 0 ? void 0 : _b.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n (_c = this.interactiveCanvas) === null || _c === void 0 ? void 0 : _c.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd);\n }\n };\n\n this.handleAppOnDrop = event => __awaiter(this, void 0, void 0, function* () {\n var _l, _m, _o, _p; // must be retrieved first, in the same frame\n\n\n const {\n file,\n fileHandle\n } = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.getFileFromEvent)(event);\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n\n try {\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.isSupportedImageFile)(file)) {\n // first attempt to decode scene from the image if it's embedded\n // ---------------------------------------------------------------------\n if ((file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.png || (file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n const scene = yield (0,_data__WEBPACK_IMPORTED_MODULE_13__.loadFromBlob)(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n appState: Object.assign(Object.assign({}, scene.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n commitToHistory: true\n }));\n return;\n } catch (error) {\n if (error.name !== \"EncodingError\") {\n throw error;\n }\n }\n } // if no scene is embedded or we fail for whatever reason, fall back\n // to importing as regular image\n // ---------------------------------------------------------------------\n\n\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n } catch (error) {\n return this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n\n const libraryJSON = event.dataTransfer.getData(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib);\n\n if (libraryJSON && typeof libraryJSON === \"string\") {\n try {\n const libraryItems = (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.parseLibraryJSON)(libraryJSON);\n this.addElementsFromPasteOrLibrary({\n elements: (0,_data_library__WEBPACK_IMPORTED_MODULE_14__.distributeLibraryItemsOnSquareGrid)(libraryItems),\n position: event,\n files: null\n });\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n\n return;\n }\n\n if (file) {\n // atetmpt to parse an excalidraw/excalidrawlib file\n yield this.loadFileToCanvas(file, fileHandle);\n }\n\n if ((_m = (_l = event.dataTransfer) === null || _l === void 0 ? void 0 : _l.types) === null || _m === void 0 ? void 0 : _m.includes(\"text/plain\")) {\n const text = (_o = event.dataTransfer) === null || _o === void 0 ? void 0 : _o.getData(\"text\");\n\n if (text && (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.embeddableURLValidator)(text, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(text) || ((_p = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)(text)) === null || _p === void 0 ? void 0 : _p.type) === \"video\")) {\n const embeddable = this.insertEmbeddableElement({\n sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(text)\n });\n\n if (embeddable) {\n this.setState({\n selectedElementIds: {\n [embeddable.id]: true\n }\n });\n }\n }\n }\n });\n\n this.loadFileToCanvas = (file, fileHandle) => __awaiter(this, void 0, void 0, function* () {\n file = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.normalizeFile)(file);\n\n try {\n const ret = yield (0,_data_blob__WEBPACK_IMPORTED_MODULE_39__.loadSceneOrLibraryFromBlob)(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);\n\n if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidraw) {\n this.setState({\n isLoading: true\n });\n this.syncActionResult(Object.assign(Object.assign({}, ret.data), {\n appState: Object.assign(Object.assign({}, ret.data.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n commitToHistory: true\n }));\n } else if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib) {\n yield this.library.updateLibrary({\n libraryItems: file,\n merge: true,\n openLibraryMenu: true\n }).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.importLibraryError\")\n });\n });\n }\n } catch (error) {\n this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n });\n\n this.handleCanvasContextMenu = event => {\n event.preventDefault();\n\n if ((\"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"touch\" || \"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"pen\" && // always allow if user uses a pen secondary button\n event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.SECONDARY) && this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const element = this.getElementAtPosition(x, y, {\n preferSelected: true,\n includeLockedElements: true\n });\n const selectedElements = this.scene.getSelectedElements(this.state);\n const isHittignCommonBoundBox = this.isHittingCommonBoundingBoxOfSelectedElements({\n x,\n y\n }, selectedElements);\n const type = element || isHittignCommonBoundBox ? \"element\" : \"canvas\";\n const container = this.excalidrawContainerRef.current;\n const {\n top: offsetTop,\n left: offsetLeft\n } = container.getBoundingClientRect();\n const left = event.clientX - offsetLeft;\n const top = event.clientY - offsetTop;\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"contextMenu\", \"openContextMenu\", type);\n this.setState(Object.assign(Object.assign({}, element && !this.state.selectedElementIds[element.id] ? Object.assign(Object.assign(Object.assign({}, this.state), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: this.state.editingGroupId,\n selectedElementIds: {\n [element.id]: true\n }\n }, this.scene.getNonDeletedElements(), this.state, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(element) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(element, this.scene) : null\n }) : this.state), {\n showHyperlinkPopup: false\n }), () => {\n this.setState({\n contextMenu: {\n top,\n left,\n items: this.getContextMenuItems(type)\n }\n });\n });\n };\n\n this.maybeDragNewGenericElement = (pointerDownState, event) => {\n var _a;\n\n const draggingElement = this.state.draggingElement;\n const pointerCoords = pointerDownState.lastCoords;\n\n if (!draggingElement) {\n return;\n }\n\n if (draggingElement.type === \"selection\" && this.state.activeTool.type !== \"eraser\") {\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)(draggingElement, this.state.activeTool.type, pointerDownState.origin.x, pointerDownState.origin.y, pointerCoords.x, pointerCoords.y, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.origin.x, pointerCoords.x), (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.origin.y, pointerCoords.y), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event));\n } else {\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(draggingElement) && ((_a = this.imageCache.get(draggingElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n const aspectRatio = image && !(image instanceof Promise) ? image.width / image.height : null;\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)(draggingElement, this.state.activeTool.type, pointerDownState.originInGrid.x, pointerDownState.originInGrid.y, gridX, gridY, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.originInGrid.x, gridX), (0,_utils__WEBPACK_IMPORTED_MODULE_33__.distance)(pointerDownState.originInGrid.y, gridY), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(draggingElement) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event), aspectRatio);\n this.maybeSuggestBindingForAll([draggingElement]); // highlight elements that are to be added to frames on frames creation\n\n if (this.state.activeTool.type === \"frame\") {\n this.setState({\n elementsToHighlight: (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), draggingElement, this.state)\n });\n }\n }\n };\n\n this.maybeHandleResize = (pointerDownState, event) => {\n const selectedElements = this.scene.getSelectedElements(this.state);\n const selectedFrames = selectedElements.filter(element => element.type === \"frame\");\n const transformHandleType = pointerDownState.resize.handleType;\n\n if (selectedFrames.length > 0 && transformHandleType === \"rotation\") {\n return false;\n }\n\n this.setState({\n // TODO: rename this state field to \"isScaling\" to distinguish\n // it from the generic \"isResizing\" which includes scaling and\n // rotating\n isResizing: transformHandleType && transformHandleType !== \"rotation\",\n isRotating: transformHandleType === \"rotation\",\n activeEmbeddable: null\n });\n const pointerCoords = pointerDownState.lastCoords;\n const [resizeX, resizeY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x - pointerDownState.resize.offset.x, pointerCoords.y - pointerDownState.resize.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const frameElementsOffsetsMap = new Map();\n selectedFrames.forEach(frame => {\n const elementsInFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameElements)(this.scene.getNonDeletedElements(), frame.id);\n elementsInFrame.forEach(element => {\n frameElementsOffsetsMap.set(frame.id + element.id, {\n x: element.x - frame.x,\n y: element.y - frame.y\n });\n });\n });\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.transformElements)(pointerDownState, transformHandleType, selectedElements, pointerDownState.resize.arrowDirection, (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event), selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(selectedElements[0]) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {\n this.maybeSuggestBindingForAll(selectedElements);\n const elementsToHighlight = new Set();\n selectedFrames.forEach(frame => {\n const elementsInFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameElements)(this.scene.getNonDeletedElements(), frame.id); // keep elements' positions relative to their frames on frames resizing\n\n if (transformHandleType) {\n if (transformHandleType.includes(\"w\")) {\n elementsInFrame.forEach(element => {\n var _a, _b;\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: frame.x + (((_a = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _a === void 0 ? void 0 : _a.x) || 0),\n y: frame.y + (((_b = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _b === void 0 ? void 0 : _b.y) || 0)\n });\n });\n }\n\n if (transformHandleType.includes(\"n\")) {\n elementsInFrame.forEach(element => {\n var _a, _b;\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: frame.x + (((_a = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _a === void 0 ? void 0 : _a.x) || 0),\n y: frame.y + (((_b = frameElementsOffsetsMap.get(frame.id + element.id)) === null || _b === void 0 ? void 0 : _b.y) || 0)\n });\n });\n }\n }\n\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), frame, this.state).forEach(element => elementsToHighlight.add(element));\n });\n this.setState({\n elementsToHighlight: [...elementsToHighlight]\n });\n return true;\n }\n\n return false;\n };\n\n this.getContextMenuItems = type => {\n const options = [];\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg); // canvas contextMenu\n // -------------------------------------------------------------------------\n\n if (type === \"canvas\") {\n if (this.state.viewModeEnabled) {\n return [...options, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_38__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats];\n }\n\n return [_actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg, _actions__WEBPACK_IMPORTED_MODULE_5__.copyText, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSelectAll, _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__.actionUnlockAllElements, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_38__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats];\n } // element contextMenu\n // -------------------------------------------------------------------------\n\n\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.copyText);\n\n if (this.state.viewModeEnabled) {\n return [_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, ...options];\n }\n\n return [_actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionSelectAllElementsInFrame, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionRemoveAllElementsFromFrame, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, ...options, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyStyles, _actions__WEBPACK_IMPORTED_MODULE_5__.actionPasteStyles, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionGroup, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUnbindText, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBindText, _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_57__.actionWrapTextInContainer, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUngroup, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionAddToLibrary, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendBackward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringForward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendToBack, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringToFront, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipHorizontal, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipVertical, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleLinearEditor, _actions__WEBPACK_IMPORTED_MODULE_5__.actionLink, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDuplicateSelection, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleElementLock, _ContextMenu__WEBPACK_IMPORTED_MODULE_35__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDeleteSelected];\n };\n\n this.handleWheel = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n event.preventDefault();\n\n if (isPanning) {\n return;\n }\n\n const {\n deltaX,\n deltaY\n } = event; // note that event.ctrlKey is necessary to handle pinch zooming\n\n if (event.metaKey || event.ctrlKey) {\n const sign = Math.sign(deltaY);\n const MAX_STEP = _constants__WEBPACK_IMPORTED_MODULE_12__.ZOOM_STEP * 100;\n const absDelta = Math.abs(deltaY);\n let delta = deltaY;\n\n if (absDelta > MAX_STEP) {\n delta = MAX_STEP * sign;\n }\n\n let newZoom = this.state.zoom.value - delta / 100; // increase zoom steps the more zoomed-in we are (applies to >100% only)\n\n newZoom += Math.log10(Math.max(1, this.state.zoom.value)) * -sign * // reduced amplification for small deltas (small movements on a trackpad)\n Math.min(1, absDelta / 20);\n this.translateCanvas(state => Object.assign(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_31__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getNormalizedZoom)(newZoom)\n }, state)), {\n shouldCacheIgnoreZoom: true\n }));\n this.resetShouldCacheIgnoreZoomDebounced();\n return;\n } // scroll horizontally when shift pressed\n\n\n if (event.shiftKey) {\n this.translateCanvas(({\n zoom,\n scrollX\n }) => ({\n // on Mac, shift+wheel tends to result in deltaX\n scrollX: scrollX - (deltaY || deltaX) / zoom.value\n }));\n return;\n }\n\n this.translateCanvas(({\n zoom,\n scrollX,\n scrollY\n }) => ({\n scrollX: scrollX - deltaX / zoom.value,\n scrollY: scrollY - deltaY / zoom.value\n }));\n });\n\n this.savePointer = (x, y, button) => {\n var _a, _b;\n\n if (!x || !y) {\n return;\n }\n\n const pointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: x,\n clientY: y\n }, this.state);\n\n if (isNaN(pointer.x) || isNaN(pointer.y)) {// sometimes the pointer goes off screen\n }\n\n (_b = (_a = this.props).onPointerUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, {\n pointer,\n button,\n pointersMap: gesture.pointers\n });\n };\n\n this.resetShouldCacheIgnoreZoomDebounced = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.debounce)(() => {\n if (!this.unmounted) {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n }\n }, 300);\n\n this.updateDOMRect = cb => {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n width,\n height,\n left: offsetLeft,\n top: offsetTop\n } = excalidrawContainer.getBoundingClientRect();\n const {\n width: currentWidth,\n height: currentHeight,\n offsetTop: currentOffsetTop,\n offsetLeft: currentOffsetLeft\n } = this.state;\n\n if (width === currentWidth && height === currentHeight && offsetLeft === currentOffsetLeft && offsetTop === currentOffsetTop) {\n if (cb) {\n cb();\n }\n\n return;\n }\n\n this.setState({\n width,\n height,\n offsetLeft,\n offsetTop\n }, () => {\n cb && cb();\n });\n }\n };\n\n this.refresh = () => {\n this.setState(Object.assign({}, this.getCanvasOffsets()));\n };\n\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)();\n const {\n excalidrawRef,\n viewModeEnabled = false,\n zenModeEnabled = false,\n gridModeEnabled = false,\n theme = defaultAppState.theme,\n name = defaultAppState.name\n } = props;\n this.state = Object.assign(Object.assign(Object.assign(Object.assign({}, defaultAppState), {\n theme,\n isLoading: true\n }), this.getCanvasOffsets()), {\n viewModeEnabled,\n zenModeEnabled,\n gridSize: gridModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.GRID_SIZE : null,\n name,\n width: window.innerWidth,\n height: window.innerHeight\n });\n this.id = (0,nanoid__WEBPACK_IMPORTED_MODULE_65__.nanoid)();\n this.library = new _data_library__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this);\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_30__[\"default\"]();\n this.canvas = document.createElement(\"canvas\");\n this.rc = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__[\"default\"].canvas(this.canvas);\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_63__.Renderer(this.scene);\n\n if (excalidrawRef) {\n const readyPromise = \"current\" in excalidrawRef && ((_a = excalidrawRef.current) === null || _a === void 0 ? void 0 : _a.readyPromise) || (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resolvablePromise)();\n const api = {\n ready: true,\n readyPromise,\n updateScene: this.updateScene,\n updateLibrary: this.library.updateLibrary,\n addFiles: this.addFiles,\n resetScene: this.resetScene,\n getSceneElementsIncludingDeleted: this.getSceneElementsIncludingDeleted,\n history: {\n clear: this.resetHistory\n },\n scrollToContent: this.scrollToContent,\n getSceneElements: this.getSceneElements,\n getAppState: () => this.state,\n getFiles: () => this.files,\n refresh: this.refresh,\n setToast: this.setToast,\n id: this.id,\n setActiveTool: this.setActiveTool,\n setCursor: this.setCursor,\n resetCursor: this.resetCursor,\n updateFrameRendering: this.updateFrameRendering,\n toggleSidebar: this.toggleSidebar\n };\n\n if (typeof excalidrawRef === \"function\") {\n excalidrawRef(api);\n } else {\n excalidrawRef.current = api;\n }\n\n readyPromise.resolve(api);\n }\n\n this.excalidrawContainerValue = {\n container: this.excalidrawContainerRef.current,\n id: this.id\n };\n this.fonts = new _scene_Fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts({\n scene: this.scene,\n onSceneUpdated: this.onSceneUpdated\n });\n this.history = new _history__WEBPACK_IMPORTED_MODULE_24__[\"default\"]();\n this.actionManager = new _actions_manager__WEBPACK_IMPORTED_MODULE_7__.ActionManager(this.syncActionResult, () => this.state, () => this.scene.getElementsIncludingDeleted(), this);\n this.actionManager.registerAll(_actions_register__WEBPACK_IMPORTED_MODULE_8__.actions);\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createUndoAction)(this.history));\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createRedoAction)(this.history));\n }\n\n onWindowMessage(event) {\n if (event.origin !== \"https://player.vimeo.com\" && event.origin !== \"https://www.youtube.com\") {\n return;\n }\n\n let data = null;\n\n try {\n data = JSON.parse(event.data);\n } catch (e) {}\n\n if (!data) {\n return;\n }\n\n switch (event.origin) {\n case \"https://player.vimeo.com\":\n //Allowing for multiple instances of Excalidraw running in the window\n if (data.method === \"paused\") {\n let source = null;\n const iframes = document.body.querySelectorAll(\"iframe.excalidraw__embeddable\");\n\n if (!iframes) {\n break;\n }\n\n for (const iframe of iframes) {\n if (iframe.contentWindow === event.source) {\n source = iframe.contentWindow;\n }\n }\n\n source === null || source === void 0 ? void 0 : source.postMessage(JSON.stringify({\n method: data.value ? \"play\" : \"pause\",\n value: true\n }), \"*\");\n }\n\n break;\n\n case \"https://www.youtube.com\":\n if (data.event === \"infoDelivery\" && data.info && data.id && typeof data.info.playerState === \"number\") {\n const id = data.id;\n const playerState = data.info.playerState;\n\n if (Object.values(_constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES).includes(playerState)) {\n YOUTUBE_VIDEO_STATES.set(id, playerState);\n }\n }\n\n break;\n }\n }\n\n updateEmbeddableRef(id, ref) {\n if (ref) {\n this.iFrameRefs.set(id, ref);\n }\n }\n\n getHTMLIFrameElement(id) {\n return this.iFrameRefs.get(id);\n }\n\n handleEmbeddableCenterClick(element) {\n var _a, _b, _c, _d;\n\n if (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) === element && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"active\") {\n return;\n } // The delay serves two purposes\n // 1. To prevent first click propagating to iframe on mobile,\n // else the click will immediately start and stop the video\n // 2. If the user double clicks the frame center to activate it\n // without the delay youtube will immediately open the video\n // in fullscreen mode\n\n\n setTimeout(() => {\n this.setState({\n activeEmbeddable: {\n element,\n state: \"active\"\n },\n selectedElementIds: {\n [element.id]: true\n },\n draggingElement: null,\n selectionElement: null\n });\n }, 100);\n const iframe = this.getHTMLIFrameElement(element.id);\n\n if (!(iframe === null || iframe === void 0 ? void 0 : iframe.contentWindow)) {\n return;\n }\n\n if (iframe.src.includes(\"youtube\")) {\n const state = YOUTUBE_VIDEO_STATES.get(element.id);\n\n if (!state) {\n YOUTUBE_VIDEO_STATES.set(element.id, _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.UNSTARTED);\n iframe.contentWindow.postMessage(JSON.stringify({\n event: \"listening\",\n id: element.id\n }), \"*\");\n }\n\n switch (state) {\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.PLAYING:\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.BUFFERING:\n (_c = iframe.contentWindow) === null || _c === void 0 ? void 0 : _c.postMessage(JSON.stringify({\n event: \"command\",\n func: \"pauseVideo\",\n args: \"\"\n }), \"*\");\n break;\n\n default:\n (_d = iframe.contentWindow) === null || _d === void 0 ? void 0 : _d.postMessage(JSON.stringify({\n event: \"command\",\n func: \"playVideo\",\n args: \"\"\n }), \"*\");\n }\n }\n\n if (iframe.src.includes(\"player.vimeo.com\")) {\n iframe.contentWindow.postMessage(JSON.stringify({\n method: \"paused\" //video play/pause in onWindowMessage handler\n\n }), \"*\");\n }\n }\n\n isEmbeddableCenter(el, event, sceneX, sceneY) {\n var _a, _b;\n\n return el && !event.altKey && !event.shiftKey && !event.metaKey && !event.ctrlKey && (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) !== el || ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\" || !this.state.activeEmbeddable) && sceneX >= el.x + el.width / 3 && sceneX <= el.x + 2 * el.width / 3 && sceneY >= el.y + el.height / 3 && sceneY <= el.y + 2 * el.height / 3;\n }\n\n renderEmbeddables() {\n const scale = this.state.zoom.value;\n const normalizedWidth = this.state.width;\n const normalizedHeight = this.state.height;\n const embeddableElements = this.scene.getNonDeletedElements().filter(el => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(el) && !!el.validated);\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: embeddableElements.map(el => {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: el.x,\n sceneY: el.y\n }, this.state);\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_34__.getEmbedLink)((0,_data_url__WEBPACK_IMPORTED_MODULE_46__.toValidURL)(el.link || \"\"));\n const isVisible = (0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(el, normalizedWidth, normalizedHeight, this.state);\n const isActive = ((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) === el && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"active\";\n const isHovered = ((_c = this.state.activeEmbeddable) === null || _c === void 0 ? void 0 : _c.element) === el && ((_d = this.state.activeEmbeddable) === null || _d === void 0 ? void 0 : _d.state) === \"hover\";\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw__embeddable-container\", {\n \"is-hovered\": isHovered\n }),\n style: {\n transform: isVisible ? `translate(${x - this.state.offsetLeft}px, ${y - this.state.offsetTop}px) scale(${scale})` : \"none\",\n display: isVisible ? \"block\" : \"none\",\n opacity: el.opacity / 100,\n [\"--embeddable-radius\"]: `${(0,_math__WEBPACK_IMPORTED_MODULE_28__.getCornerRadius)(Math.min(el.width, el.height), el)}px`\n }\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n //this is a hack that addresses isse with embedded excalidraw.com embeddable\n //https://github.com/excalidraw/excalidraw/pull/6691#issuecomment-1607383938\n\n /*ref={(ref) => {\n if (!this.excalidrawContainerRef.current) {\n return;\n }\n const container = this.excalidrawContainerRef.current;\n const sh = container.scrollHeight;\n const ch = container.clientHeight;\n if (sh !== ch) {\n container.style.height = `${sh}px`;\n setTimeout(() => {\n container.style.height = `100%`;\n });\n }\n }}*/\n className: \"excalidraw__embeddable-container__inner\",\n style: {\n width: isVisible ? `${el.width}px` : 0,\n height: isVisible ? `${el.height}px` : 0,\n transform: isVisible ? `rotate(${el.angle}rad)` : \"none\",\n pointerEvents: isActive ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled\n }\n }, {\n children: [isHovered && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable-hint\"\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"buttons.embeddableInteractionButton\")\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable__outer\",\n style: {\n padding: `${el.strokeWidth}px`\n }\n }, {\n children: (_g = (_f = (_e = this.props).renderEmbeddable) === null || _f === void 0 ? void 0 : _f.call(_e, el, this.state)) !== null && _g !== void 0 ? _g : (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"iframe\", {\n ref: ref => this.updateEmbeddableRef(el.id, ref),\n className: \"excalidraw__embeddable\",\n srcDoc: (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) === \"document\" ? embedLink.srcdoc(this.state.theme) : undefined,\n src: (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) !== \"document\" ? (_h = embedLink === null || embedLink === void 0 ? void 0 : embedLink.link) !== null && _h !== void 0 ? _h : \"\" : undefined,\n // https://stackoverflow.com/q/18470015\n scrolling: \"no\",\n referrerPolicy: \"no-referrer-when-downgrade\",\n title: \"Excalidraw Embedded Content\",\n allow: \"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\",\n allowFullScreen: true,\n sandbox: \"allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads\"\n })\n }))]\n }))\n }), el.id);\n })\n });\n }\n\n render() {\n var _a, _b, _c;\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n const {\n renderTopRightUI,\n renderCustomStats\n } = this.props;\n const versionNonce = this.scene.getVersionNonce();\n const {\n canvasElements,\n visibleElements\n } = this.renderer.getRenderableElements({\n versionNonce,\n zoom: this.state.zoom,\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n height: this.state.height,\n width: this.state.width,\n editingElement: this.state.editingElement,\n pendingImageElementId: this.state.pendingImageElementId\n });\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw excalidraw-container\", {\n \"excalidraw--view-mode\": this.state.viewModeEnabled,\n \"excalidraw--mobile\": this.device.isMobile\n }),\n style: {\n [\"--ui-pointerEvents\"]: this.state.selectionElement || this.state.draggingElement || this.state.resizingElement || this.state.editingElement && !(0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement) ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled\n },\n ref: this.excalidrawContainerRef,\n onDrop: this.handleAppOnDrop,\n tabIndex: 0,\n onKeyDown: this.props.handleKeyboardGlobally ? undefined : this.onKeyDown\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppContext.Provider, Object.assign({\n value: this\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppPropsContext.Provider, Object.assign({\n value: this.props\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawContainerContext.Provider, Object.assign({\n value: this.excalidrawContainerValue\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DeviceContext.Provider, Object.assign({\n value: this.device\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawSetAppStateContext.Provider, Object.assign({\n value: this.setAppState\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawAppStateContext.Provider, Object.assign({\n value: this.state\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawElementsContext.Provider, Object.assign({\n value: this.scene.getNonDeletedElements()\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawActionManagerContext.Provider, Object.assign({\n value: this.actionManager\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LayerUI__WEBPACK_IMPORTED_MODULE_36__[\"default\"], Object.assign({\n canvas: this.canvas,\n interactiveCanvas: this.interactiveCanvas,\n appState: this.state,\n files: this.files,\n setAppState: this.setAppState,\n actionManager: this.actionManager,\n elements: this.scene.getNonDeletedElements(),\n onLockToggle: this.toggleLock,\n onPenModeToggle: this.togglePenMode,\n onHandToolToggle: this.onHandToolToggle,\n langCode: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.getLanguage)().code,\n renderTopRightUI: renderTopRightUI,\n renderCustomStats: renderCustomStats,\n showExitZenModeBtn: typeof ((_a = this.props) === null || _a === void 0 ? void 0 : _a.zenModeEnabled) === \"undefined\" && this.state.zenModeEnabled,\n UIOptions: this.props.UIOptions,\n onImageAction: this.onImageAction,\n onExportImage: this.onExportImage,\n renderWelcomeScreen: !this.state.isLoading && this.state.showWelcomeScreen && this.state.activeTool.type === \"selection\" && !this.state.zenModeEnabled && !this.scene.getElementsIncludingDeleted().length,\n app: this\n }, {\n children: this.props.children\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-textEditorContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-contextMenuContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-eye-dropper-container\"\n }), selectedElements.length === 1 && !this.state.contextMenu && this.state.showHyperlinkPopup && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_element_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.Hyperlink, {\n element: selectedElements[0],\n setAppState: this.setAppState,\n onLinkOpen: this.props.onLinkOpen,\n setToast: this.setToast\n }, selectedElements[0].id), this.state.toast !== null && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Toast__WEBPACK_IMPORTED_MODULE_37__.Toast, {\n message: this.state.toast.message,\n onClose: () => this.setToast(null),\n duration: this.state.toast.duration,\n closable: this.state.toast.closable\n }), this.state.contextMenu && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ContextMenu__WEBPACK_IMPORTED_MODULE_35__.ContextMenu, {\n items: this.state.contextMenu.items,\n top: this.state.contextMenu.top,\n left: this.state.contextMenu.left,\n actionManager: this.actionManager\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_62__.StaticCanvas, {\n canvas: this.canvas,\n rc: this.rc,\n elements: canvasElements,\n visibleElements: visibleElements,\n versionNonce: versionNonce,\n selectionNonce: (_b = this.state.selectionElement) === null || _b === void 0 ? void 0 : _b.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: true\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_62__.InteractiveCanvas, {\n containerRef: this.excalidrawContainerRef,\n canvas: this.interactiveCanvas,\n elements: canvasElements,\n visibleElements: visibleElements,\n selectedElements: selectedElements,\n versionNonce: versionNonce,\n selectionNonce: (_c = this.state.selectionElement) === null || _c === void 0 ? void 0 : _c.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n renderInteractiveSceneCallback: this.renderInteractiveSceneCallback,\n handleCanvasRef: this.handleInteractiveCanvasRef,\n onContextMenu: this.handleCanvasContextMenu,\n onPointerMove: this.handleCanvasPointerMove,\n onPointerUp: this.handleCanvasPointerUp,\n onPointerCancel: this.removePointer,\n onTouchMove: this.handleTouchMove,\n onPointerDown: this.handleCanvasPointerDown,\n onDoubleClick: this.handleCanvasDoubleClick\n }), this.renderFrameNames()]\n })), this.renderEmbeddables()]\n }))\n }))\n }))\n }))\n }))\n }))\n }))\n }));\n }\n\n componentDidMount() {\n var _a, _b;\n\n return __awaiter(this, void 0, void 0, function* () {\n this.unmounted = false;\n this.excalidrawContainerValue.container = this.excalidrawContainerRef.current;\n\n if (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_12__.ENV.TEST || \"development\" !== \"production\") {\n const setState = this.setState.bind(this);\n Object.defineProperties(window.h, {\n state: {\n configurable: true,\n get: () => {\n return this.state;\n }\n },\n setState: {\n configurable: true,\n value: (...args) => {\n return this.setState(...args);\n }\n },\n app: {\n configurable: true,\n value: this\n },\n history: {\n configurable: true,\n value: this.history\n }\n });\n }\n\n this.scene.addCallback(this.onSceneUpdated);\n this.addEventListeners();\n\n if (this.props.autoFocus && this.excalidrawContainerRef.current) {\n this.focusContainer();\n }\n\n if (this.excalidrawContainerRef.current && // bounding rects don't work in tests so updating\n // the state on init would result in making the test enviro run\n // in mobile breakpoint (0 width/height), making everything fail\n !(0,_utils__WEBPACK_IMPORTED_MODULE_33__.isTestEnv)()) {\n this.refreshDeviceState(this.excalidrawContainerRef.current);\n }\n\n if (\"ResizeObserver\" in window && ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current)) {\n this.resizeObserver = new ResizeObserver(() => {\n // recompute device dimensions state\n // ---------------------------------------------------------------------\n this.refreshDeviceState(this.excalidrawContainerRef.current); // refresh offsets\n // ---------------------------------------------------------------------\n\n this.updateDOMRect();\n });\n (_b = this.resizeObserver) === null || _b === void 0 ? void 0 : _b.observe(this.excalidrawContainerRef.current);\n } else if (window.matchMedia) {\n const mdScreenQuery = window.matchMedia(`(max-width: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_PORTRAIT}px), (max-height: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_HEIGHT_LANDSCAPE}px) and (max-width: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_LANDSCAPE}px)`);\n const smScreenQuery = window.matchMedia(`(max-width: ${_constants__WEBPACK_IMPORTED_MODULE_12__.MQ_SM_MAX_WIDTH}px)`);\n const canDeviceFitSidebarMediaQuery = window.matchMedia(`(min-width: ${// NOTE this won't update if a different breakpoint is supplied\n // after mount\n this.props.UIOptions.dockedSidebarBreakpoint != null ? this.props.UIOptions.dockedSidebarBreakpoint : _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_RIGHT_SIDEBAR_MIN_WIDTH}px)`);\n\n const handler = () => {\n this.excalidrawContainerRef.current.getBoundingClientRect();\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateObject)(this.device, {\n isSmScreen: smScreenQuery.matches,\n isMobile: mdScreenQuery.matches,\n canDeviceFitSidebar: canDeviceFitSidebarMediaQuery.matches\n });\n };\n\n mdScreenQuery.addListener(handler);\n\n this.detachIsMobileMqHandler = () => mdScreenQuery.removeListener(handler);\n }\n\n const searchParams = new URLSearchParams(window.location.search.slice(1));\n\n if (searchParams.has(\"web-share-target\")) {\n // Obtain a file that was shared via the Web Share Target API.\n this.restoreFileFromShare();\n } else {\n this.updateDOMRect(this.initializeScene);\n } // note that this check seems to always pass in localhost\n\n\n if ((0,_constants__WEBPACK_IMPORTED_MODULE_12__.isBrave)() && !(0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.isMeasureTextSupported)()) {\n this.setState({\n errorMessage: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_58__[\"default\"], {})\n });\n }\n });\n }\n\n componentWillUnmount() {\n var _a;\n\n this.renderer.destroy();\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_30__[\"default\"]();\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_63__.Renderer(this.scene);\n this.files = {};\n this.imageCache.clear();\n (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();\n this.unmounted = true;\n this.removeEventListeners();\n this.scene.destroy();\n this.library.destroy();\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_64__.ShapeCache.destroy();\n clearTimeout(touchTimeout);\n _scene__WEBPACK_IMPORTED_MODULE_29__.isSomeElementSelected.clearCache();\n _groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements.clearCache();\n touchTimeout = 0;\n }\n\n removeEventListeners() {\n var _a, _b, _c, _d, _e;\n\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, this.removePointer);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.COPY, this.onCopy);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, this.pasteFromClipboard);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.CUT, this.onCut);\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.onWheel);\n (_b = this.nearestScrollableContainer) === null || _b === void 0 ? void 0 : _b.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.SCROLL, this.onScroll);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, this.onKeyDown, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MOUSE_MOVE, this.updateCurrentCursorPosition, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, this.onKeyUp);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.RESIZE, this.onResize, false);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.UNLOAD, this.onUnload, false);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, this.onBlur, false);\n (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DRAG_OVER, this.disableEvent, false);\n (_d = this.excalidrawContainerRef.current) === null || _d === void 0 ? void 0 : _d.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DROP, this.disableEvent, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_START, this.onGestureStart, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_CHANGE, this.onGestureChange, false);\n document.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_END, this.onGestureEnd, false);\n (_e = this.detachIsMobileMqHandler) === null || _e === void 0 ? void 0 : _e.call(this);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MESSAGE, this.onWindowMessage, false);\n }\n\n addEventListeners() {\n var _a, _b, _c, _d, _e;\n\n this.removeEventListeners();\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MESSAGE, this.onWindowMessage, false);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, this.removePointer); // #3553\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.COPY, this.onCopy);\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.onWheel, {\n passive: false\n });\n\n if (this.props.handleKeyboardGlobally) {\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, this.onKeyDown, false);\n }\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, this.onKeyUp, {\n passive: true\n });\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MOUSE_MOVE, this.updateCurrentCursorPosition); // rerender text elements on font load to fix #637 && #1553\n\n (_c = (_b = document.fonts) === null || _b === void 0 ? void 0 : _b.addEventListener) === null || _c === void 0 ? void 0 : _c.call(_b, \"loadingdone\", event => {\n const loadedFontFaces = event.fontfaces;\n this.fonts.onFontsLoaded(loadedFontFaces);\n }); // Safari-only desktop pinch zoom\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_START, this.onGestureStart, false);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_CHANGE, this.onGestureChange, false);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_END, this.onGestureEnd, false);\n\n if (this.state.viewModeEnabled) {\n return;\n }\n\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, this.pasteFromClipboard);\n document.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.CUT, this.onCut);\n\n if (this.props.detectScroll) {\n this.nearestScrollableContainer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.getNearestScrollableContainer)(this.excalidrawContainerRef.current);\n this.nearestScrollableContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.SCROLL, this.onScroll);\n }\n\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.RESIZE, this.onResize, false);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.UNLOAD, this.onUnload, false);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, this.onBlur, false);\n (_d = this.excalidrawContainerRef.current) === null || _d === void 0 ? void 0 : _d.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DRAG_OVER, this.disableEvent, false);\n (_e = this.excalidrawContainerRef.current) === null || _e === void 0 ? void 0 : _e.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DROP, this.disableEvent, false);\n }\n\n componentDidUpdate(prevProps, prevState) {\n var _a, _b, _c, _d, _e, _f;\n\n this.updateEmbeddables();\n\n if (!this.state.showWelcomeScreen && !this.scene.getElementsIncludingDeleted().length) {\n this.setState({\n showWelcomeScreen: true\n });\n }\n\n if (this.excalidrawContainerRef.current && prevProps.UIOptions.dockedSidebarBreakpoint !== this.props.UIOptions.dockedSidebarBreakpoint) {\n this.refreshDeviceState(this.excalidrawContainerRef.current);\n }\n\n if (prevState.scrollX !== this.state.scrollX || prevState.scrollY !== this.state.scrollY) {\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onScrollChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.scrollX, this.state.scrollY);\n }\n\n if (Object.keys(this.state.selectedElementIds).length && (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n\n if (this.state.activeTool.type === \"eraser\" && prevState.theme !== this.state.theme) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setEraserCursor)(this.interactiveCanvas, this.state.theme);\n } // Hide hyperlink popup if shown when element type is not selection\n\n\n if (prevState.activeTool.type === \"selection\" && this.state.activeTool.type !== \"selection\" && this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: false\n });\n }\n\n if (prevProps.langCode !== this.props.langCode) {\n this.updateLanguage();\n }\n\n if (prevProps.viewModeEnabled !== this.props.viewModeEnabled) {\n this.setState({\n viewModeEnabled: !!this.props.viewModeEnabled\n });\n }\n\n if (prevState.viewModeEnabled !== this.state.viewModeEnabled) {\n this.addEventListeners();\n this.deselectElements();\n }\n\n if (prevProps.zenModeEnabled !== this.props.zenModeEnabled) {\n this.setState({\n zenModeEnabled: !!this.props.zenModeEnabled\n });\n }\n\n if (prevProps.theme !== this.props.theme && this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n if (prevProps.gridModeEnabled !== this.props.gridModeEnabled) {\n this.setState({\n gridSize: this.props.gridModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.GRID_SIZE : null\n });\n }\n\n if (this.props.name && prevProps.name !== this.props.name) {\n this.setState({\n name: this.props.name\n });\n }\n\n (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.classList.toggle(\"theme--dark\", this.state.theme === \"dark\");\n\n if (this.state.editingLinearElement && !this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {\n // defer so that the commitToHistory flag isn't reset via current update\n setTimeout(() => {\n // execute only if the condition still holds when the deferred callback\n // executes (it can be scheduled multiple times depending on how\n // many times the component renders)\n this.state.editingLinearElement && this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } // failsafe in case the state is being updated in incorrect order resulting\n // in the editingElement being now a deleted element\n\n\n if ((_d = this.state.editingElement) === null || _d === void 0 ? void 0 : _d.isDeleted) {\n this.setState({\n editingElement: null\n });\n }\n\n if (this.state.selectedLinearElement && !this.state.selectedElementIds[this.state.selectedLinearElement.elementId]) {\n // To make sure `selectedLinearElement` is in sync with `selectedElementIds`, however this shouldn't be needed once\n // we have a single API to update `selectedElementIds`\n this.setState({\n selectedLinearElement: null\n });\n }\n\n const {\n multiElement\n } = prevState;\n\n if (prevState.activeTool !== this.state.activeTool && multiElement != null && (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(multiElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(multiElement, this.state, this.scene, (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)(_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1)));\n }\n\n this.history.record(this.state, this.scene.getElementsIncludingDeleted()); // Do not notify consumers if we're still loading the scene. Among other\n // potential issues, this fixes a case where the tab isn't focused during\n // init, which would trigger onChange with empty elements, which would then\n // override whatever is in localStorage currently.\n\n if (!this.state.isLoading) {\n (_f = (_e = this.props).onChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.scene.getElementsIncludingDeleted(), this.state, this.files);\n }\n }\n\n static resetTapTwice() {\n didTapTwice = false;\n }\n\n addTextFromPaste(text, isPlainPaste = false) {\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state);\n const textElementProps = {\n x,\n y,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roundness: null,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text,\n fontSize: this.state.currentItemFontSize,\n fontFamily: this.state.currentItemFontFamily,\n textAlign: this.state.currentItemTextAlign,\n verticalAlign: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n locked: false\n };\n const LINE_GAP = 10;\n let currentY = y;\n const lines = isPlainPaste ? [text] : text.split(\"\\n\");\n const textElements = lines.reduce((acc, line, idx) => {\n var _a;\n\n const text = line.trim();\n const lineHeight = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getDefaultLineHeight)(textElementProps.fontFamily);\n\n if (text.length) {\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x,\n y: currentY\n });\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)(Object.assign(Object.assign({}, textElementProps), {\n x,\n y: currentY,\n text,\n lineHeight,\n frameId: topLayerFrame ? topLayerFrame.id : null\n }));\n acc.push(element);\n currentY += element.height + LINE_GAP;\n } else {\n const prevLine = (_a = lines[idx - 1]) === null || _a === void 0 ? void 0 : _a.trim(); // add paragraph only if previous line was not empty, IOW don't add\n // more than one empty line\n\n if (prevLine) {\n currentY += (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getLineHeightInPx)(textElementProps.fontSize, lineHeight) + LINE_GAP;\n }\n }\n\n return acc;\n }, []);\n\n if (textElements.length === 0) {\n return;\n }\n\n const frameId = textElements[0].frameId;\n\n if (frameId) {\n this.scene.insertElementsAtIndex(textElements, this.scene.getElementIndex(frameId));\n } else {\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted(), ...textElements]);\n }\n\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.fromEntries(textElements.map(el => [el.id, true])), this.state)\n });\n\n if (!isPlainPaste && textElements.length > 1 && PLAIN_PASTE_TOAST_SHOWN === false && !this.device.isMobile) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"toast.pasteAsSingleElement\", {\n shortcut: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.getShortcutKey)(\"CtrlOrCmd+Shift+V\")\n }),\n duration: 5000\n });\n PLAIN_PASTE_TOAST_SHOWN = true;\n }\n\n this.history.resumeRecording();\n }\n\n handleTextWysiwyg(element, {\n isExistingElement = false\n }) {\n const updateElement = (text, originalText, isDeleted) => {\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted().map(_element => {\n if (_element.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(_element)) {\n return (0,_element__WEBPACK_IMPORTED_MODULE_16__.updateTextElement)(_element, {\n text,\n isDeleted,\n originalText\n });\n }\n\n return _element;\n })]);\n };\n\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.textWysiwyg)({\n id: element.id,\n canvas: this.canvas,\n getViewportCoords: (x, y) => {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: x,\n sceneY: y\n }, this.state);\n return [viewportX - this.state.offsetLeft, viewportY - this.state.offsetTop];\n },\n onChange: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(text => {\n updateElement(text, text, false);\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element);\n }\n }),\n onSubmit: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(({\n text,\n viaKeyboard,\n originalText\n }) => {\n const isDeleted = !text.trim();\n updateElement(text, originalText, isDeleted); // select the created text element only if submitting via keyboard\n // (when submitting via click it should act as signal to deselect)\n\n if (!isDeleted && viaKeyboard) {\n const elementIdToSelect = element.containerId ? element.containerId : element.id;\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [elementIdToSelect]: true\n }), prevState)\n }));\n }\n\n if (isDeleted) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDeletion)(this.scene.getNonDeletedElements(), [element]);\n }\n\n if (!isDeleted || isExistingElement) {\n this.history.resumeRecording();\n }\n\n this.setState({\n draggingElement: null,\n editingElement: null\n });\n\n if (this.state.activeTool.locked) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n this.focusContainer();\n }),\n element,\n excalidrawContainer: this.excalidrawContainerRef.current,\n app: this\n }); // deselect all other elements when inserting text\n\n this.deselectElements(); // do an initial update to re-initialize element position since we were\n // modifying element's x/y for sake of editor (case: syncing to remote)\n\n updateElement(element.text, element.originalText, false);\n }\n\n deselectElements() {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n getTextElementAtPosition(x, y) {\n const element = this.getElementAtPosition(x, y, {\n includeBoundTextElement: true\n });\n\n if (element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && !element.isDeleted) {\n return element;\n }\n\n return null;\n }\n\n getElementAtPosition(x, y, opts) {\n const allHitElements = this.getElementsAtPosition(x, y, opts === null || opts === void 0 ? void 0 : opts.includeBoundTextElement, opts === null || opts === void 0 ? void 0 : opts.includeLockedElements);\n\n if (allHitElements.length > 1) {\n if (opts === null || opts === void 0 ? void 0 : opts.preferSelected) {\n for (let index = allHitElements.length - 1; index > -1; index--) {\n if (this.state.selectedElementIds[allHitElements[index].id]) {\n return allHitElements[index];\n }\n }\n }\n\n const elementWithHighestZIndex = allHitElements[allHitElements.length - 1]; // If we're hitting element with highest z-index only on its bounding box\n // while also hitting other element figure, the latter should be considered.\n\n return (0,_element__WEBPACK_IMPORTED_MODULE_16__.isHittingElementBoundingBoxWithoutHittingElement)(elementWithHighestZIndex, this.state, this.frameNameBoundsCache, x, y) ? allHitElements[allHitElements.length - 2] : elementWithHighestZIndex;\n }\n\n if (allHitElements.length === 1) {\n return allHitElements[0];\n }\n\n return null;\n }\n\n getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {\n const elements = includeBoundTextElement && includeLockedElements ? this.scene.getNonDeletedElements() : this.scene.getNonDeletedElements().filter(element => (includeLockedElements || !element.locked) && (includeBoundTextElement || !((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && element.containerId)));\n return (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getElementsAtPosition)(elements, element => (0,_element__WEBPACK_IMPORTED_MODULE_16__.hitTest)(element, this.state, this.frameNameBoundsCache, x, y)).filter(element => {\n // hitting a frame's element from outside the frame is not considered a hit\n const containingFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(element);\n return containingFrame && this.state.frameRendering.enabled && this.state.frameRendering.clip ? (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)({\n x,\n y\n }, containingFrame) : true;\n });\n }\n\n handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {\n const element = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getElement(linearElementEditor.elementId);\n const boundTextElement = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getBoundTextElement)(element);\n\n if (!element) {\n return;\n }\n\n if (this.state.selectedLinearElement) {\n let hoverPointIndex = -1;\n let segmentMidPointHoveredCoords = null;\n\n if ((0,_element_collision__WEBPACK_IMPORTED_MODULE_44__.isHittingElementNotConsideringBoundingBox)(element, this.state, this.frameNameBoundsCache, [scenePointerX, scenePointerY])) {\n hoverPointIndex = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointIndexUnderCursor(element, this.state.zoom, scenePointerX, scenePointerY);\n segmentMidPointHoveredCoords = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, {\n x: scenePointerX,\n y: scenePointerY\n }, this.state);\n\n if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n } else if ((0,_element_transformHandles__WEBPACK_IMPORTED_MODULE_47__.shouldShowBoundingBox)([element], this.state) && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isHittingElementBoundingBoxWithoutHittingElement)(element, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n } else if (boundTextElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.hitTest)(boundTextElement, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY)) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n\n if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n hoverPointIndex\n })\n });\n }\n\n if (!_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.arePointsEqual(this.state.selectedLinearElement.segmentMidPointHoveredCoords, segmentMidPointHoveredCoords)) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n segmentMidPointHoveredCoords\n })\n });\n }\n } else {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n\n maybeCleanupAfterMissingPointerUp(event) {\n if (lastPointerUp !== null) {\n // Unfortunately, sometimes we don't get a pointerup after a pointerdown,\n // this can happen when a contextual menu or alert is triggered. In order to avoid\n // being in a weird state, we clean up on the next pointerdown\n lastPointerUp(event);\n }\n }\n\n updateGestureOnPointerDown(event) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n\n if (gesture.pointers.size === 2) {\n gesture.lastCenter = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n gesture.initialScale = this.state.zoom.value;\n gesture.initialDistance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n }\n }\n\n initialPointerDownState(event) {\n const origin = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedElements = this.scene.getSelectedElements(this.state);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n return {\n origin,\n withCmdOrCtrl: event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD],\n originInGrid: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)((0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(origin.x, origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize)),\n scrollbars: (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop),\n // we need to duplicate because we'll be updating this state\n lastCoords: Object.assign({}, origin),\n originalElements: this.scene.getNonDeletedElements().reduce((acc, element) => {\n acc.set(element.id, (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.deepCopyElement)(element));\n return acc;\n }, new Map()),\n resize: {\n handleType: false,\n isResizing: false,\n offset: {\n x: 0,\n y: 0\n },\n arrowDirection: \"origin\",\n center: {\n x: (maxX + minX) / 2,\n y: (maxY + minY) / 2\n }\n },\n hit: {\n element: null,\n allHitElements: [],\n wasAddedToSelection: false,\n hasBeenDuplicated: false,\n hasHitCommonBoundingBoxOfSelectedElements: this.isHittingCommonBoundingBoxOfSelectedElements(origin, selectedElements)\n },\n drag: {\n hasOccurred: false,\n offset: null\n },\n eventListeners: {\n onMove: null,\n onUp: null,\n onKeyUp: null,\n onKeyDown: null\n },\n boxSelection: {\n hasOccurred: false\n },\n elementIdsToErase: {}\n };\n } // Returns whether the event is a dragging a scrollbar\n\n\n handleDraggingScrollBar(event, pointerDownState) {\n if (!(pointerDownState.scrollbars.isOverEither && !this.state.multiElement)) {\n return false;\n }\n\n isDraggingScrollBar = true;\n pointerDownState.lastCoords.x = event.clientX;\n pointerDownState.lastCoords.y = event.clientY;\n const onPointerMove = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdatesThrottled)(event => {\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n this.handlePointerMoveOverScrollbars(event, pointerDownState);\n });\n const onPointerUp = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(() => {\n isDraggingScrollBar = false;\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.setCursorForShape)(this.interactiveCanvas, this.state);\n lastPointerUp = null;\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n onPointerMove.flush();\n });\n lastPointerUp = onPointerUp;\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n return true;\n }\n\n isASelectedElement(hitElement) {\n return hitElement != null && this.state.selectedElementIds[hitElement.id];\n }\n\n isHittingCommonBoundingBoxOfSelectedElements(point, selectedElements) {\n if (selectedElements.length < 2) {\n return false;\n } // How many pixels off the shape boundary we still consider a hit\n\n\n const threshold = 10 / this.state.zoom.value;\n const [x1, y1, x2, y2] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n return point.x > x1 - threshold && point.x < x2 + threshold && point.y > y1 - threshold && point.y < y2 + threshold;\n }\n\n getCurrentItemRoundness(elementType) {\n return this.state.currentItemRoundness === \"round\" ? {\n type: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isUsingAdaptiveRadius)(elementType) ? _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.ADAPTIVE_RADIUS : _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null;\n }\n\n onKeyDownFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onKeyUpFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(event => {\n // Prevents focus from escaping excalidraw tab\n event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ALT && event.preventDefault();\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onPointerMoveFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdatesThrottled)(event => {\n var _a, _b; // We need to initialize dragOffsetXY only after we've updated\n // `state.selectedElementIds` on pointerDown. Doing it here in pointerMove\n // event handler should hopefully ensure we're already working with\n // the updated state.\n\n\n if (pointerDownState.drag.offset === null) {\n pointerDownState.drag.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getDragOffsetXY)(this.scene.getSelectedElements(this.state), pointerDownState.origin.x, pointerDownState.origin.y));\n }\n\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n if (this.handlePointerMoveOverScrollbars(event, pointerDownState)) {\n return;\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(event, this.state);\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.handleEraser(event, pointerDownState, pointerCoords);\n return;\n }\n\n const [gridX, gridY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize); // for arrows/lines, don't start dragging until a given threshold\n // to ensure we don't create a 2-point arrow by mistake when\n // user clicks mouse in a way that it moves a tiny bit (thus\n // triggering pointermove)\n\n if (!pointerDownState.drag.hasOccurred && (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\")) {\n if ((0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(pointerCoords.x, pointerCoords.y, pointerDownState.origin.x, pointerDownState.origin.y) < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD) {\n return;\n }\n }\n\n if (pointerDownState.resize.isResizing) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return true;\n }\n }\n\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n\n if (_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.shouldAddMidpoint(this.state.selectedLinearElement, pointerCoords, this.state)) {\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.addMidpoint(this.state.selectedLinearElement, pointerCoords, this.state, !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]);\n\n if (!ret) {\n return;\n } // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n if (this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n });\n return;\n } else if (linearElementEditor.pointerDownState.segmentMidpoint.value !== null && !linearElementEditor.pointerDownState.segmentMidpoint.added) {\n return;\n }\n\n const didDrag = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointDragging(event, this.state, pointerCoords.x, pointerCoords.y, (element, pointsSceneCoords) => {\n this.maybeSuggestBindingsForLinearElementAtCoords(element, pointsSceneCoords);\n }, linearElementEditor);\n\n if (didDrag) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n pointerDownState.drag.hasOccurred = true;\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n isDragging: true\n })\n });\n }\n\n if (!this.state.selectedLinearElement.isDragging) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n isDragging: true\n })\n });\n }\n\n return;\n }\n }\n\n const hasHitASelectedElement = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n const isSelectingPointsInLineEditor = this.state.editingLinearElement && event.shiftKey && this.state.editingLinearElement.elementId === ((_a = pointerDownState.hit.element) === null || _a === void 0 ? void 0 : _a.id);\n\n if ((hasHitASelectedElement || pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) && !isSelectingPointsInLineEditor) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.every(element => element.locked)) {\n return;\n }\n\n const selectedElementsHasAFrame = selectedElements.find(e => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameElement)(e));\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(pointerCoords);\n this.setState({\n frameToHighlight: topLayerFrame && !selectedElementsHasAFrame ? topLayerFrame : null\n }); // Marking that click was used for dragging to check\n // if elements should be deselected on pointerup\n\n pointerDownState.drag.hasOccurred = true;\n this.setState({\n selectedElementsAreBeingDragged: true\n }); // prevent dragging even if we're no longer holding cmd/ctrl otherwise\n // it would have weird results (stuff jumping all over the screen)\n // Checking for editingElement to avoid jump while editing on mobile #6503\n\n if (selectedElements.length > 0 && !pointerDownState.withCmdOrCtrl && !this.state.editingElement && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) !== \"active\") {\n const [dragX, dragY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerCoords.x - pointerDownState.drag.offset.x, pointerCoords.y - pointerDownState.drag.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n const [dragDistanceX, dragDistanceY] = [Math.abs(pointerCoords.x - pointerDownState.origin.x), Math.abs(pointerCoords.y - pointerDownState.origin.y)]; // We only drag in one direction if shift is pressed\n\n const lockDirection = event.shiftKey; // when we're editing the name of a frame, we want the user to be\n // able to select and interact with the text input\n\n !this.state.editingFrame && (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragSelectedElements)(pointerDownState, selectedElements, dragX, dragY, lockDirection, dragDistanceX, dragDistanceY, this.state, this.scene);\n this.maybeSuggestBindingForAll(selectedElements); // We duplicate the selected element if alt is pressed on pointer move\n\n if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {\n // Move the currently selected elements to the top of the z index stack, and\n // put the duplicates where the selected elements used to be.\n // (the origin point where the dragging started)\n pointerDownState.hit.hasBeenDuplicated = true;\n const nextElements = [];\n const elementsToAppend = [];\n const groupIdMap = new Map();\n const oldIdToDuplicatedId = new Map();\n const hitElement = pointerDownState.hit.element;\n const selectedElementIds = new Set(this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n }).map(element => element.id));\n const elements = this.scene.getElementsIncludingDeleted();\n\n for (const element of elements) {\n if (selectedElementIds.has(element.id) || // case: the state.selectedElementIds might not have been\n // updated yet by the time this mousemove event is fired\n element.id === (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && pointerDownState.hit.wasAddedToSelection) {\n const duplicatedElement = (0,_element__WEBPACK_IMPORTED_MODULE_16__.duplicateElement)(this.state.editingGroupId, groupIdMap, element);\n const [originDragX, originDragY] = (0,_math__WEBPACK_IMPORTED_MODULE_28__.getGridPoint)(pointerDownState.origin.x - pointerDownState.drag.offset.x, pointerDownState.origin.y - pointerDownState.drag.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(duplicatedElement, {\n x: duplicatedElement.x + (originDragX - dragX),\n y: duplicatedElement.y + (originDragY - dragY)\n });\n nextElements.push(duplicatedElement);\n elementsToAppend.push(element);\n oldIdToDuplicatedId.set(element.id, duplicatedElement.id);\n } else {\n nextElements.push(element);\n }\n }\n\n const nextSceneElements = [...nextElements, ...elementsToAppend];\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.bindTextToShapeAfterDuplication)(nextElements, elementsToAppend, oldIdToDuplicatedId);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, \"duplicatesServeAsOld\");\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.bindElementsToFramesAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);\n this.scene.replaceAllElements(nextSceneElements);\n }\n\n return;\n }\n } // It is very important to read this.state within each move event,\n // otherwise we would read a stale one!\n\n\n const draggingElement = this.state.draggingElement;\n\n if (!draggingElement) {\n return;\n }\n\n if (draggingElement.type === \"freedraw\") {\n const points = draggingElement.points;\n const dx = pointerCoords.x - draggingElement.x;\n const dy = pointerCoords.y - draggingElement.y;\n const lastPoint = points.length > 0 && points[points.length - 1];\n const discardPoint = lastPoint && lastPoint[0] === dx && lastPoint[1] === dy;\n\n if (!discardPoint) {\n const pressures = draggingElement.simulatePressure ? draggingElement.pressures : [...draggingElement.pressures, event.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points, [dx, dy]],\n pressures\n });\n }\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(draggingElement)) {\n pointerDownState.drag.hasOccurred = true;\n this.setState({\n selectedElementsAreBeingDragged: true\n });\n const points = draggingElement.points;\n let dx = gridX - draggingElement.x;\n let dy = gridY - draggingElement.y;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event) && points.length === 2) {\n ({\n width: dx,\n height: dy\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)(draggingElement.x, draggingElement.y, pointerCoords.x, pointerCoords.y));\n }\n\n if (points.length === 1) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points, [dx, dy]]\n });\n } else if (points.length === 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points.slice(0, -1), [dx, dy]]\n });\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(draggingElement, false)) {\n // When creating a linear element by dragging\n this.maybeSuggestBindingsForLinearElementAtCoords(draggingElement, [pointerCoords], this.state.startBoundElement);\n }\n } else {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n this.maybeDragNewGenericElement(pointerDownState, event);\n }\n\n if (this.state.activeTool.type === \"selection\") {\n pointerDownState.boxSelection.hasOccurred = true;\n const elements = this.scene.getNonDeletedElements(); // box-select line editor points\n\n if (this.state.editingLinearElement) {\n _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handleBoxSelection(event, this.state, this.setState.bind(this)); // regular box-select\n } else {\n let shouldReuseSelection = true;\n\n if (!event.shiftKey && (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isSomeElementSelected)(elements, this.state)) {\n if (pointerDownState.withCmdOrCtrl && pointerDownState.hit.element) {\n this.setState(prevState => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)(Object.assign(Object.assign({}, prevState), {\n selectedElementIds: {\n [pointerDownState.hit.element.id]: true\n }\n }), this.scene.getNonDeletedElements(), prevState, this));\n } else {\n shouldReuseSelection = false;\n }\n }\n\n const elementsWithinSelection = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getElementsWithinSelection)(elements, draggingElement);\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, shouldReuseSelection && prevState.selectedElementIds), elementsWithinSelection.reduce((acc, element) => {\n acc[element.id] = true;\n return acc;\n }, {}));\n\n if (pointerDownState.hit.element) {\n // if using ctrl/cmd, select the hitElement only if we\n // haven't box-selected anything else\n if (!elementsWithinSelection.length) {\n nextSelectedElementIds[pointerDownState.hit.element.id] = true;\n } else {\n delete nextSelectedElementIds[pointerDownState.hit.element.id];\n }\n }\n\n prevState = !shouldReuseSelection ? Object.assign(Object.assign({}, prevState), {\n selectedGroupIds: {},\n editingGroupId: null\n }) : prevState;\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // select linear element only when we haven't box-selected anything else\n selectedLinearElement: elementsWithinSelection.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(elementsWithinSelection[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(elementsWithinSelection[0], this.scene) : null,\n showHyperlinkPopup: elementsWithinSelection.length === 1 && (elementsWithinSelection[0].link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(elementsWithinSelection[0])) ? \"info\" : false\n });\n });\n }\n }\n });\n } // Returns whether the pointer move happened over either scrollbar\n\n\n handlePointerMoveOverScrollbars(event, pointerDownState) {\n if (pointerDownState.scrollbars.isOverHorizontal) {\n const x = event.clientX;\n const dx = x - pointerDownState.lastCoords.x;\n this.translateCanvas({\n scrollX: this.state.scrollX - dx / this.state.zoom.value\n });\n pointerDownState.lastCoords.x = x;\n return true;\n }\n\n if (pointerDownState.scrollbars.isOverVertical) {\n const y = event.clientY;\n const dy = y - pointerDownState.lastCoords.y;\n this.translateCanvas({\n scrollY: this.state.scrollY - dy / this.state.zoom.value\n });\n pointerDownState.lastCoords.y = y;\n return true;\n }\n\n return false;\n }\n\n onPointerUpFromPointerDownHandler(pointerDownState) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_33__.withBatchedUpdates)(childEvent => {\n var _a, _b, _c, _d, _e, _f;\n\n if (pointerDownState.eventListeners.onMove) {\n pointerDownState.eventListeners.onMove.flush();\n }\n\n const {\n draggingElement,\n resizingElement,\n multiElement,\n activeTool,\n isResizing,\n isRotating\n } = this.state;\n this.setState({\n isResizing: false,\n isRotating: false,\n resizingElement: null,\n selectionElement: null,\n frameToHighlight: null,\n elementsToHighlight: null,\n cursorButton: \"up\",\n // text elements are reset on finalize, and resetting on pointerup\n // may cause issues with double taps\n editingElement: multiElement || (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(this.state.editingElement) ? this.state.editingElement : null\n });\n this.savePointer(childEvent.clientX, childEvent.clientY, \"up\");\n this.setState({\n selectedElementsAreBeingDragged: false\n }); // Handle end of dragging a point of a linear element, might close a loop\n // and sets binding element\n\n if (this.state.editingLinearElement) {\n if (!pointerDownState.boxSelection.hasOccurred && ((_b = (_a = pointerDownState.hit) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.id) !== this.state.editingLinearElement.elementId) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n } else {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state);\n\n if (editingLinearElement !== this.state.editingLinearElement) {\n this.setState({\n editingLinearElement,\n suggestedBindings: []\n });\n }\n }\n } else if (this.state.selectedLinearElement) {\n if (((_d = (_c = pointerDownState.hit) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.id) !== this.state.selectedLinearElement.elementId) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement to null if there is more than one element selected since we don't want to show linear element handles\n\n if (selectedELements.length > 1) {\n this.setState({\n selectedLinearElement: null\n });\n }\n } else {\n const linearElementEditor = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state);\n const {\n startBindingElement,\n endBindingElement\n } = linearElementEditor;\n const element = this.scene.getElement(linearElementEditor.elementId);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElement)(element, startBindingElement, endBindingElement);\n }\n\n if (linearElementEditor !== this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, linearElementEditor), {\n selectedPointsIndices: null\n }),\n suggestedBindings: []\n });\n }\n }\n }\n\n lastPointerUp = null;\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, pointerDownState.eventListeners.onMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, pointerDownState.eventListeners.onUp);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, pointerDownState.eventListeners.onKeyDown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, pointerDownState.eventListeners.onKeyUp);\n\n if (this.state.pendingImageElementId) {\n this.setState({\n pendingImageElementId: null\n });\n }\n\n if ((draggingElement === null || draggingElement === void 0 ? void 0 : draggingElement.type) === \"freedraw\") {\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(childEvent, this.state);\n const points = draggingElement.points;\n let dx = pointerCoords.x - draggingElement.x;\n let dy = pointerCoords.y - draggingElement.y; // Allows dots to avoid being flagged as infinitely small\n\n if (dx === points[0][0] && dy === points[0][1]) {\n dy += 0.0001;\n dx += 0.0001;\n }\n\n const pressures = draggingElement.simulatePressure ? [] : [...draggingElement.pressures, childEvent.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...points, [dx, dy]],\n pressures,\n lastCommittedPoint: [dx, dy]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(draggingElement)) {\n const imageElement = draggingElement;\n\n try {\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } catch (error) {\n console.error(error);\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().filter(el => el.id !== imageElement.id));\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n }\n\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(draggingElement)) {\n if (draggingElement.points.length > 1) {\n this.history.resumeRecording();\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(childEvent, this.state);\n\n if (!pointerDownState.drag.hasOccurred && draggingElement && !multiElement) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, {\n points: [...draggingElement.points, [pointerCoords.x - draggingElement.x, pointerCoords.y - draggingElement.y]]\n });\n this.setState({\n multiElement: draggingElement,\n editingElement: this.state.draggingElement\n });\n } else if (pointerDownState.drag.hasOccurred && !multiElement) {\n if ((0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(draggingElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(draggingElement, this.state, this.scene, pointerCoords);\n }\n\n this.setState({\n suggestedBindings: [],\n startBoundElement: null\n });\n\n if (!activeTool.locked) {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n this.setState(prevState => ({\n draggingElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n }),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [draggingElement.id]: true\n }), prevState),\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(draggingElement, this.scene)\n }));\n } else {\n this.setState(prevState => ({\n draggingElement: null\n }));\n }\n }\n\n return;\n }\n\n if (activeTool.type !== \"selection\" && draggingElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(draggingElement)) {\n // remove invisible element which was added in onPointerDown\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().slice(0, -1));\n this.setState({\n draggingElement: null\n });\n return;\n }\n\n if (draggingElement) {\n if (pointerDownState.drag.hasOccurred) {\n const sceneCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)(childEvent, this.state); // when editing the points of a linear element, we check if the\n // linear element still is in the frame afterwards\n // if not, the linear element will be removed from its frame (if any)\n\n if (this.state.selectedLinearElement && this.state.selectedLinearElement.isDragging) {\n const linearElement = this.scene.getElement(this.state.selectedLinearElement.elementId);\n\n if (linearElement === null || linearElement === void 0 ? void 0 : linearElement.frameId) {\n const frame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(linearElement);\n\n if (frame && linearElement) {\n if (!(0,_frame__WEBPACK_IMPORTED_MODULE_50__.elementOverlapsWithFrame)(linearElement, frame)) {\n // remove the linear element from all groups\n // before removing it from the frame as well\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(linearElement, {\n groupIds: []\n });\n this.scene.replaceAllElements((0,_frame__WEBPACK_IMPORTED_MODULE_50__.removeElementsFromFrame)(this.scene.getElementsIncludingDeleted(), [linearElement], this.state));\n }\n }\n }\n } else {\n // update the relationships between selected elements and frames\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(sceneCoords);\n const selectedElements = this.scene.getSelectedElements(this.state);\n let nextElements = this.scene.getElementsIncludingDeleted();\n\n const updateGroupIdsAfterEditingGroup = elements => {\n if (elements.length > 0) {\n for (const element of elements) {\n const index = element.groupIds.indexOf(this.state.editingGroupId);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: element.groupIds.slice(0, index)\n }, false);\n }\n\n nextElements.forEach(element => {\n if (element.groupIds.length && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(nextElements, element.groupIds[element.groupIds.length - 1]).length < 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: []\n }, false);\n }\n });\n this.setState({\n editingGroupId: null\n });\n }\n };\n\n if (topLayerFrame && !this.state.selectedElementIds[topLayerFrame.id]) {\n const elementsToAdd = selectedElements.filter(element => element.frameId !== topLayerFrame.id && (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n\n if (this.state.editingGroupId) {\n updateGroupIdsAfterEditingGroup(elementsToAdd);\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(nextElements, elementsToAdd, topLayerFrame);\n } else if (!topLayerFrame) {\n if (this.state.editingGroupId) {\n const elementsToRemove = selectedElements.filter(element => element.frameId && !(0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n updateGroupIdsAfterEditingGroup(elementsToRemove);\n }\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(nextElements, this.state, this);\n this.scene.replaceAllElements(nextElements);\n }\n }\n\n if (draggingElement.type === \"frame\") {\n const elementsInsideFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInNewFrame)(this.scene.getElementsIncludingDeleted(), draggingElement);\n this.scene.replaceAllElements((0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(this.scene.getElementsIncludingDeleted(), elementsInsideFrame, draggingElement));\n }\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(draggingElement, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getNormalizedDimensions)(draggingElement));\n }\n\n if (resizingElement) {\n this.history.resumeRecording();\n }\n\n if (resizingElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(resizingElement)) {\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().filter(el => el.id !== resizingElement.id));\n } // handle frame membership for resizing frames and/or selected elements\n\n\n if (pointerDownState.resize.isResizing) {\n let nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(this.scene.getElementsIncludingDeleted(), this.state, this);\n const selectedFrames = this.scene.getSelectedElements(this.state).filter(element => element.type === \"frame\");\n\n for (const frame of selectedFrames) {\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.replaceAllElementsInFrame)(nextElements, (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getElementsIncludingDeleted(), frame, this.state), frame, this.state);\n }\n\n this.scene.replaceAllElements(nextElements);\n } // Code below handles selection when element(s) weren't\n // drag or added to selection on pointer down phase.\n\n\n const hitElement = pointerDownState.hit.element;\n\n if (((_e = this.state.selectedLinearElement) === null || _e === void 0 ? void 0 : _e.elementId) !== (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement)) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement when no other element selected except\n // the one we've hit\n\n if (selectedELements.length === 1) {\n this.setState({\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement, this.scene)\n });\n }\n }\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_28__.distance2d)(this.lastPointerDown.clientX, this.lastPointerDown.clientY, this.lastPointerUp.clientX, this.lastPointerUp.clientY);\n\n if (draggedDistance === 0) {\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.viewportCoordsToSceneCoords)({\n clientX: this.lastPointerUp.clientX,\n clientY: this.lastPointerUp.clientY\n }, this.state);\n const hitElements = this.getElementsAtPosition(scenePointer.x, scenePointer.y);\n hitElements.forEach(hitElement => pointerDownState.elementIdsToErase[hitElement.id] = {\n erase: true,\n opacity: hitElement.opacity\n });\n }\n\n this.eraseElements(pointerDownState);\n return;\n } else if (Object.keys(pointerDownState.elementIdsToErase).length) {\n this.restoreReadyToEraseElements(pointerDownState);\n }\n\n if (hitElement && !pointerDownState.drag.hasOccurred && !pointerDownState.hit.wasAddedToSelection && ( // if we're editing a line, pointerup shouldn't switch selection if\n // box selected\n !this.state.editingLinearElement || !pointerDownState.boxSelection.hasOccurred)) {\n // when inside line editor, shift selects points instead\n if (childEvent.shiftKey && !this.state.editingLinearElement) {\n if (this.state.selectedElementIds[hitElement.id]) {\n if ((0,_groups__WEBPACK_IMPORTED_MODULE_23__.isSelectedViaGroup)(this.state, hitElement)) {\n this.setState(_prevState => {\n const nextSelectedElementIds = Object.assign({}, _prevState.selectedElementIds); // We want to unselect all groups hitElement is part of\n // as well as all elements that are part of the groups\n // hitElement is part of\n\n for (const groupedElement of hitElement.groupIds.flatMap(groupId => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), groupId))) {\n delete nextSelectedElementIds[groupedElement.id];\n }\n\n return {\n selectedGroupIds: Object.assign(Object.assign({}, _prevState.selectedElementIds), hitElement.groupIds.map(gId => ({\n [gId]: false\n })).reduce((prev, acc) => Object.assign(Object.assign({}, prev), acc), {})),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, _prevState)\n };\n }); // if not gragging a linear element point (outside editor)\n } else if (!((_f = this.state.selectedLinearElement) === null || _f === void 0 ? void 0 : _f.isDragging)) {\n // remove element from selection while\n // keeping prev elements selected\n this.setState(prevState => {\n const newSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete newSelectedElementIds[hitElement.id];\n const newSelectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_29__.getSelectedElements)(this.scene.getNonDeletedElements(), {\n selectedElementIds: newSelectedElementIds\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: newSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // set selectedLinearElement only if thats the only element selected\n selectedLinearElement: newSelectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newSelectedElements[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(newSelectedElements[0], this.scene) : prevState.selectedLinearElement\n });\n });\n }\n } else if (hitElement.frameId && this.state.selectedElementIds[hitElement.frameId]) {\n // when hitElement is part of a selected frame, deselect the frame\n // to avoid frame and containing elements selected simultaneously\n this.setState(prevState => {\n var _a, _b;\n\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n }); // deselect the frame\n\n delete nextSelectedElementIds[hitElement.frameId]; // deselect groups containing the frame\n\n ((_b = (_a = this.scene.getElement(hitElement.frameId)) === null || _a === void 0 ? void 0 : _a.groupIds) !== null && _b !== void 0 ? _b : []).flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n } else {\n // add element to selection while keeping prev elements selected\n this.setState(_prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, _prevState.selectedElementIds), {\n [hitElement.id]: true\n }), _prevState)\n }));\n }\n } else {\n this.setState(prevState => {\n var _a;\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement) && // Don't set `selectedLinearElement` if its same as the hitElement, this is mainly to prevent resetting the `hoverPointIndex` to -1.\n // Future we should update the API to take care of setting the correct `hoverPointIndex` when initialized\n ((_a = prevState.selectedLinearElement) === null || _a === void 0 ? void 0 : _a.elementId) !== hitElement.id ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement, this.scene) : prevState.selectedLinearElement\n });\n });\n }\n }\n\n if (!pointerDownState.drag.hasOccurred && !this.state.isResizing && (hitElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isHittingElementBoundingBoxWithoutHittingElement)(hitElement, this.state, this.frameNameBoundsCache, pointerDownState.origin.x, pointerDownState.origin.y) || !hitElement && pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements)) {\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: null\n });\n } else {\n // Deselect selected elements\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n return;\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\" && draggingElement && draggingElement.type !== \"selection\") {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [draggingElement.id]: true\n }), prevState),\n showHyperlinkPopup: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(draggingElement) && !draggingElement.link ? \"editor\" : prevState.showHyperlinkPopup\n }));\n }\n\n if (activeTool.type !== \"selection\" || (0,_scene__WEBPACK_IMPORTED_MODULE_29__.isSomeElementSelected)(this.scene.getNonDeletedElements(), this.state)) {\n this.history.resumeRecording();\n }\n\n if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {\n ((0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) ? _element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindSelectedElements : _element_binding__WEBPACK_IMPORTED_MODULE_17__.unbindLinearElements)(this.scene.getSelectedElements(this.state));\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\") {\n (0,_utils__WEBPACK_IMPORTED_MODULE_33__.resetCursor)(this.interactiveCanvas);\n this.setState({\n draggingElement: null,\n suggestedBindings: [],\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_33__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n } else {\n this.setState({\n draggingElement: null,\n suggestedBindings: []\n });\n }\n\n if (hitElement && this.lastPointerUp && this.lastPointerDown && this.lastPointerUp.timeStamp - this.lastPointerDown.timeStamp < 300 && gesture.pointers.size <= 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) && this.isEmbeddableCenter(hitElement, this.lastPointerUp, pointerDownState.origin.x, pointerDownState.origin.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n }\n });\n }\n\n maybeSuggestBindingForAll(selectedElements) {\n if (selectedElements.length > 50) {\n return;\n }\n\n const suggestedBindings = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getEligibleElementsForBinding)(selectedElements);\n this.setState({\n suggestedBindings\n });\n }\n\n clearSelection(hitElement) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, prevState),\n activeEmbeddable: null,\n selectedGroupIds: {},\n // Continue editing the same group if the user selected a different\n // element from it\n editingGroupId: prevState.editingGroupId && hitElement != null && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, prevState.editingGroupId) ? prevState.editingGroupId : null\n }));\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null,\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n\n getTextWysiwygSnappedToCenterPosition(x, y, appState, container) {\n if (container) {\n let elementCenterX = container.x + container.width / 2;\n let elementCenterY = container.y + container.height / 2;\n const elementCenter = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_43__.getContainerCenter)(container, appState);\n\n if (elementCenter) {\n elementCenterX = elementCenter.x;\n elementCenterY = elementCenter.y;\n }\n\n const distanceToCenter = Math.hypot(x - elementCenterX, y - elementCenterY);\n const isSnappedToCenter = distanceToCenter < _constants__WEBPACK_IMPORTED_MODULE_12__.TEXT_TO_CENTER_SNAP_THRESHOLD;\n\n if (isSnappedToCenter) {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_33__.sceneCoordsToViewportCoords)({\n sceneX: elementCenterX,\n sceneY: elementCenterY\n }, appState);\n return {\n viewportX,\n viewportY,\n elementCenterX,\n elementCenterY\n };\n }\n }\n }\n\n getCanvasOffsets() {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n left,\n top\n } = excalidrawContainer.getBoundingClientRect();\n return {\n offsetLeft: left,\n offsetTop: top\n };\n }\n\n return {\n offsetLeft: 0,\n offsetTop: 0\n };\n }\n\n updateLanguage() {\n return __awaiter(this, void 0, void 0, function* () {\n const currentLang = _i18n__WEBPACK_IMPORTED_MODULE_25__.languages.find(lang => lang.code === this.props.langCode) || _i18n__WEBPACK_IMPORTED_MODULE_25__.defaultLang;\n yield (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.setLanguage)(currentLang);\n this.setAppState({});\n });\n }\n\n}\n\nApp.defaultProps = {\n // needed for tests to pass since we directly render App in many tests\n UIOptions: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_UI_OPTIONS\n};\n\nif (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_12__.ENV.TEST || \"development\" !== \"production\") {\n window.h = window.h || {};\n Object.defineProperties(window.h, {\n elements: {\n configurable: true,\n\n get() {\n var _a;\n\n return (_a = this.app) === null || _a === void 0 ? void 0 : _a.scene.getElementsIncludingDeleted();\n },\n\n set(elements) {\n var _a;\n\n return (_a = this.app) === null || _a === void 0 ? void 0 : _a.scene.replaceAllElements(elements);\n }\n\n }\n });\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEIseUVBQWtCOztBQUU5QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1EQUFtRCxzRUFBNkI7O0FBRWhGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxFQUFFLG9FQUEyQjtBQUN2QztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEIsa0RBQWMsK0NBQStDLCtDQUFXO0FBQ2xHLFlBQVksbURBQVc7QUFDdkIseUJBQXlCO0FBQ3pCLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSwyREFBa0I7QUFDL0I7O0FBRUEsSUFBSSxhQUFvQixLQUFLLGlEQUFRLElBQUksYUFBb0I7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLE9BQU87O0FBRVA7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIOztBQUVBLGlFQUFlLEdBQUciLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi4vLi4vY29tcG9uZW50cy9BcHAudHN4PzA2MjQiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fYXdhaXRlciA9IHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICByZXNvbHZlKHZhbHVlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7XG4gICAgICByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTtcbiAgICB9XG5cbiAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gIH0pO1xufTtcblxuaW1wb3J0IHsganN4IGFzIF9qc3gsIGpzeHMgYXMgX2pzeHMsIEZyYWdtZW50IGFzIF9GcmFnbWVudCB9IGZyb20gXCJyZWFjdC9qc3gtcnVudGltZVwiO1xuaW1wb3J0IFJlYWN0LCB7IHVzZUNvbnRleHQgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IGZsdXNoU3luYyB9IGZyb20gXCJyZWFjdC1kb21cIjtcbmltcG9ydCByb3VnaCBmcm9tIFwicm91Z2hqcy9iaW4vcm91Z2hcIjtcbmltcG9ydCBjbHN4IGZyb20gXCJjbHN4XCI7XG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tIFwibmFub2lkXCI7XG5pbXBvcnQgeyBhY3Rpb25BZGRUb0xpYnJhcnksIGFjdGlvbkJyaW5nRm9yd2FyZCwgYWN0aW9uQnJpbmdUb0Zyb250LCBhY3Rpb25Db3B5LCBhY3Rpb25Db3B5QXNQbmcsIGFjdGlvbkNvcHlBc1N2ZywgY29weVRleHQsIGFjdGlvbkNvcHlTdHlsZXMsIGFjdGlvbkN1dCwgYWN0aW9uRGVsZXRlU2VsZWN0ZWQsIGFjdGlvbkR1cGxpY2F0ZVNlbGVjdGlvbiwgYWN0aW9uRmluYWxpemUsIGFjdGlvbkZsaXBIb3Jpem9udGFsLCBhY3Rpb25GbGlwVmVydGljYWwsIGFjdGlvbkdyb3VwLCBhY3Rpb25QYXN0ZVN0eWxlcywgYWN0aW9uU2VsZWN0QWxsLCBhY3Rpb25TZW5kQmFja3dhcmQsIGFjdGlvblNlbmRUb0JhY2ssIGFjdGlvblRvZ2dsZUdyaWRNb2RlLCBhY3Rpb25Ub2dnbGVTdGF0cywgYWN0aW9uVG9nZ2xlWmVuTW9kZSwgYWN0aW9uVW5iaW5kVGV4dCwgYWN0aW9uQmluZFRleHQsIGFjdGlvblVuZ3JvdXAsIGFjdGlvbkxpbmssIGFjdGlvblRvZ2dsZUVsZW1lbnRMb2NrLCBhY3Rpb25Ub2dnbGVMaW5lYXJFZGl0b3IgfSBmcm9tIFwiLi4vYWN0aW9uc1wiO1xuaW1wb3J0IHsgY3JlYXRlUmVkb0FjdGlvbiwgY3JlYXRlVW5kb0FjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvbkhpc3RvcnlcIjtcbmltcG9ydCB7IEFjdGlvbk1hbmFnZXIgfSBmcm9tIFwiLi4vYWN0aW9ucy9tYW5hZ2VyXCI7XG5pbXBvcnQgeyBhY3Rpb25zIH0gZnJvbSBcIi4uL2FjdGlvbnMvcmVnaXN0ZXJcIjtcbmltcG9ydCB7IHRyYWNrRXZlbnQgfSBmcm9tIFwiLi4vYW5hbHl0aWNzXCI7XG5pbXBvcnQgeyBnZXREZWZhdWx0QXBwU3RhdGUsIGlzRXJhc2VyQWN0aXZlLCBpc0hhbmRUb29sQWN0aXZlIH0gZnJvbSBcIi4uL2FwcFN0YXRlXCI7XG5pbXBvcnQgeyBwYXJzZUNsaXBib2FyZCB9IGZyb20gXCIuLi9jbGlwYm9hcmRcIjtcbmltcG9ydCB7IEFQUF9OQU1FLCBDVVJTT1JfVFlQRSwgREVGQVVMVF9NQVhfSU1BR0VfV0lEVEhfT1JfSEVJR0hULCBERUZBVUxUX1VJX09QVElPTlMsIERFRkFVTFRfVkVSVElDQUxfQUxJR04sIERSQUdHSU5HX1RIUkVTSE9MRCwgRUxFTUVOVF9SRUFEWV9UT19FUkFTRV9PUEFDSVRZLCBFTEVNRU5UX1NISUZUX1RSQU5TTEFURV9BTU9VTlQsIEVMRU1FTlRfVFJBTlNMQVRFX0FNT1VOVCwgRU5WLCBFVkVOVCwgRlJBTUVfU1RZTEUsIEdSSURfU0laRSwgSU1BR0VfTUlNRV9UWVBFUywgSU1BR0VfUkVOREVSX1RJTUVPVVQsIGlzQW5kcm9pZCwgaXNCcmF2ZSwgTElORV9DT05GSVJNX1RIUkVTSE9MRCwgTUFYX0FMTE9XRURfRklMRV9CWVRFUywgTUlNRV9UWVBFUywgTVFfTUFYX0hFSUdIVF9MQU5EU0NBUEUsIE1RX01BWF9XSURUSF9MQU5EU0NBUEUsIE1RX01BWF9XSURUSF9QT1JUUkFJVCwgTVFfUklHSFRfU0lERUJBUl9NSU5fV0lEVEgsIE1RX1NNX01BWF9XSURUSCwgUE9JTlRFUl9CVVRUT04sIFJPVU5ETkVTUywgU0NST0xMX1RJTUVPVVQsIFRBUF9UV0lDRV9USU1FT1VULCBURVhUX1RPX0NFTlRFUl9TTkFQX1RIUkVTSE9MRCwgVEhFTUUsIFRIRU1FX0ZJTFRFUiwgVE9VQ0hfQ1RYX01FTlVfVElNRU9VVCwgVkVSVElDQUxfQUxJR04sIFlPVVRVQkVfU1RBVEVTLCBaT09NX1NURVAsIFBPSU5URVJfRVZFTlRTIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZXhwb3J0Q2FudmFzLCBsb2FkRnJvbUJsb2IgfSBmcm9tIFwiLi4vZGF0YVwiO1xuaW1wb3J0IExpYnJhcnksIHsgZGlzdHJpYnV0ZUxpYnJhcnlJdGVtc09uU3F1YXJlR3JpZCB9IGZyb20gXCIuLi9kYXRhL2xpYnJhcnlcIjtcbmltcG9ydCB7IHJlc3RvcmUsIHJlc3RvcmVFbGVtZW50cyB9IGZyb20gXCIuLi9kYXRhL3Jlc3RvcmVcIjtcbmltcG9ydCB7IGRyYWdOZXdFbGVtZW50LCBkcmFnU2VsZWN0ZWRFbGVtZW50cywgZHVwbGljYXRlRWxlbWVudCwgZ2V0Q29tbW9uQm91bmRzLCBnZXRDdXJzb3JGb3JSZXNpemluZ0VsZW1lbnQsIGdldERyYWdPZmZzZXRYWSwgZ2V0RWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlLCBnZXROb3JtYWxpemVkRGltZW5zaW9ucywgZ2V0UmVzaXplQXJyb3dEaXJlY3Rpb24sIGdldFJlc2l6ZU9mZnNldFhZLCBnZXRMb2NrZWRMaW5lYXJDdXJzb3JBbGlnblNpemUsIGdldFRyYW5zZm9ybUhhbmRsZVR5cGVGcm9tQ29vcmRzLCBoaXRUZXN0LCBpc0hpdHRpbmdFbGVtZW50Qm91bmRpbmdCb3hXaXRob3V0SGl0dGluZ0VsZW1lbnQsIGlzSW52aXNpYmx5U21hbGxFbGVtZW50LCBpc05vbkRlbGV0ZWRFbGVtZW50LCBpc1RleHRFbGVtZW50LCBuZXdFbGVtZW50LCBuZXdMaW5lYXJFbGVtZW50LCBuZXdUZXh0RWxlbWVudCwgbmV3SW1hZ2VFbGVtZW50LCB0ZXh0V3lzaXd5ZywgdHJhbnNmb3JtRWxlbWVudHMsIHVwZGF0ZVRleHRFbGVtZW50LCByZWRyYXdUZXh0Qm91bmRpbmdCb3ggfSBmcm9tIFwiLi4vZWxlbWVudFwiO1xuaW1wb3J0IHsgYmluZE9yVW5iaW5kTGluZWFyRWxlbWVudCwgYmluZE9yVW5iaW5kU2VsZWN0ZWRFbGVtZW50cywgZml4QmluZGluZ3NBZnRlckRlbGV0aW9uLCBmaXhCaW5kaW5nc0FmdGVyRHVwbGljYXRpb24sIGdldEVsaWdpYmxlRWxlbWVudHNGb3JCaW5kaW5nLCBnZXRIb3ZlcmVkRWxlbWVudEZvckJpbmRpbmcsIGlzQmluZGluZ0VuYWJsZWQsIGlzTGluZWFyRWxlbWVudFNpbXBsZUFuZEFscmVhZHlCb3VuZCwgbWF5YmVCaW5kTGluZWFyRWxlbWVudCwgc2hvdWxkRW5hYmxlQmluZGluZ0ZvclBvaW50ZXJFdmVudCwgdW5iaW5kTGluZWFyRWxlbWVudHMsIHVwZGF0ZUJvdW5kRWxlbWVudHMgfSBmcm9tIFwiLi4vZWxlbWVudC9iaW5kaW5nXCI7XG5pbXBvcnQgeyBMaW5lYXJFbGVtZW50RWRpdG9yIH0gZnJvbSBcIi4uL2VsZW1lbnQvbGluZWFyRWxlbWVudEVkaXRvclwiO1xuaW1wb3J0IHsgbXV0YXRlRWxlbWVudCwgbmV3RWxlbWVudFdpdGggfSBmcm9tIFwiLi4vZWxlbWVudC9tdXRhdGVFbGVtZW50XCI7XG5pbXBvcnQgeyBkZWVwQ29weUVsZW1lbnQsIGR1cGxpY2F0ZUVsZW1lbnRzLCBuZXdGcmFtZUVsZW1lbnQsIG5ld0ZyZWVEcmF3RWxlbWVudCwgbmV3RW1iZWRkYWJsZUVsZW1lbnQgfSBmcm9tIFwiLi4vZWxlbWVudC9uZXdFbGVtZW50XCI7XG5pbXBvcnQgeyBoYXNCb3VuZFRleHRFbGVtZW50LCBpc0Fycm93RWxlbWVudCwgaXNCaW5kaW5nRWxlbWVudCwgaXNCaW5kaW5nRWxlbWVudFR5cGUsIGlzQm91bmRUb0NvbnRhaW5lciwgaXNGcmFtZUVsZW1lbnQsIGlzSW1hZ2VFbGVtZW50LCBpc0VtYmVkZGFibGVFbGVtZW50LCBpc0luaXRpYWxpemVkSW1hZ2VFbGVtZW50LCBpc0xpbmVhckVsZW1lbnQsIGlzTGluZWFyRWxlbWVudFR5cGUsIGlzVXNpbmdBZGFwdGl2ZVJhZGl1cyB9IGZyb20gXCIuLi9lbGVtZW50L3R5cGVDaGVja3NcIjtcbmltcG9ydCB7IGdldENlbnRlciwgZ2V0RGlzdGFuY2UgfSBmcm9tIFwiLi4vZ2VzdHVyZVwiO1xuaW1wb3J0IHsgZWRpdEdyb3VwRm9yU2VsZWN0ZWRFbGVtZW50LCBnZXRFbGVtZW50c0luR3JvdXAsIGdldFNlbGVjdGVkR3JvdXBJZEZvckVsZW1lbnQsIGdldFNlbGVjdGVkR3JvdXBJZHMsIGlzRWxlbWVudEluR3JvdXAsIGlzU2VsZWN0ZWRWaWFHcm91cCwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyB9IGZyb20gXCIuLi9ncm91cHNcIjtcbmltcG9ydCBIaXN0b3J5IGZyb20gXCIuLi9oaXN0b3J5XCI7XG5pbXBvcnQgeyBkZWZhdWx0TGFuZywgZ2V0TGFuZ3VhZ2UsIGxhbmd1YWdlcywgc2V0TGFuZ3VhZ2UsIHQgfSBmcm9tIFwiLi4vaTE4blwiO1xuaW1wb3J0IHsgQ09ERVMsIHNob3VsZFJlc2l6ZUZyb21DZW50ZXIsIHNob3VsZE1haW50YWluQXNwZWN0UmF0aW8sIHNob3VsZFJvdGF0ZVdpdGhEaXNjcmV0ZUFuZ2xlLCBpc0Fycm93S2V5LCBLRVlTIH0gZnJvbSBcIi4uL2tleXNcIjtcbmltcG9ydCB7IGlzRWxlbWVudEluVmlld3BvcnQgfSBmcm9tIFwiLi4vZWxlbWVudC9zaXplSGVscGVyc1wiO1xuaW1wb3J0IHsgZGlzdGFuY2UyZCwgZ2V0Q29ybmVyUmFkaXVzLCBnZXRHcmlkUG9pbnQsIGlzUGF0aEFMb29wIH0gZnJvbSBcIi4uL21hdGhcIjtcbmltcG9ydCB7IGNhbGN1bGF0ZVNjcm9sbENlbnRlciwgZ2V0RWxlbWVudHNBdFBvc2l0aW9uLCBnZXRFbGVtZW50c1dpdGhpblNlbGVjdGlvbiwgZ2V0Tm9ybWFsaXplZFpvb20sIGdldFNlbGVjdGVkRWxlbWVudHMsIGhhc0JhY2tncm91bmQsIGlzT3ZlclNjcm9sbEJhcnMsIGlzU29tZUVsZW1lbnRTZWxlY3RlZCB9IGZyb20gXCIuLi9zY2VuZVwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9zY2VuZS9TY2VuZVwiO1xuaW1wb3J0IHsgZ2V0U3RhdGVGb3Jab29tIH0gZnJvbSBcIi4uL3NjZW5lL3pvb21cIjtcbmltcG9ydCB7IGZpbmRTaGFwZUJ5S2V5IH0gZnJvbSBcIi4uL3NoYXBlc1wiO1xuaW1wb3J0IHsgZGVib3VuY2UsIGRpc3RhbmNlLCBnZXRGb250U3RyaW5nLCBnZXROZWFyZXN0U2Nyb2xsYWJsZUNvbnRhaW5lciwgaXNJbnB1dExpa2UsIGlzVG9vbEljb24sIGlzV3JpdGFibGVFbGVtZW50LCByZXNldEN1cnNvciwgcmVzb2x2YWJsZVByb21pc2UsIHNjZW5lQ29vcmRzVG9WaWV3cG9ydENvb3Jkcywgc2V0Q3Vyc29yLCBzZXRDdXJzb3JGb3JTaGFwZSwgdHVwbGVUb0Nvb3JzLCB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMsIHdpdGhCYXRjaGVkVXBkYXRlcywgd3JhcEV2ZW50LCB3aXRoQmF0Y2hlZFVwZGF0ZXNUaHJvdHRsZWQsIHVwZGF0ZU9iamVjdCwgc2V0RXJhc2VyQ3Vyc29yLCB1cGRhdGVBY3RpdmVUb29sLCBnZXRTaG9ydGN1dEtleSwgaXNUcmFuc3BhcmVudCwgZWFzZVRvVmFsdWVzUkFGLCBtdXRlRlNBYm9ydEVycm9yLCBpc1Rlc3RFbnYsIGVhc2VPdXQgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCB7IGVtYmVkZGFibGVVUkxWYWxpZGF0b3IsIGV4dHJhY3RTcmMsIGdldEVtYmVkTGluayB9IGZyb20gXCIuLi9lbGVtZW50L2VtYmVkZGFibGVcIjtcbmltcG9ydCB7IENvbnRleHRNZW51LCBDT05URVhUX01FTlVfU0VQQVJBVE9SIH0gZnJvbSBcIi4vQ29udGV4dE1lbnVcIjtcbmltcG9ydCBMYXllclVJIGZyb20gXCIuL0xheWVyVUlcIjtcbmltcG9ydCB7IFRvYXN0IH0gZnJvbSBcIi4vVG9hc3RcIjtcbmltcG9ydCB7IGFjdGlvblRvZ2dsZVZpZXdNb2RlIH0gZnJvbSBcIi4uL2FjdGlvbnMvYWN0aW9uVG9nZ2xlVmlld01vZGVcIjtcbmltcG9ydCB7IGRhdGFVUkxUb0ZpbGUsIGdlbmVyYXRlSWRGcm9tRmlsZSwgZ2V0RGF0YVVSTCwgZ2V0RmlsZUZyb21FdmVudCwgaXNJbWFnZUZpbGVIYW5kbGUsIGlzU3VwcG9ydGVkSW1hZ2VGaWxlLCBsb2FkU2NlbmVPckxpYnJhcnlGcm9tQmxvYiwgbm9ybWFsaXplRmlsZSwgcGFyc2VMaWJyYXJ5SlNPTiwgcmVzaXplSW1hZ2VGaWxlLCBTVkdTdHJpbmdUb0ZpbGUgfSBmcm9tIFwiLi4vZGF0YS9ibG9iXCI7XG5pbXBvcnQgeyBnZXRJbml0aWFsaXplZEltYWdlRWxlbWVudHMsIGxvYWRIVE1MSW1hZ2VFbGVtZW50LCBub3JtYWxpemVTVkcsIHVwZGF0ZUltYWdlQ2FjaGUgYXMgX3VwZGF0ZUltYWdlQ2FjaGUgfSBmcm9tIFwiLi4vZWxlbWVudC9pbWFnZVwiO1xuaW1wb3J0IHRocm90dGxlIGZyb20gXCJsb2Rhc2gudGhyb3R0bGVcIjtcbmltcG9ydCB7IGZpbGVPcGVuIH0gZnJvbSBcIi4uL2RhdGEvZmlsZXN5c3RlbVwiO1xuaW1wb3J0IHsgYmluZFRleHRUb1NoYXBlQWZ0ZXJEdXBsaWNhdGlvbiwgZ2V0QXBwcm94TWluTGluZUhlaWdodCwgZ2V0QXBwcm94TWluTGluZVdpZHRoLCBnZXRCb3VuZFRleHRFbGVtZW50LCBnZXRDb250YWluZXJDZW50ZXIsIGdldENvbnRhaW5lckVsZW1lbnQsIGdldERlZmF1bHRMaW5lSGVpZ2h0LCBnZXRMaW5lSGVpZ2h0SW5QeCwgZ2V0VGV4dEJpbmRhYmxlQ29udGFpbmVyQXRQb3NpdGlvbiwgaXNNZWFzdXJlVGV4dFN1cHBvcnRlZCwgaXNWYWxpZFRleHRDb250YWluZXIgfSBmcm9tIFwiLi4vZWxlbWVudC90ZXh0RWxlbWVudFwiO1xuaW1wb3J0IHsgaXNIaXR0aW5nRWxlbWVudE5vdENvbnNpZGVyaW5nQm91bmRpbmdCb3ggfSBmcm9tIFwiLi4vZWxlbWVudC9jb2xsaXNpb25cIjtcbmltcG9ydCB7IHNob3dIeXBlcmxpbmtUb29sdGlwLCBoaWRlSHlwZXJsaW5rVG9vbGlwLCBIeXBlcmxpbmssIGlzUG9pbnRIaXR0aW5nTGluaywgaXNQb2ludEhpdHRpbmdMaW5rSWNvbiB9IGZyb20gXCIuLi9lbGVtZW50L0h5cGVybGlua1wiO1xuaW1wb3J0IHsgaXNMb2NhbExpbmssIG5vcm1hbGl6ZUxpbmssIHRvVmFsaWRVUkwgfSBmcm9tIFwiLi4vZGF0YS91cmxcIjtcbmltcG9ydCB7IHNob3VsZFNob3dCb3VuZGluZ0JveCB9IGZyb20gXCIuLi9lbGVtZW50L3RyYW5zZm9ybUhhbmRsZXNcIjtcbmltcG9ydCB7IGFjdGlvblVubG9ja0FsbEVsZW1lbnRzIH0gZnJvbSBcIi4uL2FjdGlvbnMvYWN0aW9uRWxlbWVudExvY2tcIjtcbmltcG9ydCB7IEZvbnRzIH0gZnJvbSBcIi4uL3NjZW5lL0ZvbnRzXCI7XG5pbXBvcnQgeyBnZXRGcmFtZUVsZW1lbnRzLCBpc0N1cnNvckluRnJhbWUsIGJpbmRFbGVtZW50c1RvRnJhbWVzQWZ0ZXJEdXBsaWNhdGlvbiwgYWRkRWxlbWVudHNUb0ZyYW1lLCByZXBsYWNlQWxsRWxlbWVudHNJbkZyYW1lLCByZW1vdmVFbGVtZW50c0Zyb21GcmFtZSwgZ2V0RWxlbWVudHNJblJlc2l6aW5nRnJhbWUsIGdldEVsZW1lbnRzSW5OZXdGcmFtZSwgZ2V0Q29udGFpbmluZ0ZyYW1lLCBlbGVtZW50T3ZlcmxhcHNXaXRoRnJhbWUsIHVwZGF0ZUZyYW1lTWVtYmVyc2hpcE9mU2VsZWN0ZWRFbGVtZW50cywgaXNFbGVtZW50SW5GcmFtZSB9IGZyb20gXCIuLi9mcmFtZVwiO1xuaW1wb3J0IHsgZXhjbHVkZUVsZW1lbnRzSW5GcmFtZXNGcm9tU2VsZWN0aW9uLCBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyB9IGZyb20gXCIuLi9zY2VuZS9zZWxlY3Rpb25cIjtcbmltcG9ydCB7IGFjdGlvblBhc3RlIH0gZnJvbSBcIi4uL2FjdGlvbnMvYWN0aW9uQ2xpcGJvYXJkXCI7XG5pbXBvcnQgeyBhY3Rpb25SZW1vdmVBbGxFbGVtZW50c0Zyb21GcmFtZSwgYWN0aW9uU2VsZWN0QWxsRWxlbWVudHNJbkZyYW1lIH0gZnJvbSBcIi4uL2FjdGlvbnMvYWN0aW9uRnJhbWVcIjtcbmltcG9ydCB7IGFjdGlvblRvZ2dsZUhhbmRUb29sLCB6b29tVG9GaXQgfSBmcm9tIFwiLi4vYWN0aW9ucy9hY3Rpb25DYW52YXNcIjtcbmltcG9ydCB7IGpvdGFpU3RvcmUgfSBmcm9tIFwiLi4vam90YWlcIjtcbmltcG9ydCB7IGFjdGl2ZUNvbmZpcm1EaWFsb2dBdG9tIH0gZnJvbSBcIi4vQWN0aXZlQ29uZmlybURpYWxvZ1wiO1xuaW1wb3J0IHsgYWN0aW9uV3JhcFRleHRJbkNvbnRhaW5lciB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvbkJvdW5kVGV4dFwiO1xuaW1wb3J0IEJyYXZlTWVhc3VyZVRleHRFcnJvciBmcm9tIFwiLi9CcmF2ZU1lYXN1cmVUZXh0RXJyb3JcIjtcbmltcG9ydCB7IGFjdGl2ZUV5ZURyb3BwZXJBdG9tIH0gZnJvbSBcIi4vRXllRHJvcHBlclwiO1xuaW1wb3J0IHsgY29udmVydFRvRXhjYWxpZHJhd0VsZW1lbnRzIH0gZnJvbSBcIi4uL2RhdGEvdHJhbnNmb3JtXCI7XG5pbXBvcnQgeyBpc1NpZGViYXJEb2NrZWRBdG9tIH0gZnJvbSBcIi4vU2lkZWJhci9TaWRlYmFyXCI7XG5pbXBvcnQgeyBTdGF0aWNDYW52YXMsIEludGVyYWN0aXZlQ2FudmFzIH0gZnJvbSBcIi4vY2FudmFzZXNcIjtcbmltcG9ydCB7IFJlbmRlcmVyIH0gZnJvbSBcIi4uL3NjZW5lL1JlbmRlcmVyXCI7XG5pbXBvcnQgeyBTaGFwZUNhY2hlIH0gZnJvbSBcIi4uL3NjZW5lL1NoYXBlQ2FjaGVcIjtcbmNvbnN0IEFwcENvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KG51bGwpO1xuY29uc3QgQXBwUHJvcHNDb250ZXh0ID0gUmVhY3QuY3JlYXRlQ29udGV4dChudWxsKTtcbmNvbnN0IGRldmljZUNvbnRleHRJbml0aWFsVmFsdWUgPSB7XG4gIGlzU21TY3JlZW46IGZhbHNlLFxuICBpc01vYmlsZTogZmFsc2UsXG4gIGlzVG91Y2hTY3JlZW46IGZhbHNlLFxuICBjYW5EZXZpY2VGaXRTaWRlYmFyOiBmYWxzZSxcbiAgaXNMYW5kc2NhcGU6IGZhbHNlXG59O1xuY29uc3QgRGV2aWNlQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQoZGV2aWNlQ29udGV4dEluaXRpYWxWYWx1ZSk7XG5EZXZpY2VDb250ZXh0LmRpc3BsYXlOYW1lID0gXCJEZXZpY2VDb250ZXh0XCI7XG5leHBvcnQgY29uc3QgRXhjYWxpZHJhd0NvbnRhaW5lckNvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KHtcbiAgY29udGFpbmVyOiBudWxsLFxuICBpZDogbnVsbFxufSk7XG5FeGNhbGlkcmF3Q29udGFpbmVyQ29udGV4dC5kaXNwbGF5TmFtZSA9IFwiRXhjYWxpZHJhd0NvbnRhaW5lckNvbnRleHRcIjtcbmNvbnN0IEV4Y2FsaWRyYXdFbGVtZW50c0NvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KFtdKTtcbkV4Y2FsaWRyYXdFbGVtZW50c0NvbnRleHQuZGlzcGxheU5hbWUgPSBcIkV4Y2FsaWRyYXdFbGVtZW50c0NvbnRleHRcIjtcbmNvbnN0IEV4Y2FsaWRyYXdBcHBTdGF0ZUNvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZ2V0RGVmYXVsdEFwcFN0YXRlKCkpLCB7XG4gIHdpZHRoOiAwLFxuICBoZWlnaHQ6IDAsXG4gIG9mZnNldExlZnQ6IDAsXG4gIG9mZnNldFRvcDogMFxufSkpO1xuRXhjYWxpZHJhd0FwcFN0YXRlQ29udGV4dC5kaXNwbGF5TmFtZSA9IFwiRXhjYWxpZHJhd0FwcFN0YXRlQ29udGV4dFwiO1xuY29uc3QgRXhjYWxpZHJhd1NldEFwcFN0YXRlQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQoKCkgPT4ge1xuICBjb25zb2xlLndhcm4oXCJ1bml0aWFsaXplZCBFeGNhbGlkcmF3U2V0QXBwU3RhdGVDb250ZXh0IGNvbnRleHQhXCIpO1xufSk7XG5FeGNhbGlkcmF3U2V0QXBwU3RhdGVDb250ZXh0LmRpc3BsYXlOYW1lID0gXCJFeGNhbGlkcmF3U2V0QXBwU3RhdGVDb250ZXh0XCI7XG5jb25zdCBFeGNhbGlkcmF3QWN0aW9uTWFuYWdlckNvbnRleHQgPSBSZWFjdC5jcmVhdGVDb250ZXh0KG51bGwpO1xuRXhjYWxpZHJhd0FjdGlvbk1hbmFnZXJDb250ZXh0LmRpc3BsYXlOYW1lID0gXCJFeGNhbGlkcmF3QWN0aW9uTWFuYWdlckNvbnRleHRcIjtcbmV4cG9ydCBjb25zdCB1c2VBcHAgPSAoKSA9PiB1c2VDb250ZXh0KEFwcENvbnRleHQpO1xuZXhwb3J0IGNvbnN0IHVzZUFwcFByb3BzID0gKCkgPT4gdXNlQ29udGV4dChBcHBQcm9wc0NvbnRleHQpO1xuZXhwb3J0IGNvbnN0IHVzZURldmljZSA9ICgpID0+IHVzZUNvbnRleHQoRGV2aWNlQ29udGV4dCk7XG5leHBvcnQgY29uc3QgdXNlRXhjYWxpZHJhd0NvbnRhaW5lciA9ICgpID0+IHVzZUNvbnRleHQoRXhjYWxpZHJhd0NvbnRhaW5lckNvbnRleHQpO1xuZXhwb3J0IGNvbnN0IHVzZUV4Y2FsaWRyYXdFbGVtZW50cyA9ICgpID0+IHVzZUNvbnRleHQoRXhjYWxpZHJhd0VsZW1lbnRzQ29udGV4dCk7XG5leHBvcnQgY29uc3QgdXNlRXhjYWxpZHJhd0FwcFN0YXRlID0gKCkgPT4gdXNlQ29udGV4dChFeGNhbGlkcmF3QXBwU3RhdGVDb250ZXh0KTtcbmV4cG9ydCBjb25zdCB1c2VFeGNhbGlkcmF3U2V0QXBwU3RhdGUgPSAoKSA9PiB1c2VDb250ZXh0KEV4Y2FsaWRyYXdTZXRBcHBTdGF0ZUNvbnRleHQpO1xuZXhwb3J0IGNvbnN0IHVzZUV4Y2FsaWRyYXdBY3Rpb25NYW5hZ2VyID0gKCkgPT4gdXNlQ29udGV4dChFeGNhbGlkcmF3QWN0aW9uTWFuYWdlckNvbnRleHQpO1xubGV0IGRpZFRhcFR3aWNlID0gZmFsc2U7XG5sZXQgdGFwcGVkVHdpY2VUaW1lciA9IDA7XG5sZXQgaXNIb2xkaW5nU3BhY2UgPSBmYWxzZTtcbmxldCBpc1Bhbm5pbmcgPSBmYWxzZTtcbmxldCBpc0RyYWdnaW5nU2Nyb2xsQmFyID0gZmFsc2U7XG5sZXQgY3VycmVudFNjcm9sbEJhcnMgPSB7XG4gIGhvcml6b250YWw6IG51bGwsXG4gIHZlcnRpY2FsOiBudWxsXG59O1xubGV0IHRvdWNoVGltZW91dCA9IDA7XG5sZXQgaW52YWxpZGF0ZUNvbnRleHRNZW51ID0gZmFsc2U7XG4vKipcbiAqIE1hcCBvZiB5b3V0dWJlIGVtYmVkIHZpZGVvIHN0YXRlc1xuICovXG5cbmNvbnN0IFlPVVRVQkVfVklERU9fU1RBVEVTID0gbmV3IE1hcCgpO1xubGV0IElTX1BMQUlOX1BBU1RFID0gZmFsc2U7XG5sZXQgSVNfUExBSU5fUEFTVEVfVElNRVIgPSAwO1xubGV0IFBMQUlOX1BBU1RFX1RPQVNUX1NIT1dOID0gZmFsc2U7XG5sZXQgbGFzdFBvaW50ZXJVcCA9IG51bGw7XG5jb25zdCBnZXN0dXJlID0ge1xuICBwb2ludGVyczogbmV3IE1hcCgpLFxuICBsYXN0Q2VudGVyOiBudWxsLFxuICBpbml0aWFsRGlzdGFuY2U6IG51bGwsXG4gIGluaXRpYWxTY2FsZTogbnVsbFxufTtcblxuY2xhc3MgQXBwIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICB2YXIgX2E7XG5cbiAgICBzdXBlcihwcm9wcyk7XG4gICAgdGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyA9IG51bGw7XG4gICAgdGhpcy51bm1vdW50ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmRldmljZSA9IGRldmljZUNvbnRleHRJbml0aWFsVmFsdWU7XG4gICAgdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmID0gUmVhY3QuY3JlYXRlUmVmKCk7XG4gICAgdGhpcy5maWxlcyA9IHt9O1xuICAgIHRoaXMuaW1hZ2VDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmlGcmFtZVJlZnMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5sYXN0UG9pbnRlckRvd24gPSBudWxsO1xuICAgIHRoaXMubGFzdFBvaW50ZXJVcCA9IG51bGw7XG4gICAgdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbiA9IHtcbiAgICAgIHg6IDAsXG4gICAgICB5OiAwXG4gICAgfTtcblxuICAgIHRoaXMudXBkYXRlRW1iZWRkYWJsZXMgPSAoKSA9PiB7XG4gICAgICBjb25zdCBlbWJlZGRhYmxlRWxlbWVudHMgPSBuZXcgTWFwKCk7XG4gICAgICBsZXQgdXBkYXRlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKS5maWx0ZXIoZWxlbWVudCA9PiB7XG4gICAgICAgIGlmIChpc0VtYmVkZGFibGVFbGVtZW50KGVsZW1lbnQpKSB7XG4gICAgICAgICAgZW1iZWRkYWJsZUVsZW1lbnRzLnNldChlbGVtZW50LmlkLCB0cnVlKTtcblxuICAgICAgICAgIGlmIChlbGVtZW50LnZhbGlkYXRlZCA9PSBudWxsKSB7XG4gICAgICAgICAgICB1cGRhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRlZCA9IGVtYmVkZGFibGVVUkxWYWxpZGF0b3IoZWxlbWVudC5saW5rLCB0aGlzLnByb3BzLnZhbGlkYXRlRW1iZWRkYWJsZSk7XG4gICAgICAgICAgICBtdXRhdGVFbGVtZW50KGVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgdmFsaWRhdGVkXG4gICAgICAgICAgICB9LCBmYWxzZSk7XG4gICAgICAgICAgICBTaGFwZUNhY2hlLmRlbGV0ZShlbGVtZW50KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9KTtcblxuICAgICAgaWYgKHVwZGF0ZWQpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5pbmZvcm1NdXRhdGlvbigpO1xuICAgICAgfSAvLyBHQ1xuXG5cbiAgICAgIHRoaXMuaUZyYW1lUmVmcy5mb3JFYWNoKChyZWYsIGlkKSA9PiB7XG4gICAgICAgIGlmICghZW1iZWRkYWJsZUVsZW1lbnRzLmhhcyhpZCkpIHtcbiAgICAgICAgICB0aGlzLmlGcmFtZVJlZnMuZGVsZXRlKGlkKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuZ2V0RnJhbWVOYW1lRE9NSWQgPSBmcmFtZUVsZW1lbnQgPT4ge1xuICAgICAgcmV0dXJuIGAke3RoaXMuaWR9LWZyYW1lLW5hbWUtJHtmcmFtZUVsZW1lbnQuaWR9YDtcbiAgICB9O1xuXG4gICAgdGhpcy5mcmFtZU5hbWVCb3VuZHNDYWNoZSA9IHtcbiAgICAgIGdldDogZnJhbWVFbGVtZW50ID0+IHtcbiAgICAgICAgbGV0IGJvdW5kcyA9IHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUuX2NhY2hlLmdldChmcmFtZUVsZW1lbnQuaWQpO1xuXG4gICAgICAgIGlmICghYm91bmRzIHx8IGJvdW5kcy56b29tICE9PSB0aGlzLnN0YXRlLnpvb20udmFsdWUgfHwgYm91bmRzLnZlcnNpb25Ob25jZSAhPT0gZnJhbWVFbGVtZW50LnZlcnNpb25Ob25jZSkge1xuICAgICAgICAgIGNvbnN0IGZyYW1lTmFtZURpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RnJhbWVOYW1lRE9NSWQoZnJhbWVFbGVtZW50KSk7XG5cbiAgICAgICAgICBpZiAoZnJhbWVOYW1lRGl2KSB7XG4gICAgICAgICAgICBjb25zdCBib3ggPSBmcmFtZU5hbWVEaXYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICBjb25zdCBib3hTY2VuZVRvcExlZnQgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICAgICAgICBjbGllbnRYOiBib3gueCxcbiAgICAgICAgICAgICAgY2xpZW50WTogYm94LnlcbiAgICAgICAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgICAgICAgY29uc3QgYm94U2NlbmVCb3R0b21SaWdodCA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICAgICAgICAgIGNsaWVudFg6IGJveC5yaWdodCxcbiAgICAgICAgICAgICAgY2xpZW50WTogYm94LmJvdHRvbVxuICAgICAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgICAgICAgICBib3VuZHMgPSB7XG4gICAgICAgICAgICAgIHg6IGJveFNjZW5lVG9wTGVmdC54LFxuICAgICAgICAgICAgICB5OiBib3hTY2VuZVRvcExlZnQueSxcbiAgICAgICAgICAgICAgd2lkdGg6IGJveFNjZW5lQm90dG9tUmlnaHQueCAtIGJveFNjZW5lVG9wTGVmdC54LFxuICAgICAgICAgICAgICBoZWlnaHQ6IGJveFNjZW5lQm90dG9tUmlnaHQueSAtIGJveFNjZW5lVG9wTGVmdC55LFxuICAgICAgICAgICAgICBhbmdsZTogMCxcbiAgICAgICAgICAgICAgem9vbTogdGhpcy5zdGF0ZS56b29tLnZhbHVlLFxuICAgICAgICAgICAgICB2ZXJzaW9uTm9uY2U6IGZyYW1lRWxlbWVudC52ZXJzaW9uTm9uY2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUuX2NhY2hlLnNldChmcmFtZUVsZW1lbnQuaWQsIGJvdW5kcyk7XG5cbiAgICAgICAgICAgIHJldHVybiBib3VuZHM7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYm91bmRzO1xuICAgICAgfSxcblxuICAgICAgLyoqXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICovXG4gICAgICBfY2FjaGU6IG5ldyBNYXAoKVxuICAgIH07XG5cbiAgICB0aGlzLnJlbmRlckZyYW1lTmFtZXMgPSAoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuc3RhdGUuZnJhbWVSZW5kZXJpbmcuZW5hYmxlZCB8fCAhdGhpcy5zdGF0ZS5mcmFtZVJlbmRlcmluZy5uYW1lKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpc0RhcmtUaGVtZSA9IHRoaXMuc3RhdGUudGhlbWUgPT09IFwiZGFya1wiO1xuICAgICAgcmV0dXJuIHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEZyYW1lcygpLm1hcCgoZiwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKCFpc0VsZW1lbnRJblZpZXdwb3J0KGYsIHRoaXMuY2FudmFzLndpZHRoIC8gd2luZG93LmRldmljZVBpeGVsUmF0aW8sIHRoaXMuY2FudmFzLmhlaWdodCAvIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLCB7XG4gICAgICAgICAgb2Zmc2V0TGVmdDogdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0LFxuICAgICAgICAgIG9mZnNldFRvcDogdGhpcy5zdGF0ZS5vZmZzZXRUb3AsXG4gICAgICAgICAgc2Nyb2xsWDogdGhpcy5zdGF0ZS5zY3JvbGxYLFxuICAgICAgICAgIHNjcm9sbFk6IHRoaXMuc3RhdGUuc2Nyb2xsWSxcbiAgICAgICAgICB6b29tOiB0aGlzLnN0YXRlLnpvb21cbiAgICAgICAgfSkpIHtcbiAgICAgICAgICAvLyBpZiBmcmFtZSBub3QgdmlzaWJsZSwgZG9uJ3QgcmVuZGVyIGl0cyBuYW1lXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeDogeDEsXG4gICAgICAgICAgeTogeTFcbiAgICAgICAgfSA9IHNjZW5lQ29vcmRzVG9WaWV3cG9ydENvb3Jkcyh7XG4gICAgICAgICAgc2NlbmVYOiBmLngsXG4gICAgICAgICAgc2NlbmVZOiBmLnlcbiAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB4OiB4MlxuICAgICAgICB9ID0gc2NlbmVDb29yZHNUb1ZpZXdwb3J0Q29vcmRzKHtcbiAgICAgICAgICBzY2VuZVg6IGYueCArIGYud2lkdGgsXG4gICAgICAgICAgc2NlbmVZOiBmLnkgKyBmLmhlaWdodFxuICAgICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgY29uc3QgRlJBTUVfTkFNRV9HQVAgPSAyMDtcbiAgICAgICAgY29uc3QgRlJBTUVfTkFNRV9FRElUX1BBRERJTkcgPSA2O1xuXG4gICAgICAgIGNvbnN0IHJlc2V0ID0gKCkgPT4ge1xuICAgICAgICAgIHZhciBfYTtcblxuICAgICAgICAgIGlmICgoKF9hID0gZi5uYW1lKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudHJpbSgpKSA9PT0gXCJcIikge1xuICAgICAgICAgICAgbXV0YXRlRWxlbWVudChmLCB7XG4gICAgICAgICAgICAgIG5hbWU6IG51bGxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgZWRpdGluZ0ZyYW1lOiBudWxsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IGZyYW1lTmFtZUpTWDtcblxuICAgICAgICBpZiAoZi5pZCA9PT0gdGhpcy5zdGF0ZS5lZGl0aW5nRnJhbWUpIHtcbiAgICAgICAgICBjb25zdCBmcmFtZU5hbWVJbkVkaXQgPSBmLm5hbWUgPT0gbnVsbCA/IGBGcmFtZSAke2luZGV4ICsgMX1gIDogZi5uYW1lO1xuICAgICAgICAgIGZyYW1lTmFtZUpTWCA9IF9qc3goXCJpbnB1dFwiLCB7XG4gICAgICAgICAgICBhdXRvRm9jdXM6IHRydWUsXG4gICAgICAgICAgICB2YWx1ZTogZnJhbWVOYW1lSW5FZGl0LFxuICAgICAgICAgICAgb25DaGFuZ2U6IGUgPT4ge1xuICAgICAgICAgICAgICBtdXRhdGVFbGVtZW50KGYsIHtcbiAgICAgICAgICAgICAgICBuYW1lOiBlLnRhcmdldC52YWx1ZVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkJsdXI6ICgpID0+IHJlc2V0KCksXG4gICAgICAgICAgICBvbktleURvd246IGV2ZW50ID0+IHtcbiAgICAgICAgICAgICAgLy8gZm9yIHNvbWUgaW5leHBsaWNhYmxlIHJlYXNvbiwgYG9uQmx1cmAgdHJpZ2dlcmVkIG9uIEVTQ1xuICAgICAgICAgICAgICAvLyBkb2VzIG5vdCByZXNldCBgc3RhdGUuZWRpdGluZ0ZyYW1lYCBkZXNwaXRlIGJlaW5nIGNhbGxlZCxcbiAgICAgICAgICAgICAgLy8gYW5kIHdlIG5lZWQgdG8gcmVzZXQgaXQgaGVyZSBhcyB3ZWxsXG4gICAgICAgICAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuRVNDQVBFIHx8IGV2ZW50LmtleSA9PT0gS0VZUy5FTlRFUikge1xuICAgICAgICAgICAgICAgIHJlc2V0KCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiB0aGlzLnN0YXRlLnZpZXdCYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgICAgIGZpbHRlcjogaXNEYXJrVGhlbWUgPyBUSEVNRV9GSUxURVIgOiBcIm5vbmVcIixcbiAgICAgICAgICAgICAgekluZGV4OiAyLFxuICAgICAgICAgICAgICBib3JkZXI6IFwibm9uZVwiLFxuICAgICAgICAgICAgICBkaXNwbGF5OiBcImJsb2NrXCIsXG4gICAgICAgICAgICAgIHBhZGRpbmc6IGAke0ZSQU1FX05BTUVfRURJVF9QQURESU5HfXB4YCxcbiAgICAgICAgICAgICAgYm9yZGVyUmFkaXVzOiA0LFxuICAgICAgICAgICAgICBib3hTaGFkb3c6IFwiaW5zZXQgMCAwIDAgMXB4IHZhcigtLWNvbG9yLXByaW1hcnkpXCIsXG4gICAgICAgICAgICAgIGZvbnRGYW1pbHk6IFwiQXNzaXN0YW50XCIsXG4gICAgICAgICAgICAgIGZvbnRTaXplOiBcIjE0cHhcIixcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlWSgtJHtGUkFNRV9OQU1FX0VESVRfUEFERElOR31weClgLFxuICAgICAgICAgICAgICBjb2xvcjogXCJ2YXIoLS1jb2xvci1ncmF5LTgwKVwiLFxuICAgICAgICAgICAgICBvdmVyZmxvdzogXCJoaWRkZW5cIixcbiAgICAgICAgICAgICAgbWF4V2lkdGg6IGAke01hdGgubWluKHgyIC0geDEgLSBGUkFNRV9OQU1FX0VESVRfUEFERElORywgZG9jdW1lbnQuYm9keS5jbGllbnRXaWR0aCAtIHgxIC0gRlJBTUVfTkFNRV9FRElUX1BBRERJTkcpfXB4YFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNpemU6IGZyYW1lTmFtZUluRWRpdC5sZW5ndGggKyAxIHx8IDEsXG4gICAgICAgICAgICBkaXI6IFwiYXV0b1wiLFxuICAgICAgICAgICAgYXV0b0NvbXBsZXRlOiBcIm9mZlwiLFxuICAgICAgICAgICAgYXV0b0NhcGl0YWxpemU6IFwib2ZmXCIsXG4gICAgICAgICAgICBhdXRvQ29ycmVjdDogXCJvZmZcIlxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZyYW1lTmFtZUpTWCA9IGYubmFtZSA9PSBudWxsIHx8IGYubmFtZS50cmltKCkgPT09IFwiXCIgPyBgRnJhbWUgJHtpbmRleCArIDF9YCA6IGYubmFtZS50cmltKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gX2pzeChcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICBpZDogdGhpcy5nZXRGcmFtZU5hbWVET01JZChmKSxcbiAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgcG9zaXRpb246IFwiYWJzb2x1dGVcIixcbiAgICAgICAgICAgIHRvcDogYCR7eTEgLSBGUkFNRV9OQU1FX0dBUCAtIHRoaXMuc3RhdGUub2Zmc2V0VG9wfXB4YCxcbiAgICAgICAgICAgIGxlZnQ6IGAke3gxIC0gdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0IC0gKHRoaXMuc3RhdGUuZWRpdGluZ0ZyYW1lID09PSBmLmlkID8gRlJBTUVfTkFNRV9FRElUX1BBRERJTkcgOiAwKX1weGAsXG4gICAgICAgICAgICB6SW5kZXg6IDIsXG4gICAgICAgICAgICBmb250U2l6ZTogXCIxNHB4XCIsXG4gICAgICAgICAgICBjb2xvcjogaXNEYXJrVGhlbWUgPyBcInZhcigtLWNvbG9yLWdyYXktNjApXCIgOiBcInZhcigtLWNvbG9yLWdyYXktNTApXCIsXG4gICAgICAgICAgICB3aWR0aDogXCJtYXgtY29udGVudFwiLFxuICAgICAgICAgICAgbWF4V2lkdGg6IGAke3gyIC0geDEgKyBGUkFNRV9OQU1FX0VESVRfUEFERElORyAqIDJ9cHhgLFxuICAgICAgICAgICAgb3ZlcmZsb3c6IGYuaWQgPT09IHRoaXMuc3RhdGUuZWRpdGluZ0ZyYW1lID8gXCJ2aXNpYmxlXCIgOiBcImhpZGRlblwiLFxuICAgICAgICAgICAgd2hpdGVTcGFjZTogXCJub3dyYXBcIixcbiAgICAgICAgICAgIHRleHRPdmVyZmxvdzogXCJlbGxpcHNpc1wiLFxuICAgICAgICAgICAgY3Vyc29yOiBDVVJTT1JfVFlQRS5NT1ZFLFxuICAgICAgICAgICAgcG9pbnRlckV2ZW50czogdGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQgPyBQT0lOVEVSX0VWRU5UUy5kaXNhYmxlZCA6IFBPSU5URVJfRVZFTlRTLmluaGVyaXRGcm9tVUlcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uUG9pbnRlckRvd246IGV2ZW50ID0+IHRoaXMuaGFuZGxlQ2FudmFzUG9pbnRlckRvd24oZXZlbnQpLFxuICAgICAgICAgIG9uV2hlZWw6IGV2ZW50ID0+IHRoaXMuaGFuZGxlV2hlZWwoZXZlbnQpLFxuICAgICAgICAgIG9uQ29udGV4dE1lbnU6IHRoaXMuaGFuZGxlQ2FudmFzQ29udGV4dE1lbnUsXG4gICAgICAgICAgb25Eb3VibGVDbGljazogKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIGVkaXRpbmdGcmFtZTogZi5pZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IGZyYW1lTmFtZUpTWFxuICAgICAgICB9KSwgZi5pZCk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5mb2N1c0NvbnRhaW5lciA9ICgpID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5mb2N1cygpO1xuICAgIH07XG5cbiAgICB0aGlzLmdldFNjZW5lRWxlbWVudHNJbmNsdWRpbmdEZWxldGVkID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCk7XG4gICAgfTtcblxuICAgIHRoaXMuZ2V0U2NlbmVFbGVtZW50cyA9ICgpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpO1xuICAgIH07XG5cbiAgICB0aGlzLm9uSW5zZXJ0RWxlbWVudHMgPSBlbGVtZW50cyA9PiB7XG4gICAgICB0aGlzLmFkZEVsZW1lbnRzRnJvbVBhc3RlT3JMaWJyYXJ5KHtcbiAgICAgICAgZWxlbWVudHMsXG4gICAgICAgIHBvc2l0aW9uOiBcImNlbnRlclwiLFxuICAgICAgICBmaWxlczogbnVsbFxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMub25FeHBvcnRJbWFnZSA9ICh0eXBlLCBlbGVtZW50cykgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgdHJhY2tFdmVudChcImV4cG9ydFwiLCB0eXBlLCBcInVpXCIpO1xuICAgICAgY29uc3QgZmlsZUhhbmRsZSA9IHlpZWxkIGV4cG9ydENhbnZhcyh0eXBlLCBlbGVtZW50cywgdGhpcy5zdGF0ZSwgdGhpcy5maWxlcywge1xuICAgICAgICBleHBvcnRCYWNrZ3JvdW5kOiB0aGlzLnN0YXRlLmV4cG9ydEJhY2tncm91bmQsXG4gICAgICAgIG5hbWU6IHRoaXMuc3RhdGUubmFtZSxcbiAgICAgICAgdmlld0JhY2tncm91bmRDb2xvcjogdGhpcy5zdGF0ZS52aWV3QmFja2dyb3VuZENvbG9yXG4gICAgICB9KS5jYXRjaChtdXRlRlNBYm9ydEVycm9yKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLm1lc3NhZ2VcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMuc3RhdGUuZXhwb3J0RW1iZWRTY2VuZSAmJiBmaWxlSGFuZGxlICYmIGlzSW1hZ2VGaWxlSGFuZGxlKGZpbGVIYW5kbGUpKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGZpbGVIYW5kbGVcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLm9wZW5FeWVEcm9wcGVyID0gKHtcbiAgICAgIHR5cGVcbiAgICB9KSA9PiB7XG4gICAgICBqb3RhaVN0b3JlLnNldChhY3RpdmVFeWVEcm9wcGVyQXRvbSwge1xuICAgICAgICBzd2FwUHJldmlld09uQWx0OiB0cnVlLFxuICAgICAgICBjb2xvclBpY2tlclR5cGU6IHR5cGUgPT09IFwic3Ryb2tlXCIgPyBcImVsZW1lbnRTdHJva2VcIiA6IFwiZWxlbWVudEJhY2tncm91bmRcIixcbiAgICAgICAgb25TZWxlY3Q6IChjb2xvciwgZXZlbnQpID0+IHtcbiAgICAgICAgICBjb25zdCBzaG91bGRVcGRhdGVTdHJva2VDb2xvciA9IHR5cGUgPT09IFwiYmFja2dyb3VuZFwiICYmIGV2ZW50LmFsdEtleSB8fCB0eXBlID09PSBcInN0cm9rZVwiICYmICFldmVudC5hbHRLZXk7XG4gICAgICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcblxuICAgICAgICAgIGlmICghc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggfHwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgICAgIGlmIChzaG91bGRVcGRhdGVTdHJva2VDb2xvcikge1xuICAgICAgICAgICAgICB0aGlzLnN5bmNBY3Rpb25SZXN1bHQoe1xuICAgICAgICAgICAgICAgIGFwcFN0YXRlOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUpLCB7XG4gICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbVN0cm9rZUNvbG9yOiBjb2xvclxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIGNvbW1pdFRvSGlzdG9yeTogdHJ1ZVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuc3luY0FjdGlvblJlc3VsdCh7XG4gICAgICAgICAgICAgICAgYXBwU3RhdGU6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZSksIHtcbiAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtQmFja2dyb3VuZENvbG9yOiBjb2xvclxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIGNvbW1pdFRvSGlzdG9yeTogdHJ1ZVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVTY2VuZSh7XG4gICAgICAgICAgICAgIGVsZW1lbnRzOiB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLm1hcChlbCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2VsLmlkXSkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnRXaXRoKGVsLCB7XG4gICAgICAgICAgICAgICAgICAgIFtzaG91bGRVcGRhdGVTdHJva2VDb2xvciA/IFwic3Ryb2tlQ29sb3JcIiA6IFwiYmFja2dyb3VuZENvbG9yXCJdOiBjb2xvclxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBrZWVwT3Blbk9uQWx0OiBmYWxzZVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuc3luY0FjdGlvblJlc3VsdCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhhY3Rpb25SZXN1bHQgPT4ge1xuICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2YsIF9nLCBfaCwgX2o7XG5cbiAgICAgIGlmICh0aGlzLnVubW91bnRlZCB8fCBhY3Rpb25SZXN1bHQgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IGVkaXRpbmdFbGVtZW50ID0gbnVsbDtcblxuICAgICAgaWYgKGFjdGlvblJlc3VsdC5lbGVtZW50cykge1xuICAgICAgICBhY3Rpb25SZXN1bHQuZWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICB2YXIgX2E7XG5cbiAgICAgICAgICBpZiAoKChfYSA9IHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pZCkgPT09IGVsZW1lbnQuaWQgJiYgdGhpcy5zdGF0ZS5lZGl0aW5nRWxlbWVudCAhPT0gZWxlbWVudCAmJiBpc05vbkRlbGV0ZWRFbGVtZW50KGVsZW1lbnQpKSB7XG4gICAgICAgICAgICBlZGl0aW5nRWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoYWN0aW9uUmVzdWx0LmVsZW1lbnRzKTtcblxuICAgICAgICBpZiAoYWN0aW9uUmVzdWx0LmNvbW1pdFRvSGlzdG9yeSkge1xuICAgICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYWN0aW9uUmVzdWx0LmZpbGVzKSB7XG4gICAgICAgIHRoaXMuZmlsZXMgPSBhY3Rpb25SZXN1bHQucmVwbGFjZUZpbGVzID8gYWN0aW9uUmVzdWx0LmZpbGVzIDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLmZpbGVzKSwgYWN0aW9uUmVzdWx0LmZpbGVzKTtcbiAgICAgICAgdGhpcy5hZGROZXdJbWFnZXNUb0ltYWdlQ2FjaGUoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFjdGlvblJlc3VsdC5hcHBTdGF0ZSB8fCBlZGl0aW5nRWxlbWVudCB8fCB0aGlzLnN0YXRlLmNvbnRleHRNZW51KSB7XG4gICAgICAgIGlmIChhY3Rpb25SZXN1bHQuY29tbWl0VG9IaXN0b3J5KSB7XG4gICAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHZpZXdNb2RlRW5hYmxlZCA9ICgoX2EgPSBhY3Rpb25SZXN1bHQgPT09IG51bGwgfHwgYWN0aW9uUmVzdWx0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhY3Rpb25SZXN1bHQuYXBwU3RhdGUpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS52aWV3TW9kZUVuYWJsZWQpIHx8IGZhbHNlO1xuICAgICAgICBsZXQgemVuTW9kZUVuYWJsZWQgPSAoKF9iID0gYWN0aW9uUmVzdWx0ID09PSBudWxsIHx8IGFjdGlvblJlc3VsdCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYWN0aW9uUmVzdWx0LmFwcFN0YXRlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuemVuTW9kZUVuYWJsZWQpIHx8IGZhbHNlO1xuICAgICAgICBsZXQgZ3JpZFNpemUgPSAoKF9jID0gYWN0aW9uUmVzdWx0ID09PSBudWxsIHx8IGFjdGlvblJlc3VsdCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYWN0aW9uUmVzdWx0LmFwcFN0YXRlKSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MuZ3JpZFNpemUpIHx8IG51bGw7XG4gICAgICAgIGNvbnN0IHRoZW1lID0gKChfZCA9IGFjdGlvblJlc3VsdCA9PT0gbnVsbCB8fCBhY3Rpb25SZXN1bHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGFjdGlvblJlc3VsdC5hcHBTdGF0ZSkgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLnRoZW1lKSB8fCB0aGlzLnByb3BzLnRoZW1lIHx8IFRIRU1FLkxJR0hUO1xuICAgICAgICBsZXQgbmFtZSA9IChfZiA9IChfZSA9IGFjdGlvblJlc3VsdCA9PT0gbnVsbCB8fCBhY3Rpb25SZXN1bHQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGFjdGlvblJlc3VsdC5hcHBTdGF0ZSkgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLm5hbWUpICE9PSBudWxsICYmIF9mICE9PSB2b2lkIDAgPyBfZiA6IHRoaXMuc3RhdGUubmFtZTtcbiAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gKF9oID0gKF9nID0gYWN0aW9uUmVzdWx0ID09PSBudWxsIHx8IGFjdGlvblJlc3VsdCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYWN0aW9uUmVzdWx0LmFwcFN0YXRlKSA9PT0gbnVsbCB8fCBfZyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2cuZXJyb3JNZXNzYWdlKSAhPT0gbnVsbCAmJiBfaCAhPT0gdm9pZCAwID8gX2ggOiB0aGlzLnN0YXRlLmVycm9yTWVzc2FnZTtcblxuICAgICAgICBpZiAodHlwZW9mIHRoaXMucHJvcHMudmlld01vZGVFbmFibGVkICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgdmlld01vZGVFbmFibGVkID0gdGhpcy5wcm9wcy52aWV3TW9kZUVuYWJsZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHRoaXMucHJvcHMuemVuTW9kZUVuYWJsZWQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICB6ZW5Nb2RlRW5hYmxlZCA9IHRoaXMucHJvcHMuemVuTW9kZUVuYWJsZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHRoaXMucHJvcHMuZ3JpZE1vZGVFbmFibGVkICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgZ3JpZFNpemUgPSB0aGlzLnByb3BzLmdyaWRNb2RlRW5hYmxlZCA/IEdSSURfU0laRSA6IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHRoaXMucHJvcHMubmFtZSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgIG5hbWUgPSB0aGlzLnByb3BzLm5hbWU7XG4gICAgICAgIH1cblxuICAgICAgICBlZGl0aW5nRWxlbWVudCA9IGVkaXRpbmdFbGVtZW50IHx8ICgoX2ogPSBhY3Rpb25SZXN1bHQuYXBwU3RhdGUpID09PSBudWxsIHx8IF9qID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfai5lZGl0aW5nRWxlbWVudCkgfHwgbnVsbDtcblxuICAgICAgICBpZiAoZWRpdGluZ0VsZW1lbnQgPT09IG51bGwgfHwgZWRpdGluZ0VsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGVkaXRpbmdFbGVtZW50LmlzRGVsZXRlZCkge1xuICAgICAgICAgIGVkaXRpbmdFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoc3RhdGUgPT4ge1xuICAgICAgICAgIC8vIHVzaW5nIE9iamVjdC5hc3NpZ24gaW5zdGVhZCBvZiBzcHJlYWQgdG8gZm9vbCBUUyA0LjIuMisgaW50b1xuICAgICAgICAgIC8vIHJlZ2FyZGluZyB0aGUgcmVzdWx0aW5nIHR5cGUgYXMgbm90IGNvbnRhaW5pbmcgdW5kZWZpbmVkXG4gICAgICAgICAgLy8gKHdoaWNoIHRoZSBmb2xsb3dpbmcgZXhwcmVzc2lvbiB3aWxsIG5ldmVyIGNvbnRhaW4pXG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oYWN0aW9uUmVzdWx0LmFwcFN0YXRlIHx8IHt9LCB7XG4gICAgICAgICAgICAvLyBOT1RFIHRoaXMgd2lsbCBwcmV2ZW50IG9wZW5pbmcgY29udGV4dCBtZW51IHVzaW5nIGFuIGFjdGlvblxuICAgICAgICAgICAgLy8gb3IgcHJvZ3JhbW1hdGljYWxseSBmcm9tIHRoZSBob3N0LCBzbyBpdCB3aWxsIG5lZWQgdG8gYmVcbiAgICAgICAgICAgIC8vIHJld3JpdHRlbiBsYXRlclxuICAgICAgICAgICAgY29udGV4dE1lbnU6IG51bGwsXG4gICAgICAgICAgICBlZGl0aW5nRWxlbWVudCxcbiAgICAgICAgICAgIHZpZXdNb2RlRW5hYmxlZCxcbiAgICAgICAgICAgIHplbk1vZGVFbmFibGVkLFxuICAgICAgICAgICAgZ3JpZFNpemUsXG4gICAgICAgICAgICB0aGVtZSxcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBlcnJvck1lc3NhZ2VcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgIGlmIChhY3Rpb25SZXN1bHQuc3luY0hpc3RvcnkpIHtcbiAgICAgICAgICAgIHRoaXMuaGlzdG9yeS5zZXRDdXJyZW50U3RhdGUodGhpcy5zdGF0ZSwgdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTsgLy8gTGlmZWN5Y2xlXG5cbiAgICB0aGlzLm9uQmx1ciA9IHdpdGhCYXRjaGVkVXBkYXRlcygoKSA9PiB7XG4gICAgICBpc0hvbGRpbmdTcGFjZSA9IGZhbHNlO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGlzQmluZGluZ0VuYWJsZWQ6IHRydWVcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vblVubG9hZCA9ICgpID0+IHtcbiAgICAgIHRoaXMub25CbHVyKCk7XG4gICAgfTtcblxuICAgIHRoaXMuZGlzYWJsZUV2ZW50ID0gZXZlbnQgPT4ge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZXNldEhpc3RvcnkgPSAoKSA9PiB7XG4gICAgICB0aGlzLmhpc3RvcnkuY2xlYXIoKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJlc2V0cyBzY2VuZSAmIGhpc3RvcnkuXG4gICAgICogISBEbyBub3QgdXNlIHRvIGNsZWFyIHNjZW5lIHVzZXIgYWN0aW9uICFcbiAgICAgKi9cblxuXG4gICAgdGhpcy5yZXNldFNjZW5lID0gd2l0aEJhdGNoZWRVcGRhdGVzKG9wdHMgPT4ge1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoW10pO1xuICAgICAgdGhpcy5zZXRTdGF0ZShzdGF0ZSA9PiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGdldERlZmF1bHRBcHBTdGF0ZSgpKSwge1xuICAgICAgICBpc0xvYWRpbmc6IChvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMucmVzZXRMb2FkaW5nU3RhdGUpID8gZmFsc2UgOiBzdGF0ZS5pc0xvYWRpbmcsXG4gICAgICAgIHRoZW1lOiB0aGlzLnN0YXRlLnRoZW1lXG4gICAgICB9KSk7XG4gICAgICB0aGlzLnJlc2V0SGlzdG9yeSgpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5pbml0aWFsaXplU2NlbmUgPSAoKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICB2YXIgX2I7XG5cbiAgICAgIGlmIChcImxhdW5jaFF1ZXVlXCIgaW4gd2luZG93ICYmIFwiTGF1bmNoUGFyYW1zXCIgaW4gd2luZG93KSB7XG4gICAgICAgIHdpbmRvdy5sYXVuY2hRdWV1ZS5zZXRDb25zdW1lcihsYXVuY2hQYXJhbXMgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgICAgIGlmICghbGF1bmNoUGFyYW1zLmZpbGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGZpbGVIYW5kbGUgPSBsYXVuY2hQYXJhbXMuZmlsZXNbMF07XG4gICAgICAgICAgY29uc3QgYmxvYiA9IHlpZWxkIGZpbGVIYW5kbGUuZ2V0RmlsZSgpO1xuICAgICAgICAgIHRoaXMubG9hZEZpbGVUb0NhbnZhcyhuZXcgRmlsZShbYmxvYl0sIGJsb2IubmFtZSB8fCBcIlwiLCB7XG4gICAgICAgICAgICB0eXBlOiBibG9iLnR5cGVcbiAgICAgICAgICB9KSwgZmlsZUhhbmRsZSk7XG4gICAgICAgIH0pKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucHJvcHMudGhlbWUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgdGhlbWU6IHRoaXMucHJvcHMudGhlbWVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5zdGF0ZS5pc0xvYWRpbmcpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgaXNMb2FkaW5nOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBsZXQgaW5pdGlhbERhdGEgPSBudWxsO1xuXG4gICAgICB0cnkge1xuICAgICAgICBpbml0aWFsRGF0YSA9ICh5aWVsZCB0aGlzLnByb3BzLmluaXRpYWxEYXRhKSB8fCBudWxsO1xuXG4gICAgICAgIGlmIChpbml0aWFsRGF0YSA9PT0gbnVsbCB8fCBpbml0aWFsRGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogaW5pdGlhbERhdGEubGlicmFyeUl0ZW1zKSB7XG4gICAgICAgICAgdGhpcy5saWJyYXJ5LnVwZGF0ZUxpYnJhcnkoe1xuICAgICAgICAgICAgbGlicmFyeUl0ZW1zOiBpbml0aWFsRGF0YS5saWJyYXJ5SXRlbXMsXG4gICAgICAgICAgICBtZXJnZTogdHJ1ZVxuICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgaW5pdGlhbERhdGEgPSB7XG4gICAgICAgICAgYXBwU3RhdGU6IHtcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZTogZXJyb3IubWVzc2FnZSB8fCBcIkVuY291bnRlcmVkIGFuIGVycm9yIGR1cmluZyBpbXBvcnRpbmcgb3IgcmVzdG9yaW5nIHNjZW5lIGRhdGFcIlxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2NlbmUgPSByZXN0b3JlKGluaXRpYWxEYXRhLCBudWxsLCBudWxsLCB7XG4gICAgICAgIHJlcGFpckJpbmRpbmdzOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIHNjZW5lLmFwcFN0YXRlID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzY2VuZS5hcHBTdGF0ZSksIHtcbiAgICAgICAgdGhlbWU6IHRoaXMucHJvcHMudGhlbWUgfHwgc2NlbmUuYXBwU3RhdGUudGhlbWUsXG4gICAgICAgIC8vIHdlJ3JlIGZhbGxpbmcgYmFjayB0byBjdXJyZW50IChwcmUtaW5pdCkgc3RhdGUgd2hlbiBkZWNpZGluZ1xuICAgICAgICAvLyB3aGV0aGVyIHRvIG9wZW4gdGhlIGxpYnJhcnksIHRvIGhhbmRsZSBhIGNhc2Ugd2hlcmUgd2VcbiAgICAgICAgLy8gdXBkYXRlIHRoZSBzdGF0ZSBvdXRzaWRlIG9mIGluaXRpYWxEYXRhIChlLmcuIHdoZW4gbG9hZGluZyB0aGUgYXBwXG4gICAgICAgIC8vIHdpdGggYSBsaWJyYXJ5IGluc3RhbGwgbGluaywgd2hpY2ggc2hvdWxkIGF1dG8tb3BlbiB0aGUgbGlicmFyeSlcbiAgICAgICAgb3BlblNpZGViYXI6ICgoX2IgPSBzY2VuZS5hcHBTdGF0ZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLm9wZW5TaWRlYmFyKSB8fCB0aGlzLnN0YXRlLm9wZW5TaWRlYmFyLFxuICAgICAgICBhY3RpdmVUb29sOiBzY2VuZS5hcHBTdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiaW1hZ2VcIiA/IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2NlbmUuYXBwU3RhdGUuYWN0aXZlVG9vbCksIHtcbiAgICAgICAgICB0eXBlOiBcInNlbGVjdGlvblwiXG4gICAgICAgIH0pIDogc2NlbmUuYXBwU3RhdGUuYWN0aXZlVG9vbCxcbiAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgdG9hc3Q6IHRoaXMuc3RhdGUudG9hc3RcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoaW5pdGlhbERhdGEgPT09IG51bGwgfHwgaW5pdGlhbERhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGluaXRpYWxEYXRhLnNjcm9sbFRvQ29udGVudCkge1xuICAgICAgICBzY2VuZS5hcHBTdGF0ZSA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2NlbmUuYXBwU3RhdGUpLCBjYWxjdWxhdGVTY3JvbGxDZW50ZXIoc2NlbmUuZWxlbWVudHMsIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2NlbmUuYXBwU3RhdGUpLCB7XG4gICAgICAgICAgd2lkdGg6IHRoaXMuc3RhdGUud2lkdGgsXG4gICAgICAgICAgaGVpZ2h0OiB0aGlzLnN0YXRlLmhlaWdodCxcbiAgICAgICAgICBvZmZzZXRUb3A6IHRoaXMuc3RhdGUub2Zmc2V0VG9wLFxuICAgICAgICAgIG9mZnNldExlZnQ6IHRoaXMuc3RhdGUub2Zmc2V0TGVmdFxuICAgICAgICB9KSkpO1xuICAgICAgfSAvLyBGb250RmFjZVNldCBsb2FkaW5nZG9uZSBldmVudCB3ZSBsaXN0ZW4gb24gbWF5IG5vdCBhbHdheXMgZmlyZVxuICAgICAgLy8gKGxvb2tpbmcgYXQgeW91IFNhZmFyaSksIHNvIG9uIGluaXQgd2UgbWFudWFsbHkgbG9hZCBmb250cyBmb3IgY3VycmVudFxuICAgICAgLy8gdGV4dCBlbGVtZW50cyBvbiBjYW52YXMsIGFuZCByZXJlbmRlciB0aGVtIG9uY2UgZG9uZS4gVGhpcyBhbHNvXG4gICAgICAvLyBzZWVtcyBmYXN0ZXIgZXZlbiBpbiBicm93c2VycyB0aGF0IGRvIGZpcmUgdGhlIGxvYWRpbmdkb25lIGV2ZW50LlxuXG5cbiAgICAgIHRoaXMuZm9udHMubG9hZEZvbnRzRm9yRWxlbWVudHMoc2NlbmUuZWxlbWVudHMpO1xuICAgICAgdGhpcy5yZXNldEhpc3RvcnkoKTtcbiAgICAgIHRoaXMuc3luY0FjdGlvblJlc3VsdChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNjZW5lKSwge1xuICAgICAgICBjb21taXRUb0hpc3Rvcnk6IHRydWVcbiAgICAgIH0pKTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVmcmVzaERldmljZVN0YXRlID0gY29udGFpbmVyID0+IHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodFxuICAgICAgfSA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGNvbnN0IHNpZGViYXJCcmVha3BvaW50ID0gdGhpcy5wcm9wcy5VSU9wdGlvbnMuZG9ja2VkU2lkZWJhckJyZWFrcG9pbnQgIT0gbnVsbCA/IHRoaXMucHJvcHMuVUlPcHRpb25zLmRvY2tlZFNpZGViYXJCcmVha3BvaW50IDogTVFfUklHSFRfU0lERUJBUl9NSU5fV0lEVEg7XG4gICAgICB0aGlzLmRldmljZSA9IHVwZGF0ZU9iamVjdCh0aGlzLmRldmljZSwge1xuICAgICAgICBpc0xhbmRzY2FwZTogd2lkdGggPiBoZWlnaHQsXG4gICAgICAgIGlzU21TY3JlZW46IHdpZHRoIDwgTVFfU01fTUFYX1dJRFRILFxuICAgICAgICBpc01vYmlsZTogd2lkdGggPCBNUV9NQVhfV0lEVEhfUE9SVFJBSVQgfHwgaGVpZ2h0IDwgTVFfTUFYX0hFSUdIVF9MQU5EU0NBUEUgJiYgd2lkdGggPCBNUV9NQVhfV0lEVEhfTEFORFNDQVBFLFxuICAgICAgICBjYW5EZXZpY2VGaXRTaWRlYmFyOiB3aWR0aCA+IHNpZGViYXJCcmVha3BvaW50XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5vblJlc2l6ZSA9IHdpdGhCYXRjaGVkVXBkYXRlcygoKSA9PiB7XG4gICAgICB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLmZvckVhY2goZWxlbWVudCA9PiBTaGFwZUNhY2hlLmRlbGV0ZShlbGVtZW50KSk7XG4gICAgICB0aGlzLnNldFN0YXRlKHt9KTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVuZGVySW50ZXJhY3RpdmVTY2VuZUNhbGxiYWNrID0gKHtcbiAgICAgIGF0TGVhc3RPbmVWaXNpYmxlRWxlbWVudCxcbiAgICAgIHNjcm9sbEJhcnMsXG4gICAgICBlbGVtZW50c1xuICAgIH0pID0+IHtcbiAgICAgIGlmIChzY3JvbGxCYXJzKSB7XG4gICAgICAgIGN1cnJlbnRTY3JvbGxCYXJzID0gc2Nyb2xsQmFycztcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2Nyb2xsZWRPdXRzaWRlID0gLy8gaGlkZSB3aGVuIGVkaXRpbmcgdGV4dFxuICAgICAgaXNUZXh0RWxlbWVudCh0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50KSA/IGZhbHNlIDogIWF0TGVhc3RPbmVWaXNpYmxlRWxlbWVudCAmJiBlbGVtZW50cy5sZW5ndGggPiAwO1xuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5zY3JvbGxlZE91dHNpZGUgIT09IHNjcm9sbGVkT3V0c2lkZSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzY3JvbGxlZE91dHNpZGVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2NoZWR1bGVJbWFnZVJlZnJlc2goKTtcbiAgICB9O1xuXG4gICAgdGhpcy5vblNjcm9sbCA9IGRlYm91bmNlKCgpID0+IHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgb2Zmc2V0VG9wLFxuICAgICAgICBvZmZzZXRMZWZ0XG4gICAgICB9ID0gdGhpcy5nZXRDYW52YXNPZmZzZXRzKCk7XG4gICAgICB0aGlzLnNldFN0YXRlKHN0YXRlID0+IHtcbiAgICAgICAgaWYgKHN0YXRlLm9mZnNldExlZnQgPT09IG9mZnNldExlZnQgJiYgc3RhdGUub2Zmc2V0VG9wID09PSBvZmZzZXRUb3ApIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgb2Zmc2V0VG9wLFxuICAgICAgICAgIG9mZnNldExlZnRcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH0sIFNDUk9MTF9USU1FT1VUKTsgLy8gQ29weS9wYXN0ZVxuXG4gICAgdGhpcy5vbkN1dCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIGNvbnN0IGlzRXhjYWxpZHJhd0FjdGl2ZSA9IChfYSA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY29udGFpbnMoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgIGlmICghaXNFeGNhbGlkcmF3QWN0aXZlIHx8IGlzV3JpdGFibGVFbGVtZW50KGV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmN1dEFsbCgpO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH0pO1xuICAgIHRoaXMub25Db3B5ID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgY29uc3QgaXNFeGNhbGlkcmF3QWN0aXZlID0gKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jb250YWlucyhkb2N1bWVudC5hY3RpdmVFbGVtZW50KTtcblxuICAgICAgaWYgKCFpc0V4Y2FsaWRyYXdBY3RpdmUgfHwgaXNXcml0YWJsZUVsZW1lbnQoZXZlbnQudGFyZ2V0KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY29weUFsbCgpO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5jdXRBbGwgPSAoKSA9PiB7XG4gICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25DdXQsIFwia2V5Ym9hcmRcIik7XG4gICAgfTtcblxuICAgIHRoaXMuY29weUFsbCA9ICgpID0+IHtcbiAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkNvcHksIFwia2V5Ym9hcmRcIik7XG4gICAgfTtcblxuICAgIHRoaXMub25Ub3VjaFN0YXJ0ID0gZXZlbnQgPT4ge1xuICAgICAgLy8gZml4IGZvciBBcHBsZSBQZW5jaWwgU2NyaWJibGVcbiAgICAgIC8vIE9uIEFuZHJvaWQsIHByZXZlbnRpbmcgdGhlIGV2ZW50IHdvdWxkIGRpc2FibGUgY29udGV4dE1lbnUgb24gdGFwLWhvbGRcbiAgICAgIGlmICghaXNBbmRyb2lkKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghZGlkVGFwVHdpY2UpIHtcbiAgICAgICAgZGlkVGFwVHdpY2UgPSB0cnVlO1xuICAgICAgICBjbGVhclRpbWVvdXQodGFwcGVkVHdpY2VUaW1lcik7XG4gICAgICAgIHRhcHBlZFR3aWNlVGltZXIgPSB3aW5kb3cuc2V0VGltZW91dChBcHAucmVzZXRUYXBUd2ljZSwgVEFQX1RXSUNFX1RJTUVPVVQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIGluc2VydCB0ZXh0IG9ubHkgaWYgd2UgdGFwcGVkIHR3aWNlIHdpdGggYSBzaW5nbGUgZmluZ2VyXG4gICAgICAvLyBldmVudC50b3VjaGVzLmxlbmd0aCA9PT0gMSB3aWxsIGFsc28gcHJldmVudCBpbnNlcnRpbmcgdGV4dCB3aGVuIHVzZXIncyB6b29taW5nXG5cblxuICAgICAgaWYgKGRpZFRhcFR3aWNlICYmIGV2ZW50LnRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIGNvbnN0IHRvdWNoID0gZXZlbnQudG91Y2hlc1swXTsgLy8gQHRzLWlnbm9yZVxuXG4gICAgICAgIHRoaXMuaGFuZGxlQ2FudmFzRG91YmxlQ2xpY2soe1xuICAgICAgICAgIGNsaWVudFg6IHRvdWNoLmNsaWVudFgsXG4gICAgICAgICAgY2xpZW50WTogdG91Y2guY2xpZW50WVxuICAgICAgICB9KTtcbiAgICAgICAgZGlkVGFwVHdpY2UgPSBmYWxzZTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRhcHBlZFR3aWNlVGltZXIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNBbmRyb2lkKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudC50b3VjaGVzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLm9uVG91Y2hFbmQgPSBldmVudCA9PiB7XG4gICAgICB0aGlzLnJlc2V0Q29udGV4dE1lbnVUaW1lcigpO1xuXG4gICAgICBpZiAoZXZlbnQudG91Y2hlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHByZXZpb3VzU2VsZWN0ZWRFbGVtZW50SWRzOiB7fSxcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHRoaXMuc3RhdGUucHJldmlvdXNTZWxlY3RlZEVsZW1lbnRJZHMsIHRoaXMuc3RhdGUpXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZ2VzdHVyZS5wb2ludGVycy5jbGVhcigpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLnBhc3RlRnJvbUNsaXBib2FyZCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICB2YXIgX2MsIF9kLCBfZTtcblxuICAgICAgY29uc3QgaXNQbGFpblBhc3RlID0gISEoSVNfUExBSU5fUEFTVEUgJiYgZXZlbnQpOyAvLyAjNjg2XG5cbiAgICAgIGNvbnN0IHRhcmdldCA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG4gICAgICBjb25zdCBpc0V4Y2FsaWRyYXdBY3RpdmUgPSAoX2MgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLmNvbnRhaW5zKHRhcmdldCk7XG5cbiAgICAgIGlmIChldmVudCAmJiAhaXNFeGNhbGlkcmF3QWN0aXZlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZWxlbWVudFVuZGVyQ3Vyc29yID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLngsIHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueSk7XG5cbiAgICAgIGlmIChldmVudCAmJiAoIShlbGVtZW50VW5kZXJDdXJzb3IgaW5zdGFuY2VvZiBIVE1MQ2FudmFzRWxlbWVudCkgfHwgaXNXcml0YWJsZUVsZW1lbnQodGFyZ2V0KSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBtdXN0IGJlIGNhbGxlZCBpbiB0aGUgc2FtZSBmcmFtZSAodGh1cyBiZWZvcmUgYW55IGF3YWl0cykgYXMgdGhlIHBhc3RlXG4gICAgICAvLyBldmVudCBlbHNlIHNvbWUgYnJvd3NlcnMgKEZGLi4uKSB3aWxsIGNsZWFyIHRoZSBjbGlwYm9hcmREYXRhXG4gICAgICAvLyAoc29tZXRoaW5nIHNvbWV0aGluZyBzZWN1cml0eSlcblxuXG4gICAgICBsZXQgZmlsZSA9IChfZCA9IGV2ZW50ID09PSBudWxsIHx8IGV2ZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBldmVudC5jbGlwYm9hcmREYXRhKSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QuZmlsZXNbMF07XG4gICAgICBjb25zdCBkYXRhID0geWllbGQgcGFyc2VDbGlwYm9hcmQoZXZlbnQsIGlzUGxhaW5QYXN0ZSk7XG5cbiAgICAgIGlmICghZmlsZSAmJiBkYXRhLnRleHQgJiYgIWlzUGxhaW5QYXN0ZSkge1xuICAgICAgICBjb25zdCBzdHJpbmcgPSBkYXRhLnRleHQudHJpbSgpO1xuXG4gICAgICAgIGlmIChzdHJpbmcuc3RhcnRzV2l0aChcIjxzdmdcIikgJiYgc3RyaW5nLmVuZHNXaXRoKFwiPC9zdmc+XCIpKSB7XG4gICAgICAgICAgLy8gaWdub3JlIFNWRyB2YWxpZGF0aW9uL25vcm1hbGl6YXRpb24gd2hpY2ggd2lsbCBiZSBkb25lIGR1cmluZyBpbWFnZVxuICAgICAgICAgIC8vIGluaXRpYWxpemF0aW9uXG4gICAgICAgICAgZmlsZSA9IFNWR1N0cmluZ1RvRmlsZShzdHJpbmcpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtcbiAgICAgICAgeDogc2NlbmVYLFxuICAgICAgICB5OiBzY2VuZVlcbiAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICBjbGllbnRYOiB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLngsXG4gICAgICAgIGNsaWVudFk6IHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueVxuICAgICAgfSwgdGhpcy5zdGF0ZSk7IC8vIHByZWZlciBzcHJlYWRzaGVldCBkYXRhIG92ZXIgaW1hZ2UgZmlsZSAoTVMgT2ZmaWNlL0xpYnJlIE9mZmljZSlcblxuICAgICAgaWYgKGlzU3VwcG9ydGVkSW1hZ2VGaWxlKGZpbGUpICYmICFkYXRhLnNwcmVhZHNoZWV0KSB7XG4gICAgICAgIGNvbnN0IGltYWdlRWxlbWVudCA9IHRoaXMuY3JlYXRlSW1hZ2VFbGVtZW50KHtcbiAgICAgICAgICBzY2VuZVgsXG4gICAgICAgICAgc2NlbmVZXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmluc2VydEltYWdlRWxlbWVudChpbWFnZUVsZW1lbnQsIGZpbGUpO1xuICAgICAgICB0aGlzLmluaXRpYWxpemVJbWFnZURpbWVuc2lvbnMoaW1hZ2VFbGVtZW50KTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7XG4gICAgICAgICAgICBbaW1hZ2VFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgIH0sIHRoaXMuc3RhdGUpXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnByb3BzLm9uUGFzdGUpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAoKHlpZWxkIHRoaXMucHJvcHMub25QYXN0ZShkYXRhLCBldmVudCkpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZGF0YS5lcnJvck1lc3NhZ2UpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlOiBkYXRhLmVycm9yTWVzc2FnZVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoZGF0YS5zcHJlYWRzaGVldCAmJiAhaXNQbGFpblBhc3RlKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHBhc3RlRGlhbG9nOiB7XG4gICAgICAgICAgICBkYXRhOiBkYXRhLnNwcmVhZHNoZWV0LFxuICAgICAgICAgICAgc2hvd246IHRydWVcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLmVsZW1lbnRzKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gZGF0YS5wcm9ncmFtbWF0aWNBUEkgPyBjb252ZXJ0VG9FeGNhbGlkcmF3RWxlbWVudHMoZGF0YS5lbGVtZW50cykgOiBkYXRhLmVsZW1lbnRzOyAvLyBUT0RPIHJlbW92ZSBmb3JtYXR0aW5nIGZyb20gZWxlbWVudHMgaWYgaXNQbGFpblBhc3RlXG5cbiAgICAgICAgdGhpcy5hZGRFbGVtZW50c0Zyb21QYXN0ZU9yTGlicmFyeSh7XG4gICAgICAgICAgZWxlbWVudHMsXG4gICAgICAgICAgZmlsZXM6IGRhdGEuZmlsZXMgfHwgbnVsbCxcbiAgICAgICAgICBwb3NpdGlvbjogXCJjdXJzb3JcIixcbiAgICAgICAgICByZXRhaW5TZWVkOiBpc1BsYWluUGFzdGVcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGRhdGEudGV4dCkge1xuICAgICAgICBjb25zdCBtYXliZVVybCA9IGV4dHJhY3RTcmMoZGF0YS50ZXh0KTtcblxuICAgICAgICBpZiAoIWlzUGxhaW5QYXN0ZSAmJiBlbWJlZGRhYmxlVVJMVmFsaWRhdG9yKG1heWJlVXJsLCB0aGlzLnByb3BzLnZhbGlkYXRlRW1iZWRkYWJsZSkgJiYgKC9eKGh0dHB8aHR0cHMpOlxcL1xcL1teXFxzLyQuPyNdLlteXFxzXSokLy50ZXN0KG1heWJlVXJsKSB8fCAoKF9lID0gZ2V0RW1iZWRMaW5rKG1heWJlVXJsKSkgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLnR5cGUpID09PSBcInZpZGVvXCIpKSB7XG4gICAgICAgICAgY29uc3QgZW1iZWRkYWJsZSA9IHRoaXMuaW5zZXJ0RW1iZWRkYWJsZUVsZW1lbnQoe1xuICAgICAgICAgICAgc2NlbmVYLFxuICAgICAgICAgICAgc2NlbmVZLFxuICAgICAgICAgICAgbGluazogbm9ybWFsaXplTGluayhtYXliZVVybClcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChlbWJlZGRhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiB7XG4gICAgICAgICAgICAgICAgW2VtYmVkZGFibGUuaWRdOiB0cnVlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYWRkVGV4dEZyb21QYXN0ZShkYXRhLnRleHQsIGlzUGxhaW5QYXN0ZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2V0QWN0aXZlVG9vbCh7XG4gICAgICAgIHR5cGU6IFwic2VsZWN0aW9uXCJcbiAgICAgIH0pO1xuICAgICAgZXZlbnQgPT09IG51bGwgfHwgZXZlbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSkpO1xuXG4gICAgdGhpcy5hZGRFbGVtZW50c0Zyb21QYXN0ZU9yTGlicmFyeSA9IG9wdHMgPT4ge1xuICAgICAgY29uc3QgZWxlbWVudHMgPSByZXN0b3JlRWxlbWVudHMob3B0cy5lbGVtZW50cywgbnVsbCwgdW5kZWZpbmVkKTtcbiAgICAgIGNvbnN0IFttaW5YLCBtaW5ZLCBtYXhYLCBtYXhZXSA9IGdldENvbW1vbkJvdW5kcyhlbGVtZW50cyk7XG4gICAgICBjb25zdCBlbGVtZW50c0NlbnRlclggPSBkaXN0YW5jZShtaW5YLCBtYXhYKSAvIDI7XG4gICAgICBjb25zdCBlbGVtZW50c0NlbnRlclkgPSBkaXN0YW5jZShtaW5ZLCBtYXhZKSAvIDI7XG4gICAgICBjb25zdCBjbGllbnRYID0gdHlwZW9mIG9wdHMucG9zaXRpb24gPT09IFwib2JqZWN0XCIgPyBvcHRzLnBvc2l0aW9uLmNsaWVudFggOiBvcHRzLnBvc2l0aW9uID09PSBcImN1cnNvclwiID8gdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi54IDogdGhpcy5zdGF0ZS53aWR0aCAvIDIgKyB0aGlzLnN0YXRlLm9mZnNldExlZnQ7XG4gICAgICBjb25zdCBjbGllbnRZID0gdHlwZW9mIG9wdHMucG9zaXRpb24gPT09IFwib2JqZWN0XCIgPyBvcHRzLnBvc2l0aW9uLmNsaWVudFkgOiBvcHRzLnBvc2l0aW9uID09PSBcImN1cnNvclwiID8gdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi55IDogdGhpcy5zdGF0ZS5oZWlnaHQgLyAyICsgdGhpcy5zdGF0ZS5vZmZzZXRUb3A7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHgsXG4gICAgICAgIHlcbiAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICBjbGllbnRYLFxuICAgICAgICBjbGllbnRZXG4gICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IGR4ID0geCAtIGVsZW1lbnRzQ2VudGVyWDtcbiAgICAgIGNvbnN0IGR5ID0geSAtIGVsZW1lbnRzQ2VudGVyWTtcbiAgICAgIGNvbnN0IFtncmlkWCwgZ3JpZFldID0gZ2V0R3JpZFBvaW50KGR4LCBkeSwgdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICBjb25zdCBuZXdFbGVtZW50cyA9IGR1cGxpY2F0ZUVsZW1lbnRzKGVsZW1lbnRzLm1hcChlbGVtZW50ID0+IHtcbiAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnRXaXRoKGVsZW1lbnQsIHtcbiAgICAgICAgICB4OiBlbGVtZW50LnggKyBncmlkWCAtIG1pblgsXG4gICAgICAgICAgeTogZWxlbWVudC55ICsgZ3JpZFkgLSBtaW5ZXG4gICAgICAgIH0pO1xuICAgICAgfSksIHtcbiAgICAgICAgcmFuZG9taXplU2VlZDogIW9wdHMucmV0YWluU2VlZFxuICAgICAgfSk7XG4gICAgICBjb25zdCBuZXh0RWxlbWVudHMgPSBbLi4udGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgLi4ubmV3RWxlbWVudHNdO1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMobmV4dEVsZW1lbnRzKTtcbiAgICAgIG5ld0VsZW1lbnRzLmZvckVhY2gobmV3RWxlbWVudCA9PiB7XG4gICAgICAgIGlmIChpc1RleHRFbGVtZW50KG5ld0VsZW1lbnQpICYmIGlzQm91bmRUb0NvbnRhaW5lcihuZXdFbGVtZW50KSkge1xuICAgICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGdldENvbnRhaW5lckVsZW1lbnQobmV3RWxlbWVudCk7XG4gICAgICAgICAgcmVkcmF3VGV4dEJvdW5kaW5nQm94KG5ld0VsZW1lbnQsIGNvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAob3B0cy5maWxlcykge1xuICAgICAgICB0aGlzLmZpbGVzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLmZpbGVzKSwgb3B0cy5maWxlcyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgIGNvbnN0IG5leHRFbGVtZW50c1RvU2VsZWN0ID0gZXhjbHVkZUVsZW1lbnRzSW5GcmFtZXNGcm9tU2VsZWN0aW9uKG5ld0VsZW1lbnRzKTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUpLCB7XG4gICAgICAgIC8vIGtlZXAgc2lkZWJhciAocHJlc3VtYWJseSB0aGUgbGlicmFyeSkgb3BlbiBpZiBpdCdzIGRvY2tlZCBhbmRcbiAgICAgICAgLy8gY2FuIGZpdC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gTm90ZSwgd2Ugc2hvdWxkIGNsb3NlIHRoZSBzaWRlYmFyIG9ubHkgaWYgd2UncmUgZHJvcHBpbmcgaXRlbXNcbiAgICAgICAgLy8gZnJvbSBsaWJyYXJ5LCBub3Qgd2hlbiBwYXN0aW5nIGZyb20gY2xpcGJvYXJkLiBBbGFzLlxuICAgICAgICBvcGVuU2lkZWJhcjogdGhpcy5zdGF0ZS5vcGVuU2lkZWJhciAmJiB0aGlzLmRldmljZS5jYW5EZXZpY2VGaXRTaWRlYmFyICYmIGpvdGFpU3RvcmUuZ2V0KGlzU2lkZWJhckRvY2tlZEF0b20pID8gdGhpcy5zdGF0ZS5vcGVuU2lkZWJhciA6IG51bGxcbiAgICAgIH0pLCBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGwsXG4gICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbmV4dEVsZW1lbnRzVG9TZWxlY3QucmVkdWNlKChhY2MsIGVsZW1lbnQpID0+IHtcbiAgICAgICAgICBpZiAoIWlzQm91bmRUb0NvbnRhaW5lcihlbGVtZW50KSkge1xuICAgICAgICAgICAgYWNjW2VsZW1lbnQuaWRdID0gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB9LCB7fSlcbiAgICAgIH0sIHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIHRoaXMuc3RhdGUsIHRoaXMpKSwgKCkgPT4ge1xuICAgICAgICBpZiAob3B0cy5maWxlcykge1xuICAgICAgICAgIHRoaXMuYWRkTmV3SW1hZ2VzVG9JbWFnZUNhY2hlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5zZXRBY3RpdmVUb29sKHtcbiAgICAgICAgdHlwZTogXCJzZWxlY3Rpb25cIlxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuc2V0QXBwU3RhdGUgPSAoc3RhdGUsIGNhbGxiYWNrKSA9PiB7XG4gICAgICB0aGlzLnNldFN0YXRlKHN0YXRlLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHRoaXMucmVtb3ZlUG9pbnRlciA9IGV2ZW50ID0+IHtcbiAgICAgIGlmICh0b3VjaFRpbWVvdXQpIHtcbiAgICAgICAgdGhpcy5yZXNldENvbnRleHRNZW51VGltZXIoKTtcbiAgICAgIH1cblxuICAgICAgZ2VzdHVyZS5wb2ludGVycy5kZWxldGUoZXZlbnQucG9pbnRlcklkKTtcbiAgICB9O1xuXG4gICAgdGhpcy50b2dnbGVMb2NrID0gKHNvdXJjZSA9IFwidWlcIikgPT4ge1xuICAgICAgaWYgKCF0aGlzLnN0YXRlLmFjdGl2ZVRvb2wubG9ja2VkKSB7XG4gICAgICAgIHRyYWNrRXZlbnQoXCJ0b29sYmFyXCIsIFwidG9nZ2xlTG9ja1wiLCBgJHtzb3VyY2V9ICgke3RoaXMuZGV2aWNlLmlzTW9iaWxlID8gXCJtb2JpbGVcIiA6IFwiZGVza3RvcFwifSlgKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGFjdGl2ZVRvb2w6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuYWN0aXZlVG9vbCksIHVwZGF0ZUFjdGl2ZVRvb2wodGhpcy5zdGF0ZSwgcHJldlN0YXRlLmFjdGl2ZVRvb2wubG9ja2VkID8ge1xuICAgICAgICAgICAgdHlwZTogXCJzZWxlY3Rpb25cIlxuICAgICAgICAgIH0gOiBwcmV2U3RhdGUuYWN0aXZlVG9vbCkpLCB7XG4gICAgICAgICAgICBsb2NrZWQ6ICFwcmV2U3RhdGUuYWN0aXZlVG9vbC5sb2NrZWRcbiAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMudXBkYXRlRnJhbWVSZW5kZXJpbmcgPSBvcHRzID0+IHtcbiAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kO1xuXG4gICAgICAgIGNvbnN0IG5leHQgPSB0eXBlb2Ygb3B0cyA9PT0gXCJmdW5jdGlvblwiID8gb3B0cyhwcmV2U3RhdGUuZnJhbWVSZW5kZXJpbmcpIDogb3B0cztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBmcmFtZVJlbmRlcmluZzoge1xuICAgICAgICAgICAgZW5hYmxlZDogKF9hID0gbmV4dCA9PT0gbnVsbCB8fCBuZXh0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBuZXh0LmVuYWJsZWQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IHByZXZTdGF0ZS5mcmFtZVJlbmRlcmluZy5lbmFibGVkLFxuICAgICAgICAgICAgY2xpcDogKF9iID0gbmV4dCA9PT0gbnVsbCB8fCBuZXh0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBuZXh0LmNsaXApICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IHByZXZTdGF0ZS5mcmFtZVJlbmRlcmluZy5jbGlwLFxuICAgICAgICAgICAgbmFtZTogKF9jID0gbmV4dCA9PT0gbnVsbCB8fCBuZXh0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBuZXh0Lm5hbWUpICE9PSBudWxsICYmIF9jICE9PSB2b2lkIDAgPyBfYyA6IHByZXZTdGF0ZS5mcmFtZVJlbmRlcmluZy5uYW1lLFxuICAgICAgICAgICAgb3V0bGluZTogKF9kID0gbmV4dCA9PT0gbnVsbCB8fCBuZXh0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBuZXh0Lm91dGxpbmUpICE9PSBudWxsICYmIF9kICE9PSB2b2lkIDAgPyBfZCA6IHByZXZTdGF0ZS5mcmFtZVJlbmRlcmluZy5vdXRsaW5lXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMudG9nZ2xlUGVuTW9kZSA9ICgpID0+IHtcbiAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwZW5Nb2RlOiAhcHJldlN0YXRlLnBlbk1vZGVcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLm9uSGFuZFRvb2xUb2dnbGUgPSAoKSA9PiB7XG4gICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25Ub2dnbGVIYW5kVG9vbCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBab29tcyBvbiBjYW52YXMgdmlld3BvcnQgY2VudGVyXG4gICAgICovXG5cblxuICAgIHRoaXMuem9vbUNhbnZhcyA9IChcbiAgICAvKiogZGVjaW1hbCBmcmFjdGlvbiBiZXR3ZWVuIDAuMSAoMTAlIHpvb20pIGFuZCAzMCAoMzAwMCUgem9vbSkgKi9cbiAgICB2YWx1ZSkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZShPYmplY3QuYXNzaWduKHt9LCBnZXRTdGF0ZUZvclpvb20oe1xuICAgICAgICB2aWV3cG9ydFg6IHRoaXMuc3RhdGUud2lkdGggLyAyICsgdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0LFxuICAgICAgICB2aWV3cG9ydFk6IHRoaXMuc3RhdGUuaGVpZ2h0IC8gMiArIHRoaXMuc3RhdGUub2Zmc2V0VG9wLFxuICAgICAgICBuZXh0Wm9vbTogZ2V0Tm9ybWFsaXplZFpvb20odmFsdWUpXG4gICAgICB9LCB0aGlzLnN0YXRlKSkpO1xuICAgIH07XG5cbiAgICB0aGlzLmNhbmNlbEluUHJvZ3Jlc0FuaW1hdGlvbiA9IG51bGw7XG5cbiAgICB0aGlzLnNjcm9sbFRvQ29udGVudCA9ICh0YXJnZXQgPSB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBvcHRzKSA9PiB7XG4gICAgICB2YXIgX2EsIF9iO1xuXG4gICAgICAoX2EgPSB0aGlzLmNhbmNlbEluUHJvZ3Jlc0FuaW1hdGlvbikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNhbGwodGhpcyk7IC8vIGNvbnZlcnQgcHJvdmlkZWQgdGFyZ2V0IGludG8gRXhjYWxpZHJhd0VsZW1lbnRbXSBpZiBuZWNlc3NhcnlcblxuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudHMgPSBBcnJheS5pc0FycmF5KHRhcmdldCkgPyB0YXJnZXQgOiBbdGFyZ2V0XTtcbiAgICAgIGxldCB6b29tID0gdGhpcy5zdGF0ZS56b29tO1xuICAgICAgbGV0IHNjcm9sbFggPSB0aGlzLnN0YXRlLnNjcm9sbFg7XG4gICAgICBsZXQgc2Nyb2xsWSA9IHRoaXMuc3RhdGUuc2Nyb2xsWTtcblxuICAgICAgaWYgKChvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMuZml0VG9Db250ZW50KSB8fCAob3B0cyA9PT0gbnVsbCB8fCBvcHRzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRzLmZpdFRvVmlld3BvcnQpKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBhcHBTdGF0ZVxuICAgICAgICB9ID0gem9vbVRvRml0KHtcbiAgICAgICAgICB0YXJnZXRFbGVtZW50cyxcbiAgICAgICAgICBhcHBTdGF0ZTogdGhpcy5zdGF0ZSxcbiAgICAgICAgICBmaXRUb1ZpZXdwb3J0OiAhIShvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMuZml0VG9WaWV3cG9ydCksXG4gICAgICAgICAgdmlld3BvcnRab29tRmFjdG9yOiBvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMudmlld3BvcnRab29tRmFjdG9yXG4gICAgICAgIH0pO1xuICAgICAgICB6b29tID0gYXBwU3RhdGUuem9vbTtcbiAgICAgICAgc2Nyb2xsWCA9IGFwcFN0YXRlLnNjcm9sbFg7XG4gICAgICAgIHNjcm9sbFkgPSBhcHBTdGF0ZS5zY3JvbGxZO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gY29tcHV0ZSBvbmx5IHRoZSB2aWV3cG9ydCBsb2NhdGlvbiwgd2l0aG91dCBhbnkgem9vbSBhZGp1c3RtZW50XG4gICAgICAgIGNvbnN0IHNjcm9sbCA9IGNhbGN1bGF0ZVNjcm9sbENlbnRlcih0YXJnZXRFbGVtZW50cywgdGhpcy5zdGF0ZSk7XG4gICAgICAgIHNjcm9sbFggPSBzY3JvbGwuc2Nyb2xsWDtcbiAgICAgICAgc2Nyb2xsWSA9IHNjcm9sbC5zY3JvbGxZO1xuICAgICAgfSAvLyB3aGVuIGFuaW1hdGluZywgd2UgdXNlIFJlcXVlc3RBbmltYXRpb25GcmFtZSB0byBwcmV2ZW50IHRoZSBhbmltYXRpb25cbiAgICAgIC8vIGZyb20gc2xvd2luZyBkb3duIG90aGVyIHByb2Nlc3Nlc1xuXG5cbiAgICAgIGlmIChvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMuYW5pbWF0ZSkge1xuICAgICAgICBjb25zdCBvcmlnU2Nyb2xsWCA9IHRoaXMuc3RhdGUuc2Nyb2xsWDtcbiAgICAgICAgY29uc3Qgb3JpZ1Njcm9sbFkgPSB0aGlzLnN0YXRlLnNjcm9sbFk7XG4gICAgICAgIGNvbnN0IG9yaWdab29tID0gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuICAgICAgICBjb25zdCBjYW5jZWwgPSBlYXNlVG9WYWx1ZXNSQUYoe1xuICAgICAgICAgIGZyb21WYWx1ZXM6IHtcbiAgICAgICAgICAgIHNjcm9sbFg6IG9yaWdTY3JvbGxYLFxuICAgICAgICAgICAgc2Nyb2xsWTogb3JpZ1Njcm9sbFksXG4gICAgICAgICAgICB6b29tOiBvcmlnWm9vbVxuICAgICAgICAgIH0sXG4gICAgICAgICAgdG9WYWx1ZXM6IHtcbiAgICAgICAgICAgIHNjcm9sbFgsXG4gICAgICAgICAgICBzY3JvbGxZLFxuICAgICAgICAgICAgem9vbTogem9vbS52YWx1ZVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW50ZXJwb2xhdGVWYWx1ZTogKGZyb20sIHRvLCBwcm9ncmVzcywga2V5KSA9PiB7XG4gICAgICAgICAgICAvLyBmb3Igem9vbSwgdXNlIGRpZmZlcmVudCBlYXNpbmdcbiAgICAgICAgICAgIGlmIChrZXkgPT09IFwiem9vbVwiKSB7XG4gICAgICAgICAgICAgIHJldHVybiBmcm9tICogTWF0aC5wb3codG8gLyBmcm9tLCBlYXNlT3V0KHByb2dyZXNzKSk7XG4gICAgICAgICAgICB9IC8vIGhhbmRsZSB1c2luZyBkZWZhdWx0XG5cblxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uU3RlcDogKHtcbiAgICAgICAgICAgIHNjcm9sbFgsXG4gICAgICAgICAgICBzY3JvbGxZLFxuICAgICAgICAgICAgem9vbVxuICAgICAgICAgIH0pID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzY3JvbGxYLFxuICAgICAgICAgICAgICBzY3JvbGxZLFxuICAgICAgICAgICAgICB6b29tOiB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IHpvb21cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvblN0YXJ0OiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2hvdWxkQ2FjaGVJZ25vcmVab29tOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uRW5kOiAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2hvdWxkQ2FjaGVJZ25vcmVab29tOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkNhbmNlbDogKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIHNob3VsZENhY2hlSWdub3JlWm9vbTogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZHVyYXRpb246IChfYiA9IG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5kdXJhdGlvbikgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDogNTAwXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuY2FuY2VsSW5Qcm9ncmVzQW5pbWF0aW9uID0gKCkgPT4ge1xuICAgICAgICAgIGNhbmNlbCgpO1xuICAgICAgICAgIHRoaXMuY2FuY2VsSW5Qcm9ncmVzQW5pbWF0aW9uID0gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNjcm9sbFgsXG4gICAgICAgICAgc2Nyb2xsWSxcbiAgICAgICAgICB6b29tXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG4gICAgLyoqIHVzZSB3aGVuIGNoYW5naW5nIHNjcm9sbFgvc2Nyb2xsWS96b29tIGJhc2VkIG9uIHVzZXIgaW50ZXJhY3Rpb24gKi9cblxuXG4gICAgdGhpcy50cmFuc2xhdGVDYW52YXMgPSBzdGF0ZSA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIChfYSA9IHRoaXMuY2FuY2VsSW5Qcm9ncmVzQW5pbWF0aW9uKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY2FsbCh0aGlzKTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoc3RhdGUpO1xuICAgIH07XG5cbiAgICB0aGlzLnNldFRvYXN0ID0gdG9hc3QgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHRvYXN0XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZXN0b3JlRmlsZUZyb21TaGFyZSA9ICgpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHdlYlNoYXJlVGFyZ2V0Q2FjaGUgPSB5aWVsZCBjYWNoZXMub3BlbihcIndlYi1zaGFyZS10YXJnZXRcIik7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0geWllbGQgd2ViU2hhcmVUYXJnZXRDYWNoZS5tYXRjaChcInNoYXJlZC1maWxlXCIpO1xuXG4gICAgICAgIGlmIChyZXNwb25zZSkge1xuICAgICAgICAgIGNvbnN0IGJsb2IgPSB5aWVsZCByZXNwb25zZS5ibG9iKCk7XG4gICAgICAgICAgY29uc3QgZmlsZSA9IG5ldyBGaWxlKFtibG9iXSwgYmxvYi5uYW1lIHx8IFwiXCIsIHtcbiAgICAgICAgICAgIHR5cGU6IGJsb2IudHlwZVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMubG9hZEZpbGVUb0NhbnZhcyhmaWxlLCBudWxsKTtcbiAgICAgICAgICB5aWVsZCB3ZWJTaGFyZVRhcmdldENhY2hlLmRlbGV0ZShcInNoYXJlZC1maWxlXCIpO1xuICAgICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCBBUFBfTkFNRSwgd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnJvci5tZXNzYWdlXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIC8qKiBhZGRzIHN1cHBsaWVkIGZpbGVzIHRvIGV4aXN0aW5nIGZpbGVzIGluIHRoZSBhcHBTdGF0ZSAqL1xuXG5cbiAgICB0aGlzLmFkZEZpbGVzID0gd2l0aEJhdGNoZWRVcGRhdGVzKGZpbGVzID0+IHtcbiAgICAgIGNvbnN0IGZpbGVzTWFwID0gZmlsZXMucmVkdWNlKChhY2MsIGZpbGVEYXRhKSA9PiB7XG4gICAgICAgIGFjYy5zZXQoZmlsZURhdGEuaWQsIGZpbGVEYXRhKTtcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sIG5ldyBNYXAoKSk7XG4gICAgICB0aGlzLmZpbGVzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLmZpbGVzKSwgT2JqZWN0LmZyb21FbnRyaWVzKGZpbGVzTWFwKSk7XG4gICAgICB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgIGlmIChpc0luaXRpYWxpemVkSW1hZ2VFbGVtZW50KGVsZW1lbnQpICYmIGZpbGVzTWFwLmhhcyhlbGVtZW50LmZpbGVJZCkpIHtcbiAgICAgICAgICB0aGlzLmltYWdlQ2FjaGUuZGVsZXRlKGVsZW1lbnQuZmlsZUlkKTtcbiAgICAgICAgICBTaGFwZUNhY2hlLmRlbGV0ZShlbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB0aGlzLnNjZW5lLmluZm9ybU11dGF0aW9uKCk7XG4gICAgICB0aGlzLmFkZE5ld0ltYWdlc1RvSW1hZ2VDYWNoZSgpO1xuICAgIH0pO1xuICAgIHRoaXMudXBkYXRlU2NlbmUgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoc2NlbmVEYXRhID0+IHtcbiAgICAgIGlmIChzY2VuZURhdGEuY29tbWl0VG9IaXN0b3J5KSB7XG4gICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjZW5lRGF0YS5hcHBTdGF0ZSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHNjZW5lRGF0YS5hcHBTdGF0ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY2VuZURhdGEuZWxlbWVudHMpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoc2NlbmVEYXRhLmVsZW1lbnRzKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjZW5lRGF0YS5jb2xsYWJvcmF0b3JzKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGNvbGxhYm9yYXRvcnM6IHNjZW5lRGF0YS5jb2xsYWJvcmF0b3JzXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5vblNjZW5lVXBkYXRlZCA9ICgpID0+IHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe30pO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogQHJldHVybnMgd2hldGhlciB0aGUgbWVudSB3YXMgdG9nZ2xlZCBvbiBvciBvZmZcbiAgICAgKi9cblxuXG4gICAgdGhpcy50b2dnbGVTaWRlYmFyID0gKHtcbiAgICAgIG5hbWUsXG4gICAgICB0YWIsXG4gICAgICBmb3JjZVxuICAgIH0pID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgbGV0IG5leHROYW1lO1xuXG4gICAgICBpZiAoZm9yY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBuZXh0TmFtZSA9ICgoX2EgPSB0aGlzLnN0YXRlLm9wZW5TaWRlYmFyKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EubmFtZSkgPT09IG5hbWUgPyBudWxsIDogbmFtZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5leHROYW1lID0gZm9yY2UgPyBuYW1lIDogbnVsbDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIG9wZW5TaWRlYmFyOiBuZXh0TmFtZSA/IHtcbiAgICAgICAgICBuYW1lOiBuZXh0TmFtZSxcbiAgICAgICAgICB0YWJcbiAgICAgICAgfSA6IG51bGxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICEhbmV4dE5hbWU7XG4gICAgfTtcblxuICAgIHRoaXMudXBkYXRlQ3VycmVudEN1cnNvclBvc2l0aW9uID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueCA9IGV2ZW50LmNsaWVudFg7XG4gICAgICB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLnkgPSBldmVudC5jbGllbnRZO1xuICAgIH0pOyAvLyBJbnB1dCBoYW5kbGluZ1xuXG4gICAgdGhpcy5vbktleURvd24gPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgLy8gbm9ybWFsaXplIGBldmVudC5rZXlgIHdoZW4gQ2Fwc0xvY2sgaXMgcHJlc3NlZCAjMjM3MlxuICAgICAgaWYgKFwiUHJveHlcIiBpbiB3aW5kb3cgJiYgKCFldmVudC5zaGlmdEtleSAmJiAvXltBLVpdJC8udGVzdChldmVudC5rZXkpIHx8IGV2ZW50LnNoaWZ0S2V5ICYmIC9eW2Etel0kLy50ZXN0KGV2ZW50LmtleSkpKSB7XG4gICAgICAgIGV2ZW50ID0gbmV3IFByb3h5KGV2ZW50LCB7XG4gICAgICAgICAgZ2V0KGV2LCBwcm9wKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGV2W3Byb3BdO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgLy8gZml4IGZvciBQcm94aWVzIGhpamFja2luZyBgdGhpc2BcbiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmJpbmQoZXYpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcHJvcCA9PT0gXCJrZXlcIiA/IC8vIENhcHNMb2NrIGludmVydHMgY2FwaXRhbGl6YXRpb24gYmFzZWQgb24gU2hpZnRLZXksIHNvIGludmVydFxuICAgICAgICAgICAgLy8gaXQgYmFja1xuICAgICAgICAgICAgZXZlbnQuc2hpZnRLZXkgPyBldi5rZXkudG9VcHBlckNhc2UoKSA6IGV2LmtleS50b0xvd2VyQ2FzZSgpIDogdmFsdWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgZXZlbnQua2V5LnRvTG93ZXJDYXNlKCkgPT09IEtFWVMuVikge1xuICAgICAgICBJU19QTEFJTl9QQVNURSA9IGV2ZW50LnNoaWZ0S2V5O1xuICAgICAgICBjbGVhclRpbWVvdXQoSVNfUExBSU5fUEFTVEVfVElNRVIpOyAvLyByZXNldCAoMTAwbXMgdG8gYmUgc2FmZSB0aGF0IHdlIGl0IHJ1bnMgYWZ0ZXIgdGhlIGVuc3VpbmdcbiAgICAgICAgLy8gcGFzdGUgZXZlbnQpLiBUaG91Z2gsIHRlY2huaWNhbGx5IHVubmVjZXNzYXJ5IHRvIHJlc2V0IHNpbmNlIHdlXG4gICAgICAgIC8vIChyZSlzZXQgdGhlIGZsYWcgYmVmb3JlIGVhY2ggcGFzdGUgZXZlbnQuXG5cbiAgICAgICAgSVNfUExBSU5fUEFTVEVfVElNRVIgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgSVNfUExBSU5fUEFTVEUgPSBmYWxzZTtcbiAgICAgICAgfSwgMTAwKTtcbiAgICAgIH0gLy8gcHJldmVudCBicm93c2VyIHpvb20gaW4gaW5wdXQgZmllbGRzXG5cblxuICAgICAgaWYgKGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdICYmIGlzV3JpdGFibGVFbGVtZW50KGV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgaWYgKGV2ZW50LmNvZGUgPT09IENPREVTLk1JTlVTIHx8IGV2ZW50LmNvZGUgPT09IENPREVTLkVRVUFMKSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gLy8gYmFpbCBpZlxuXG5cbiAgICAgIGlmICggLy8gaW5zaWRlIGFuIGlucHV0XG4gICAgICBpc1dyaXRhYmxlRWxlbWVudChldmVudC50YXJnZXQpICYmIC8vIHVubGVzcyBwcmVzc2luZyBlc2NhcGUgKGZpbmFsaXplIGFjdGlvbilcbiAgICAgIGV2ZW50LmtleSAhPT0gS0VZUy5FU0NBUEUgfHwgLy8gb3IgdW5sZXNzIHVzaW5nIGFycm93cyAodG8gbW92ZSBiZXR3ZWVuIGJ1dHRvbnMpXG4gICAgICBpc0Fycm93S2V5KGV2ZW50LmtleSkgJiYgaXNJbnB1dExpa2UoZXZlbnQudGFyZ2V0KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuUVVFU1RJT05fTUFSSykge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBvcGVuRGlhbG9nOiBcImhlbHBcIlxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkudG9Mb3dlckNhc2UoKSA9PT0gS0VZUy5FICYmIGV2ZW50LnNoaWZ0S2V5ICYmIGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIG9wZW5EaWFsb2c6IFwiaW1hZ2VFeHBvcnRcIlxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLlBBR0VfVVAgfHwgZXZlbnQua2V5ID09PSBLRVlTLlBBR0VfRE9XTikge1xuICAgICAgICBsZXQgb2Zmc2V0ID0gKGV2ZW50LnNoaWZ0S2V5ID8gdGhpcy5zdGF0ZS53aWR0aCA6IHRoaXMuc3RhdGUuaGVpZ2h0KSAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcblxuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLlBBR0VfRE9XTikge1xuICAgICAgICAgIG9mZnNldCA9IC1vZmZzZXQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcyhzdGF0ZSA9PiAoe1xuICAgICAgICAgICAgc2Nyb2xsWDogc3RhdGUuc2Nyb2xsWCArIG9mZnNldFxuICAgICAgICAgIH0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcyhzdGF0ZSA9PiAoe1xuICAgICAgICAgICAgc2Nyb2xsWTogc3RhdGUuc2Nyb2xsWSArIG9mZnNldFxuICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5hY3Rpb25NYW5hZ2VyLmhhbmRsZUtleURvd24oZXZlbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdICYmIHRoaXMuc3RhdGUuaXNCaW5kaW5nRW5hYmxlZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc0JpbmRpbmdFbmFibGVkOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzQXJyb3dLZXkoZXZlbnQua2V5KSkge1xuICAgICAgICBjb25zdCBzdGVwID0gdGhpcy5zdGF0ZS5ncmlkU2l6ZSAmJiAoZXZlbnQuc2hpZnRLZXkgPyBFTEVNRU5UX1RSQU5TTEFURV9BTU9VTlQgOiB0aGlzLnN0YXRlLmdyaWRTaXplKSB8fCAoZXZlbnQuc2hpZnRLZXkgPyBFTEVNRU5UX1NISUZUX1RSQU5TTEFURV9BTU9VTlQgOiBFTEVNRU5UX1RSQU5TTEFURV9BTU9VTlQpO1xuICAgICAgICBsZXQgb2Zmc2V0WCA9IDA7XG4gICAgICAgIGxldCBvZmZzZXRZID0gMDtcblxuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkFSUk9XX0xFRlQpIHtcbiAgICAgICAgICBvZmZzZXRYID0gLXN0ZXA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkFSUk9XX1JJR0hUKSB7XG4gICAgICAgICAgb2Zmc2V0WCA9IHN0ZXA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkFSUk9XX1VQKSB7XG4gICAgICAgICAgb2Zmc2V0WSA9IC1zdGVwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5BUlJPV19ET1dOKSB7XG4gICAgICAgICAgb2Zmc2V0WSA9IHN0ZXA7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzLFxuICAgICAgICAgIGluY2x1ZGVCb3VuZFRleHRFbGVtZW50OiB0cnVlLFxuICAgICAgICAgIGluY2x1ZGVFbGVtZW50c0luRnJhbWVzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBzZWxlY3RlZEVsZW1lbnRzLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgICB4OiBlbGVtZW50LnggKyBvZmZzZXRYLFxuICAgICAgICAgICAgeTogZWxlbWVudC55ICsgb2Zmc2V0WVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHVwZGF0ZUJvdW5kRWxlbWVudHMoZWxlbWVudCwge1xuICAgICAgICAgICAgc2ltdWx0YW5lb3VzbHlVcGRhdGVkOiBzZWxlY3RlZEVsZW1lbnRzXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdGb3JBbGwoc2VsZWN0ZWRFbGVtZW50cyk7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5FTlRFUikge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmIChzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudCA9IHNlbGVjdGVkRWxlbWVudHNbMF07XG5cbiAgICAgICAgICBpZiAoZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0pIHtcbiAgICAgICAgICAgIGlmIChpc0xpbmVhckVsZW1lbnQoc2VsZWN0ZWRFbGVtZW50KSkge1xuICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgfHwgdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudC5lbGVtZW50SWQgIT09IHNlbGVjdGVkRWxlbWVudHNbMF0uaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpc3RvcnkucmVzdW1lUmVjb3JkaW5nKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICBlZGl0aW5nTGluZWFyRWxlbWVudDogbmV3IExpbmVhckVsZW1lbnRFZGl0b3Ioc2VsZWN0ZWRFbGVtZW50LCB0aGlzLnNjZW5lKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmIChpc1RleHRFbGVtZW50KHNlbGVjdGVkRWxlbWVudCkgfHwgaXNWYWxpZFRleHRDb250YWluZXIoc2VsZWN0ZWRFbGVtZW50KSkge1xuICAgICAgICAgICAgbGV0IGNvbnRhaW5lcjtcblxuICAgICAgICAgICAgaWYgKCFpc1RleHRFbGVtZW50KHNlbGVjdGVkRWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgY29udGFpbmVyID0gc2VsZWN0ZWRFbGVtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBtaWRQb2ludCA9IGdldENvbnRhaW5lckNlbnRlcihzZWxlY3RlZEVsZW1lbnQsIHRoaXMuc3RhdGUpO1xuICAgICAgICAgICAgY29uc3Qgc2NlbmVYID0gbWlkUG9pbnQueDtcbiAgICAgICAgICAgIGNvbnN0IHNjZW5lWSA9IG1pZFBvaW50Lnk7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0VGV4dEVkaXRpbmcoe1xuICAgICAgICAgICAgICBzY2VuZVgsXG4gICAgICAgICAgICAgIHNjZW5lWSxcbiAgICAgICAgICAgICAgY29udGFpbmVyXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSBlbHNlIGlmIChpc0ZyYW1lRWxlbWVudChzZWxlY3RlZEVsZW1lbnQpKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgZWRpdGluZ0ZyYW1lOiBzZWxlY3RlZEVsZW1lbnQuaWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghZXZlbnQuY3RybEtleSAmJiAhZXZlbnQuYWx0S2V5ICYmICFldmVudC5tZXRhS2V5ICYmIHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50ID09PSBudWxsKSB7XG4gICAgICAgIGNvbnN0IHNoYXBlID0gZmluZFNoYXBlQnlLZXkoZXZlbnQua2V5KTtcblxuICAgICAgICBpZiAoc2hhcGUpIHtcbiAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IHNoYXBlKSB7XG4gICAgICAgICAgICB0cmFja0V2ZW50KFwidG9vbGJhclwiLCBzaGFwZSwgYGtleWJvYXJkICgke3RoaXMuZGV2aWNlLmlzTW9iaWxlID8gXCJtb2JpbGVcIiA6IFwiZGVza3RvcFwifSlgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnNldEFjdGl2ZVRvb2woe1xuICAgICAgICAgICAgdHlwZTogc2hhcGVcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09IEtFWVMuUSkge1xuICAgICAgICAgIHRoaXMudG9nZ2xlTG9jayhcImtleWJvYXJkXCIpO1xuICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuU1BBQ0UgJiYgZ2VzdHVyZS5wb2ludGVycy5zaXplID09PSAwKSB7XG4gICAgICAgIGlzSG9sZGluZ1NwYWNlID0gdHJ1ZTtcbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkdSQUIpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoKGV2ZW50LmtleSA9PT0gS0VZUy5HIHx8IGV2ZW50LmtleSA9PT0gS0VZUy5TKSAmJiAhZXZlbnQuYWx0S2V5ICYmICFldmVudFtLRVlTLkNUUkxfT1JfQ01EXSkge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJzZWxlY3Rpb25cIiAmJiAhc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLkcgJiYgKGhhc0JhY2tncm91bmQodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUpIHx8IHNlbGVjdGVkRWxlbWVudHMuc29tZShlbGVtZW50ID0+IGhhc0JhY2tncm91bmQoZWxlbWVudC50eXBlKSkpKSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBvcGVuUG9wdXA6IFwiZWxlbWVudEJhY2tncm91bmRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5TKSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBvcGVuUG9wdXA6IFwiZWxlbWVudFN0cm9rZVwiXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdICYmIChldmVudC5rZXkgPT09IEtFWVMuQkFDS1NQQUNFIHx8IGV2ZW50LmtleSA9PT0gS0VZUy5ERUxFVEUpKSB7XG4gICAgICAgIGpvdGFpU3RvcmUuc2V0KGFjdGl2ZUNvbmZpcm1EaWFsb2dBdG9tLCBcImNsZWFyQ2FudmFzXCIpO1xuICAgICAgfSAvLyBleWUgZHJvcHBlclxuICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG4gICAgICBjb25zdCBsb3dlckNhc2VkID0gZXZlbnQua2V5LnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBpc1BpY2tpbmdTdHJva2UgPSBsb3dlckNhc2VkID09PSBLRVlTLlMgJiYgZXZlbnQuc2hpZnRLZXk7XG4gICAgICBjb25zdCBpc1BpY2tpbmdCYWNrZ3JvdW5kID0gZXZlbnQua2V5ID09PSBLRVlTLkkgfHwgbG93ZXJDYXNlZCA9PT0gS0VZUy5HICYmIGV2ZW50LnNoaWZ0S2V5O1xuXG4gICAgICBpZiAoaXNQaWNraW5nU3Ryb2tlIHx8IGlzUGlja2luZ0JhY2tncm91bmQpIHtcbiAgICAgICAgdGhpcy5vcGVuRXllRHJvcHBlcih7XG4gICAgICAgICAgdHlwZTogaXNQaWNraW5nU3Ryb2tlID8gXCJzdHJva2VcIiA6IFwiYmFja2dyb3VuZFwiXG4gICAgICAgIH0pO1xuICAgICAgfSAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgfSk7XG4gICAgdGhpcy5vbldoZWVsID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIC8vIHByZXZlbnQgYnJvd3NlciBwaW5jaCB6b29tIG9uIERPTSBlbGVtZW50c1xuICAgICAgaWYgKCEoZXZlbnQudGFyZ2V0IGluc3RhbmNlb2YgSFRNTENhbnZhc0VsZW1lbnQpICYmIGV2ZW50LmN0cmxLZXkpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLm9uS2V5VXAgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5TUEFDRSkge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuR1JBQik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRDdXJzb3JGb3JTaGFwZSh0aGlzLmludGVyYWN0aXZlQ2FudmFzLCB0aGlzLnN0YXRlKTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe30sIHRoaXMuc3RhdGUpLFxuICAgICAgICAgICAgc2VsZWN0ZWRHcm91cElkczoge30sXG4gICAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogbnVsbCxcbiAgICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlzSG9sZGluZ1NwYWNlID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICghZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgIXRoaXMuc3RhdGUuaXNCaW5kaW5nRW5hYmxlZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBpc0JpbmRpbmdFbmFibGVkOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNBcnJvd0tleShldmVudC5rZXkpKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG4gICAgICAgIGlzQmluZGluZ0VuYWJsZWQodGhpcy5zdGF0ZSkgPyBiaW5kT3JVbmJpbmRTZWxlY3RlZEVsZW1lbnRzKHNlbGVjdGVkRWxlbWVudHMpIDogdW5iaW5kTGluZWFyRWxlbWVudHMoc2VsZWN0ZWRFbGVtZW50cyk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuc2V0QWN0aXZlVG9vbCA9IHRvb2wgPT4ge1xuICAgICAgY29uc3QgbmV4dEFjdGl2ZVRvb2wgPSB1cGRhdGVBY3RpdmVUb29sKHRoaXMuc3RhdGUsIHRvb2wpO1xuXG4gICAgICBpZiAobmV4dEFjdGl2ZVRvb2wudHlwZSA9PT0gXCJoYW5kXCIpIHtcbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkdSQUIpO1xuICAgICAgfSBlbHNlIGlmICghaXNIb2xkaW5nU3BhY2UpIHtcbiAgICAgICAgc2V0Q3Vyc29yRm9yU2hhcGUodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc1Rvb2xJY29uKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgIHRoaXMuZm9jdXNDb250YWluZXIoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc0xpbmVhckVsZW1lbnRUeXBlKG5leHRBY3RpdmVUb29sLnR5cGUpKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5leHRBY3RpdmVUb29sLnR5cGUgPT09IFwiaW1hZ2VcIikge1xuICAgICAgICB0aGlzLm9uSW1hZ2VBY3Rpb24oKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5leHRBY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgYWN0aXZlVG9vbDogbmV4dEFjdGl2ZVRvb2wsXG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7fSwgdGhpcy5zdGF0ZSksXG4gICAgICAgICAgc2VsZWN0ZWRHcm91cElkczoge30sXG4gICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGwsXG4gICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGFjdGl2ZVRvb2w6IG5leHRBY3RpdmVUb29sLFxuICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuc2V0Q3Vyc29yID0gY3Vyc29yID0+IHtcbiAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBjdXJzb3IpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlc2V0Q3Vyc29yID0gKCkgPT4ge1xuICAgICAgcmVzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiByZXR1cm5zIHdoZXRoZXIgdXNlciBpcyBtYWtpbmcgYSBnZXN0dXJlIHdpdGggPj0gMiBmaW5nZXJzIChwb2ludHMpXG4gICAgICogb24gbyB0b3VjaCBzY3JlZW4gKG5vdCBvbiBhIHRyYWNrcGFkKS4gQ3VycmVudGx5IG9ubHkgcmVsYXRlcyB0byBEYXJ3aW5cbiAgICAgKiAoaU9TL2lQYWRPUyxNYWNPUyksIGJ1dCBtYXkgd29yayBvbiBvdGhlciBkZXZpY2VzIGluIHRoZSBmdXR1cmUgaWZcbiAgICAgKiBHZXN0dXJlRXZlbnQgaXMgc3RhbmRhcmRpemVkLlxuICAgICAqL1xuXG5cbiAgICB0aGlzLmlzVG91Y2hTY3JlZW5NdWx0aVRvdWNoR2VzdHVyZSA9ICgpID0+IHtcbiAgICAgIC8vIHdlIGRvbid0IHdhbnQgdG8gZGVzZWxlY3Qgd2hlbiB1c2luZyB0cmFja3BhZCwgYW5kIG11bHRpLXBvaW50IGdlc3R1cmVzXG4gICAgICAvLyBvbmx5IHdvcmsgb24gdG91Y2ggc2NyZWVucywgc28gY2hlY2tpbmcgZm9yID49IHBvaW50ZXJzIG1lYW5zIHdlJ3JlIG9uIGFcbiAgICAgIC8vIHRvdWNoc2NyZWVuXG4gICAgICByZXR1cm4gZ2VzdHVyZS5wb2ludGVycy5zaXplID49IDI7XG4gICAgfTsgLy8gZmlyZXMgb25seSBvbiBTYWZhcmlcblxuXG4gICAgdGhpcy5vbkdlc3R1cmVTdGFydCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyB3ZSBvbmx5IHdhbnQgdG8gZGVzZWxlY3Qgb24gdG91Y2ggc2NyZWVucyBiZWNhdXNlIHVzZXIgbWF5IGhhdmUgc2VsZWN0ZWRcbiAgICAgIC8vIGVsZW1lbnRzIGJ5IG1pc3Rha2Ugd2hpbGUgem9vbWluZ1xuXG4gICAgICBpZiAodGhpcy5pc1RvdWNoU2NyZWVuTXVsdGlUb3VjaEdlc3R1cmUoKSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBnZXN0dXJlLmluaXRpYWxTY2FsZSA9IHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcbiAgICB9KTsgLy8gZmlyZXMgb25seSBvbiBTYWZhcmlcblxuICAgIHRoaXMub25HZXN0dXJlQ2hhbmdlID0gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIG9uR2VzdHVyZUNoYW5nZSBvbmx5IGhhcyB6b29tIGZhY3RvciBidXQgbm90IHRoZSBjZW50ZXIuXG4gICAgICAvLyBJZiB3ZSdyZSBvbiBpUGFkIG9yIGlQaG9uZSwgdGhlbiB3ZSByZWNvZ25pemUgbXVsdGktdG91Y2ggYW5kIHdpbGxcbiAgICAgIC8vIHpvb20gaW4gYXQgdGhlIHJpZ2h0IGxvY2F0aW9uIGluIHRoZSB0b3VjaG1vdmUgaGFuZGxlclxuICAgICAgLy8gKGhhbmRsZUNhbnZhc1BvaW50ZXJNb3ZlKS5cbiAgICAgIC8vXG4gICAgICAvLyBPbiBNYWNib29rIHRyYWNrcGFkLCB3ZSBkb24ndCBoYXZlIHRob3NlIGV2ZW50cyBzbyB3aWxsIHpvb20gaW4gYXQgdGhlXG4gICAgICAvLyBjdXJyZW50IGxvY2F0aW9uIGluc3RlYWQuXG4gICAgICAvL1xuICAgICAgLy8gQXMgc3VjaCwgYmFpbCBmcm9tIHRoaXMgaGFuZGxlciBvbiB0b3VjaCBkZXZpY2VzLlxuXG4gICAgICBpZiAodGhpcy5pc1RvdWNoU2NyZWVuTXVsdGlUb3VjaEdlc3R1cmUoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGluaXRpYWxTY2FsZSA9IGdlc3R1cmUuaW5pdGlhbFNjYWxlO1xuXG4gICAgICBpZiAoaW5pdGlhbFNjYWxlKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoc3RhdGUgPT4gT2JqZWN0LmFzc2lnbih7fSwgZ2V0U3RhdGVGb3Jab29tKHtcbiAgICAgICAgICB2aWV3cG9ydFg6IHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueCxcbiAgICAgICAgICB2aWV3cG9ydFk6IHRoaXMubGFzdFZpZXdwb3J0UG9zaXRpb24ueSxcbiAgICAgICAgICBuZXh0Wm9vbTogZ2V0Tm9ybWFsaXplZFpvb20oaW5pdGlhbFNjYWxlICogZXZlbnQuc2NhbGUpXG4gICAgICAgIH0sIHN0YXRlKSkpO1xuICAgICAgfVxuICAgIH0pOyAvLyBmaXJlcyBvbmx5IG9uIFNhZmFyaVxuXG4gICAgdGhpcy5vbkdlc3R1cmVFbmQgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoZXZlbnQgPT4ge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gcmVzZWxlY3QgZWxlbWVudHMgb25seSBvbiB0b3VjaCBzY3JlZW5zIChzZWUgb25HZXN0dXJlU3RhcnQpXG5cbiAgICAgIGlmICh0aGlzLmlzVG91Y2hTY3JlZW5NdWx0aVRvdWNoR2VzdHVyZSgpKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHByZXZpb3VzU2VsZWN0ZWRFbGVtZW50SWRzOiB7fSxcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHRoaXMuc3RhdGUucHJldmlvdXNTZWxlY3RlZEVsZW1lbnRJZHMsIHRoaXMuc3RhdGUpXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBnZXN0dXJlLmluaXRpYWxTY2FsZSA9IG51bGw7XG4gICAgfSk7XG5cbiAgICB0aGlzLnN0YXJ0VGV4dEVkaXRpbmcgPSAoe1xuICAgICAgc2NlbmVYLFxuICAgICAgc2NlbmVZLFxuICAgICAgaW5zZXJ0QXRQYXJlbnRDZW50ZXIgPSB0cnVlLFxuICAgICAgY29udGFpbmVyXG4gICAgfSkgPT4ge1xuICAgICAgdmFyIF9hLCBfYjtcblxuICAgICAgbGV0IHNob3VsZEJpbmRUb0NvbnRhaW5lciA9IGZhbHNlO1xuICAgICAgbGV0IHBhcmVudENlbnRlclBvc2l0aW9uID0gaW5zZXJ0QXRQYXJlbnRDZW50ZXIgJiYgdGhpcy5nZXRUZXh0V3lzaXd5Z1NuYXBwZWRUb0NlbnRlclBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZLCB0aGlzLnN0YXRlLCBjb250YWluZXIpO1xuXG4gICAgICBpZiAoY29udGFpbmVyICYmIHBhcmVudENlbnRlclBvc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IGJvdW5kVGV4dEVsZW1lbnRUb0NvbnRhaW5lciA9IGdldEJvdW5kVGV4dEVsZW1lbnQoY29udGFpbmVyKTtcblxuICAgICAgICBpZiAoIWJvdW5kVGV4dEVsZW1lbnRUb0NvbnRhaW5lcikge1xuICAgICAgICAgIHNob3VsZEJpbmRUb0NvbnRhaW5lciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbGV0IGV4aXN0aW5nVGV4dEVsZW1lbnQgPSBudWxsO1xuICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcblxuICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIGlmIChpc1RleHRFbGVtZW50KHNlbGVjdGVkRWxlbWVudHNbMF0pKSB7XG4gICAgICAgICAgZXhpc3RpbmdUZXh0RWxlbWVudCA9IHNlbGVjdGVkRWxlbWVudHNbMF07XG4gICAgICAgIH0gZWxzZSBpZiAoY29udGFpbmVyKSB7XG4gICAgICAgICAgZXhpc3RpbmdUZXh0RWxlbWVudCA9IGdldEJvdW5kVGV4dEVsZW1lbnQoc2VsZWN0ZWRFbGVtZW50c1swXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXhpc3RpbmdUZXh0RWxlbWVudCA9IHRoaXMuZ2V0VGV4dEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmdUZXh0RWxlbWVudCA9IHRoaXMuZ2V0VGV4dEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZm9udEZhbWlseSA9IChleGlzdGluZ1RleHRFbGVtZW50ID09PSBudWxsIHx8IGV4aXN0aW5nVGV4dEVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGV4aXN0aW5nVGV4dEVsZW1lbnQuZm9udEZhbWlseSkgfHwgdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZvbnRGYW1pbHk7XG4gICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gKGV4aXN0aW5nVGV4dEVsZW1lbnQgPT09IG51bGwgfHwgZXhpc3RpbmdUZXh0RWxlbWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogZXhpc3RpbmdUZXh0RWxlbWVudC5saW5lSGVpZ2h0KSB8fCBnZXREZWZhdWx0TGluZUhlaWdodChmb250RmFtaWx5KTtcbiAgICAgIGNvbnN0IGZvbnRTaXplID0gdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZvbnRTaXplO1xuXG4gICAgICBpZiAoIWV4aXN0aW5nVGV4dEVsZW1lbnQgJiYgc2hvdWxkQmluZFRvQ29udGFpbmVyICYmIGNvbnRhaW5lciAmJiAhaXNBcnJvd0VsZW1lbnQoY29udGFpbmVyKSkge1xuICAgICAgICBjb25zdCBmb250U3RyaW5nID0ge1xuICAgICAgICAgIGZvbnRTaXplLFxuICAgICAgICAgIGZvbnRGYW1pbHlcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgbWluV2lkdGggPSBnZXRBcHByb3hNaW5MaW5lV2lkdGgoZ2V0Rm9udFN0cmluZyhmb250U3RyaW5nKSwgbGluZUhlaWdodCk7XG4gICAgICAgIGNvbnN0IG1pbkhlaWdodCA9IGdldEFwcHJveE1pbkxpbmVIZWlnaHQoZm9udFNpemUsIGxpbmVIZWlnaHQpO1xuICAgICAgICBjb25zdCBuZXdIZWlnaHQgPSBNYXRoLm1heChjb250YWluZXIuaGVpZ2h0LCBtaW5IZWlnaHQpO1xuICAgICAgICBjb25zdCBuZXdXaWR0aCA9IE1hdGgubWF4KGNvbnRhaW5lci53aWR0aCwgbWluV2lkdGgpO1xuICAgICAgICBtdXRhdGVFbGVtZW50KGNvbnRhaW5lciwge1xuICAgICAgICAgIGhlaWdodDogbmV3SGVpZ2h0LFxuICAgICAgICAgIHdpZHRoOiBuZXdXaWR0aFxuICAgICAgICB9KTtcbiAgICAgICAgc2NlbmVYID0gY29udGFpbmVyLnggKyBuZXdXaWR0aCAvIDI7XG4gICAgICAgIHNjZW5lWSA9IGNvbnRhaW5lci55ICsgbmV3SGVpZ2h0IC8gMjtcblxuICAgICAgICBpZiAocGFyZW50Q2VudGVyUG9zaXRpb24pIHtcbiAgICAgICAgICBwYXJlbnRDZW50ZXJQb3NpdGlvbiA9IHRoaXMuZ2V0VGV4dFd5c2l3eWdTbmFwcGVkVG9DZW50ZXJQb3NpdGlvbihzY2VuZVgsIHNjZW5lWSwgdGhpcy5zdGF0ZSwgY29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCB0b3BMYXllckZyYW1lID0gdGhpcy5nZXRUb3BMYXllckZyYW1lQXRTY2VuZUNvb3Jkcyh7XG4gICAgICAgIHg6IHNjZW5lWCxcbiAgICAgICAgeTogc2NlbmVZXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBleGlzdGluZ1RleHRFbGVtZW50ID8gZXhpc3RpbmdUZXh0RWxlbWVudCA6IG5ld1RleHRFbGVtZW50KHtcbiAgICAgICAgeDogcGFyZW50Q2VudGVyUG9zaXRpb24gPyBwYXJlbnRDZW50ZXJQb3NpdGlvbi5lbGVtZW50Q2VudGVyWCA6IHNjZW5lWCxcbiAgICAgICAgeTogcGFyZW50Q2VudGVyUG9zaXRpb24gPyBwYXJlbnRDZW50ZXJQb3NpdGlvbi5lbGVtZW50Q2VudGVyWSA6IHNjZW5lWSxcbiAgICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VDb2xvcixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtQmFja2dyb3VuZENvbG9yLFxuICAgICAgICBmaWxsU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1GaWxsU3R5bGUsXG4gICAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlV2lkdGgsXG4gICAgICAgIHN0cm9rZVN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlU3R5bGUsXG4gICAgICAgIHJvdWdobmVzczogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVJvdWdobmVzcyxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICAgIHRleHQ6IFwiXCIsXG4gICAgICAgIGZvbnRTaXplLFxuICAgICAgICBmb250RmFtaWx5LFxuICAgICAgICB0ZXh0QWxpZ246IHBhcmVudENlbnRlclBvc2l0aW9uID8gXCJjZW50ZXJcIiA6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1UZXh0QWxpZ24sXG4gICAgICAgIHZlcnRpY2FsQWxpZ246IHBhcmVudENlbnRlclBvc2l0aW9uID8gVkVSVElDQUxfQUxJR04uTUlERExFIDogREVGQVVMVF9WRVJUSUNBTF9BTElHTixcbiAgICAgICAgY29udGFpbmVySWQ6IHNob3VsZEJpbmRUb0NvbnRhaW5lciA/IGNvbnRhaW5lciA9PT0gbnVsbCB8fCBjb250YWluZXIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGNvbnRhaW5lci5pZCA6IHVuZGVmaW5lZCxcbiAgICAgICAgZ3JvdXBJZHM6IChfYSA9IGNvbnRhaW5lciA9PT0gbnVsbCB8fCBjb250YWluZXIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGNvbnRhaW5lci5ncm91cElkcykgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogW10sXG4gICAgICAgIGxpbmVIZWlnaHQsXG4gICAgICAgIGFuZ2xlOiAoX2IgPSBjb250YWluZXIgPT09IG51bGwgfHwgY29udGFpbmVyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBjb250YWluZXIuYW5nbGUpICE9PSBudWxsICYmIF9iICE9PSB2b2lkIDAgPyBfYiA6IDAsXG4gICAgICAgIGZyYW1lSWQ6IHRvcExheWVyRnJhbWUgPyB0b3BMYXllckZyYW1lLmlkIDogbnVsbFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghZXhpc3RpbmdUZXh0RWxlbWVudCAmJiBzaG91bGRCaW5kVG9Db250YWluZXIgJiYgY29udGFpbmVyKSB7XG4gICAgICAgIG11dGF0ZUVsZW1lbnQoY29udGFpbmVyLCB7XG4gICAgICAgICAgYm91bmRFbGVtZW50czogKGNvbnRhaW5lci5ib3VuZEVsZW1lbnRzIHx8IFtdKS5jb25jYXQoe1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICBpZDogZWxlbWVudC5pZFxuICAgICAgICAgIH0pXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IGVsZW1lbnRcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIWV4aXN0aW5nVGV4dEVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGNvbnRhaW5lciAmJiBzaG91bGRCaW5kVG9Db250YWluZXIpIHtcbiAgICAgICAgICBjb25zdCBjb250YWluZXJJbmRleCA9IHRoaXMuc2NlbmUuZ2V0RWxlbWVudEluZGV4KGNvbnRhaW5lci5pZCk7XG4gICAgICAgICAgdGhpcy5zY2VuZS5pbnNlcnRFbGVtZW50QXRJbmRleChlbGVtZW50LCBjb250YWluZXJJbmRleCArIDEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2NlbmUuYWRkTmV3RWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IGVsZW1lbnRcbiAgICAgIH0pO1xuICAgICAgdGhpcy5oYW5kbGVUZXh0V3lzaXd5ZyhlbGVtZW50LCB7XG4gICAgICAgIGlzRXhpc3RpbmdFbGVtZW50OiAhIWV4aXN0aW5nVGV4dEVsZW1lbnRcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZUNhbnZhc0RvdWJsZUNsaWNrID0gZXZlbnQgPT4ge1xuICAgICAgLy8gY2FzZTogZG91YmxlLWNsaWNraW5nIHdpdGggYXJyb3cvbGluZSB0b29sIHNlbGVjdGVkIHdvdWxkIGJvdGggY3JlYXRlXG4gICAgICAvLyB0ZXh0IGFuZCBlbnRlciBtdWx0aUVsZW1lbnQgbW9kZVxuICAgICAgaWYgKHRoaXMuc3RhdGUubXVsdGlFbGVtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gd2Ugc2hvdWxkIG9ubHkgYmUgYWJsZSB0byBkb3VibGUgY2xpY2sgd2hlbiBtb2RlIGlzIHNlbGVjdGlvblxuXG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG5cbiAgICAgIGlmIChzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA9PT0gMSAmJiBpc0xpbmVhckVsZW1lbnQoc2VsZWN0ZWRFbGVtZW50c1swXSkpIHtcbiAgICAgICAgaWYgKGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdICYmICghdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCB8fCB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZCAhPT0gc2VsZWN0ZWRFbGVtZW50c1swXS5pZCkpIHtcbiAgICAgICAgICB0aGlzLmhpc3RvcnkucmVzdW1lUmVjb3JkaW5nKCk7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBlZGl0aW5nTGluZWFyRWxlbWVudDogbmV3IExpbmVhckVsZW1lbnRFZGl0b3Ioc2VsZWN0ZWRFbGVtZW50c1swXSwgdGhpcy5zY2VuZSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCAmJiB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZCA9PT0gc2VsZWN0ZWRFbGVtZW50c1swXS5pZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcbiAgICAgIGxldCB7XG4gICAgICAgIHg6IHNjZW5lWCxcbiAgICAgICAgeTogc2NlbmVZXG4gICAgICB9ID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKGV2ZW50LCB0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IHNlbGVjdGVkR3JvdXBJZHMgPSBnZXRTZWxlY3RlZEdyb3VwSWRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICBpZiAoc2VsZWN0ZWRHcm91cElkcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZKTtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRHcm91cElkID0gaGl0RWxlbWVudCAmJiBnZXRTZWxlY3RlZEdyb3VwSWRGb3JFbGVtZW50KGhpdEVsZW1lbnQsIHRoaXMuc3RhdGUuc2VsZWN0ZWRHcm91cElkcyk7XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkR3JvdXBJZCkge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlKSwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogc2VsZWN0ZWRHcm91cElkLFxuICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiB7XG4gICAgICAgICAgICAgIFtoaXRFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIHByZXZTdGF0ZSwgdGhpcykpKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyk7XG5cbiAgICAgIGlmICghZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gJiYgIXRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lWCwgc2NlbmVZKTtcblxuICAgICAgICBpZiAoaXNFbWJlZGRhYmxlRWxlbWVudChoaXRFbGVtZW50KSkge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZToge1xuICAgICAgICAgICAgICBlbGVtZW50OiBoaXRFbGVtZW50LFxuICAgICAgICAgICAgICBzdGF0ZTogXCJhY3RpdmVcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGdldFRleHRCaW5kYWJsZUNvbnRhaW5lckF0UG9zaXRpb24odGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgdGhpcy5zdGF0ZSwgc2NlbmVYLCBzY2VuZVkpO1xuXG4gICAgICAgIGlmIChjb250YWluZXIpIHtcbiAgICAgICAgICBpZiAoaGFzQm91bmRUZXh0RWxlbWVudChjb250YWluZXIpIHx8ICFpc1RyYW5zcGFyZW50KGNvbnRhaW5lci5iYWNrZ3JvdW5kQ29sb3IpIHx8IGlzSGl0dGluZ0VsZW1lbnROb3RDb25zaWRlcmluZ0JvdW5kaW5nQm94KGNvbnRhaW5lciwgdGhpcy5zdGF0ZSwgdGhpcy5mcmFtZU5hbWVCb3VuZHNDYWNoZSwgW3NjZW5lWCwgc2NlbmVZXSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG1pZFBvaW50ID0gZ2V0Q29udGFpbmVyQ2VudGVyKGNvbnRhaW5lciwgdGhpcy5zdGF0ZSk7XG4gICAgICAgICAgICBzY2VuZVggPSBtaWRQb2ludC54O1xuICAgICAgICAgICAgc2NlbmVZID0gbWlkUG9pbnQueTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0YXJ0VGV4dEVkaXRpbmcoe1xuICAgICAgICAgIHNjZW5lWCxcbiAgICAgICAgICBzY2VuZVksXG4gICAgICAgICAgaW5zZXJ0QXRQYXJlbnRDZW50ZXI6ICFldmVudC5hbHRLZXksXG4gICAgICAgICAgY29udGFpbmVyXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmdldEVsZW1lbnRMaW5rQXRQb3NpdGlvbiA9IChzY2VuZVBvaW50ZXIsIGhpdEVsZW1lbnQpID0+IHtcbiAgICAgIC8vIFJldmVyc2luZyBzbyB3ZSB0cmF2ZXJzZSB0aGUgZWxlbWVudHMgaW4gZGVjcmVhc2luZyBvcmRlclxuICAgICAgLy8gb2Ygei1pbmRleFxuICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLnNsaWNlKCkucmV2ZXJzZSgpO1xuICAgICAgbGV0IGhpdEVsZW1lbnRJbmRleCA9IEluZmluaXR5O1xuICAgICAgcmV0dXJuIGVsZW1lbnRzLmZpbmQoKGVsZW1lbnQsIGluZGV4KSA9PiB7XG4gICAgICAgIGlmIChoaXRFbGVtZW50ICYmIGVsZW1lbnQuaWQgPT09IGhpdEVsZW1lbnQuaWQpIHtcbiAgICAgICAgICBoaXRFbGVtZW50SW5kZXggPSBpbmRleDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbGVtZW50LmxpbmsgJiYgaW5kZXggPD0gaGl0RWxlbWVudEluZGV4ICYmIGlzUG9pbnRIaXR0aW5nTGluayhlbGVtZW50LCB0aGlzLnN0YXRlLCBbc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55XSwgdGhpcy5kZXZpY2UuaXNNb2JpbGUpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMucmVkaXJlY3RUb0xpbmsgPSAoZXZlbnQsIGlzVG91Y2hTY3JlZW4pID0+IHtcbiAgICAgIGNvbnN0IGRyYWdnZWREaXN0YW5jZSA9IGRpc3RhbmNlMmQodGhpcy5sYXN0UG9pbnRlckRvd24uY2xpZW50WCwgdGhpcy5sYXN0UG9pbnRlckRvd24uY2xpZW50WSwgdGhpcy5sYXN0UG9pbnRlclVwLmNsaWVudFgsIHRoaXMubGFzdFBvaW50ZXJVcC5jbGllbnRZKTtcblxuICAgICAgaWYgKCF0aGlzLmhpdExpbmtFbGVtZW50IHx8IC8vIEZvciB0b3VjaCBzY3JlZW4gYWxsb3cgZHJhZ2dpbmcgdGhyZXNob2xkIGVsc2Ugc3RyaWN0IGNoZWNrXG4gICAgICBpc1RvdWNoU2NyZWVuICYmIGRyYWdnZWREaXN0YW5jZSA+IERSQUdHSU5HX1RIUkVTSE9MRCB8fCAhaXNUb3VjaFNjcmVlbiAmJiBkcmFnZ2VkRGlzdGFuY2UgIT09IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsYXN0UG9pbnRlckRvd25Db29yZHMgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHModGhpcy5sYXN0UG9pbnRlckRvd24sIHRoaXMuc3RhdGUpO1xuICAgICAgY29uc3QgbGFzdFBvaW50ZXJEb3duSGl0dGluZ0xpbmtJY29uID0gaXNQb2ludEhpdHRpbmdMaW5rKHRoaXMuaGl0TGlua0VsZW1lbnQsIHRoaXMuc3RhdGUsIFtsYXN0UG9pbnRlckRvd25Db29yZHMueCwgbGFzdFBvaW50ZXJEb3duQ29vcmRzLnldLCB0aGlzLmRldmljZS5pc01vYmlsZSk7XG4gICAgICBjb25zdCBsYXN0UG9pbnRlclVwQ29vcmRzID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKHRoaXMubGFzdFBvaW50ZXJVcCwgdGhpcy5zdGF0ZSk7XG4gICAgICBjb25zdCBsYXN0UG9pbnRlclVwSGl0dGluZ0xpbmtJY29uID0gaXNQb2ludEhpdHRpbmdMaW5rKHRoaXMuaGl0TGlua0VsZW1lbnQsIHRoaXMuc3RhdGUsIFtsYXN0UG9pbnRlclVwQ29vcmRzLngsIGxhc3RQb2ludGVyVXBDb29yZHMueV0sIHRoaXMuZGV2aWNlLmlzTW9iaWxlKTtcblxuICAgICAgaWYgKGxhc3RQb2ludGVyRG93bkhpdHRpbmdMaW5rSWNvbiAmJiBsYXN0UG9pbnRlclVwSGl0dGluZ0xpbmtJY29uKSB7XG4gICAgICAgIGxldCB1cmwgPSB0aGlzLmhpdExpbmtFbGVtZW50Lmxpbms7XG5cbiAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgIHVybCA9IG5vcm1hbGl6ZUxpbmsodXJsKTtcbiAgICAgICAgICBsZXQgY3VzdG9tRXZlbnQ7XG5cbiAgICAgICAgICBpZiAodGhpcy5wcm9wcy5vbkxpbmtPcGVuKSB7XG4gICAgICAgICAgICBjdXN0b21FdmVudCA9IHdyYXBFdmVudChFVkVOVC5FWENBTElEUkFXX0xJTkssIGV2ZW50Lm5hdGl2ZUV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMucHJvcHMub25MaW5rT3BlbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuaGl0TGlua0VsZW1lbnQpLCB7XG4gICAgICAgICAgICAgIGxpbms6IHVybFxuICAgICAgICAgICAgfSksIGN1c3RvbUV2ZW50KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIShjdXN0b21FdmVudCA9PT0gbnVsbCB8fCBjdXN0b21FdmVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogY3VzdG9tRXZlbnQuZGVmYXVsdFByZXZlbnRlZCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGlzTG9jYWxMaW5rKHVybCkgPyBcIl9zZWxmXCIgOiBcIl9ibGFua1wiO1xuICAgICAgICAgICAgY29uc3QgbmV3V2luZG93ID0gd2luZG93Lm9wZW4odW5kZWZpbmVkLCB0YXJnZXQpOyAvLyBodHRwczovL21hdGhpYXNieW5lbnMuZ2l0aHViLmlvL3JlbC1ub29wZW5lci9cblxuICAgICAgICAgICAgaWYgKG5ld1dpbmRvdykge1xuICAgICAgICAgICAgICBuZXdXaW5kb3cub3BlbmVyID0gbnVsbDtcbiAgICAgICAgICAgICAgbmV3V2luZG93LmxvY2F0aW9uID0gdXJsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmdldFRvcExheWVyRnJhbWVBdFNjZW5lQ29vcmRzID0gc2NlbmVDb29yZHMgPT4ge1xuICAgICAgY29uc3QgZnJhbWVzID0gdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRnJhbWVzKCkuZmlsdGVyKGZyYW1lID0+IGlzQ3Vyc29ySW5GcmFtZShzY2VuZUNvb3JkcywgZnJhbWUpKTtcbiAgICAgIHJldHVybiBmcmFtZXMubGVuZ3RoID8gZnJhbWVzW2ZyYW1lcy5sZW5ndGggLSAxXSA6IG51bGw7XG4gICAgfTtcblxuICAgIHRoaXMuaGFuZGxlQ2FudmFzUG9pbnRlck1vdmUgPSBldmVudCA9PiB7XG4gICAgICB2YXIgX2EsIF9iO1xuXG4gICAgICB0aGlzLnNhdmVQb2ludGVyKGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIHRoaXMuc3RhdGUuY3Vyc29yQnV0dG9uKTtcblxuICAgICAgaWYgKGdlc3R1cmUucG9pbnRlcnMuaGFzKGV2ZW50LnBvaW50ZXJJZCkpIHtcbiAgICAgICAgZ2VzdHVyZS5wb2ludGVycy5zZXQoZXZlbnQucG9pbnRlcklkLCB7XG4gICAgICAgICAgeDogZXZlbnQuY2xpZW50WCxcbiAgICAgICAgICB5OiBldmVudC5jbGllbnRZXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpbml0aWFsU2NhbGUgPSBnZXN0dXJlLmluaXRpYWxTY2FsZTtcblxuICAgICAgaWYgKGdlc3R1cmUucG9pbnRlcnMuc2l6ZSA9PT0gMiAmJiBnZXN0dXJlLmxhc3RDZW50ZXIgJiYgaW5pdGlhbFNjYWxlICYmIGdlc3R1cmUuaW5pdGlhbERpc3RhbmNlKSB7XG4gICAgICAgIGNvbnN0IGNlbnRlciA9IGdldENlbnRlcihnZXN0dXJlLnBvaW50ZXJzKTtcbiAgICAgICAgY29uc3QgZGVsdGFYID0gY2VudGVyLnggLSBnZXN0dXJlLmxhc3RDZW50ZXIueDtcbiAgICAgICAgY29uc3QgZGVsdGFZID0gY2VudGVyLnkgLSBnZXN0dXJlLmxhc3RDZW50ZXIueTtcbiAgICAgICAgZ2VzdHVyZS5sYXN0Q2VudGVyID0gY2VudGVyO1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGdldERpc3RhbmNlKEFycmF5LmZyb20oZ2VzdHVyZS5wb2ludGVycy52YWx1ZXMoKSkpO1xuICAgICAgICBjb25zdCBzY2FsZUZhY3RvciA9IHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImZyZWVkcmF3XCIgJiYgdGhpcy5zdGF0ZS5wZW5Nb2RlID8gMSA6IGRpc3RhbmNlIC8gZ2VzdHVyZS5pbml0aWFsRGlzdGFuY2U7XG4gICAgICAgIGNvbnN0IG5leHRab29tID0gc2NhbGVGYWN0b3IgPyBnZXROb3JtYWxpemVkWm9vbShpbml0aWFsU2NhbGUgKiBzY2FsZUZhY3RvcikgOiB0aGlzLnN0YXRlLnpvb20udmFsdWU7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoc3RhdGUgPT4ge1xuICAgICAgICAgIGNvbnN0IHpvb21TdGF0ZSA9IGdldFN0YXRlRm9yWm9vbSh7XG4gICAgICAgICAgICB2aWV3cG9ydFg6IGNlbnRlci54LFxuICAgICAgICAgICAgdmlld3BvcnRZOiBjZW50ZXIueSxcbiAgICAgICAgICAgIG5leHRab29tXG4gICAgICAgICAgfSwgc3RhdGUpO1xuICAgICAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHtcbiAgICAgICAgICAgIHpvb206IHpvb21TdGF0ZS56b29tLFxuICAgICAgICAgICAgc2Nyb2xsWDogem9vbVN0YXRlLnNjcm9sbFggKyBkZWx0YVggLyBuZXh0Wm9vbSxcbiAgICAgICAgICAgIHNjcm9sbFk6IHpvb21TdGF0ZS5zY3JvbGxZICsgZGVsdGFZIC8gbmV4dFpvb20sXG4gICAgICAgICAgICBzaG91bGRDYWNoZUlnbm9yZVpvb206IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVzZXRTaG91bGRDYWNoZUlnbm9yZVpvb21EZWJvdW5jZWQoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdlc3R1cmUubGFzdENlbnRlciA9IGdlc3R1cmUuaW5pdGlhbERpc3RhbmNlID0gZ2VzdHVyZS5pbml0aWFsU2NhbGUgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNIb2xkaW5nU3BhY2UgfHwgaXNQYW5uaW5nIHx8IGlzRHJhZ2dpbmdTY3JvbGxCYXIgfHwgaXNIYW5kVG9vbEFjdGl2ZSh0aGlzLnN0YXRlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGlzUG9pbnRlck92ZXJTY3JvbGxCYXJzID0gaXNPdmVyU2Nyb2xsQmFycyhjdXJyZW50U2Nyb2xsQmFycywgZXZlbnQuY2xpZW50WCAtIHRoaXMuc3RhdGUub2Zmc2V0TGVmdCwgZXZlbnQuY2xpZW50WSAtIHRoaXMuc3RhdGUub2Zmc2V0VG9wKTtcbiAgICAgIGNvbnN0IGlzT3ZlclNjcm9sbEJhciA9IGlzUG9pbnRlck92ZXJTY3JvbGxCYXJzLmlzT3ZlckVpdGhlcjtcblxuICAgICAgaWYgKCF0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudCAmJiAhdGhpcy5zdGF0ZS5tdWx0aUVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGlzT3ZlclNjcm9sbEJhcikge1xuICAgICAgICAgIHJlc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNldEN1cnNvckZvclNoYXBlKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNjZW5lUG9pbnRlciA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhldmVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHg6IHNjZW5lUG9pbnRlclgsXG4gICAgICAgIHk6IHNjZW5lUG9pbnRlcllcbiAgICAgIH0gPSBzY2VuZVBvaW50ZXI7XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50ICYmICF0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgY29uc3QgZWRpdGluZ0xpbmVhckVsZW1lbnQgPSBMaW5lYXJFbGVtZW50RWRpdG9yLmhhbmRsZVBvaW50ZXJNb3ZlKGV2ZW50LCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZLCB0aGlzLnN0YXRlKTtcblxuICAgICAgICBpZiAoZWRpdGluZ0xpbmVhckVsZW1lbnQgJiYgZWRpdGluZ0xpbmVhckVsZW1lbnQgIT09IHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICAvLyBTaW5jZSB3ZSBhcmUgcmVhZGluZyBmcm9tIHByZXZpb3VzIHN0YXRlIHdoaWNoIGlzIG5vdCBwb3NzaWJsZSB3aXRoXG4gICAgICAgICAgLy8gYXV0b21hdGljIGJhdGNoaW5nIGluIFJlYWN0IDE4IGhlbmNlIHVzaW5nIGZsdXNoIHN5bmMgdG8gc3luY2hyb25vdXNseVxuICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgc3RhdGUuIENoZWNrIGh0dHBzOi8vZ2l0aHViLmNvbS9leGNhbGlkcmF3L2V4Y2FsaWRyYXcvcHVsbC81NTA4IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgICAgZmx1c2hTeW5jKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBlZGl0aW5nTGluZWFyRWxlbWVudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKGVkaXRpbmdMaW5lYXJFbGVtZW50ID09PSBudWxsIHx8IGVkaXRpbmdMaW5lYXJFbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBlZGl0aW5nTGluZWFyRWxlbWVudC5sYXN0VW5jb21taXR0ZWRQb2ludCkgIT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMubWF5YmVTdWdnZXN0QmluZGluZ0F0Q3Vyc29yKHNjZW5lUG9pbnRlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gY2F1c2VzIHN0YWNrIG92ZXJmbG93IGlmIG5vdCBzeW5jXG4gICAgICAgICAgZmx1c2hTeW5jKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0JpbmRpbmdFbGVtZW50VHlwZSh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSkpIHtcbiAgICAgICAgLy8gSG92ZXJpbmcgd2l0aCBhIHNlbGVjdGVkIHRvb2wgb3IgY3JlYXRpbmcgbmV3IGxpbmVhciBlbGVtZW50IHZpYSBjbGlja1xuICAgICAgICAvLyBhbmQgcG9pbnRcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudFxuICAgICAgICB9ID0gdGhpcy5zdGF0ZTtcblxuICAgICAgICBpZiAoaXNCaW5kaW5nRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQsIGZhbHNlKSkge1xuICAgICAgICAgIHRoaXMubWF5YmVTdWdnZXN0QmluZGluZ3NGb3JMaW5lYXJFbGVtZW50QXRDb29yZHMoZHJhZ2dpbmdFbGVtZW50LCBbc2NlbmVQb2ludGVyXSwgdGhpcy5zdGF0ZS5zdGFydEJvdW5kRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nQXRDdXJzb3Ioc2NlbmVQb2ludGVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5tdWx0aUVsZW1lbnQpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIG11bHRpRWxlbWVudFxuICAgICAgICB9ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHg6IHJ4LFxuICAgICAgICAgIHk6IHJ5XG4gICAgICAgIH0gPSBtdWx0aUVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBwb2ludHMsXG4gICAgICAgICAgbGFzdENvbW1pdHRlZFBvaW50XG4gICAgICAgIH0gPSBtdWx0aUVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IGxhc3RQb2ludCA9IHBvaW50c1twb2ludHMubGVuZ3RoIC0gMV07XG4gICAgICAgIHNldEN1cnNvckZvclNoYXBlKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmIChsYXN0UG9pbnQgPT09IGxhc3RDb21taXR0ZWRQb2ludCkge1xuICAgICAgICAgIC8vIGlmIHdlIGhhdmVuJ3QgeWV0IGNyZWF0ZWQgYSB0ZW1wIHBvaW50IGFuZCB3ZSdyZSBiZXlvbmQgY29tbWl0LXpvbmVcbiAgICAgICAgICAvLyB0aHJlc2hvbGQsIGFkZCBhIHBvaW50XG4gICAgICAgICAgaWYgKGRpc3RhbmNlMmQoc2NlbmVQb2ludGVyWCAtIHJ4LCBzY2VuZVBvaW50ZXJZIC0gcnksIGxhc3RQb2ludFswXSwgbGFzdFBvaW50WzFdKSA+PSBMSU5FX0NPTkZJUk1fVEhSRVNIT0xEKSB7XG4gICAgICAgICAgICBtdXRhdGVFbGVtZW50KG11bHRpRWxlbWVudCwge1xuICAgICAgICAgICAgICBwb2ludHM6IFsuLi5wb2ludHMsIFtzY2VuZVBvaW50ZXJYIC0gcngsIHNjZW5lUG9pbnRlclkgLSByeV1dXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLlBPSU5URVIpOyAvLyBpbiB0aGlzIGJyYW5jaCwgd2UncmUgaW5zaWRlIHRoZSBjb21taXQgem9uZSwgYW5kIG5vIHVuY29tbWl0dGVkXG4gICAgICAgICAgICAvLyBwb2ludCBleGlzdHMuIFRodXMgZG8gbm90aGluZyAoZG9uJ3QgYWRkL3JlbW92ZSBwb2ludHMpLlxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChwb2ludHMubGVuZ3RoID4gMiAmJiBsYXN0Q29tbWl0dGVkUG9pbnQgJiYgZGlzdGFuY2UyZChzY2VuZVBvaW50ZXJYIC0gcngsIHNjZW5lUG9pbnRlclkgLSByeSwgbGFzdENvbW1pdHRlZFBvaW50WzBdLCBsYXN0Q29tbWl0dGVkUG9pbnRbMV0pIDwgTElORV9DT05GSVJNX1RIUkVTSE9MRCkge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5QT0lOVEVSKTtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KG11bHRpRWxlbWVudCwge1xuICAgICAgICAgICAgcG9pbnRzOiBwb2ludHMuc2xpY2UoMCwgLTEpXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQoc2NlbmVQb2ludGVyWCwgc2NlbmVQb2ludGVyWSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICAgICAgY29uc3QgW2xhc3RDb21taXR0ZWRYLCBsYXN0Q29tbWl0dGVkWV0gPSAoX2EgPSBtdWx0aUVsZW1lbnQgPT09IG51bGwgfHwgbXVsdGlFbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBtdWx0aUVsZW1lbnQubGFzdENvbW1pdHRlZFBvaW50KSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiBbMCwgMF07XG4gICAgICAgICAgbGV0IGR4RnJvbUxhc3RDb21taXR0ZWQgPSBncmlkWCAtIHJ4IC0gbGFzdENvbW1pdHRlZFg7XG4gICAgICAgICAgbGV0IGR5RnJvbUxhc3RDb21taXR0ZWQgPSBncmlkWSAtIHJ5IC0gbGFzdENvbW1pdHRlZFk7XG5cbiAgICAgICAgICBpZiAoc2hvdWxkUm90YXRlV2l0aERpc2NyZXRlQW5nbGUoZXZlbnQpKSB7XG4gICAgICAgICAgICAoe1xuICAgICAgICAgICAgICB3aWR0aDogZHhGcm9tTGFzdENvbW1pdHRlZCxcbiAgICAgICAgICAgICAgaGVpZ2h0OiBkeUZyb21MYXN0Q29tbWl0dGVkXG4gICAgICAgICAgICB9ID0gZ2V0TG9ja2VkTGluZWFyQ3Vyc29yQWxpZ25TaXplKCAvLyBhY3R1YWwgY29vcmRpbmF0ZSBvZiB0aGUgbGFzdCBjb21taXR0ZWQgcG9pbnRcbiAgICAgICAgICAgIGxhc3RDb21taXR0ZWRYICsgcngsIGxhc3RDb21taXR0ZWRZICsgcnksIC8vIGN1cnNvci1ncmlkIGNvb3JkaW5hdGVcbiAgICAgICAgICAgIGdyaWRYLCBncmlkWSkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChpc1BhdGhBTG9vcChwb2ludHMsIHRoaXMuc3RhdGUuem9vbS52YWx1ZSkpIHtcbiAgICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5QT0lOVEVSKTtcbiAgICAgICAgICB9IC8vIHVwZGF0ZSBsYXN0IHVuY29tbWl0dGVkIHBvaW50XG5cblxuICAgICAgICAgIG11dGF0ZUVsZW1lbnQobXVsdGlFbGVtZW50LCB7XG4gICAgICAgICAgICBwb2ludHM6IFsuLi5wb2ludHMuc2xpY2UoMCwgLTEpLCBbbGFzdENvbW1pdHRlZFggKyBkeEZyb21MYXN0Q29tbWl0dGVkLCBsYXN0Q29tbWl0dGVkWSArIGR5RnJvbUxhc3RDb21taXR0ZWRdXVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBoYXNEZXNlbGVjdGVkQnV0dG9uID0gQm9vbGVhbihldmVudC5idXR0b25zKTtcblxuICAgICAgaWYgKGhhc0Rlc2VsZWN0ZWRCdXR0b24gfHwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIgJiYgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwidGV4dFwiICYmIHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcImVyYXNlclwiKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpO1xuICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcblxuICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxICYmICFpc092ZXJTY3JvbGxCYXIgJiYgIXRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlID0gZ2V0RWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlKGVsZW1lbnRzLCB0aGlzLnN0YXRlLCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZLCB0aGlzLnN0YXRlLnpvb20sIGV2ZW50LnBvaW50ZXJUeXBlKTtcblxuICAgICAgICBpZiAoZWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlICYmIGVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZS50cmFuc2Zvcm1IYW5kbGVUeXBlKSB7XG4gICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIGdldEN1cnNvckZvclJlc2l6aW5nRWxlbWVudChlbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUpKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPiAxICYmICFpc092ZXJTY3JvbGxCYXIpIHtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtSGFuZGxlVHlwZSA9IGdldFRyYW5zZm9ybUhhbmRsZVR5cGVGcm9tQ29vcmRzKGdldENvbW1vbkJvdW5kcyhzZWxlY3RlZEVsZW1lbnRzKSwgc2NlbmVQb2ludGVyWCwgc2NlbmVQb2ludGVyWSwgdGhpcy5zdGF0ZS56b29tLCBldmVudC5wb2ludGVyVHlwZSk7XG5cbiAgICAgICAgaWYgKHRyYW5zZm9ybUhhbmRsZVR5cGUpIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgZ2V0Q3Vyc29yRm9yUmVzaXppbmdFbGVtZW50KHtcbiAgICAgICAgICAgIHRyYW5zZm9ybUhhbmRsZVR5cGVcbiAgICAgICAgICB9KSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lUG9pbnRlci54LCBzY2VuZVBvaW50ZXIueSk7XG4gICAgICB0aGlzLmhpdExpbmtFbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50TGlua0F0UG9zaXRpb24oc2NlbmVQb2ludGVyLCBoaXRFbGVtZW50KTtcblxuICAgICAgaWYgKGlzRXJhc2VyQWN0aXZlKHRoaXMuc3RhdGUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuaGl0TGlua0VsZW1lbnQgJiYgIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW3RoaXMuaGl0TGlua0VsZW1lbnQuaWRdKSB7XG4gICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5QT0lOVEVSKTtcbiAgICAgICAgc2hvd0h5cGVybGlua1Rvb2x0aXAodGhpcy5oaXRMaW5rRWxlbWVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBoaWRlSHlwZXJsaW5rVG9vbGlwKCk7XG5cbiAgICAgICAgaWYgKGhpdEVsZW1lbnQgJiYgKGhpdEVsZW1lbnQubGluayB8fCBpc0VtYmVkZGFibGVFbGVtZW50KGhpdEVsZW1lbnQpKSAmJiB0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1toaXRFbGVtZW50LmlkXSAmJiAhdGhpcy5zdGF0ZS5jb250ZXh0TWVudSAmJiAhdGhpcy5zdGF0ZS5zaG93SHlwZXJsaW5rUG9wdXApIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNob3dIeXBlcmxpbmtQb3B1cDogXCJpbmZvXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJ0ZXh0XCIpIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgaXNUZXh0RWxlbWVudChoaXRFbGVtZW50KSA/IENVUlNPUl9UWVBFLlRFWFQgOiBDVVJTT1JfVFlQRS5DUk9TU0hBSVIpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkdSQUIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzT3ZlclNjcm9sbEJhcikge1xuICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5BVVRPKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgIHRoaXMuaGFuZGxlSG92ZXJTZWxlY3RlZExpbmVhckVsZW1lbnQodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclkpO1xuICAgICAgICB9IGVsc2UgaWYgKCAvLyBpZiB1c2luZyBjbWQvY3RybCwgd2UncmUgbm90IGRyYWdnaW5nXG4gICAgICAgICFldmVudFtLRVlTLkNUUkxfT1JfQ01EXSkge1xuICAgICAgICAgIGlmICgoaGl0RWxlbWVudCB8fCB0aGlzLmlzSGl0dGluZ0NvbW1vbkJvdW5kaW5nQm94T2ZTZWxlY3RlZEVsZW1lbnRzKHNjZW5lUG9pbnRlciwgc2VsZWN0ZWRFbGVtZW50cykpICYmICEoaGl0RWxlbWVudCA9PT0gbnVsbCB8fCBoaXRFbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBoaXRFbGVtZW50LmxvY2tlZCkpIHtcbiAgICAgICAgICAgIGlmIChoaXRFbGVtZW50ICYmIGlzRW1iZWRkYWJsZUVsZW1lbnQoaGl0RWxlbWVudCkgJiYgdGhpcy5pc0VtYmVkZGFibGVDZW50ZXIoaGl0RWxlbWVudCwgZXZlbnQsIHNjZW5lUG9pbnRlclgsIHNjZW5lUG9pbnRlclkpKSB7XG4gICAgICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5QT0lOVEVSKTtcbiAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZToge1xuICAgICAgICAgICAgICAgICAgZWxlbWVudDogaGl0RWxlbWVudCxcbiAgICAgICAgICAgICAgICAgIHN0YXRlOiBcImhvdmVyXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLk1PVkUpO1xuXG4gICAgICAgICAgICAgIGlmICgoKF9iID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iuc3RhdGUpID09PSBcImhvdmVyXCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuQVVUTyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVFcmFzZXIgPSAoZXZlbnQsIHBvaW50ZXJEb3duU3RhdGUsIHNjZW5lUG9pbnRlcikgPT4ge1xuICAgICAgY29uc3QgdXBkYXRlRWxlbWVudElkcyA9IGVsZW1lbnRzID0+IHtcbiAgICAgICAgZWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICBpZiAoZWxlbWVudC5sb2NrZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZHNUb1VwZGF0ZS5wdXNoKGVsZW1lbnQuaWQpO1xuXG4gICAgICAgICAgaWYgKGV2ZW50LmFsdEtleSkge1xuICAgICAgICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlbWVudC5pZF0gJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGVtZW50LmlkXS5lcmFzZSkge1xuICAgICAgICAgICAgICBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZW1lbnQuaWRdLmVyYXNlID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIGlmICghcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGVtZW50LmlkXSkge1xuICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGVtZW50LmlkXSA9IHtcbiAgICAgICAgICAgICAgZXJhc2U6IHRydWUsXG4gICAgICAgICAgICAgIG9wYWNpdHk6IGVsZW1lbnQub3BhY2l0eVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgaWRzVG9VcGRhdGUgPSBbXTtcbiAgICAgIGNvbnN0IGRpc3RhbmNlID0gZGlzdGFuY2UyZChwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueCwgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnksIHNjZW5lUG9pbnRlci54LCBzY2VuZVBvaW50ZXIueSk7XG4gICAgICBjb25zdCB0aHJlc2hvbGQgPSAxMCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcbiAgICAgIGNvbnN0IHBvaW50ID0gT2JqZWN0LmFzc2lnbih7fSwgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzKTtcbiAgICAgIGxldCBzYW1wbGluZ0ludGVydmFsID0gMDtcblxuICAgICAgd2hpbGUgKHNhbXBsaW5nSW50ZXJ2YWwgPD0gZGlzdGFuY2UpIHtcbiAgICAgICAgY29uc3QgaGl0RWxlbWVudHMgPSB0aGlzLmdldEVsZW1lbnRzQXRQb3NpdGlvbihwb2ludC54LCBwb2ludC55KTtcbiAgICAgICAgdXBkYXRlRWxlbWVudElkcyhoaXRFbGVtZW50cyk7IC8vIEV4aXQgc2luY2Ugd2UgcmVhY2hlZCBjdXJyZW50IHBvaW50XG5cbiAgICAgICAgaWYgKHNhbXBsaW5nSW50ZXJ2YWwgPT09IGRpc3RhbmNlKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gLy8gQ2FsY3VsYXRlIG5leHQgcG9pbnQgaW4gdGhlIGxpbmUgYXQgYSBkaXN0YW5jZSBvZiBzYW1wbGluZyBpbnRlcnZhbFxuXG5cbiAgICAgICAgc2FtcGxpbmdJbnRlcnZhbCA9IE1hdGgubWluKHNhbXBsaW5nSW50ZXJ2YWwgKyB0aHJlc2hvbGQsIGRpc3RhbmNlKTtcbiAgICAgICAgY29uc3QgZGlzdGFuY2VSYXRpbyA9IHNhbXBsaW5nSW50ZXJ2YWwgLyBkaXN0YW5jZTtcbiAgICAgICAgY29uc3QgbmV4dFggPSAoMSAtIGRpc3RhbmNlUmF0aW8pICogcG9pbnQueCArIGRpc3RhbmNlUmF0aW8gKiBzY2VuZVBvaW50ZXIueDtcbiAgICAgICAgY29uc3QgbmV4dFkgPSAoMSAtIGRpc3RhbmNlUmF0aW8pICogcG9pbnQueSArIGRpc3RhbmNlUmF0aW8gKiBzY2VuZVBvaW50ZXIueTtcbiAgICAgICAgcG9pbnQueCA9IG5leHRYO1xuICAgICAgICBwb2ludC55ID0gbmV4dFk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5tYXAoZWxlID0+IHtcbiAgICAgICAgY29uc3QgaWQgPSBpc0JvdW5kVG9Db250YWluZXIoZWxlKSAmJiBpZHNUb1VwZGF0ZS5pbmNsdWRlcyhlbGUuY29udGFpbmVySWQpID8gZWxlLmNvbnRhaW5lcklkIDogZWxlLmlkO1xuXG4gICAgICAgIGlmIChpZHNUb1VwZGF0ZS5pbmNsdWRlcyhpZCkpIHtcbiAgICAgICAgICBpZiAoZXZlbnQuYWx0S2V5KSB7XG4gICAgICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtpZF0gJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtpZF0uZXJhc2UgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgIHJldHVybiBuZXdFbGVtZW50V2l0aChlbGUsIHtcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2lkXS5vcGFjaXR5XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICAgIG9wYWNpdHk6IEVMRU1FTlRfUkVBRFlfVE9fRVJBU0VfT1BBQ0lUWVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoZWxlbWVudHMpO1xuICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnggPSBzY2VuZVBvaW50ZXIueDtcbiAgICAgIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy55ID0gc2NlbmVQb2ludGVyLnk7XG4gICAgfTsgLy8gc2V0IHRvdWNoIG1vdmluZyBmb3IgbW9iaWxlIGNvbnRleHQgbWVudVxuXG5cbiAgICB0aGlzLmhhbmRsZVRvdWNoTW92ZSA9IGV2ZW50ID0+IHtcbiAgICAgIGludmFsaWRhdGVDb250ZXh0TWVudSA9IHRydWU7XG4gICAgfTtcblxuICAgIHRoaXMuaGFuZGxlQ2FudmFzUG9pbnRlckRvd24gPSBldmVudCA9PiB7XG4gICAgICB2YXIgX2EsIF9iOyAvLyBzaW5jZSBjb250ZXh0TWVudSBvcHRpb25zIGFyZSBwb3RlbnRpYWxseSBldmFsdWF0ZWQgb24gZWFjaCByZW5kZXIsXG4gICAgICAvLyBhbmQgYW4gY29udGV4dE1lbnUgYWN0aW9uIG1heSBkZXBlbmQgb24gc2VsZWN0aW9uIHN0YXRlLCB3ZSBtdXN0XG4gICAgICAvLyBjbG9zZSB0aGUgY29udGV4dE1lbnUgYmVmb3JlIHdlIHVwZGF0ZSB0aGUgc2VsZWN0aW9uIG9uIHBvaW50ZXJEb3duXG4gICAgICAvLyAoZS5nLiByZXNldHRpbmcgc2VsZWN0aW9uKVxuXG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmNvbnRleHRNZW51KSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGNvbnRleHRNZW51OiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnVwZGF0ZUdlc3R1cmVPblBvaW50ZXJEb3duKGV2ZW50KTsgLy8gaWYgZHJhZ2dpbmcgZWxlbWVudCBpcyBmcmVlZHJhdyBhbmQgYW5vdGhlciBwb2ludGVyZG93biBldmVudCBvY2N1cnNcbiAgICAgIC8vIGEgc2Vjb25kIGZpbmdlciBpcyBvbiB0aGUgc2NyZWVuXG4gICAgICAvLyBkaXNjYXJkIHRoZSBmcmVlZHJhdyBlbGVtZW50IGlmIGl0IGlzIHZlcnkgc2hvcnQgYmVjYXVzZSBpdCBpcyBsaWtlbHlcbiAgICAgIC8vIGp1c3QgYSBzcGlrZSwgb3RoZXJ3aXNlIGZpbmFsaXplIHRoZSBmcmVlZHJhdyBlbGVtZW50IHdoZW4gdGhlIHNlY29uZFxuICAgICAgLy8gZmluZ2VyIGlzIGxpZnRlZFxuXG4gICAgICBpZiAoZXZlbnQucG9pbnRlclR5cGUgPT09IFwidG91Y2hcIiAmJiB0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudCAmJiB0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudC50eXBlID09PSBcImZyZWVkcmF3XCIpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50O1xuICAgICAgICB0aGlzLnVwZGF0ZVNjZW5lKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZWxlbWVudC5wb2ludHMubGVuZ3RoIDwgMTAgPyB7XG4gICAgICAgICAgZWxlbWVudHM6IHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkuZmlsdGVyKGVsID0+IGVsLmlkICE9PSBlbGVtZW50LmlkKVxuICAgICAgICB9IDoge30pLCB7XG4gICAgICAgICAgYXBwU3RhdGU6IHtcbiAgICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgICAgIGVkaXRpbmdFbGVtZW50OiBudWxsLFxuICAgICAgICAgICAgc3RhcnRCb3VuZEVsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW10sXG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKE9iamVjdC5rZXlzKHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKS5maWx0ZXIoa2V5ID0+IGtleSAhPT0gZWxlbWVudC5pZCkucmVkdWNlKChvYmosIGtleSkgPT4ge1xuICAgICAgICAgICAgICBvYmpba2V5XSA9IHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2tleV07XG4gICAgICAgICAgICAgIHJldHVybiBvYmo7XG4gICAgICAgICAgICB9LCB7fSksIHRoaXMuc3RhdGUpXG4gICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gcmVtb3ZlIGFueSBhY3RpdmUgc2VsZWN0aW9uIHdoZW4gd2Ugc3RhcnQgdG8gaW50ZXJhY3Qgd2l0aCBjYW52YXNcbiAgICAgIC8vIChtYWlubHksIHdlIGNhcmUgYWJvdXQgcmVtb3Zpbmcgc2VsZWN0aW9uIG91dHNpZGUgdGhlIGNvbXBvbmVudCB3aGljaFxuICAgICAgLy8gIHdvdWxkIHByZXZlbnQgb3VyIGNvcHkgaGFuZGxpbmcgb3RoZXJ3aXNlKVxuXG5cbiAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IGRvY3VtZW50LmdldFNlbGVjdGlvbigpO1xuXG4gICAgICBpZiAoc2VsZWN0aW9uID09PSBudWxsIHx8IHNlbGVjdGlvbiA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2VsZWN0aW9uLmFuY2hvck5vZGUpIHtcbiAgICAgICAgc2VsZWN0aW9uLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm1heWJlT3BlbkNvbnRleHRNZW51QWZ0ZXJQb2ludGVyRG93bk9uVG91Y2hEZXZpY2VzKGV2ZW50KTtcbiAgICAgIHRoaXMubWF5YmVDbGVhbnVwQWZ0ZXJNaXNzaW5nUG9pbnRlclVwKGV2ZW50KTsgLy9maXJlcyBvbmx5IG9uY2UsIGlmIHBlbiBpcyBkZXRlY3RlZCwgcGVuTW9kZSBpcyBlbmFibGVkXG4gICAgICAvL3RoZSB1c2VyIGNhbiBkaXNhYmxlIHRoaXMgYnkgdG9nZ2xpbmcgdGhlIHBlbk1vZGUgYnV0dG9uXG5cbiAgICAgIGlmICghdGhpcy5zdGF0ZS5wZW5EZXRlY3RlZCAmJiBldmVudC5wb2ludGVyVHlwZSA9PT0gXCJwZW5cIikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHBlbk1vZGU6IHRydWUsXG4gICAgICAgICAgICBwZW5EZXRlY3RlZDogdHJ1ZVxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuZGV2aWNlLmlzVG91Y2hTY3JlZW4gJiYgW1wicGVuXCIsIFwidG91Y2hcIl0uaW5jbHVkZXMoZXZlbnQucG9pbnRlclR5cGUpKSB7XG4gICAgICAgIHRoaXMuZGV2aWNlID0gdXBkYXRlT2JqZWN0KHRoaXMuZGV2aWNlLCB7XG4gICAgICAgICAgaXNUb3VjaFNjcmVlbjogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUGFubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGFzdFBvaW50ZXJEb3duID0gZXZlbnQ7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgbGFzdFBvaW50ZXJEb3duV2l0aDogZXZlbnQucG9pbnRlclR5cGUsXG4gICAgICAgIGN1cnNvckJ1dHRvbjogXCJkb3duXCJcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zYXZlUG9pbnRlcihldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZLCBcImRvd25cIik7XG5cbiAgICAgIGlmICh0aGlzLmhhbmRsZUNhbnZhc1BhblVzaW5nV2hlZWxPclNwYWNlRHJhZyhldmVudCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBvbmx5IGhhbmRsZSBsZWZ0IG1vdXNlIGJ1dHRvbiBvciB0b3VjaFxuXG5cbiAgICAgIGlmIChldmVudC5idXR0b24gIT09IFBPSU5URVJfQlVUVE9OLk1BSU4gJiYgZXZlbnQuYnV0dG9uICE9PSBQT0lOVEVSX0JVVFRPTi5UT1VDSCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9IC8vIGRvbid0IHNlbGVjdCB3aGlsZSBwYW5uaW5nXG5cblxuICAgICAgaWYgKGdlc3R1cmUucG9pbnRlcnMuc2l6ZSA+IDEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSAvLyBTdGF0ZSBmb3IgdGhlIGR1cmF0aW9uIG9mIGEgcG9pbnRlciBpbnRlcmFjdGlvbiwgd2hpY2ggc3RhcnRzIHdpdGggYVxuICAgICAgLy8gcG9pbnRlckRvd24gZXZlbnQsIGVuZHMgd2l0aCBhIHBvaW50ZXJVcCBldmVudCAob3IgYW5vdGhlciBwb2ludGVyRG93bilcblxuXG4gICAgICBjb25zdCBwb2ludGVyRG93blN0YXRlID0gdGhpcy5pbml0aWFsUG9pbnRlckRvd25TdGF0ZShldmVudCk7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc2VsZWN0ZWRFbGVtZW50c0FyZUJlaW5nRHJhZ2dlZDogZmFsc2VcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodGhpcy5oYW5kbGVEcmFnZ2luZ1Njcm9sbEJhcihldmVudCwgcG9pbnRlckRvd25TdGF0ZSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmNsZWFyU2VsZWN0aW9uSWZOb3RVc2luZ1NlbGVjdGlvbigpO1xuICAgICAgdGhpcy51cGRhdGVCaW5kaW5nRW5hYmxlZE9uUG9pbnRlck1vdmUoZXZlbnQpO1xuXG4gICAgICBpZiAodGhpcy5oYW5kbGVTZWxlY3Rpb25PblBvaW50ZXJEb3duKGV2ZW50LCBwb2ludGVyRG93blN0YXRlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFsbG93T25Qb2ludGVyRG93biA9ICF0aGlzLnN0YXRlLnBlbk1vZGUgfHwgZXZlbnQucG9pbnRlclR5cGUgIT09IFwidG91Y2hcIiB8fCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJzZWxlY3Rpb25cIiB8fCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJ0ZXh0XCIgfHwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiaW1hZ2VcIjtcblxuICAgICAgaWYgKCFhbGxvd09uUG9pbnRlckRvd24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwidGV4dFwiKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlVGV4dE9uUG9pbnRlckRvd24oZXZlbnQsIHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImFycm93XCIgfHwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwibGluZVwiKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlTGluZWFyRWxlbWVudE9uUG9pbnRlckRvd24oZXZlbnQsIHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlLCBwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiaW1hZ2VcIikge1xuICAgICAgICAvLyByZXNldCBpbWFnZSBwcmV2aWV3IG9uIHBvaW50ZXJkb3duXG4gICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5DUk9TU0hBSVIpOyAvLyByZXRyaWV2ZSB0aGUgbGF0ZXN0IGVsZW1lbnQgYXMgdGhlIHN0YXRlIG1heSBiZSBzdGFsZVxuXG4gICAgICAgIGNvbnN0IHBlbmRpbmdJbWFnZUVsZW1lbnQgPSB0aGlzLnN0YXRlLnBlbmRpbmdJbWFnZUVsZW1lbnRJZCAmJiB0aGlzLnNjZW5lLmdldEVsZW1lbnQodGhpcy5zdGF0ZS5wZW5kaW5nSW1hZ2VFbGVtZW50SWQpO1xuXG4gICAgICAgIGlmICghcGVuZGluZ0ltYWdlRWxlbWVudCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogcGVuZGluZ0ltYWdlRWxlbWVudCxcbiAgICAgICAgICBlZGl0aW5nRWxlbWVudDogcGVuZGluZ0ltYWdlRWxlbWVudCxcbiAgICAgICAgICBwZW5kaW5nSW1hZ2VFbGVtZW50SWQ6IG51bGwsXG4gICAgICAgICAgbXVsdGlFbGVtZW50OiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5XG4gICAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoZXZlbnQsIHRoaXMuc3RhdGUpO1xuICAgICAgICBtdXRhdGVFbGVtZW50KHBlbmRpbmdJbWFnZUVsZW1lbnQsIHtcbiAgICAgICAgICB4LFxuICAgICAgICAgIHlcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImZyZWVkcmF3XCIpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVGcmVlRHJhd0VsZW1lbnRPblBvaW50ZXJEb3duKGV2ZW50LCB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSwgcG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImN1c3RvbVwiKSB7XG4gICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5BVVRPKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiZnJhbWVcIikge1xuICAgICAgICB0aGlzLmNyZWF0ZUZyYW1lRWxlbWVudE9uUG9pbnRlckRvd24ocG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcImVyYXNlclwiICYmIHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcImhhbmRcIikge1xuICAgICAgICB0aGlzLmNyZWF0ZUdlbmVyaWNFbGVtZW50T25Qb2ludGVyRG93bih0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSwgcG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICB9XG5cbiAgICAgIChfYiA9IChfYSA9IHRoaXMucHJvcHMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5vblBvaW50ZXJEb3duKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuY2FsbChfYSwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLCBwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIGNvbnN0IG9uUG9pbnRlck1vdmUgPSB0aGlzLm9uUG9pbnRlck1vdmVGcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgY29uc3Qgb25Qb2ludGVyVXAgPSB0aGlzLm9uUG9pbnRlclVwRnJvbVBvaW50ZXJEb3duSGFuZGxlcihwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIGNvbnN0IG9uS2V5RG93biA9IHRoaXMub25LZXlEb3duRnJvbVBvaW50ZXJEb3duSGFuZGxlcihwb2ludGVyRG93blN0YXRlKTtcbiAgICAgIGNvbnN0IG9uS2V5VXAgPSB0aGlzLm9uS2V5VXBGcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgbGFzdFBvaW50ZXJVcCA9IG9uUG9pbnRlclVwO1xuXG4gICAgICBpZiAoIXRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfTU9WRSwgb25Qb2ludGVyTW92ZSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIG9uUG9pbnRlclVwKTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZRE9XTiwgb25LZXlEb3duKTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZVVAsIG9uS2V5VXApO1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uTW92ZSA9IG9uUG9pbnRlck1vdmU7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25VcCA9IG9uUG9pbnRlclVwO1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uS2V5VXAgPSBvbktleVVwO1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uS2V5RG93biA9IG9uS2V5RG93bjtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVDYW52YXNQb2ludGVyVXAgPSBldmVudCA9PiB7XG4gICAgICB2YXIgX2EsIF9iO1xuXG4gICAgICB0aGlzLnJlbW92ZVBvaW50ZXIoZXZlbnQpO1xuICAgICAgdGhpcy5sYXN0UG9pbnRlclVwID0gZXZlbnQ7XG4gICAgICBjb25zdCBzY2VuZVBvaW50ZXIgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICBjbGllbnRYOiBldmVudC5jbGllbnRYLFxuICAgICAgICBjbGllbnRZOiBldmVudC5jbGllbnRZXG4gICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgIGNvbnN0IGNsaWNrbGVuZ3RoID0gZXZlbnQudGltZVN0YW1wIC0gKChfYiA9IChfYSA9IHRoaXMubGFzdFBvaW50ZXJEb3duKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudGltZVN0YW1wKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiAwKTtcblxuICAgICAgaWYgKHRoaXMuZGV2aWNlLmlzTW9iaWxlICYmIGNsaWNrbGVuZ3RoIDwgMzAwKSB7XG4gICAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRBdFBvc2l0aW9uKHNjZW5lUG9pbnRlci54LCBzY2VuZVBvaW50ZXIueSk7XG5cbiAgICAgICAgaWYgKGlzRW1iZWRkYWJsZUVsZW1lbnQoaGl0RWxlbWVudCkgJiYgdGhpcy5pc0VtYmVkZGFibGVDZW50ZXIoaGl0RWxlbWVudCwgZXZlbnQsIHNjZW5lUG9pbnRlci54LCBzY2VuZVBvaW50ZXIueSkpIHtcbiAgICAgICAgICB0aGlzLmhhbmRsZUVtYmVkZGFibGVDZW50ZXJDbGljayhoaXRFbGVtZW50KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZGV2aWNlLmlzVG91Y2hTY3JlZW4pIHtcbiAgICAgICAgY29uc3QgaGl0RWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55KTtcbiAgICAgICAgdGhpcy5oaXRMaW5rRWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudExpbmtBdFBvc2l0aW9uKHNjZW5lUG9pbnRlciwgaGl0RWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmhpdExpbmtFbGVtZW50ICYmICF0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1t0aGlzLmhpdExpbmtFbGVtZW50LmlkXSkge1xuICAgICAgICBpZiAoY2xpY2tsZW5ndGggPCAzMDAgJiYgdGhpcy5oaXRMaW5rRWxlbWVudC50eXBlID09PSBcImVtYmVkZGFibGVcIiAmJiAhaXNQb2ludEhpdHRpbmdMaW5rSWNvbih0aGlzLmhpdExpbmtFbGVtZW50LCB0aGlzLnN0YXRlLCBbc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55XSkpIHtcbiAgICAgICAgICB0aGlzLmhhbmRsZUVtYmVkZGFibGVDZW50ZXJDbGljayh0aGlzLmhpdExpbmtFbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnJlZGlyZWN0VG9MaW5rKGV2ZW50LCB0aGlzLmRldmljZS5pc1RvdWNoU2NyZWVuKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsLFxuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczoge31cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMubWF5YmVPcGVuQ29udGV4dE1lbnVBZnRlclBvaW50ZXJEb3duT25Ub3VjaERldmljZXMgPSBldmVudCA9PiB7XG4gICAgICAvLyBkZWFsIHdpdGggb3BlbmluZyBjb250ZXh0IG1lbnUgb24gdG91Y2ggZGV2aWNlc1xuICAgICAgaWYgKGV2ZW50LnBvaW50ZXJUeXBlID09PSBcInRvdWNoXCIpIHtcbiAgICAgICAgaW52YWxpZGF0ZUNvbnRleHRNZW51ID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRvdWNoVGltZW91dCkge1xuICAgICAgICAgIC8vIElmIHRoZXJlJ3MgYWxyZWFkeSBhIHRvdWNoVGltZW91dCwgdGhpcyBtZWFucyB0aGF0IHRoZXJlJ3MgYW5vdGhlclxuICAgICAgICAgIC8vIHRvdWNoIGRvd24gYW5kIHdlIGFyZSBkb2luZyBhbm90aGVyIHRvdWNoLCBzbyB3ZSBzaG91bGRuJ3Qgb3BlbiB0aGVcbiAgICAgICAgICAvLyBjb250ZXh0IG1lbnUuXG4gICAgICAgICAgaW52YWxpZGF0ZUNvbnRleHRNZW51ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBvcGVuIHRoZSBjb250ZXh0IG1lbnUgd2l0aCB0aGUgZmlyc3QgdG91Y2gncyBjbGllbnRYIGFuZCBjbGllbnRZXG4gICAgICAgICAgLy8gaWYgdGhlIHRvdWNoIGlzIG5vdCBtb3ZpbmdcbiAgICAgICAgICB0b3VjaFRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0b3VjaFRpbWVvdXQgPSAwO1xuXG4gICAgICAgICAgICBpZiAoIWludmFsaWRhdGVDb250ZXh0TWVudSkge1xuICAgICAgICAgICAgICB0aGlzLmhhbmRsZUNhbnZhc0NvbnRleHRNZW51KGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LCBUT1VDSF9DVFhfTUVOVV9USU1FT1VUKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLnJlc2V0Q29udGV4dE1lbnVUaW1lciA9ICgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dCh0b3VjaFRpbWVvdXQpO1xuICAgICAgdG91Y2hUaW1lb3V0ID0gMDtcbiAgICAgIGludmFsaWRhdGVDb250ZXh0TWVudSA9IGZhbHNlO1xuICAgIH07IC8vIFJldHVybnMgd2hldGhlciB0aGUgZXZlbnQgaXMgYSBwYW5uaW5nXG5cblxuICAgIHRoaXMuaGFuZGxlQ2FudmFzUGFuVXNpbmdXaGVlbE9yU3BhY2VEcmFnID0gZXZlbnQgPT4ge1xuICAgICAgaWYgKCEoZ2VzdHVyZS5wb2ludGVycy5zaXplIDw9IDEgJiYgKGV2ZW50LmJ1dHRvbiA9PT0gUE9JTlRFUl9CVVRUT04uV0hFRUwgfHwgZXZlbnQuYnV0dG9uID09PSBQT0lOVEVSX0JVVFRPTi5NQUlOICYmIGlzSG9sZGluZ1NwYWNlIHx8IGlzSGFuZFRvb2xBY3RpdmUodGhpcy5zdGF0ZSkgfHwgdGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpKSB8fCBpc1RleHRFbGVtZW50KHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaXNQYW5uaW5nID0gdHJ1ZTtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBsZXQgbmV4dFBhc3RlUHJldmVudGVkID0gZmFsc2U7XG4gICAgICBjb25zdCBpc0xpbnV4ID0gL0xpbnV4Ly50ZXN0KHdpbmRvdy5uYXZpZ2F0b3IucGxhdGZvcm0pO1xuICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkdSQUJCSU5HKTtcbiAgICAgIGxldCB7XG4gICAgICAgIGNsaWVudFg6IGxhc3RYLFxuICAgICAgICBjbGllbnRZOiBsYXN0WVxuICAgICAgfSA9IGV2ZW50O1xuICAgICAgY29uc3Qgb25Qb2ludGVyTW92ZSA9IHdpdGhCYXRjaGVkVXBkYXRlc1Rocm90dGxlZChldmVudCA9PiB7XG4gICAgICAgIGNvbnN0IGRlbHRhWCA9IGxhc3RYIC0gZXZlbnQuY2xpZW50WDtcbiAgICAgICAgY29uc3QgZGVsdGFZID0gbGFzdFkgLSBldmVudC5jbGllbnRZO1xuICAgICAgICBsYXN0WCA9IGV2ZW50LmNsaWVudFg7XG4gICAgICAgIGxhc3RZID0gZXZlbnQuY2xpZW50WTtcbiAgICAgICAgLypcbiAgICAgICAgICogUHJldmVudCBwYXN0ZSBldmVudCBpZiB3ZSBtb3ZlIHdoaWxlIG1pZGRsZSBjbGlja2luZyBvbiBMaW51eC5cbiAgICAgICAgICogU2VlIGlzc3VlICMxMzgzLlxuICAgICAgICAgKi9cblxuICAgICAgICBpZiAoaXNMaW51eCAmJiAhbmV4dFBhc3RlUHJldmVudGVkICYmIChNYXRoLmFicyhkZWx0YVgpID4gMSB8fCBNYXRoLmFicyhkZWx0YVkpID4gMSkpIHtcbiAgICAgICAgICBuZXh0UGFzdGVQcmV2ZW50ZWQgPSB0cnVlO1xuICAgICAgICAgIC8qIFByZXZlbnQgdGhlIG5leHQgcGFzdGUgZXZlbnQgKi9cblxuICAgICAgICAgIGNvbnN0IHByZXZlbnROZXh0UGFzdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUEFTVEUsIHByZXZlbnROZXh0UGFzdGUpO1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICAvKlxuICAgICAgICAgICAqIFJlZW5hYmxlIG5leHQgcGFzdGUgaW4gY2FzZSBvZiBkaXNhYmxlZCBtaWRkbGUgY2xpY2sgcGFzdGUgZm9yXG4gICAgICAgICAgICogYW55IHJlYXNvbjpcbiAgICAgICAgICAgKiAtIHJpZ2h0IGNsaWNrIHBhc3RlXG4gICAgICAgICAgICogLSBlbXB0eSBjbGlwYm9hcmRcbiAgICAgICAgICAgKi9cblxuXG4gICAgICAgICAgY29uc3QgZW5hYmxlTmV4dFBhc3RlID0gKCkgPT4ge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QQVNURSwgcHJldmVudE5leHRQYXN0ZSk7XG4gICAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIGVuYWJsZU5leHRQYXN0ZSk7XG4gICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgIH07XG5cbiAgICAgICAgICBkb2N1bWVudC5ib2R5LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUEFTVEUsIHByZXZlbnROZXh0UGFzdGUpO1xuICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIGVuYWJsZU5leHRQYXN0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcyh7XG4gICAgICAgICAgc2Nyb2xsWDogdGhpcy5zdGF0ZS5zY3JvbGxYIC0gZGVsdGFYIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlLFxuICAgICAgICAgIHNjcm9sbFk6IHRoaXMuc3RhdGUuc2Nyb2xsWSAtIGRlbHRhWSAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdGVhcmRvd24gPSB3aXRoQmF0Y2hlZFVwZGF0ZXMobGFzdFBvaW50ZXJVcCA9ICgpID0+IHtcbiAgICAgICAgbGFzdFBvaW50ZXJVcCA9IG51bGw7XG4gICAgICAgIGlzUGFubmluZyA9IGZhbHNlO1xuXG4gICAgICAgIGlmICghaXNIb2xkaW5nU3BhY2UpIHtcbiAgICAgICAgICBpZiAodGhpcy5zdGF0ZS52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgICAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBDVVJTT1JfVFlQRS5HUkFCKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0Q3Vyc29yRm9yU2hhcGUodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgY3Vyc29yQnV0dG9uOiBcInVwXCJcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc2F2ZVBvaW50ZXIoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgXCJ1cFwiKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9NT1ZFLCBvblBvaW50ZXJNb3ZlKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgdGVhcmRvd24pO1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5CTFVSLCB0ZWFyZG93bik7XG4gICAgICAgIG9uUG9pbnRlck1vdmUuZmx1c2goKTtcbiAgICAgIH0pO1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuQkxVUiwgdGVhcmRvd24pO1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9NT1ZFLCBvblBvaW50ZXJNb3ZlLCB7XG4gICAgICAgIHBhc3NpdmU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgdGVhcmRvd24pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIHRoaXMuY2xlYXJTZWxlY3Rpb25JZk5vdFVzaW5nU2VsZWN0aW9uID0gKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcInNlbGVjdGlvblwiKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe30sIHRoaXMuc3RhdGUpLFxuICAgICAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IHt9LFxuICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBudWxsLFxuICAgICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyB3aGV0aGVyIHRoZSBwb2ludGVyIGV2ZW50IGhhcyBiZWVuIGNvbXBsZXRlbHkgaGFuZGxlZFxuICAgICAqL1xuXG5cbiAgICB0aGlzLmhhbmRsZVNlbGVjdGlvbk9uUG9pbnRlckRvd24gPSAoZXZlbnQsIHBvaW50ZXJEb3duU3RhdGUpID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInNlbGVjdGlvblwiKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKTtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTtcblxuICAgICAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDEgJiYgIXRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICBjb25zdCBlbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUgPSBnZXRFbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUoZWxlbWVudHMsIHRoaXMuc3RhdGUsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnksIHRoaXMuc3RhdGUuem9vbSwgZXZlbnQucG9pbnRlclR5cGUpO1xuXG4gICAgICAgICAgaWYgKGVsZW1lbnRXaXRoVHJhbnNmb3JtSGFuZGxlVHlwZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgcmVzaXppbmdFbGVtZW50OiBlbGVtZW50V2l0aFRyYW5zZm9ybUhhbmRsZVR5cGUuZWxlbWVudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5oYW5kbGVUeXBlID0gZWxlbWVudFdpdGhUcmFuc2Zvcm1IYW5kbGVUeXBlLnRyYW5zZm9ybUhhbmRsZVR5cGU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmhhbmRsZVR5cGUgPSBnZXRUcmFuc2Zvcm1IYW5kbGVUeXBlRnJvbUNvb3JkcyhnZXRDb21tb25Cb3VuZHMoc2VsZWN0ZWRFbGVtZW50cyksIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnksIHRoaXMuc3RhdGUuem9vbSwgZXZlbnQucG9pbnRlclR5cGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmhhbmRsZVR5cGUpIHtcbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5pc1Jlc2l6aW5nID0gdHJ1ZTtcbiAgICAgICAgICBwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5vZmZzZXQgPSB0dXBsZVRvQ29vcnMoZ2V0UmVzaXplT2Zmc2V0WFkocG9pbnRlckRvd25TdGF0ZS5yZXNpemUuaGFuZGxlVHlwZSwgc2VsZWN0ZWRFbGVtZW50cywgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSkpO1xuXG4gICAgICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxICYmIGlzTGluZWFyRWxlbWVudChzZWxlY3RlZEVsZW1lbnRzWzBdKSAmJiBzZWxlY3RlZEVsZW1lbnRzWzBdLnBvaW50cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmFycm93RGlyZWN0aW9uID0gZ2V0UmVzaXplQXJyb3dEaXJlY3Rpb24ocG9pbnRlckRvd25TdGF0ZS5yZXNpemUuaGFuZGxlVHlwZSwgc2VsZWN0ZWRFbGVtZW50c1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgY29uc3QgbGluZWFyRWxlbWVudEVkaXRvciA9IHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgfHwgdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQ7XG4gICAgICAgICAgICBjb25zdCByZXQgPSBMaW5lYXJFbGVtZW50RWRpdG9yLmhhbmRsZVBvaW50ZXJEb3duKGV2ZW50LCB0aGlzLnN0YXRlLCB0aGlzLmhpc3RvcnksIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLCBsaW5lYXJFbGVtZW50RWRpdG9yKTtcblxuICAgICAgICAgICAgaWYgKHJldC5oaXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQgPSByZXQuaGl0RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJldC5saW5lYXJFbGVtZW50RWRpdG9yKSB7XG4gICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogcmV0LmxpbmVhckVsZW1lbnRFZGl0b3JcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgIGVkaXRpbmdMaW5lYXJFbGVtZW50OiByZXQubGluZWFyRWxlbWVudEVkaXRvclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZXQuZGlkQWRkUG9pbnQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyBoaXRFbGVtZW50IG1heSBhbHJlYWR5IGJlIHNldCBhYm92ZSwgc28gY2hlY2sgZmlyc3RcblxuXG4gICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudCA9IChfYSA9IHBvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24ocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSk7XG5cbiAgICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudCkge1xuICAgICAgICAgICAgLy8gRWFybHkgcmV0dXJuIGlmIHBvaW50ZXIgaXMgaGl0dGluZyBsaW5rIGljb25cbiAgICAgICAgICAgIGNvbnN0IGhpdExpbmtFbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50TGlua0F0UG9zaXRpb24oe1xuICAgICAgICAgICAgICB4OiBwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LFxuICAgICAgICAgICAgICB5OiBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55XG4gICAgICAgICAgICB9LCBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50KTtcblxuICAgICAgICAgICAgaWYgKGhpdExpbmtFbGVtZW50KSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IC8vIEZvciBvdmVybGFwcGVkIGVsZW1lbnRzIG9uZSBwb3NpdGlvbiBtYXkgaGl0XG4gICAgICAgICAgLy8gbXVsdGlwbGUgZWxlbWVudHNcblxuXG4gICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5oaXQuYWxsSGl0RWxlbWVudHMgPSB0aGlzLmdldEVsZW1lbnRzQXRQb3NpdGlvbihwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55KTtcbiAgICAgICAgICBjb25zdCBoaXRFbGVtZW50ID0gcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudDtcbiAgICAgICAgICBjb25zdCBzb21lSGl0RWxlbWVudElzU2VsZWN0ZWQgPSBwb2ludGVyRG93blN0YXRlLmhpdC5hbGxIaXRFbGVtZW50cy5zb21lKGVsZW1lbnQgPT4gdGhpcy5pc0FTZWxlY3RlZEVsZW1lbnQoZWxlbWVudCkpO1xuXG4gICAgICAgICAgaWYgKChoaXRFbGVtZW50ID09PSBudWxsIHx8ICFzb21lSGl0RWxlbWVudElzU2VsZWN0ZWQpICYmICFldmVudC5zaGlmdEtleSAmJiAhcG9pbnRlckRvd25TdGF0ZS5oaXQuaGFzSGl0Q29tbW9uQm91bmRpbmdCb3hPZlNlbGVjdGVkRWxlbWVudHMpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJTZWxlY3Rpb24oaGl0RWxlbWVudCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHtcbiAgICAgICAgICAgICAgICBbdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudC5lbGVtZW50SWRdOiB0cnVlXG4gICAgICAgICAgICAgIH0sIHRoaXMuc3RhdGUpXG4gICAgICAgICAgICB9KTsgLy8gSWYgd2UgY2xpY2sgb24gc29tZXRoaW5nXG4gICAgICAgICAgfSBlbHNlIGlmIChoaXRFbGVtZW50ICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIG9uIENNRC9DVFJMLCBkcmlsbCBkb3duIHRvIGhpdCBlbGVtZW50IHJlZ2FyZGxlc3Mgb2YgZ3JvdXBzIGV0Yy5cbiAgICAgICAgICAgIGlmIChldmVudFtLRVlTLkNUUkxfT1JfQ01EXSkge1xuICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5oaXQud2FzQWRkZWRUb1NlbGVjdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGVkaXRHcm91cEZvclNlbGVjdGVkRWxlbWVudChwcmV2U3RhdGUsIGhpdEVsZW1lbnQpKSwge1xuICAgICAgICAgICAgICAgIHByZXZpb3VzU2VsZWN0ZWRFbGVtZW50SWRzOiB0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1xuICAgICAgICAgICAgICB9KSk7IC8vIG1hcmsgYXMgbm90IGNvbXBsZXRlbHkgaGFuZGxlZCBzbyBhcyB0byBhbGxvdyBkcmFnZ2luZyBldGMuXG5cbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSAvLyBkZXNlbGVjdCBpZiBpdGVtIGlzIHNlbGVjdGVkXG4gICAgICAgICAgICAvLyBpZiBzaGlmdCBpcyBub3QgY2xpY2tlZCwgdGhpcyB3aWxsIGFsd2F5cyByZXR1cm4gdHJ1ZVxuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlLCBpdCB3aWxsIHRyaWdnZXIgc2VsZWN0aW9uIGJhc2VkIG9uIGN1cnJlbnRcbiAgICAgICAgICAgIC8vIHN0YXRlIG9mIHRoZSBib3hcblxuXG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdKSB7XG4gICAgICAgICAgICAgIC8vIGlmIHdlIGFyZSBjdXJyZW50bHkgZWRpdGluZyBhIGdyb3VwLCBleGl0aW5nIGVkaXRpbmcgbW9kZSBhbmQgZGVzZWxlY3QgdGhlIGdyb3VwLlxuICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nR3JvdXBJZCAmJiAhaXNFbGVtZW50SW5Hcm91cChoaXRFbGVtZW50LCB0aGlzLnN0YXRlLmVkaXRpbmdHcm91cElkKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7fSwgdGhpcy5zdGF0ZSksXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZEdyb3VwSWRzOiB7fSxcbiAgICAgICAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBudWxsLFxuICAgICAgICAgICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IC8vIEFkZCBoaXQgZWxlbWVudCB0byBzZWxlY3Rpb24uIEF0IHRoaXMgcG9pbnQgaWYgd2UncmUgbm90IGhvbGRpbmdcbiAgICAgICAgICAgICAgLy8gU0hJRlQgdGhlIHByZXZpb3VzbHkgc2VsZWN0ZWQgZWxlbWVudChzKSB3ZXJlIGRlc2VsZWN0ZWQgYWJvdmVcbiAgICAgICAgICAgICAgLy8gKG1ha2Ugc3VyZSB5b3UgdXNlIHNldFN0YXRlIHVwZGF0ZXIgdG8gdXNlIGxhdGVzdCBzdGF0ZSlcbiAgICAgICAgICAgICAgLy8gV2l0aCBzaGlmdC1zZWxlY3Rpb24sIHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoYXQgZnJhbWVzIGFuZCB0aGVpciBjb250YWluaW5nXG4gICAgICAgICAgICAgIC8vIGVsZW1lbnRzIGFyZSBub3Qgc2VsZWN0ZWQgYXQgdGhlIHNhbWUgdGltZS5cblxuXG4gICAgICAgICAgICAgIGlmICghc29tZUhpdEVsZW1lbnRJc1NlbGVjdGVkICYmICFwb2ludGVyRG93blN0YXRlLmhpdC5oYXNIaXRDb21tb25Cb3VuZGluZ0JveE9mU2VsZWN0ZWRFbGVtZW50cykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHRTZWxlY3RlZEVsZW1lbnRJZHMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLCB7XG4gICAgICAgICAgICAgICAgICAgIFtoaXRFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBwcmV2aW91c2x5U2VsZWN0ZWRFbGVtZW50cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMocHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcykuZm9yRWFjaChpZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnQoaWQpO1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50ICYmIHByZXZpb3VzbHlTZWxlY3RlZEVsZW1lbnRzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICB9KTsgLy8gaWYgaGl0RWxlbWVudCBpcyBmcmFtZSwgZGVzZWxlY3QgYWxsIG9mIGl0cyBlbGVtZW50cyBpZiB0aGV5IGFyZSBzZWxlY3RlZFxuXG4gICAgICAgICAgICAgICAgICBpZiAoaGl0RWxlbWVudC50eXBlID09PSBcImZyYW1lXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0RnJhbWVFbGVtZW50cyhwcmV2aW91c2x5U2VsZWN0ZWRFbGVtZW50cywgaGl0RWxlbWVudC5pZCkuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGhpdEVsZW1lbnQuZnJhbWVJZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiBoaXRFbGVtZW50IGlzIGluIGEgZnJhbWUgYW5kIGl0cyBmcmFtZSBoYXMgYmVlbiBzZWxlY3RlZFxuICAgICAgICAgICAgICAgICAgICAvLyBkaXNhYmxlIHNlbGVjdGlvbiBmb3IgdGhlIGdpdmVuIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRTZWxlY3RlZEVsZW1lbnRJZHNbaGl0RWxlbWVudC5mcmFtZUlkXSkge1xuICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBoaXRFbGVtZW50IGlzIG5laXRoZXIgYSBmcmFtZSBub3IgYW4gZWxlbWVudCBpbiBhIGZyYW1lXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBzaW5jZSBoaXRFbGVtZW50IGNvdWxkIGJlIGluIGEgZ3JvdXAgd2l0aCBzb21lIGZyYW1lc1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIG1lYW5zIHNlbGVjdGluZyBoaXRFbGVtZW50IHdpbGwgaGF2ZSB0aGUgZnJhbWVzIHNlbGVjdGVkIGFzIHdlbGxcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVjYXVzZSB3ZSB3YW50IHRvIGtlZXAgdGhlIGludmFyaWFudDpcbiAgICAgICAgICAgICAgICAgICAgLy8gLSBmcmFtZXMgYW5kIHRoZWlyIGVsZW1lbnRzIGFyZSBub3Qgc2VsZWN0ZWQgYXQgdGhlIHNhbWUgdGltZVxuICAgICAgICAgICAgICAgICAgICAvLyB3ZSBkZXNlbGVjdCBlbGVtZW50cyBpbiB0aG9zZSBmcmFtZXMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgc2VsZWN0ZWRcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBJZHMgPSBoaXRFbGVtZW50Lmdyb3VwSWRzO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmcmFtZXNJbkdyb3VwcyA9IG5ldyBTZXQoZ3JvdXBJZHMuZmxhdE1hcChnaWQgPT4gZ2V0RWxlbWVudHNJbkdyb3VwKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIGdpZCkpLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQudHlwZSA9PT0gXCJmcmFtZVwiKS5tYXAoZnJhbWUgPT4gZnJhbWUuaWQpKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZnJhbWVzSW5Hcm91cHMuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c2x5U2VsZWN0ZWRFbGVtZW50cy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuZnJhbWVJZCAmJiBmcmFtZXNJbkdyb3Vwcy5oYXMoZWxlbWVudC5mcmFtZUlkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBkZXNlbGVjdCBlbGVtZW50IGFuZCBncm91cHMgY29udGFpbmluZyB0aGUgZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5ncm91cElkcy5mbGF0TWFwKGdpZCA9PiBnZXRFbGVtZW50c0luR3JvdXAodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZ2lkKSkuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgICAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBwcmV2U3RhdGUuZWRpdGluZ0dyb3VwSWQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbmV4dFNlbGVjdGVkRWxlbWVudElkc1xuICAgICAgICAgICAgICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgcHJldlN0YXRlLCB0aGlzKSksIHtcbiAgICAgICAgICAgICAgICAgICAgc2hvd0h5cGVybGlua1BvcHVwOiBoaXRFbGVtZW50LmxpbmsgfHwgaXNFbWJlZGRhYmxlRWxlbWVudChoaXRFbGVtZW50KSA/IFwiaW5mb1wiIDogZmFsc2VcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGUuaGl0Lndhc0FkZGVkVG9TZWxlY3Rpb24gPSB0cnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBwcmV2aW91c1NlbGVjdGVkRWxlbWVudElkczogdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIHRoaXMuaGFuZGxlVGV4dE9uUG9pbnRlckRvd24gPSAoZXZlbnQsIHBvaW50ZXJEb3duU3RhdGUpID0+IHtcbiAgICAgIC8vIGlmIHdlJ3JlIGN1cnJlbnRseSBzdGlsbCBlZGl0aW5nIHRleHQsIGNsaWNraW5nIG91dHNpZGVcbiAgICAgIC8vIHNob3VsZCBvbmx5IGZpbmFsaXplIGl0LCBub3QgY3JlYXRlIGFub3RoZXIgKGlycmVzcGVjdGl2ZVxuICAgICAgLy8gb2Ygc3RhdGUuYWN0aXZlVG9vbC5sb2NrZWQpXG4gICAgICBpZiAoaXNUZXh0RWxlbWVudCh0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGxldCBzY2VuZVggPSBwb2ludGVyRG93blN0YXRlLm9yaWdpbi54O1xuICAgICAgbGV0IHNjZW5lWSA9IHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnk7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5nZXRFbGVtZW50QXRQb3NpdGlvbihzY2VuZVgsIHNjZW5lWSwge1xuICAgICAgICBpbmNsdWRlQm91bmRUZXh0RWxlbWVudDogdHJ1ZVxuICAgICAgfSk7IC8vIEZJWE1FXG5cbiAgICAgIGxldCBjb250YWluZXIgPSBnZXRUZXh0QmluZGFibGVDb250YWluZXJBdFBvc2l0aW9uKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIHRoaXMuc3RhdGUsIHNjZW5lWCwgc2NlbmVZKTtcblxuICAgICAgaWYgKGhhc0JvdW5kVGV4dEVsZW1lbnQoZWxlbWVudCkpIHtcbiAgICAgICAgY29udGFpbmVyID0gZWxlbWVudDtcbiAgICAgICAgc2NlbmVYID0gZWxlbWVudC54ICsgZWxlbWVudC53aWR0aCAvIDI7XG4gICAgICAgIHNjZW5lWSA9IGVsZW1lbnQueSArIGVsZW1lbnQuaGVpZ2h0IC8gMjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zdGFydFRleHRFZGl0aW5nKHtcbiAgICAgICAgc2NlbmVYLFxuICAgICAgICBzY2VuZVksXG4gICAgICAgIGluc2VydEF0UGFyZW50Q2VudGVyOiAhZXZlbnQuYWx0S2V5LFxuICAgICAgICBjb250YWluZXJcbiAgICAgIH0pO1xuICAgICAgcmVzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyk7XG5cbiAgICAgIGlmICghdGhpcy5zdGF0ZS5hY3RpdmVUb29sLmxvY2tlZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBhY3RpdmVUb29sOiB1cGRhdGVBY3RpdmVUb29sKHRoaXMuc3RhdGUsIHtcbiAgICAgICAgICAgIHR5cGU6IFwic2VsZWN0aW9uXCJcbiAgICAgICAgICB9KVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVGcmVlRHJhd0VsZW1lbnRPblBvaW50ZXJEb3duID0gKGV2ZW50LCBlbGVtZW50VHlwZSwgcG9pbnRlckRvd25TdGF0ZSkgPT4ge1xuICAgICAgLy8gQmVnaW4gYSBtYXJrIGNhcHR1cmUuIFRoaXMgZG9lcyBub3QgaGF2ZSB0byB1cGRhdGUgc3RhdGUgeWV0LlxuICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSwgbnVsbCk7XG4gICAgICBjb25zdCB0b3BMYXllckZyYW1lID0gdGhpcy5nZXRUb3BMYXllckZyYW1lQXRTY2VuZUNvb3Jkcyh7XG4gICAgICAgIHg6IGdyaWRYLFxuICAgICAgICB5OiBncmlkWVxuICAgICAgfSk7XG4gICAgICBjb25zdCBlbGVtZW50ID0gbmV3RnJlZURyYXdFbGVtZW50KHtcbiAgICAgICAgdHlwZTogZWxlbWVudFR5cGUsXG4gICAgICAgIHg6IGdyaWRYLFxuICAgICAgICB5OiBncmlkWSxcbiAgICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VDb2xvcixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtQmFja2dyb3VuZENvbG9yLFxuICAgICAgICBmaWxsU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1GaWxsU3R5bGUsXG4gICAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlV2lkdGgsXG4gICAgICAgIHN0cm9rZVN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlU3R5bGUsXG4gICAgICAgIHJvdWdobmVzczogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVJvdWdobmVzcyxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICAgIHJvdW5kbmVzczogbnVsbCxcbiAgICAgICAgc2ltdWxhdGVQcmVzc3VyZTogZXZlbnQucHJlc3N1cmUgPT09IDAuNSxcbiAgICAgICAgbG9ja2VkOiBmYWxzZSxcbiAgICAgICAgZnJhbWVJZDogdG9wTGF5ZXJGcmFtZSA/IHRvcExheWVyRnJhbWUuaWQgOiBudWxsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+IHtcbiAgICAgICAgY29uc3QgbmV4dFNlbGVjdGVkRWxlbWVudElkcyA9IE9iamVjdC5hc3NpZ24oe30sIHByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpO1xuICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKG5leHRTZWxlY3RlZEVsZW1lbnRJZHMsIHByZXZTdGF0ZSlcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcHJlc3N1cmVzID0gZWxlbWVudC5zaW11bGF0ZVByZXNzdXJlID8gZWxlbWVudC5wcmVzc3VyZXMgOiBbLi4uZWxlbWVudC5wcmVzc3VyZXMsIGV2ZW50LnByZXNzdXJlXTtcbiAgICAgIG11dGF0ZUVsZW1lbnQoZWxlbWVudCwge1xuICAgICAgICBwb2ludHM6IFtbMCwgMF1dLFxuICAgICAgICBwcmVzc3VyZXNcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYm91bmRFbGVtZW50ID0gZ2V0SG92ZXJlZEVsZW1lbnRGb3JCaW5kaW5nKHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLCB0aGlzLnNjZW5lKTtcbiAgICAgIHRoaXMuc2NlbmUuYWRkTmV3RWxlbWVudChlbGVtZW50KTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IGVsZW1lbnQsXG4gICAgICAgIGVkaXRpbmdFbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBzdGFydEJvdW5kRWxlbWVudDogYm91bmRFbGVtZW50LFxuICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW11cbiAgICAgIH0pO1xuICAgIH07IC8vY3JlYXRlIHJlY3RhbmdsZSBlbGVtZW50IHdpdGggeW91dHViZSB0b3AgbGVmdCBvbiBuZWFyZXN0IGdyaWQgcG9pbnQgd2lkdGggLyBoaWdodCA2NDAvMzYwXG5cblxuICAgIHRoaXMuaW5zZXJ0RW1iZWRkYWJsZUVsZW1lbnQgPSAoe1xuICAgICAgc2NlbmVYLFxuICAgICAgc2NlbmVZLFxuICAgICAgbGlua1xuICAgIH0pID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQoc2NlbmVYLCBzY2VuZVksICgoX2EgPSB0aGlzLmxhc3RQb2ludGVyRG93bikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hW0tFWVMuQ1RSTF9PUl9DTURdKSA/IG51bGwgOiB0aGlzLnN0YXRlLmdyaWRTaXplKTtcbiAgICAgIGNvbnN0IGVtYmVkTGluayA9IGdldEVtYmVkTGluayhsaW5rKTtcblxuICAgICAgaWYgKCFlbWJlZExpbmspIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZW1iZWRMaW5rLndhcm5pbmcpIHtcbiAgICAgICAgdGhpcy5zZXRUb2FzdCh7XG4gICAgICAgICAgbWVzc2FnZTogZW1iZWRMaW5rLndhcm5pbmcsXG4gICAgICAgICAgY2xvc2FibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBuZXdFbWJlZGRhYmxlRWxlbWVudCh7XG4gICAgICAgIHR5cGU6IFwiZW1iZWRkYWJsZVwiLFxuICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgeTogZ3JpZFksXG4gICAgICAgIHN0cm9rZUNvbG9yOiBcInRyYW5zcGFyZW50XCIsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogXCJ0cmFuc3BhcmVudFwiLFxuICAgICAgICBmaWxsU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1GaWxsU3R5bGUsXG4gICAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlV2lkdGgsXG4gICAgICAgIHN0cm9rZVN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlU3R5bGUsXG4gICAgICAgIHJvdWdobmVzczogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVJvdWdobmVzcyxcbiAgICAgICAgcm91bmRuZXNzOiB0aGlzLmdldEN1cnJlbnRJdGVtUm91bmRuZXNzKFwiZW1iZWRkYWJsZVwiKSxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICAgIGxvY2tlZDogZmFsc2UsXG4gICAgICAgIHdpZHRoOiBlbWJlZExpbmsuYXNwZWN0UmF0aW8udyxcbiAgICAgICAgaGVpZ2h0OiBlbWJlZExpbmsuYXNwZWN0UmF0aW8uaCxcbiAgICAgICAgbGluayxcbiAgICAgICAgdmFsaWRhdGVkOiBudWxsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKFsuLi50aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCBlbGVtZW50XSk7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9O1xuXG4gICAgdGhpcy5jcmVhdGVJbWFnZUVsZW1lbnQgPSAoe1xuICAgICAgc2NlbmVYLFxuICAgICAgc2NlbmVZXG4gICAgfSkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChzY2VuZVgsIHNjZW5lWSwgKChfYSA9IHRoaXMubGFzdFBvaW50ZXJEb3duKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbS0VZUy5DVFJMX09SX0NNRF0pID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpO1xuICAgICAgY29uc3QgdG9wTGF5ZXJGcmFtZSA9IHRoaXMuZ2V0VG9wTGF5ZXJGcmFtZUF0U2NlbmVDb29yZHMoe1xuICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgeTogZ3JpZFlcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZWxlbWVudCA9IG5ld0ltYWdlRWxlbWVudCh7XG4gICAgICAgIHR5cGU6IFwiaW1hZ2VcIixcbiAgICAgICAgeDogZ3JpZFgsXG4gICAgICAgIHk6IGdyaWRZLFxuICAgICAgICBzdHJva2VDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZUNvbG9yLFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1CYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgIGZpbGxTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZpbGxTdHlsZSxcbiAgICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VXaWR0aCxcbiAgICAgICAgc3Ryb2tlU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VTdHlsZSxcbiAgICAgICAgcm91Z2huZXNzOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91Z2huZXNzLFxuICAgICAgICByb3VuZG5lc3M6IG51bGwsXG4gICAgICAgIG9wYWNpdHk6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1PcGFjaXR5LFxuICAgICAgICBsb2NrZWQ6IGZhbHNlLFxuICAgICAgICBmcmFtZUlkOiB0b3BMYXllckZyYW1lID8gdG9wTGF5ZXJGcmFtZS5pZCA6IG51bGxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfTtcblxuICAgIHRoaXMuaGFuZGxlTGluZWFyRWxlbWVudE9uUG9pbnRlckRvd24gPSAoZXZlbnQsIGVsZW1lbnRUeXBlLCBwb2ludGVyRG93blN0YXRlKSA9PiB7XG4gICAgICBpZiAodGhpcy5zdGF0ZS5tdWx0aUVsZW1lbnQpIHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIG11bHRpRWxlbWVudFxuICAgICAgICB9ID0gdGhpcy5zdGF0ZTsgLy8gZmluYWxpemUgaWYgY29tcGxldGluZyBhIGxvb3BcblxuICAgICAgICBpZiAobXVsdGlFbGVtZW50LnR5cGUgPT09IFwibGluZVwiICYmIGlzUGF0aEFMb29wKG11bHRpRWxlbWVudC5wb2ludHMsIHRoaXMuc3RhdGUuem9vbS52YWx1ZSkpIHtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KG11bHRpRWxlbWVudCwge1xuICAgICAgICAgICAgbGFzdENvbW1pdHRlZFBvaW50OiBtdWx0aUVsZW1lbnQucG9pbnRzW211bHRpRWxlbWVudC5wb2ludHMubGVuZ3RoIC0gMV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHg6IHJ4LFxuICAgICAgICAgIHk6IHJ5LFxuICAgICAgICAgIGxhc3RDb21taXR0ZWRQb2ludFxuICAgICAgICB9ID0gbXVsdGlFbGVtZW50OyAvLyBjbGlja2luZyBpbnNpZGUgY29tbWl0IHpvbmUg4oaSIGZpbmFsaXplIGFycm93XG5cbiAgICAgICAgaWYgKG11bHRpRWxlbWVudC5wb2ludHMubGVuZ3RoID4gMSAmJiBsYXN0Q29tbWl0dGVkUG9pbnQgJiYgZGlzdGFuY2UyZChwb2ludGVyRG93blN0YXRlLm9yaWdpbi54IC0gcngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnkgLSByeSwgbGFzdENvbW1pdHRlZFBvaW50WzBdLCBsYXN0Q29tbWl0dGVkUG9pbnRbMV0pIDwgTElORV9DT05GSVJNX1RIUkVTSE9MRCkge1xuICAgICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiAoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKSwge1xuICAgICAgICAgICAgW211bHRpRWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICB9KSwgcHJldlN0YXRlKVxuICAgICAgICB9KSk7IC8vIGNsaWNraW5nIG91dHNpZGUgY29tbWl0IHpvbmUg4oaSIHVwZGF0ZSByZWZlcmVuY2UgZm9yIGxhc3QgY29tbWl0dGVkXG4gICAgICAgIC8vIHBvaW50XG5cbiAgICAgICAgbXV0YXRlRWxlbWVudChtdWx0aUVsZW1lbnQsIHtcbiAgICAgICAgICBsYXN0Q29tbWl0dGVkUG9pbnQ6IG11bHRpRWxlbWVudC5wb2ludHNbbXVsdGlFbGVtZW50LnBvaW50cy5sZW5ndGggLSAxXVxuICAgICAgICB9KTtcbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLlBPSU5URVIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICAgIGNvbnN0IHRvcExheWVyRnJhbWUgPSB0aGlzLmdldFRvcExheWVyRnJhbWVBdFNjZW5lQ29vcmRzKHtcbiAgICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgICB5OiBncmlkWVxuICAgICAgICB9KTtcbiAgICAgICAgLyogSWYgYXJyb3cgaXMgcHJlLWFycm93aGVhZHMsIGl0IHdpbGwgaGF2ZSB1bmRlZmluZWQgZm9yIGJvdGggc3RhcnQgYW5kIGVuZCBhcnJvd2hlYWRzLlxuICAgICAgICBJZiBzbywgd2Ugd2FudCBpdCB0byBiZSBudWxsIGZvciBzdGFydCBhbmQgXCJhcnJvd1wiIGZvciBlbmQuIElmIHRoZSBsaW5lYXIgaXRlbSBpcyBub3RcbiAgICAgICAgYW4gYXJyb3csIHdlIHdhbnQgaXQgdG8gYmUgbnVsbCBmb3IgYm90aC4gT3RoZXJ3aXNlLCB3ZSB3YW50IGl0IHRvIHVzZSB0aGVcbiAgICAgICAgdmFsdWVzIGZyb20gYXBwU3RhdGUuICovXG5cbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIGN1cnJlbnRJdGVtU3RhcnRBcnJvd2hlYWQsXG4gICAgICAgICAgY3VycmVudEl0ZW1FbmRBcnJvd2hlYWRcbiAgICAgICAgfSA9IHRoaXMuc3RhdGU7XG4gICAgICAgIGNvbnN0IFtzdGFydEFycm93aGVhZCwgZW5kQXJyb3doZWFkXSA9IGVsZW1lbnRUeXBlID09PSBcImFycm93XCIgPyBbY3VycmVudEl0ZW1TdGFydEFycm93aGVhZCwgY3VycmVudEl0ZW1FbmRBcnJvd2hlYWRdIDogW251bGwsIG51bGxdO1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gbmV3TGluZWFyRWxlbWVudCh7XG4gICAgICAgICAgdHlwZTogZWxlbWVudFR5cGUsXG4gICAgICAgICAgeDogZ3JpZFgsXG4gICAgICAgICAgeTogZ3JpZFksXG4gICAgICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VDb2xvcixcbiAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1CYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgICAgZmlsbFN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtRmlsbFN0eWxlLFxuICAgICAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlV2lkdGgsXG4gICAgICAgICAgc3Ryb2tlU3R5bGU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VTdHlsZSxcbiAgICAgICAgICByb3VnaG5lc3M6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Sb3VnaG5lc3MsXG4gICAgICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICAgICAgcm91bmRuZXNzOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91bmRuZXNzID09PSBcInJvdW5kXCIgPyB7XG4gICAgICAgICAgICB0eXBlOiBST1VORE5FU1MuUFJPUE9SVElPTkFMX1JBRElVU1xuICAgICAgICAgIH0gOiBudWxsLFxuICAgICAgICAgIHN0YXJ0QXJyb3doZWFkLFxuICAgICAgICAgIGVuZEFycm93aGVhZCxcbiAgICAgICAgICBsb2NrZWQ6IGZhbHNlLFxuICAgICAgICAgIGZyYW1lSWQ6IHRvcExheWVyRnJhbWUgPyB0b3BMYXllckZyYW1lLmlkIDogbnVsbFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICAgIGNvbnN0IG5leHRTZWxlY3RlZEVsZW1lbnRJZHMgPSBPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKTtcbiAgICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyhuZXh0U2VsZWN0ZWRFbGVtZW50SWRzLCBwcmV2U3RhdGUpXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIG11dGF0ZUVsZW1lbnQoZWxlbWVudCwge1xuICAgICAgICAgIHBvaW50czogWy4uLmVsZW1lbnQucG9pbnRzLCBbMCwgMF1dXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBib3VuZEVsZW1lbnQgPSBnZXRIb3ZlcmVkRWxlbWVudEZvckJpbmRpbmcocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4sIHRoaXMuc2NlbmUpO1xuICAgICAgICB0aGlzLnNjZW5lLmFkZE5ld0VsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogZWxlbWVudCxcbiAgICAgICAgICBlZGl0aW5nRWxlbWVudDogZWxlbWVudCxcbiAgICAgICAgICBzdGFydEJvdW5kRWxlbWVudDogYm91bmRFbGVtZW50LFxuICAgICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzOiBbXVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5jcmVhdGVHZW5lcmljRWxlbWVudE9uUG9pbnRlckRvd24gPSAoZWxlbWVudFR5cGUsIHBvaW50ZXJEb3duU3RhdGUpID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSwgKChfYSA9IHRoaXMubGFzdFBvaW50ZXJEb3duKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbS0VZUy5DVFJMX09SX0NNRF0pID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpO1xuICAgICAgY29uc3QgdG9wTGF5ZXJGcmFtZSA9IHRoaXMuZ2V0VG9wTGF5ZXJGcmFtZUF0U2NlbmVDb29yZHMoe1xuICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgeTogZ3JpZFlcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYmFzZUVsZW1lbnRBdHRyaWJ1dGVzID0ge1xuICAgICAgICB4OiBncmlkWCxcbiAgICAgICAgeTogZ3JpZFksXG4gICAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlQ29sb3IsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUJhY2tncm91bmRDb2xvcixcbiAgICAgICAgZmlsbFN0eWxlOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtRmlsbFN0eWxlLFxuICAgICAgICBzdHJva2VXaWR0aDogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZVdpZHRoLFxuICAgICAgICBzdHJva2VTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZVN0eWxlLFxuICAgICAgICByb3VnaG5lc3M6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Sb3VnaG5lc3MsXG4gICAgICAgIG9wYWNpdHk6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1PcGFjaXR5LFxuICAgICAgICByb3VuZG5lc3M6IHRoaXMuZ2V0Q3VycmVudEl0ZW1Sb3VuZG5lc3MoZWxlbWVudFR5cGUpLFxuICAgICAgICBsb2NrZWQ6IGZhbHNlLFxuICAgICAgICBmcmFtZUlkOiB0b3BMYXllckZyYW1lID8gdG9wTGF5ZXJGcmFtZS5pZCA6IG51bGxcbiAgICAgIH07XG4gICAgICBsZXQgZWxlbWVudDtcblxuICAgICAgaWYgKGVsZW1lbnRUeXBlID09PSBcImVtYmVkZGFibGVcIikge1xuICAgICAgICBlbGVtZW50ID0gbmV3RW1iZWRkYWJsZUVsZW1lbnQoT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgdHlwZTogXCJlbWJlZGRhYmxlXCIsXG4gICAgICAgICAgdmFsaWRhdGVkOiBudWxsXG4gICAgICAgIH0sIGJhc2VFbGVtZW50QXR0cmlidXRlcykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudCA9IG5ld0VsZW1lbnQoT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgdHlwZTogZWxlbWVudFR5cGVcbiAgICAgICAgfSwgYmFzZUVsZW1lbnRBdHRyaWJ1dGVzKSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChlbGVtZW50LnR5cGUgPT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc2VsZWN0aW9uRWxlbWVudDogZWxlbWVudCxcbiAgICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IGVsZW1lbnRcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnNjZW5lLmFkZE5ld0VsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIG11bHRpRWxlbWVudDogbnVsbCxcbiAgICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IGVsZW1lbnQsXG4gICAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IGVsZW1lbnRcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuY3JlYXRlRnJhbWVFbGVtZW50T25Qb2ludGVyRG93biA9IHBvaW50ZXJEb3duU3RhdGUgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBbZ3JpZFgsIGdyaWRZXSA9IGdldEdyaWRQb2ludChwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyRG93blN0YXRlLm9yaWdpbi55LCAoKF9hID0gdGhpcy5sYXN0UG9pbnRlckRvd24pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYVtLRVlTLkNUUkxfT1JfQ01EXSkgPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICBjb25zdCBmcmFtZSA9IG5ld0ZyYW1lRWxlbWVudChPYmplY3QuYXNzaWduKHtcbiAgICAgICAgeDogZ3JpZFgsXG4gICAgICAgIHk6IGdyaWRZLFxuICAgICAgICBvcGFjaXR5OiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtT3BhY2l0eSxcbiAgICAgICAgbG9ja2VkOiBmYWxzZVxuICAgICAgfSwgRlJBTUVfU1RZTEUpKTtcbiAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKFsuLi50aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCBmcmFtZV0pO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIG11bHRpRWxlbWVudDogbnVsbCxcbiAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBmcmFtZSxcbiAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IGZyYW1lXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5yZXN0b3JlUmVhZHlUb0VyYXNlRWxlbWVudHMgPSBwb2ludGVyRG93blN0YXRlID0+IHtcbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5tYXAoZWxlID0+IHtcbiAgICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmlkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5pZF0uZXJhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICBvcGFjaXR5OiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5pZF0ub3BhY2l0eVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQm91bmRUb0NvbnRhaW5lcihlbGUpICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmNvbnRhaW5lcklkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5jb250YWluZXJJZF0uZXJhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICBvcGFjaXR5OiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5jb250YWluZXJJZF0ub3BhY2l0eVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGVsZS5mcmFtZUlkICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmZyYW1lSWRdICYmIHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmZyYW1lSWRdLmVyYXNlKSB7XG4gICAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnRXaXRoKGVsZSwge1xuICAgICAgICAgICAgb3BhY2l0eTogcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuZnJhbWVJZF0ub3BhY2l0eVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoZWxlbWVudHMpO1xuICAgIH07XG5cbiAgICB0aGlzLmVyYXNlRWxlbWVudHMgPSBwb2ludGVyRG93blN0YXRlID0+IHtcbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5tYXAoZWxlID0+IHtcbiAgICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZWxlbWVudElkc1RvRXJhc2VbZWxlLmlkXSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5pZF0uZXJhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICBpc0RlbGV0ZWQ6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0JvdW5kVG9Db250YWluZXIoZWxlKSAmJiBwb2ludGVyRG93blN0YXRlLmVsZW1lbnRJZHNUb0VyYXNlW2VsZS5jb250YWluZXJJZF0gJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuY29udGFpbmVySWRdLmVyYXNlKSB7XG4gICAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnRXaXRoKGVsZSwge1xuICAgICAgICAgICAgaXNEZWxldGVkOiB0cnVlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZWxlLmZyYW1lSWQgJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuZnJhbWVJZF0gJiYgcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtlbGUuZnJhbWVJZF0uZXJhc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3RWxlbWVudFdpdGgoZWxlLCB7XG4gICAgICAgICAgICBpc0RlbGV0ZWQ6IHRydWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbGU7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKGVsZW1lbnRzKTtcbiAgICB9O1xuXG4gICAgdGhpcy5pbml0aWFsaXplSW1hZ2UgPSAoe1xuICAgICAgaW1hZ2VGaWxlLFxuICAgICAgaW1hZ2VFbGVtZW50OiBfaW1hZ2VFbGVtZW50LFxuICAgICAgc2hvd0N1cnNvckltYWdlUHJldmlldyA9IGZhbHNlXG4gICAgfSkgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgdmFyIF9mLCBfZywgX2gsIF9qOyAvLyBhdCB0aGlzIHBvaW50IHRoaXMgc2hvdWxkIGJlIGd1YXJhbnRlZWQgaW1hZ2UgZmlsZSwgYnV0IHdlIGRvIHRoaXMgY2hlY2tcbiAgICAgIC8vIHRvIHNhdGlzZnkgVFMgZG93biB0aGUgbGluZVxuXG5cbiAgICAgIGlmICghaXNTdXBwb3J0ZWRJbWFnZUZpbGUoaW1hZ2VGaWxlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IodChcImVycm9ycy51bnN1cHBvcnRlZEZpbGVUeXBlXCIpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWltZVR5cGUgPSBpbWFnZUZpbGUudHlwZTtcbiAgICAgIHNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzLCBcIndhaXRcIik7XG5cbiAgICAgIGlmIChtaW1lVHlwZSA9PT0gTUlNRV9UWVBFUy5zdmcpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpbWFnZUZpbGUgPSBTVkdTdHJpbmdUb0ZpbGUoeWllbGQgbm9ybWFsaXplU1ZHKHlpZWxkIGltYWdlRmlsZS50ZXh0KCkpLCBpbWFnZUZpbGUubmFtZSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKGVycm9yKTtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodChcImVycm9ycy5zdmdJbWFnZUluc2VydEVycm9yXCIpKTtcbiAgICAgICAgfVxuICAgICAgfSAvLyBnZW5lcmF0ZSBpbWFnZSBpZCAoYnkgZGVmYXVsdCB0aGUgZmlsZSBkaWdlc3QpIGJlZm9yZSBhbnlcbiAgICAgIC8vIHJlc2l6aW5nL2NvbXByZXNzaW9uIHRha2VzIHBsYWNlIHRvIGtlZXAgaXQgbW9yZSBwb3J0YWJsZVxuXG5cbiAgICAgIGNvbnN0IGZpbGVJZCA9IHlpZWxkICgoX2cgPSAoX2YgPSB0aGlzLnByb3BzKS5nZW5lcmF0ZUlkRm9yRmlsZSkgPT09IG51bGwgfHwgX2cgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9nLmNhbGwoX2YsIGltYWdlRmlsZSkpIHx8IGdlbmVyYXRlSWRGcm9tRmlsZShpbWFnZUZpbGUpO1xuXG4gICAgICBpZiAoIWZpbGVJZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oXCJDb3VsZG4ndCBnZW5lcmF0ZSBmaWxlIGlkIG9yIHRoZSBzdXBwbGllZCBgZ2VuZXJhdGVJZEZvckZpbGVgIGRpZG4ndCByZXNvbHZlIHRvIG9uZS5cIik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih0KFwiZXJyb3JzLmltYWdlSW5zZXJ0RXJyb3JcIikpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleGlzdGluZ0ZpbGVEYXRhID0gdGhpcy5maWxlc1tmaWxlSWRdO1xuXG4gICAgICBpZiAoIShleGlzdGluZ0ZpbGVEYXRhID09PSBudWxsIHx8IGV4aXN0aW5nRmlsZURhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGV4aXN0aW5nRmlsZURhdGEuZGF0YVVSTCkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpbWFnZUZpbGUgPSB5aWVsZCByZXNpemVJbWFnZUZpbGUoaW1hZ2VGaWxlLCB7XG4gICAgICAgICAgICBtYXhXaWR0aE9ySGVpZ2h0OiBERUZBVUxUX01BWF9JTUFHRV9XSURUSF9PUl9IRUlHSFRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiZXJyb3IgdHJ5aW5nIHRvIHJlc2luZyBpbWFnZSBmaWxlIG9uIGluc2VydGlvblwiLCBlcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaW1hZ2VGaWxlLnNpemUgPiBNQVhfQUxMT1dFRF9GSUxFX0JZVEVTKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHQoXCJlcnJvcnMuZmlsZVRvb0JpZ1wiLCB7XG4gICAgICAgICAgICBtYXhTaXplOiBgJHtNYXRoLnRydW5jKE1BWF9BTExPV0VEX0ZJTEVfQllURVMgLyAxMDI0IC8gMTAyNCl9TUJgXG4gICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChzaG93Q3Vyc29ySW1hZ2VQcmV2aWV3KSB7XG4gICAgICAgIGNvbnN0IGRhdGFVUkwgPSAoX2ggPSB0aGlzLmZpbGVzW2ZpbGVJZF0pID09PSBudWxsIHx8IF9oID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfaC5kYXRhVVJMOyAvLyBvcHRpbWl6YXRpb24gc28gdGhhdCB3ZSBkb24ndCB1bm5lY2Vzc2FyaWx5IHJlc2l6ZSB0aGUgb3JpZ2luYWxcbiAgICAgICAgLy8gZnVsbC1zaXplIGZpbGUgZm9yIGN1cnNvciBwcmV2aWV3XG4gICAgICAgIC8vIChpdCdzIG11Y2ggZmFzdGVyIHRvIGNvbnZlcnQgdGhlIHJlc2l6ZWQgZGF0YVVSTCB0byBGaWxlKVxuXG4gICAgICAgIGNvbnN0IHJlc2l6ZWRGaWxlID0gZGF0YVVSTCAmJiBkYXRhVVJMVG9GaWxlKGRhdGFVUkwpO1xuICAgICAgICB0aGlzLnNldEltYWdlUHJldmlld0N1cnNvcihyZXNpemVkRmlsZSB8fCBpbWFnZUZpbGUpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkYXRhVVJMID0gKChfaiA9IHRoaXMuZmlsZXNbZmlsZUlkXSkgPT09IG51bGwgfHwgX2ogPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9qLmRhdGFVUkwpIHx8ICh5aWVsZCBnZXREYXRhVVJMKGltYWdlRmlsZSkpO1xuICAgICAgY29uc3QgaW1hZ2VFbGVtZW50ID0gbXV0YXRlRWxlbWVudChfaW1hZ2VFbGVtZW50LCB7XG4gICAgICAgIGZpbGVJZFxuICAgICAgfSwgZmFsc2UpO1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgICAgdmFyIF9rO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhpcy5maWxlcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5maWxlcyksIHtcbiAgICAgICAgICAgIFtmaWxlSWRdOiB7XG4gICAgICAgICAgICAgIG1pbWVUeXBlLFxuICAgICAgICAgICAgICBpZDogZmlsZUlkLFxuICAgICAgICAgICAgICBkYXRhVVJMLFxuICAgICAgICAgICAgICBjcmVhdGVkOiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICBsYXN0UmV0cmlldmVkOiBEYXRlLm5vdygpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3QgY2FjaGVkSW1hZ2VEYXRhID0gdGhpcy5pbWFnZUNhY2hlLmdldChmaWxlSWQpO1xuXG4gICAgICAgICAgaWYgKCFjYWNoZWRJbWFnZURhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkTmV3SW1hZ2VzVG9JbWFnZUNhY2hlKCk7XG4gICAgICAgICAgICB5aWVsZCB0aGlzLnVwZGF0ZUltYWdlQ2FjaGUoW2ltYWdlRWxlbWVudF0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICgoY2FjaGVkSW1hZ2VEYXRhID09PSBudWxsIHx8IGNhY2hlZEltYWdlRGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogY2FjaGVkSW1hZ2VEYXRhLmltYWdlKSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgIHlpZWxkIGNhY2hlZEltYWdlRGF0YS5pbWFnZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5wZW5kaW5nSW1hZ2VFbGVtZW50SWQgIT09IGltYWdlRWxlbWVudC5pZCAmJiAoKF9rID0gdGhpcy5zdGF0ZS5kcmFnZ2luZ0VsZW1lbnQpID09PSBudWxsIHx8IF9rID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfay5pZCkgIT09IGltYWdlRWxlbWVudC5pZCkge1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplSW1hZ2VEaW1lbnNpb25zKGltYWdlRWxlbWVudCwgdHJ1ZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmVzb2x2ZShpbWFnZUVsZW1lbnQpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IodChcImVycm9ycy5pbWFnZUluc2VydEVycm9yXCIpKSk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgaWYgKCFzaG93Q3Vyc29ySW1hZ2VQcmV2aWV3KSB7XG4gICAgICAgICAgICByZXNldEN1cnNvcih0aGlzLmludGVyYWN0aXZlQ2FudmFzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pKTtcbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiBpbnNlcnRzIGltYWdlIGludG8gZWxlbWVudHMgYXJyYXkgYW5kIHJlcmVuZGVyc1xuICAgICAqL1xuXG5cbiAgICB0aGlzLmluc2VydEltYWdlRWxlbWVudCA9IChpbWFnZUVsZW1lbnQsIGltYWdlRmlsZSwgc2hvd0N1cnNvckltYWdlUHJldmlldykgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgdGhpcy5zY2VuZS5hZGROZXdFbGVtZW50KGltYWdlRWxlbWVudCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHlpZWxkIHRoaXMuaW5pdGlhbGl6ZUltYWdlKHtcbiAgICAgICAgICBpbWFnZUZpbGUsXG4gICAgICAgICAgaW1hZ2VFbGVtZW50LFxuICAgICAgICAgIHNob3dDdXJzb3JJbWFnZVByZXZpZXdcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBtdXRhdGVFbGVtZW50KGltYWdlRWxlbWVudCwge1xuICAgICAgICAgIGlzRGVsZXRlZDogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hY3Rpb25NYW5hZ2VyLmV4ZWN1dGVBY3Rpb24oYWN0aW9uRmluYWxpemUpO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UgfHwgdChcImVycm9ycy5pbWFnZUluc2VydEVycm9yXCIpXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXRJbWFnZVByZXZpZXdDdXJzb3IgPSBpbWFnZUZpbGUgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgLy8gbXVzdG4ndCBiZSBsYXJnZXIgdGhhbiAxMjggcHhcbiAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0NTUy9DU1NfQmFzaWNfVXNlcl9JbnRlcmZhY2UvVXNpbmdfVVJMX3ZhbHVlc19mb3JfdGhlX2N1cnNvcl9wcm9wZXJ0eVxuICAgICAgY29uc3QgY3Vyc29ySW1hZ2VTaXplUHggPSA5NjtcbiAgICAgIGNvbnN0IGltYWdlUHJldmlldyA9IHlpZWxkIHJlc2l6ZUltYWdlRmlsZShpbWFnZUZpbGUsIHtcbiAgICAgICAgbWF4V2lkdGhPckhlaWdodDogY3Vyc29ySW1hZ2VTaXplUHhcbiAgICAgIH0pO1xuICAgICAgbGV0IHByZXZpZXdEYXRhVVJMID0geWllbGQgZ2V0RGF0YVVSTChpbWFnZVByZXZpZXcpOyAvLyBTVkcgY2Fubm90IGJlIHJlc2l6ZWQgdmlhIGByZXNpemVJbWFnZUZpbGVgIHNvIHdlIHJlc2l6ZSBieSByZW5kZXJpbmcgdG9cbiAgICAgIC8vIGEgc21hbGwgY2FudmFzXG5cbiAgICAgIGlmIChpbWFnZUZpbGUudHlwZSA9PT0gTUlNRV9UWVBFUy5zdmcpIHtcbiAgICAgICAgY29uc3QgaW1nID0geWllbGQgbG9hZEhUTUxJbWFnZUVsZW1lbnQocHJldmlld0RhdGFVUkwpO1xuICAgICAgICBsZXQgaGVpZ2h0ID0gTWF0aC5taW4oaW1nLmhlaWdodCwgY3Vyc29ySW1hZ2VTaXplUHgpO1xuICAgICAgICBsZXQgd2lkdGggPSBoZWlnaHQgKiAoaW1nLndpZHRoIC8gaW1nLmhlaWdodCk7XG5cbiAgICAgICAgaWYgKHdpZHRoID4gY3Vyc29ySW1hZ2VTaXplUHgpIHtcbiAgICAgICAgICB3aWR0aCA9IGN1cnNvckltYWdlU2l6ZVB4O1xuICAgICAgICAgIGhlaWdodCA9IHdpZHRoICogKGltZy5oZWlnaHQgLyBpbWcud2lkdGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShpbWcsIDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICBwcmV2aWV3RGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoTUlNRV9UWVBFUy5zdmcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5wZW5kaW5nSW1hZ2VFbGVtZW50SWQpIHtcbiAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIGB1cmwoJHtwcmV2aWV3RGF0YVVSTH0pIDQgNCwgYXV0b2ApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5vbkltYWdlQWN0aW9uID0gKHtcbiAgICAgIGluc2VydE9uQ2FudmFzRGlyZWN0bHlcbiAgICB9ID0ge1xuICAgICAgaW5zZXJ0T25DYW52YXNEaXJlY3RseTogZmFsc2VcbiAgICB9KSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjbGllbnRYID0gdGhpcy5zdGF0ZS53aWR0aCAvIDIgKyB0aGlzLnN0YXRlLm9mZnNldExlZnQ7XG4gICAgICAgIGNvbnN0IGNsaWVudFkgPSB0aGlzLnN0YXRlLmhlaWdodCAvIDIgKyB0aGlzLnN0YXRlLm9mZnNldFRvcDtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHgsXG4gICAgICAgICAgeVxuICAgICAgICB9ID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKHtcbiAgICAgICAgICBjbGllbnRYLFxuICAgICAgICAgIGNsaWVudFlcbiAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIGNvbnN0IGltYWdlRmlsZSA9IHlpZWxkIGZpbGVPcGVuKHtcbiAgICAgICAgICBkZXNjcmlwdGlvbjogXCJJbWFnZVwiLFxuICAgICAgICAgIGV4dGVuc2lvbnM6IE9iamVjdC5rZXlzKElNQUdFX01JTUVfVFlQRVMpXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBpbWFnZUVsZW1lbnQgPSB0aGlzLmNyZWF0ZUltYWdlRWxlbWVudCh7XG4gICAgICAgICAgc2NlbmVYOiB4LFxuICAgICAgICAgIHNjZW5lWTogeVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoaW5zZXJ0T25DYW52YXNEaXJlY3RseSkge1xuICAgICAgICAgIHRoaXMuaW5zZXJ0SW1hZ2VFbGVtZW50KGltYWdlRWxlbWVudCwgaW1hZ2VGaWxlKTtcbiAgICAgICAgICB0aGlzLmluaXRpYWxpemVJbWFnZURpbWVuc2lvbnMoaW1hZ2VFbGVtZW50KTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoe1xuICAgICAgICAgICAgICBbaW1hZ2VFbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICAgICAgfSwgdGhpcy5zdGF0ZSlcbiAgICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBwZW5kaW5nSW1hZ2VFbGVtZW50SWQ6IGltYWdlRWxlbWVudC5pZFxuICAgICAgICAgIH0sICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0SW1hZ2VFbGVtZW50KGltYWdlRWxlbWVudCwgaW1hZ2VGaWxlLFxuICAgICAgICAgICAgLyogc2hvd0N1cnNvckltYWdlUHJldmlldyAqL1xuICAgICAgICAgICAgdHJ1ZSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvci5uYW1lICE9PSBcIkFib3J0RXJyb3JcIikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUud2FybihlcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBwZW5kaW5nSW1hZ2VFbGVtZW50SWQ6IG51bGwsXG4gICAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgYWN0aXZlVG9vbDogdXBkYXRlQWN0aXZlVG9vbCh0aGlzLnN0YXRlLCB7XG4gICAgICAgICAgICB0eXBlOiBcInNlbGVjdGlvblwiXG4gICAgICAgICAgfSlcbiAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgIHRoaXMuYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvbkZpbmFsaXplKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmluaXRpYWxpemVJbWFnZURpbWVuc2lvbnMgPSAoaW1hZ2VFbGVtZW50LCBmb3JjZU5hdHVyYWxTaXplID0gZmFsc2UpID0+IHtcbiAgICAgIHZhciBfYTtcblxuICAgICAgY29uc3QgaW1hZ2UgPSBpc0luaXRpYWxpemVkSW1hZ2VFbGVtZW50KGltYWdlRWxlbWVudCkgJiYgKChfYSA9IHRoaXMuaW1hZ2VDYWNoZS5nZXQoaW1hZ2VFbGVtZW50LmZpbGVJZCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pbWFnZSk7XG5cbiAgICAgIGlmICghaW1hZ2UgfHwgaW1hZ2UgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgIGlmIChpbWFnZUVsZW1lbnQud2lkdGggPCBEUkFHR0lOR19USFJFU0hPTEQgLyB0aGlzLnN0YXRlLnpvb20udmFsdWUgJiYgaW1hZ2VFbGVtZW50LmhlaWdodCA8IERSQUdHSU5HX1RIUkVTSE9MRCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZSkge1xuICAgICAgICAgIGNvbnN0IHBsYWNlaG9sZGVyU2l6ZSA9IDEwMCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KGltYWdlRWxlbWVudCwge1xuICAgICAgICAgICAgeDogaW1hZ2VFbGVtZW50LnggLSBwbGFjZWhvbGRlclNpemUgLyAyLFxuICAgICAgICAgICAgeTogaW1hZ2VFbGVtZW50LnkgLSBwbGFjZWhvbGRlclNpemUgLyAyLFxuICAgICAgICAgICAgd2lkdGg6IHBsYWNlaG9sZGVyU2l6ZSxcbiAgICAgICAgICAgIGhlaWdodDogcGxhY2Vob2xkZXJTaXplXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChmb3JjZU5hdHVyYWxTaXplIHx8IC8vIGlmIHVzZXItY3JlYXRlZCBib3VuZGluZyBib3ggaXMgYmVsb3cgdGhyZXNob2xkLCBhc3N1bWUgdGhlXG4gICAgICAvLyBpbnRlbnRpb24gd2FzIHRvIGNsaWNrIGluc3RlYWQgb2YgZHJhZywgYW5kIHVzZSB0aGUgaW1hZ2Unc1xuICAgICAgLy8gaW50cmluc2ljIHNpemVcbiAgICAgIGltYWdlRWxlbWVudC53aWR0aCA8IERSQUdHSU5HX1RIUkVTSE9MRCAvIHRoaXMuc3RhdGUuem9vbS52YWx1ZSAmJiBpbWFnZUVsZW1lbnQuaGVpZ2h0IDwgRFJBR0dJTkdfVEhSRVNIT0xEIC8gdGhpcy5zdGF0ZS56b29tLnZhbHVlKSB7XG4gICAgICAgIGNvbnN0IG1pbkhlaWdodCA9IE1hdGgubWF4KHRoaXMuc3RhdGUuaGVpZ2h0IC0gMTIwLCAxNjApOyAvLyBtYXggNjUlIG9mIGNhbnZhcyBoZWlnaHQsIGNsYW1wZWQgdG8gPDMwMHB4LCB2aCAtIDEyMHB4PlxuXG4gICAgICAgIGNvbnN0IG1heEhlaWdodCA9IE1hdGgubWluKG1pbkhlaWdodCwgTWF0aC5mbG9vcih0aGlzLnN0YXRlLmhlaWdodCAqIDAuNSkgLyB0aGlzLnN0YXRlLnpvb20udmFsdWUpO1xuICAgICAgICBjb25zdCBoZWlnaHQgPSBNYXRoLm1pbihpbWFnZS5uYXR1cmFsSGVpZ2h0LCBtYXhIZWlnaHQpO1xuICAgICAgICBjb25zdCB3aWR0aCA9IGhlaWdodCAqIChpbWFnZS5uYXR1cmFsV2lkdGggLyBpbWFnZS5uYXR1cmFsSGVpZ2h0KTsgLy8gYWRkIGN1cnJlbnQgaW1hZ2VFbGVtZW50IHdpZHRoL2hlaWdodCB0byBhY2NvdW50IGZvciBwcmV2aW91cyBjZW50ZXJpbmdcbiAgICAgICAgLy8gb2YgdGhlIHBsYWNlaG9sZGVyIGltYWdlXG5cbiAgICAgICAgY29uc3QgeCA9IGltYWdlRWxlbWVudC54ICsgaW1hZ2VFbGVtZW50LndpZHRoIC8gMiAtIHdpZHRoIC8gMjtcbiAgICAgICAgY29uc3QgeSA9IGltYWdlRWxlbWVudC55ICsgaW1hZ2VFbGVtZW50LmhlaWdodCAvIDIgLSBoZWlnaHQgLyAyO1xuICAgICAgICBtdXRhdGVFbGVtZW50KGltYWdlRWxlbWVudCwge1xuICAgICAgICAgIHgsXG4gICAgICAgICAgeSxcbiAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICBoZWlnaHRcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcbiAgICAvKiogdXBkYXRlcyBpbWFnZSBjYWNoZSwgcmVmcmVzaGluZyB1cGRhdGVkIGVsZW1lbnRzIGFuZC9vciBzZXR0aW5nIHN0YXR1c1xuICAgICAgICB0byBlcnJvciBmb3IgaW1hZ2VzIHRoYXQgZmFpbCBkdXJpbmcgPGltZz4gZWxlbWVudCBjcmVhdGlvbiAqL1xuXG5cbiAgICB0aGlzLnVwZGF0ZUltYWdlQ2FjaGUgPSAoZWxlbWVudHMsIGZpbGVzID0gdGhpcy5maWxlcykgPT4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgY29uc3Qge1xuICAgICAgICB1cGRhdGVkRmlsZXMsXG4gICAgICAgIGVycm9yZWRGaWxlc1xuICAgICAgfSA9IHlpZWxkIF91cGRhdGVJbWFnZUNhY2hlKHtcbiAgICAgICAgaW1hZ2VDYWNoZTogdGhpcy5pbWFnZUNhY2hlLFxuICAgICAgICBmaWxlSWRzOiBlbGVtZW50cy5tYXAoZWxlbWVudCA9PiBlbGVtZW50LmZpbGVJZCksXG4gICAgICAgIGZpbGVzXG4gICAgICB9KTtcblxuICAgICAgaWYgKHVwZGF0ZWRGaWxlcy5zaXplIHx8IGVycm9yZWRGaWxlcy5zaXplKSB7XG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykge1xuICAgICAgICAgIGlmICh1cGRhdGVkRmlsZXMuaGFzKGVsZW1lbnQuZmlsZUlkKSkge1xuICAgICAgICAgICAgU2hhcGVDYWNoZS5kZWxldGUoZWxlbWVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChlcnJvcmVkRmlsZXMuc2l6ZSkge1xuICAgICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyh0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLm1hcChlbGVtZW50ID0+IHtcbiAgICAgICAgICBpZiAoaXNJbml0aWFsaXplZEltYWdlRWxlbWVudChlbGVtZW50KSAmJiBlcnJvcmVkRmlsZXMuaGFzKGVsZW1lbnQuZmlsZUlkKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ld0VsZW1lbnRXaXRoKGVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgc3RhdHVzOiBcImVycm9yXCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgICAgICB9KSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHVwZGF0ZWRGaWxlcyxcbiAgICAgICAgZXJyb3JlZEZpbGVzXG4gICAgICB9O1xuICAgIH0pO1xuICAgIC8qKiBhZGRzIG5ldyBpbWFnZXMgdG8gaW1hZ2VDYWNoZSBhbmQgcmUtcmVuZGVycyBpZiBuZWVkZWQgKi9cblxuXG4gICAgdGhpcy5hZGROZXdJbWFnZXNUb0ltYWdlQ2FjaGUgPSAoaW1hZ2VFbGVtZW50cyA9IGdldEluaXRpYWxpemVkSW1hZ2VFbGVtZW50cyh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpKSwgZmlsZXMgPSB0aGlzLmZpbGVzKSA9PiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICBjb25zdCB1bmNhY2hlZEltYWdlRWxlbWVudHMgPSBpbWFnZUVsZW1lbnRzLmZpbHRlcihlbGVtZW50ID0+ICFlbGVtZW50LmlzRGVsZXRlZCAmJiAhdGhpcy5pbWFnZUNhY2hlLmhhcyhlbGVtZW50LmZpbGVJZCkpO1xuXG4gICAgICBpZiAodW5jYWNoZWRJbWFnZUVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgdXBkYXRlZEZpbGVzXG4gICAgICAgIH0gPSB5aWVsZCB0aGlzLnVwZGF0ZUltYWdlQ2FjaGUodW5jYWNoZWRJbWFnZUVsZW1lbnRzLCBmaWxlcyk7XG5cbiAgICAgICAgaWYgKHVwZGF0ZWRGaWxlcy5zaXplKSB7XG4gICAgICAgICAgdGhpcy5zY2VuZS5pbmZvcm1NdXRhdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgLyoqIGdlbmVyYWxseSB5b3Ugc2hvdWxkIHVzZSBgYWRkTmV3SW1hZ2VzVG9JbWFnZUNhY2hlKClgIGRpcmVjdGx5IGlmIHlvdSBuZWVkXG4gICAgICogIHRvIHJlbmRlciBuZXcgaW1hZ2VzLiBUaGlzIGlzIGp1c3QgYSBmYWlsc2FmZSAgKi9cblxuXG4gICAgdGhpcy5zY2hlZHVsZUltYWdlUmVmcmVzaCA9IHRocm90dGxlKCgpID0+IHtcbiAgICAgIHRoaXMuYWRkTmV3SW1hZ2VzVG9JbWFnZUNhY2hlKCk7XG4gICAgfSwgSU1BR0VfUkVOREVSX1RJTUVPVVQpO1xuXG4gICAgdGhpcy51cGRhdGVCaW5kaW5nRW5hYmxlZE9uUG9pbnRlck1vdmUgPSBldmVudCA9PiB7XG4gICAgICBjb25zdCBzaG91bGRFbmFibGVCaW5kaW5nID0gc2hvdWxkRW5hYmxlQmluZGluZ0ZvclBvaW50ZXJFdmVudChldmVudCk7XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmlzQmluZGluZ0VuYWJsZWQgIT09IHNob3VsZEVuYWJsZUJpbmRpbmcpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgaXNCaW5kaW5nRW5hYmxlZDogc2hvdWxkRW5hYmxlQmluZGluZ1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nQXRDdXJzb3IgPSBwb2ludGVyQ29vcmRzID0+IHtcbiAgICAgIGNvbnN0IGhvdmVyZWRCaW5kYWJsZUVsZW1lbnQgPSBnZXRIb3ZlcmVkRWxlbWVudEZvckJpbmRpbmcocG9pbnRlckNvb3JkcywgdGhpcy5zY2VuZSk7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc3VnZ2VzdGVkQmluZGluZ3M6IGhvdmVyZWRCaW5kYWJsZUVsZW1lbnQgIT0gbnVsbCA/IFtob3ZlcmVkQmluZGFibGVFbGVtZW50XSA6IFtdXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nc0ZvckxpbmVhckVsZW1lbnRBdENvb3JkcyA9IChsaW5lYXJFbGVtZW50LFxuICAgIC8qKiBzY2VuZSBjb29yZHMgKi9cbiAgICBwb2ludGVyQ29vcmRzLCAvLyBEdXJpbmcgbGluZSBjcmVhdGlvbiB0aGUgc3RhcnQgYmluZGluZyBoYXNuJ3QgYmVlbiB3cml0dGVuIHlldFxuICAgIC8vIGludG8gYGxpbmVhckVsZW1lbnRgXG4gICAgb3Bwb3NpdGVCaW5kaW5nQm91bmRFbGVtZW50KSA9PiB7XG4gICAgICBpZiAoIXBvaW50ZXJDb29yZHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3VnZ2VzdGVkQmluZGluZ3MgPSBwb2ludGVyQ29vcmRzLnJlZHVjZSgoYWNjLCBjb29yZHMpID0+IHtcbiAgICAgICAgY29uc3QgaG92ZXJlZEJpbmRhYmxlRWxlbWVudCA9IGdldEhvdmVyZWRFbGVtZW50Rm9yQmluZGluZyhjb29yZHMsIHRoaXMuc2NlbmUpO1xuXG4gICAgICAgIGlmIChob3ZlcmVkQmluZGFibGVFbGVtZW50ICE9IG51bGwgJiYgIWlzTGluZWFyRWxlbWVudFNpbXBsZUFuZEFscmVhZHlCb3VuZChsaW5lYXJFbGVtZW50LCBvcHBvc2l0ZUJpbmRpbmdCb3VuZEVsZW1lbnQgPT09IG51bGwgfHwgb3Bwb3NpdGVCaW5kaW5nQm91bmRFbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHBvc2l0ZUJpbmRpbmdCb3VuZEVsZW1lbnQuaWQsIGhvdmVyZWRCaW5kYWJsZUVsZW1lbnQpKSB7XG4gICAgICAgICAgYWNjLnB1c2goaG92ZXJlZEJpbmRhYmxlRWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwgW10pO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHN1Z2dlc3RlZEJpbmRpbmdzXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVJbnRlcmFjdGl2ZUNhbnZhc1JlZiA9IGNhbnZhcyA9PiB7XG4gICAgICB2YXIgX2EsIF9iLCBfYzsgLy8gY2FudmFzIGlzIG51bGwgd2hlbiB1bm1vdW50aW5nXG5cblxuICAgICAgaWYgKGNhbnZhcyAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmludGVyYWN0aXZlQ2FudmFzID0gY2FudmFzOyAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICAvLyBOT1RFIHdoZWVsLCB0b3VjaHN0YXJ0LCB0b3VjaGVuZCBldmVudHMgbXVzdCBiZSByZWdpc3RlcmVkIG91dHNpZGVcbiAgICAgICAgLy8gb2YgcmVhY3QgYmVjYXVzZSByZWFjdCBiaW5kcyB0aGVtIHRoZW0gcGFzc2l2ZWx5IChzbyB3ZSBjYW4ndCBwcmV2ZW50XG4gICAgICAgIC8vIGRlZmF1bHQgb24gdGhlbSlcblxuICAgICAgICB0aGlzLmludGVyYWN0aXZlQ2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuV0hFRUwsIHRoaXMuaGFuZGxlV2hlZWwpO1xuICAgICAgICB0aGlzLmludGVyYWN0aXZlQ2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuVE9VQ0hfU1RBUlQsIHRoaXMub25Ub3VjaFN0YXJ0KTtcbiAgICAgICAgdGhpcy5pbnRlcmFjdGl2ZUNhbnZhcy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlRPVUNIX0VORCwgdGhpcy5vblRvdWNoRW5kKTsgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIChfYSA9IHRoaXMuaW50ZXJhY3RpdmVDYW52YXMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULldIRUVMLCB0aGlzLmhhbmRsZVdoZWVsKTtcbiAgICAgICAgKF9iID0gdGhpcy5pbnRlcmFjdGl2ZUNhbnZhcykgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuVE9VQ0hfU1RBUlQsIHRoaXMub25Ub3VjaFN0YXJ0KTtcbiAgICAgICAgKF9jID0gdGhpcy5pbnRlcmFjdGl2ZUNhbnZhcykgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuVE9VQ0hfRU5ELCB0aGlzLm9uVG91Y2hFbmQpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmhhbmRsZUFwcE9uRHJvcCA9IGV2ZW50ID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIHZhciBfbCwgX20sIF9vLCBfcDsgLy8gbXVzdCBiZSByZXRyaWV2ZWQgZmlyc3QsIGluIHRoZSBzYW1lIGZyYW1lXG5cblxuICAgICAgY29uc3Qge1xuICAgICAgICBmaWxlLFxuICAgICAgICBmaWxlSGFuZGxlXG4gICAgICB9ID0geWllbGQgZ2V0RmlsZUZyb21FdmVudChldmVudCk7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHg6IHNjZW5lWCxcbiAgICAgICAgeTogc2NlbmVZXG4gICAgICB9ID0gdmlld3BvcnRDb29yZHNUb1NjZW5lQ29vcmRzKGV2ZW50LCB0aGlzLnN0YXRlKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGlzU3VwcG9ydGVkSW1hZ2VGaWxlKGZpbGUpKSB7XG4gICAgICAgICAgLy8gZmlyc3QgYXR0ZW1wdCB0byBkZWNvZGUgc2NlbmUgZnJvbSB0aGUgaW1hZ2UgaWYgaXQncyBlbWJlZGRlZFxuICAgICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICAgIGlmICgoZmlsZSA9PT0gbnVsbCB8fCBmaWxlID09PSB2b2lkIDAgPyB2b2lkIDAgOiBmaWxlLnR5cGUpID09PSBNSU1FX1RZUEVTLnBuZyB8fCAoZmlsZSA9PT0gbnVsbCB8fCBmaWxlID09PSB2b2lkIDAgPyB2b2lkIDAgOiBmaWxlLnR5cGUpID09PSBNSU1FX1RZUEVTLnN2Zykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3Qgc2NlbmUgPSB5aWVsZCBsb2FkRnJvbUJsb2IoZmlsZSwgdGhpcy5zdGF0ZSwgdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgZmlsZUhhbmRsZSk7XG4gICAgICAgICAgICAgIHRoaXMuc3luY0FjdGlvblJlc3VsdChPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNjZW5lKSwge1xuICAgICAgICAgICAgICAgIGFwcFN0YXRlOiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNjZW5lLmFwcFN0YXRlIHx8IHRoaXMuc3RhdGUpLCB7XG4gICAgICAgICAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgcmVwbGFjZUZpbGVzOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbW1pdFRvSGlzdG9yeTogdHJ1ZVxuICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIGlmIChlcnJvci5uYW1lICE9PSBcIkVuY29kaW5nRXJyb3JcIikge1xuICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyBpZiBubyBzY2VuZSBpcyBlbWJlZGRlZCBvciB3ZSBmYWlsIGZvciB3aGF0ZXZlciByZWFzb24sIGZhbGwgYmFja1xuICAgICAgICAgIC8vIHRvIGltcG9ydGluZyBhcyByZWd1bGFyIGltYWdlXG4gICAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblxuICAgICAgICAgIGNvbnN0IGltYWdlRWxlbWVudCA9IHRoaXMuY3JlYXRlSW1hZ2VFbGVtZW50KHtcbiAgICAgICAgICAgIHNjZW5lWCxcbiAgICAgICAgICAgIHNjZW5lWVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMuaW5zZXJ0SW1hZ2VFbGVtZW50KGltYWdlRWxlbWVudCwgZmlsZSk7XG4gICAgICAgICAgdGhpcy5pbml0aWFsaXplSW1hZ2VEaW1lbnNpb25zKGltYWdlRWxlbWVudCk7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHtcbiAgICAgICAgICAgICAgW2ltYWdlRWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgIH0sIHRoaXMuc3RhdGUpXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLm1lc3NhZ2VcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxpYnJhcnlKU09OID0gZXZlbnQuZGF0YVRyYW5zZmVyLmdldERhdGEoTUlNRV9UWVBFUy5leGNhbGlkcmF3bGliKTtcblxuICAgICAgaWYgKGxpYnJhcnlKU09OICYmIHR5cGVvZiBsaWJyYXJ5SlNPTiA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGxpYnJhcnlJdGVtcyA9IHBhcnNlTGlicmFyeUpTT04obGlicmFyeUpTT04pO1xuICAgICAgICAgIHRoaXMuYWRkRWxlbWVudHNGcm9tUGFzdGVPckxpYnJhcnkoe1xuICAgICAgICAgICAgZWxlbWVudHM6IGRpc3RyaWJ1dGVMaWJyYXJ5SXRlbXNPblNxdWFyZUdyaWQobGlicmFyeUl0ZW1zKSxcbiAgICAgICAgICAgIHBvc2l0aW9uOiBldmVudCxcbiAgICAgICAgICAgIGZpbGVzOiBudWxsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLm1lc3NhZ2VcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGZpbGUpIHtcbiAgICAgICAgLy8gYXRldG1wdCB0byBwYXJzZSBhbiBleGNhbGlkcmF3L2V4Y2FsaWRyYXdsaWIgZmlsZVxuICAgICAgICB5aWVsZCB0aGlzLmxvYWRGaWxlVG9DYW52YXMoZmlsZSwgZmlsZUhhbmRsZSk7XG4gICAgICB9XG5cbiAgICAgIGlmICgoX20gPSAoX2wgPSBldmVudC5kYXRhVHJhbnNmZXIpID09PSBudWxsIHx8IF9sID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfbC50eXBlcykgPT09IG51bGwgfHwgX20gPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9tLmluY2x1ZGVzKFwidGV4dC9wbGFpblwiKSkge1xuICAgICAgICBjb25zdCB0ZXh0ID0gKF9vID0gZXZlbnQuZGF0YVRyYW5zZmVyKSA9PT0gbnVsbCB8fCBfbyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX28uZ2V0RGF0YShcInRleHRcIik7XG5cbiAgICAgICAgaWYgKHRleHQgJiYgZW1iZWRkYWJsZVVSTFZhbGlkYXRvcih0ZXh0LCB0aGlzLnByb3BzLnZhbGlkYXRlRW1iZWRkYWJsZSkgJiYgKC9eKGh0dHB8aHR0cHMpOlxcL1xcL1teXFxzLyQuPyNdLlteXFxzXSokLy50ZXN0KHRleHQpIHx8ICgoX3AgPSBnZXRFbWJlZExpbmsodGV4dCkpID09PSBudWxsIHx8IF9wID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfcC50eXBlKSA9PT0gXCJ2aWRlb1wiKSkge1xuICAgICAgICAgIGNvbnN0IGVtYmVkZGFibGUgPSB0aGlzLmluc2VydEVtYmVkZGFibGVFbGVtZW50KHtcbiAgICAgICAgICAgIHNjZW5lWCxcbiAgICAgICAgICAgIHNjZW5lWSxcbiAgICAgICAgICAgIGxpbms6IG5vcm1hbGl6ZUxpbmsodGV4dClcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChlbWJlZGRhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiB7XG4gICAgICAgICAgICAgICAgW2VtYmVkZGFibGUuaWRdOiB0cnVlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2FkRmlsZVRvQ2FudmFzID0gKGZpbGUsIGZpbGVIYW5kbGUpID0+IF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHtcbiAgICAgIGZpbGUgPSB5aWVsZCBub3JtYWxpemVGaWxlKGZpbGUpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXQgPSB5aWVsZCBsb2FkU2NlbmVPckxpYnJhcnlGcm9tQmxvYihmaWxlLCB0aGlzLnN0YXRlLCB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCBmaWxlSGFuZGxlKTtcblxuICAgICAgICBpZiAocmV0LnR5cGUgPT09IE1JTUVfVFlQRVMuZXhjYWxpZHJhdykge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgaXNMb2FkaW5nOiB0cnVlXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy5zeW5jQWN0aW9uUmVzdWx0KE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcmV0LmRhdGEpLCB7XG4gICAgICAgICAgICBhcHBTdGF0ZTogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCByZXQuZGF0YS5hcHBTdGF0ZSB8fCB0aGlzLnN0YXRlKSwge1xuICAgICAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHJlcGxhY2VGaWxlczogdHJ1ZSxcbiAgICAgICAgICAgIGNvbW1pdFRvSGlzdG9yeTogdHJ1ZVxuICAgICAgICAgIH0pKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXQudHlwZSA9PT0gTUlNRV9UWVBFUy5leGNhbGlkcmF3bGliKSB7XG4gICAgICAgICAgeWllbGQgdGhpcy5saWJyYXJ5LnVwZGF0ZUxpYnJhcnkoe1xuICAgICAgICAgICAgbGlicmFyeUl0ZW1zOiBmaWxlLFxuICAgICAgICAgICAgbWVyZ2U6IHRydWUsXG4gICAgICAgICAgICBvcGVuTGlicmFyeU1lbnU6IHRydWVcbiAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHQoXCJlcnJvcnMuaW1wb3J0TGlicmFyeUVycm9yXCIpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLm1lc3NhZ2VcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmhhbmRsZUNhbnZhc0NvbnRleHRNZW51ID0gZXZlbnQgPT4ge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgaWYgKChcInBvaW50ZXJUeXBlXCIgaW4gZXZlbnQubmF0aXZlRXZlbnQgJiYgZXZlbnQubmF0aXZlRXZlbnQucG9pbnRlclR5cGUgPT09IFwidG91Y2hcIiB8fCBcInBvaW50ZXJUeXBlXCIgaW4gZXZlbnQubmF0aXZlRXZlbnQgJiYgZXZlbnQubmF0aXZlRXZlbnQucG9pbnRlclR5cGUgPT09IFwicGVuXCIgJiYgLy8gYWx3YXlzIGFsbG93IGlmIHVzZXIgdXNlcyBhIHBlbiBzZWNvbmRhcnkgYnV0dG9uXG4gICAgICBldmVudC5idXR0b24gIT09IFBPSU5URVJfQlVUVE9OLlNFQ09OREFSWSkgJiYgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIHgsXG4gICAgICAgIHlcbiAgICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoZXZlbnQsIHRoaXMuc3RhdGUpO1xuICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuZ2V0RWxlbWVudEF0UG9zaXRpb24oeCwgeSwge1xuICAgICAgICBwcmVmZXJTZWxlY3RlZDogdHJ1ZSxcbiAgICAgICAgaW5jbHVkZUxvY2tlZEVsZW1lbnRzOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG4gICAgICBjb25zdCBpc0hpdHRpZ25Db21tb25Cb3VuZEJveCA9IHRoaXMuaXNIaXR0aW5nQ29tbW9uQm91bmRpbmdCb3hPZlNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICB4LFxuICAgICAgICB5XG4gICAgICB9LCBzZWxlY3RlZEVsZW1lbnRzKTtcbiAgICAgIGNvbnN0IHR5cGUgPSBlbGVtZW50IHx8IGlzSGl0dGlnbkNvbW1vbkJvdW5kQm94ID8gXCJlbGVtZW50XCIgOiBcImNhbnZhc1wiO1xuICAgICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQ7XG4gICAgICBjb25zdCB7XG4gICAgICAgIHRvcDogb2Zmc2V0VG9wLFxuICAgICAgICBsZWZ0OiBvZmZzZXRMZWZ0XG4gICAgICB9ID0gY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3QgbGVmdCA9IGV2ZW50LmNsaWVudFggLSBvZmZzZXRMZWZ0O1xuICAgICAgY29uc3QgdG9wID0gZXZlbnQuY2xpZW50WSAtIG9mZnNldFRvcDtcbiAgICAgIHRyYWNrRXZlbnQoXCJjb250ZXh0TWVudVwiLCBcIm9wZW5Db250ZXh0TWVudVwiLCB0eXBlKTtcbiAgICAgIHRoaXMuc2V0U3RhdGUoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBlbGVtZW50ICYmICF0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1tlbGVtZW50LmlkXSA/IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlKSwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgIGVkaXRpbmdHcm91cElkOiB0aGlzLnN0YXRlLmVkaXRpbmdHcm91cElkLFxuICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHtcbiAgICAgICAgICBbZWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgfVxuICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgdGhpcy5zdGF0ZSwgdGhpcykpLCB7XG4gICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogaXNMaW5lYXJFbGVtZW50KGVsZW1lbnQpID8gbmV3IExpbmVhckVsZW1lbnRFZGl0b3IoZWxlbWVudCwgdGhpcy5zY2VuZSkgOiBudWxsXG4gICAgICB9KSA6IHRoaXMuc3RhdGUpLCB7XG4gICAgICAgIHNob3dIeXBlcmxpbmtQb3B1cDogZmFsc2VcbiAgICAgIH0pLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGNvbnRleHRNZW51OiB7XG4gICAgICAgICAgICB0b3AsXG4gICAgICAgICAgICBsZWZ0LFxuICAgICAgICAgICAgaXRlbXM6IHRoaXMuZ2V0Q29udGV4dE1lbnVJdGVtcyh0eXBlKVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy5tYXliZURyYWdOZXdHZW5lcmljRWxlbWVudCA9IChwb2ludGVyRG93blN0YXRlLCBldmVudCkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCBkcmFnZ2luZ0VsZW1lbnQgPSB0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudDtcbiAgICAgIGNvbnN0IHBvaW50ZXJDb29yZHMgPSBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHM7XG5cbiAgICAgIGlmICghZHJhZ2dpbmdFbGVtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGRyYWdnaW5nRWxlbWVudC50eXBlID09PSBcInNlbGVjdGlvblwiICYmIHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlICE9PSBcImVyYXNlclwiKSB7XG4gICAgICAgIGRyYWdOZXdFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnksIHBvaW50ZXJDb29yZHMueCwgcG9pbnRlckNvb3Jkcy55LCBkaXN0YW5jZShwb2ludGVyRG93blN0YXRlLm9yaWdpbi54LCBwb2ludGVyQ29vcmRzLngpLCBkaXN0YW5jZShwb2ludGVyRG93blN0YXRlLm9yaWdpbi55LCBwb2ludGVyQ29vcmRzLnkpLCBzaG91bGRNYWludGFpbkFzcGVjdFJhdGlvKGV2ZW50KSwgc2hvdWxkUmVzaXplRnJvbUNlbnRlcihldmVudCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckNvb3Jkcy54LCBwb2ludGVyQ29vcmRzLnksIGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpO1xuICAgICAgICBjb25zdCBpbWFnZSA9IGlzSW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50KSAmJiAoKF9hID0gdGhpcy5pbWFnZUNhY2hlLmdldChkcmFnZ2luZ0VsZW1lbnQuZmlsZUlkKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmltYWdlKTtcbiAgICAgICAgY29uc3QgYXNwZWN0UmF0aW8gPSBpbWFnZSAmJiAhKGltYWdlIGluc3RhbmNlb2YgUHJvbWlzZSkgPyBpbWFnZS53aWR0aCAvIGltYWdlLmhlaWdodCA6IG51bGw7XG4gICAgICAgIGRyYWdOZXdFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luSW5HcmlkLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luSW5HcmlkLnksIGdyaWRYLCBncmlkWSwgZGlzdGFuY2UocG9pbnRlckRvd25TdGF0ZS5vcmlnaW5JbkdyaWQueCwgZ3JpZFgpLCBkaXN0YW5jZShwb2ludGVyRG93blN0YXRlLm9yaWdpbkluR3JpZC55LCBncmlkWSksIGlzSW1hZ2VFbGVtZW50KGRyYWdnaW5nRWxlbWVudCkgPyAhc2hvdWxkTWFpbnRhaW5Bc3BlY3RSYXRpbyhldmVudCkgOiBzaG91bGRNYWludGFpbkFzcGVjdFJhdGlvKGV2ZW50KSwgc2hvdWxkUmVzaXplRnJvbUNlbnRlcihldmVudCksIGFzcGVjdFJhdGlvKTtcbiAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nRm9yQWxsKFtkcmFnZ2luZ0VsZW1lbnRdKTsgLy8gaGlnaGxpZ2h0IGVsZW1lbnRzIHRoYXQgYXJlIHRvIGJlIGFkZGVkIHRvIGZyYW1lcyBvbiBmcmFtZXMgY3JlYXRpb25cblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwiZnJhbWVcIikge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgZWxlbWVudHNUb0hpZ2hsaWdodDogZ2V0RWxlbWVudHNJblJlc2l6aW5nRnJhbWUodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZHJhZ2dpbmdFbGVtZW50LCB0aGlzLnN0YXRlKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMubWF5YmVIYW5kbGVSZXNpemUgPSAocG9pbnRlckRvd25TdGF0ZSwgZXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG4gICAgICBjb25zdCBzZWxlY3RlZEZyYW1lcyA9IHNlbGVjdGVkRWxlbWVudHMuZmlsdGVyKGVsZW1lbnQgPT4gZWxlbWVudC50eXBlID09PSBcImZyYW1lXCIpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtSGFuZGxlVHlwZSA9IHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmhhbmRsZVR5cGU7XG5cbiAgICAgIGlmIChzZWxlY3RlZEZyYW1lcy5sZW5ndGggPiAwICYmIHRyYW5zZm9ybUhhbmRsZVR5cGUgPT09IFwicm90YXRpb25cIikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAvLyBUT0RPOiByZW5hbWUgdGhpcyBzdGF0ZSBmaWVsZCB0byBcImlzU2NhbGluZ1wiIHRvIGRpc3Rpbmd1aXNoXG4gICAgICAgIC8vIGl0IGZyb20gdGhlIGdlbmVyaWMgXCJpc1Jlc2l6aW5nXCIgd2hpY2ggaW5jbHVkZXMgc2NhbGluZyBhbmRcbiAgICAgICAgLy8gcm90YXRpbmdcbiAgICAgICAgaXNSZXNpemluZzogdHJhbnNmb3JtSGFuZGxlVHlwZSAmJiB0cmFuc2Zvcm1IYW5kbGVUeXBlICE9PSBcInJvdGF0aW9uXCIsXG4gICAgICAgIGlzUm90YXRpbmc6IHRyYW5zZm9ybUhhbmRsZVR5cGUgPT09IFwicm90YXRpb25cIixcbiAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgfSk7XG4gICAgICBjb25zdCBwb2ludGVyQ29vcmRzID0gcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzO1xuICAgICAgY29uc3QgW3Jlc2l6ZVgsIHJlc2l6ZVldID0gZ2V0R3JpZFBvaW50KHBvaW50ZXJDb29yZHMueCAtIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLm9mZnNldC54LCBwb2ludGVyQ29vcmRzLnkgLSBwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5vZmZzZXQueSwgZXZlbnRbS0VZUy5DVFJMX09SX0NNRF0gPyBudWxsIDogdGhpcy5zdGF0ZS5ncmlkU2l6ZSk7XG4gICAgICBjb25zdCBmcmFtZUVsZW1lbnRzT2Zmc2V0c01hcCA9IG5ldyBNYXAoKTtcbiAgICAgIHNlbGVjdGVkRnJhbWVzLmZvckVhY2goZnJhbWUgPT4ge1xuICAgICAgICBjb25zdCBlbGVtZW50c0luRnJhbWUgPSBnZXRGcmFtZUVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIGZyYW1lLmlkKTtcbiAgICAgICAgZWxlbWVudHNJbkZyYW1lLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgZnJhbWVFbGVtZW50c09mZnNldHNNYXAuc2V0KGZyYW1lLmlkICsgZWxlbWVudC5pZCwge1xuICAgICAgICAgICAgeDogZWxlbWVudC54IC0gZnJhbWUueCxcbiAgICAgICAgICAgIHk6IGVsZW1lbnQueSAtIGZyYW1lLnlcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaWYgKHRyYW5zZm9ybUVsZW1lbnRzKHBvaW50ZXJEb3duU3RhdGUsIHRyYW5zZm9ybUhhbmRsZVR5cGUsIHNlbGVjdGVkRWxlbWVudHMsIHBvaW50ZXJEb3duU3RhdGUucmVzaXplLmFycm93RGlyZWN0aW9uLCBzaG91bGRSb3RhdGVXaXRoRGlzY3JldGVBbmdsZShldmVudCksIHNob3VsZFJlc2l6ZUZyb21DZW50ZXIoZXZlbnQpLCBzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA9PT0gMSAmJiBpc0ltYWdlRWxlbWVudChzZWxlY3RlZEVsZW1lbnRzWzBdKSA/ICFzaG91bGRNYWludGFpbkFzcGVjdFJhdGlvKGV2ZW50KSA6IHNob3VsZE1haW50YWluQXNwZWN0UmF0aW8oZXZlbnQpLCByZXNpemVYLCByZXNpemVZLCBwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5jZW50ZXIueCwgcG9pbnRlckRvd25TdGF0ZS5yZXNpemUuY2VudGVyLnkpKSB7XG4gICAgICAgIHRoaXMubWF5YmVTdWdnZXN0QmluZGluZ0ZvckFsbChzZWxlY3RlZEVsZW1lbnRzKTtcbiAgICAgICAgY29uc3QgZWxlbWVudHNUb0hpZ2hsaWdodCA9IG5ldyBTZXQoKTtcbiAgICAgICAgc2VsZWN0ZWRGcmFtZXMuZm9yRWFjaChmcmFtZSA9PiB7XG4gICAgICAgICAgY29uc3QgZWxlbWVudHNJbkZyYW1lID0gZ2V0RnJhbWVFbGVtZW50cyh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBmcmFtZS5pZCk7IC8vIGtlZXAgZWxlbWVudHMnIHBvc2l0aW9ucyByZWxhdGl2ZSB0byB0aGVpciBmcmFtZXMgb24gZnJhbWVzIHJlc2l6aW5nXG5cbiAgICAgICAgICBpZiAodHJhbnNmb3JtSGFuZGxlVHlwZSkge1xuICAgICAgICAgICAgaWYgKHRyYW5zZm9ybUhhbmRsZVR5cGUuaW5jbHVkZXMoXCJ3XCIpKSB7XG4gICAgICAgICAgICAgIGVsZW1lbnRzSW5GcmFtZS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgIHZhciBfYSwgX2I7XG5cbiAgICAgICAgICAgICAgICBtdXRhdGVFbGVtZW50KGVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgICAgIHg6IGZyYW1lLnggKyAoKChfYSA9IGZyYW1lRWxlbWVudHNPZmZzZXRzTWFwLmdldChmcmFtZS5pZCArIGVsZW1lbnQuaWQpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EueCkgfHwgMCksXG4gICAgICAgICAgICAgICAgICB5OiBmcmFtZS55ICsgKCgoX2IgPSBmcmFtZUVsZW1lbnRzT2Zmc2V0c01hcC5nZXQoZnJhbWUuaWQgKyBlbGVtZW50LmlkKSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnkpIHx8IDApXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtSGFuZGxlVHlwZS5pbmNsdWRlcyhcIm5cIikpIHtcbiAgICAgICAgICAgICAgZWxlbWVudHNJbkZyYW1lLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIF9hLCBfYjtcblxuICAgICAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZWxlbWVudCwge1xuICAgICAgICAgICAgICAgICAgeDogZnJhbWUueCArICgoKF9hID0gZnJhbWVFbGVtZW50c09mZnNldHNNYXAuZ2V0KGZyYW1lLmlkICsgZWxlbWVudC5pZCkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS54KSB8fCAwKSxcbiAgICAgICAgICAgICAgICAgIHk6IGZyYW1lLnkgKyAoKChfYiA9IGZyYW1lRWxlbWVudHNPZmZzZXRzTWFwLmdldChmcmFtZS5pZCArIGVsZW1lbnQuaWQpKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IueSkgfHwgMClcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZ2V0RWxlbWVudHNJblJlc2l6aW5nRnJhbWUodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZnJhbWUsIHRoaXMuc3RhdGUpLmZvckVhY2goZWxlbWVudCA9PiBlbGVtZW50c1RvSGlnaGxpZ2h0LmFkZChlbGVtZW50KSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBlbGVtZW50c1RvSGlnaGxpZ2h0OiBbLi4uZWxlbWVudHNUb0hpZ2hsaWdodF1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIHRoaXMuZ2V0Q29udGV4dE1lbnVJdGVtcyA9IHR5cGUgPT4ge1xuICAgICAgY29uc3Qgb3B0aW9ucyA9IFtdO1xuICAgICAgb3B0aW9ucy5wdXNoKGFjdGlvbkNvcHlBc1BuZywgYWN0aW9uQ29weUFzU3ZnKTsgLy8gY2FudmFzIGNvbnRleHRNZW51XG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICAgIGlmICh0eXBlID09PSBcImNhbnZhc1wiKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgICAgIHJldHVybiBbLi4ub3B0aW9ucywgYWN0aW9uVG9nZ2xlR3JpZE1vZGUsIGFjdGlvblRvZ2dsZVplbk1vZGUsIGFjdGlvblRvZ2dsZVZpZXdNb2RlLCBhY3Rpb25Ub2dnbGVTdGF0c107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW2FjdGlvblBhc3RlLCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCBhY3Rpb25Db3B5QXNQbmcsIGFjdGlvbkNvcHlBc1N2ZywgY29weVRleHQsIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvblNlbGVjdEFsbCwgYWN0aW9uVW5sb2NrQWxsRWxlbWVudHMsIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvblRvZ2dsZUdyaWRNb2RlLCBhY3Rpb25Ub2dnbGVaZW5Nb2RlLCBhY3Rpb25Ub2dnbGVWaWV3TW9kZSwgYWN0aW9uVG9nZ2xlU3RhdHNdO1xuICAgICAgfSAvLyBlbGVtZW50IGNvbnRleHRNZW51XG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblxuICAgICAgb3B0aW9ucy5wdXNoKGNvcHlUZXh0KTtcblxuICAgICAgaWYgKHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkKSB7XG4gICAgICAgIHJldHVybiBbYWN0aW9uQ29weSwgLi4ub3B0aW9uc107XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbYWN0aW9uQ3V0LCBhY3Rpb25Db3B5LCBhY3Rpb25QYXN0ZSwgYWN0aW9uU2VsZWN0QWxsRWxlbWVudHNJbkZyYW1lLCBhY3Rpb25SZW1vdmVBbGxFbGVtZW50c0Zyb21GcmFtZSwgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgLi4ub3B0aW9ucywgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgYWN0aW9uQ29weVN0eWxlcywgYWN0aW9uUGFzdGVTdHlsZXMsIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvbkdyb3VwLCBhY3Rpb25VbmJpbmRUZXh0LCBhY3Rpb25CaW5kVGV4dCwgYWN0aW9uV3JhcFRleHRJbkNvbnRhaW5lciwgYWN0aW9uVW5ncm91cCwgQ09OVEVYVF9NRU5VX1NFUEFSQVRPUiwgYWN0aW9uQWRkVG9MaWJyYXJ5LCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCBhY3Rpb25TZW5kQmFja3dhcmQsIGFjdGlvbkJyaW5nRm9yd2FyZCwgYWN0aW9uU2VuZFRvQmFjaywgYWN0aW9uQnJpbmdUb0Zyb250LCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCBhY3Rpb25GbGlwSG9yaXpvbnRhbCwgYWN0aW9uRmxpcFZlcnRpY2FsLCBDT05URVhUX01FTlVfU0VQQVJBVE9SLCBhY3Rpb25Ub2dnbGVMaW5lYXJFZGl0b3IsIGFjdGlvbkxpbmssIGFjdGlvbkR1cGxpY2F0ZVNlbGVjdGlvbiwgYWN0aW9uVG9nZ2xlRWxlbWVudExvY2ssIENPTlRFWFRfTUVOVV9TRVBBUkFUT1IsIGFjdGlvbkRlbGV0ZVNlbGVjdGVkXTtcbiAgICB9O1xuXG4gICAgdGhpcy5oYW5kbGVXaGVlbCA9IHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICBpZiAoaXNQYW5uaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qge1xuICAgICAgICBkZWx0YVgsXG4gICAgICAgIGRlbHRhWVxuICAgICAgfSA9IGV2ZW50OyAvLyBub3RlIHRoYXQgZXZlbnQuY3RybEtleSBpcyBuZWNlc3NhcnkgdG8gaGFuZGxlIHBpbmNoIHpvb21pbmdcblxuICAgICAgaWYgKGV2ZW50Lm1ldGFLZXkgfHwgZXZlbnQuY3RybEtleSkge1xuICAgICAgICBjb25zdCBzaWduID0gTWF0aC5zaWduKGRlbHRhWSk7XG4gICAgICAgIGNvbnN0IE1BWF9TVEVQID0gWk9PTV9TVEVQICogMTAwO1xuICAgICAgICBjb25zdCBhYnNEZWx0YSA9IE1hdGguYWJzKGRlbHRhWSk7XG4gICAgICAgIGxldCBkZWx0YSA9IGRlbHRhWTtcblxuICAgICAgICBpZiAoYWJzRGVsdGEgPiBNQVhfU1RFUCkge1xuICAgICAgICAgIGRlbHRhID0gTUFYX1NURVAgKiBzaWduO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5ld1pvb20gPSB0aGlzLnN0YXRlLnpvb20udmFsdWUgLSBkZWx0YSAvIDEwMDsgLy8gaW5jcmVhc2Ugem9vbSBzdGVwcyB0aGUgbW9yZSB6b29tZWQtaW4gd2UgYXJlIChhcHBsaWVzIHRvID4xMDAlIG9ubHkpXG5cbiAgICAgICAgbmV3Wm9vbSArPSBNYXRoLmxvZzEwKE1hdGgubWF4KDEsIHRoaXMuc3RhdGUuem9vbS52YWx1ZSkpICogLXNpZ24gKiAvLyByZWR1Y2VkIGFtcGxpZmljYXRpb24gZm9yIHNtYWxsIGRlbHRhcyAoc21hbGwgbW92ZW1lbnRzIG9uIGEgdHJhY2twYWQpXG4gICAgICAgIE1hdGgubWluKDEsIGFic0RlbHRhIC8gMjApO1xuICAgICAgICB0aGlzLnRyYW5zbGF0ZUNhbnZhcyhzdGF0ZSA9PiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGdldFN0YXRlRm9yWm9vbSh7XG4gICAgICAgICAgdmlld3BvcnRYOiB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLngsXG4gICAgICAgICAgdmlld3BvcnRZOiB0aGlzLmxhc3RWaWV3cG9ydFBvc2l0aW9uLnksXG4gICAgICAgICAgbmV4dFpvb206IGdldE5vcm1hbGl6ZWRab29tKG5ld1pvb20pXG4gICAgICAgIH0sIHN0YXRlKSksIHtcbiAgICAgICAgICBzaG91bGRDYWNoZUlnbm9yZVpvb206IHRydWVcbiAgICAgICAgfSkpO1xuICAgICAgICB0aGlzLnJlc2V0U2hvdWxkQ2FjaGVJZ25vcmVab29tRGVib3VuY2VkKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gc2Nyb2xsIGhvcml6b250YWxseSB3aGVuIHNoaWZ0IHByZXNzZWRcblxuXG4gICAgICBpZiAoZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgdGhpcy50cmFuc2xhdGVDYW52YXMoKHtcbiAgICAgICAgICB6b29tLFxuICAgICAgICAgIHNjcm9sbFhcbiAgICAgICAgfSkgPT4gKHtcbiAgICAgICAgICAvLyBvbiBNYWMsIHNoaWZ0K3doZWVsIHRlbmRzIHRvIHJlc3VsdCBpbiBkZWx0YVhcbiAgICAgICAgICBzY3JvbGxYOiBzY3JvbGxYIC0gKGRlbHRhWSB8fCBkZWx0YVgpIC8gem9vbS52YWx1ZVxuICAgICAgICB9KSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy50cmFuc2xhdGVDYW52YXMoKHtcbiAgICAgICAgem9vbSxcbiAgICAgICAgc2Nyb2xsWCxcbiAgICAgICAgc2Nyb2xsWVxuICAgICAgfSkgPT4gKHtcbiAgICAgICAgc2Nyb2xsWDogc2Nyb2xsWCAtIGRlbHRhWCAvIHpvb20udmFsdWUsXG4gICAgICAgIHNjcm9sbFk6IHNjcm9sbFkgLSBkZWx0YVkgLyB6b29tLnZhbHVlXG4gICAgICB9KSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnNhdmVQb2ludGVyID0gKHgsIHksIGJ1dHRvbikgPT4ge1xuICAgICAgdmFyIF9hLCBfYjtcblxuICAgICAgaWYgKCF4IHx8ICF5KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcG9pbnRlciA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3Jkcyh7XG4gICAgICAgIGNsaWVudFg6IHgsXG4gICAgICAgIGNsaWVudFk6IHlcbiAgICAgIH0sIHRoaXMuc3RhdGUpO1xuXG4gICAgICBpZiAoaXNOYU4ocG9pbnRlci54KSB8fCBpc05hTihwb2ludGVyLnkpKSB7Ly8gc29tZXRpbWVzIHRoZSBwb2ludGVyIGdvZXMgb2ZmIHNjcmVlblxuICAgICAgfVxuXG4gICAgICAoX2IgPSAoX2EgPSB0aGlzLnByb3BzKS5vblBvaW50ZXJVcGRhdGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCB7XG4gICAgICAgIHBvaW50ZXIsXG4gICAgICAgIGJ1dHRvbixcbiAgICAgICAgcG9pbnRlcnNNYXA6IGdlc3R1cmUucG9pbnRlcnNcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLnJlc2V0U2hvdWxkQ2FjaGVJZ25vcmVab29tRGVib3VuY2VkID0gZGVib3VuY2UoKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLnVubW91bnRlZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzaG91bGRDYWNoZUlnbm9yZVpvb206IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sIDMwMCk7XG5cbiAgICB0aGlzLnVwZGF0ZURPTVJlY3QgPSBjYiA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIGlmICgoX2EgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jdXJyZW50KSB7XG4gICAgICAgIGNvbnN0IGV4Y2FsaWRyYXdDb250YWluZXIgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudDtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHdpZHRoLFxuICAgICAgICAgIGhlaWdodCxcbiAgICAgICAgICBsZWZ0OiBvZmZzZXRMZWZ0LFxuICAgICAgICAgIHRvcDogb2Zmc2V0VG9wXG4gICAgICAgIH0gPSBleGNhbGlkcmF3Q29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgd2lkdGg6IGN1cnJlbnRXaWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IGN1cnJlbnRIZWlnaHQsXG4gICAgICAgICAgb2Zmc2V0VG9wOiBjdXJyZW50T2Zmc2V0VG9wLFxuICAgICAgICAgIG9mZnNldExlZnQ6IGN1cnJlbnRPZmZzZXRMZWZ0XG4gICAgICAgIH0gPSB0aGlzLnN0YXRlO1xuXG4gICAgICAgIGlmICh3aWR0aCA9PT0gY3VycmVudFdpZHRoICYmIGhlaWdodCA9PT0gY3VycmVudEhlaWdodCAmJiBvZmZzZXRMZWZ0ID09PSBjdXJyZW50T2Zmc2V0TGVmdCAmJiBvZmZzZXRUb3AgPT09IGN1cnJlbnRPZmZzZXRUb3ApIHtcbiAgICAgICAgICBpZiAoY2IpIHtcbiAgICAgICAgICAgIGNiKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgd2lkdGgsXG4gICAgICAgICAgaGVpZ2h0LFxuICAgICAgICAgIG9mZnNldExlZnQsXG4gICAgICAgICAgb2Zmc2V0VG9wXG4gICAgICAgIH0sICgpID0+IHtcbiAgICAgICAgICBjYiAmJiBjYigpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5yZWZyZXNoID0gKCkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZShPYmplY3QuYXNzaWduKHt9LCB0aGlzLmdldENhbnZhc09mZnNldHMoKSkpO1xuICAgIH07XG5cbiAgICBjb25zdCBkZWZhdWx0QXBwU3RhdGUgPSBnZXREZWZhdWx0QXBwU3RhdGUoKTtcbiAgICBjb25zdCB7XG4gICAgICBleGNhbGlkcmF3UmVmLFxuICAgICAgdmlld01vZGVFbmFibGVkID0gZmFsc2UsXG4gICAgICB6ZW5Nb2RlRW5hYmxlZCA9IGZhbHNlLFxuICAgICAgZ3JpZE1vZGVFbmFibGVkID0gZmFsc2UsXG4gICAgICB0aGVtZSA9IGRlZmF1bHRBcHBTdGF0ZS50aGVtZSxcbiAgICAgIG5hbWUgPSBkZWZhdWx0QXBwU3RhdGUubmFtZVxuICAgIH0gPSBwcm9wcztcbiAgICB0aGlzLnN0YXRlID0gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdEFwcFN0YXRlKSwge1xuICAgICAgdGhlbWUsXG4gICAgICBpc0xvYWRpbmc6IHRydWVcbiAgICB9KSwgdGhpcy5nZXRDYW52YXNPZmZzZXRzKCkpLCB7XG4gICAgICB2aWV3TW9kZUVuYWJsZWQsXG4gICAgICB6ZW5Nb2RlRW5hYmxlZCxcbiAgICAgIGdyaWRTaXplOiBncmlkTW9kZUVuYWJsZWQgPyBHUklEX1NJWkUgOiBudWxsLFxuICAgICAgbmFtZSxcbiAgICAgIHdpZHRoOiB3aW5kb3cuaW5uZXJXaWR0aCxcbiAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0XG4gICAgfSk7XG4gICAgdGhpcy5pZCA9IG5hbm9pZCgpO1xuICAgIHRoaXMubGlicmFyeSA9IG5ldyBMaWJyYXJ5KHRoaXMpO1xuICAgIHRoaXMuc2NlbmUgPSBuZXcgU2NlbmUoKTtcbiAgICB0aGlzLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIik7XG4gICAgdGhpcy5yYyA9IHJvdWdoLmNhbnZhcyh0aGlzLmNhbnZhcyk7XG4gICAgdGhpcy5yZW5kZXJlciA9IG5ldyBSZW5kZXJlcih0aGlzLnNjZW5lKTtcblxuICAgIGlmIChleGNhbGlkcmF3UmVmKSB7XG4gICAgICBjb25zdCByZWFkeVByb21pc2UgPSBcImN1cnJlbnRcIiBpbiBleGNhbGlkcmF3UmVmICYmICgoX2EgPSBleGNhbGlkcmF3UmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5yZWFkeVByb21pc2UpIHx8IHJlc29sdmFibGVQcm9taXNlKCk7XG4gICAgICBjb25zdCBhcGkgPSB7XG4gICAgICAgIHJlYWR5OiB0cnVlLFxuICAgICAgICByZWFkeVByb21pc2UsXG4gICAgICAgIHVwZGF0ZVNjZW5lOiB0aGlzLnVwZGF0ZVNjZW5lLFxuICAgICAgICB1cGRhdGVMaWJyYXJ5OiB0aGlzLmxpYnJhcnkudXBkYXRlTGlicmFyeSxcbiAgICAgICAgYWRkRmlsZXM6IHRoaXMuYWRkRmlsZXMsXG4gICAgICAgIHJlc2V0U2NlbmU6IHRoaXMucmVzZXRTY2VuZSxcbiAgICAgICAgZ2V0U2NlbmVFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQ6IHRoaXMuZ2V0U2NlbmVFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQsXG4gICAgICAgIGhpc3Rvcnk6IHtcbiAgICAgICAgICBjbGVhcjogdGhpcy5yZXNldEhpc3RvcnlcbiAgICAgICAgfSxcbiAgICAgICAgc2Nyb2xsVG9Db250ZW50OiB0aGlzLnNjcm9sbFRvQ29udGVudCxcbiAgICAgICAgZ2V0U2NlbmVFbGVtZW50czogdGhpcy5nZXRTY2VuZUVsZW1lbnRzLFxuICAgICAgICBnZXRBcHBTdGF0ZTogKCkgPT4gdGhpcy5zdGF0ZSxcbiAgICAgICAgZ2V0RmlsZXM6ICgpID0+IHRoaXMuZmlsZXMsXG4gICAgICAgIHJlZnJlc2g6IHRoaXMucmVmcmVzaCxcbiAgICAgICAgc2V0VG9hc3Q6IHRoaXMuc2V0VG9hc3QsXG4gICAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgICBzZXRBY3RpdmVUb29sOiB0aGlzLnNldEFjdGl2ZVRvb2wsXG4gICAgICAgIHNldEN1cnNvcjogdGhpcy5zZXRDdXJzb3IsXG4gICAgICAgIHJlc2V0Q3Vyc29yOiB0aGlzLnJlc2V0Q3Vyc29yLFxuICAgICAgICB1cGRhdGVGcmFtZVJlbmRlcmluZzogdGhpcy51cGRhdGVGcmFtZVJlbmRlcmluZyxcbiAgICAgICAgdG9nZ2xlU2lkZWJhcjogdGhpcy50b2dnbGVTaWRlYmFyXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIGV4Y2FsaWRyYXdSZWYgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBleGNhbGlkcmF3UmVmKGFwaSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleGNhbGlkcmF3UmVmLmN1cnJlbnQgPSBhcGk7XG4gICAgICB9XG5cbiAgICAgIHJlYWR5UHJvbWlzZS5yZXNvbHZlKGFwaSk7XG4gICAgfVxuXG4gICAgdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyVmFsdWUgPSB7XG4gICAgICBjb250YWluZXI6IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50LFxuICAgICAgaWQ6IHRoaXMuaWRcbiAgICB9O1xuICAgIHRoaXMuZm9udHMgPSBuZXcgRm9udHMoe1xuICAgICAgc2NlbmU6IHRoaXMuc2NlbmUsXG4gICAgICBvblNjZW5lVXBkYXRlZDogdGhpcy5vblNjZW5lVXBkYXRlZFxuICAgIH0pO1xuICAgIHRoaXMuaGlzdG9yeSA9IG5ldyBIaXN0b3J5KCk7XG4gICAgdGhpcy5hY3Rpb25NYW5hZ2VyID0gbmV3IEFjdGlvbk1hbmFnZXIodGhpcy5zeW5jQWN0aW9uUmVzdWx0LCAoKSA9PiB0aGlzLnN0YXRlLCAoKSA9PiB0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCB0aGlzKTtcbiAgICB0aGlzLmFjdGlvbk1hbmFnZXIucmVnaXN0ZXJBbGwoYWN0aW9ucyk7XG4gICAgdGhpcy5hY3Rpb25NYW5hZ2VyLnJlZ2lzdGVyQWN0aW9uKGNyZWF0ZVVuZG9BY3Rpb24odGhpcy5oaXN0b3J5KSk7XG4gICAgdGhpcy5hY3Rpb25NYW5hZ2VyLnJlZ2lzdGVyQWN0aW9uKGNyZWF0ZVJlZG9BY3Rpb24odGhpcy5oaXN0b3J5KSk7XG4gIH1cblxuICBvbldpbmRvd01lc3NhZ2UoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQub3JpZ2luICE9PSBcImh0dHBzOi8vcGxheWVyLnZpbWVvLmNvbVwiICYmIGV2ZW50Lm9yaWdpbiAhPT0gXCJodHRwczovL3d3dy55b3V0dWJlLmNvbVwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IGRhdGEgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGV2ZW50LmRhdGEpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICBpZiAoIWRhdGEpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGV2ZW50Lm9yaWdpbikge1xuICAgICAgY2FzZSBcImh0dHBzOi8vcGxheWVyLnZpbWVvLmNvbVwiOlxuICAgICAgICAvL0FsbG93aW5nIGZvciBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgRXhjYWxpZHJhdyBydW5uaW5nIGluIHRoZSB3aW5kb3dcbiAgICAgICAgaWYgKGRhdGEubWV0aG9kID09PSBcInBhdXNlZFwiKSB7XG4gICAgICAgICAgbGV0IHNvdXJjZSA9IG51bGw7XG4gICAgICAgICAgY29uc3QgaWZyYW1lcyA9IGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvckFsbChcImlmcmFtZS5leGNhbGlkcmF3X19lbWJlZGRhYmxlXCIpO1xuXG4gICAgICAgICAgaWYgKCFpZnJhbWVzKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IGlmcmFtZSBvZiBpZnJhbWVzKSB7XG4gICAgICAgICAgICBpZiAoaWZyYW1lLmNvbnRlbnRXaW5kb3cgPT09IGV2ZW50LnNvdXJjZSkge1xuICAgICAgICAgICAgICBzb3VyY2UgPSBpZnJhbWUuY29udGVudFdpbmRvdztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzb3VyY2UgPT09IG51bGwgfHwgc291cmNlID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzb3VyY2UucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgbWV0aG9kOiBkYXRhLnZhbHVlID8gXCJwbGF5XCIgOiBcInBhdXNlXCIsXG4gICAgICAgICAgICB2YWx1ZTogdHJ1ZVxuICAgICAgICAgIH0pLCBcIipcIik7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImh0dHBzOi8vd3d3LnlvdXR1YmUuY29tXCI6XG4gICAgICAgIGlmIChkYXRhLmV2ZW50ID09PSBcImluZm9EZWxpdmVyeVwiICYmIGRhdGEuaW5mbyAmJiBkYXRhLmlkICYmIHR5cGVvZiBkYXRhLmluZm8ucGxheWVyU3RhdGUgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICBjb25zdCBpZCA9IGRhdGEuaWQ7XG4gICAgICAgICAgY29uc3QgcGxheWVyU3RhdGUgPSBkYXRhLmluZm8ucGxheWVyU3RhdGU7XG5cbiAgICAgICAgICBpZiAoT2JqZWN0LnZhbHVlcyhZT1VUVUJFX1NUQVRFUykuaW5jbHVkZXMocGxheWVyU3RhdGUpKSB7XG4gICAgICAgICAgICBZT1VUVUJFX1ZJREVPX1NUQVRFUy5zZXQoaWQsIHBsYXllclN0YXRlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICB1cGRhdGVFbWJlZGRhYmxlUmVmKGlkLCByZWYpIHtcbiAgICBpZiAocmVmKSB7XG4gICAgICB0aGlzLmlGcmFtZVJlZnMuc2V0KGlkLCByZWYpO1xuICAgIH1cbiAgfVxuXG4gIGdldEhUTUxJRnJhbWVFbGVtZW50KGlkKSB7XG4gICAgcmV0dXJuIHRoaXMuaUZyYW1lUmVmcy5nZXQoaWQpO1xuICB9XG5cbiAgaGFuZGxlRW1iZWRkYWJsZUNlbnRlckNsaWNrKGVsZW1lbnQpIHtcbiAgICB2YXIgX2EsIF9iLCBfYywgX2Q7XG5cbiAgICBpZiAoKChfYSA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmVsZW1lbnQpID09PSBlbGVtZW50ICYmICgoX2IgPSB0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5zdGF0ZSkgPT09IFwiYWN0aXZlXCIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IC8vIFRoZSBkZWxheSBzZXJ2ZXMgdHdvIHB1cnBvc2VzXG4gICAgLy8gMS4gVG8gcHJldmVudCBmaXJzdCBjbGljayBwcm9wYWdhdGluZyB0byBpZnJhbWUgb24gbW9iaWxlLFxuICAgIC8vICAgIGVsc2UgdGhlIGNsaWNrIHdpbGwgaW1tZWRpYXRlbHkgc3RhcnQgYW5kIHN0b3AgdGhlIHZpZGVvXG4gICAgLy8gMi4gSWYgdGhlIHVzZXIgZG91YmxlIGNsaWNrcyB0aGUgZnJhbWUgY2VudGVyIHRvIGFjdGl2YXRlIGl0XG4gICAgLy8gICAgd2l0aG91dCB0aGUgZGVsYXkgeW91dHViZSB3aWxsIGltbWVkaWF0ZWx5IG9wZW4gdGhlIHZpZGVvXG4gICAgLy8gICAgaW4gZnVsbHNjcmVlbiBtb2RlXG5cblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGFjdGl2ZUVtYmVkZGFibGU6IHtcbiAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgIHN0YXRlOiBcImFjdGl2ZVwiXG4gICAgICAgIH0sXG4gICAgICAgIHNlbGVjdGVkRWxlbWVudElkczoge1xuICAgICAgICAgIFtlbGVtZW50LmlkXTogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IG51bGwsXG4gICAgICAgIHNlbGVjdGlvbkVsZW1lbnQ6IG51bGxcbiAgICAgIH0pO1xuICAgIH0sIDEwMCk7XG4gICAgY29uc3QgaWZyYW1lID0gdGhpcy5nZXRIVE1MSUZyYW1lRWxlbWVudChlbGVtZW50LmlkKTtcblxuICAgIGlmICghKGlmcmFtZSA9PT0gbnVsbCB8fCBpZnJhbWUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGlmcmFtZS5jb250ZW50V2luZG93KSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChpZnJhbWUuc3JjLmluY2x1ZGVzKFwieW91dHViZVwiKSkge1xuICAgICAgY29uc3Qgc3RhdGUgPSBZT1VUVUJFX1ZJREVPX1NUQVRFUy5nZXQoZWxlbWVudC5pZCk7XG5cbiAgICAgIGlmICghc3RhdGUpIHtcbiAgICAgICAgWU9VVFVCRV9WSURFT19TVEFURVMuc2V0KGVsZW1lbnQuaWQsIFlPVVRVQkVfU1RBVEVTLlVOU1RBUlRFRCk7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBldmVudDogXCJsaXN0ZW5pbmdcIixcbiAgICAgICAgICBpZDogZWxlbWVudC5pZFxuICAgICAgICB9KSwgXCIqXCIpO1xuICAgICAgfVxuXG4gICAgICBzd2l0Y2ggKHN0YXRlKSB7XG4gICAgICAgIGNhc2UgWU9VVFVCRV9TVEFURVMuUExBWUlORzpcbiAgICAgICAgY2FzZSBZT1VUVUJFX1NUQVRFUy5CVUZGRVJJTkc6XG4gICAgICAgICAgKF9jID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBldmVudDogXCJjb21tYW5kXCIsXG4gICAgICAgICAgICBmdW5jOiBcInBhdXNlVmlkZW9cIixcbiAgICAgICAgICAgIGFyZ3M6IFwiXCJcbiAgICAgICAgICB9KSwgXCIqXCIpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgKF9kID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBldmVudDogXCJjb21tYW5kXCIsXG4gICAgICAgICAgICBmdW5jOiBcInBsYXlWaWRlb1wiLFxuICAgICAgICAgICAgYXJnczogXCJcIlxuICAgICAgICAgIH0pLCBcIipcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlmcmFtZS5zcmMuaW5jbHVkZXMoXCJwbGF5ZXIudmltZW8uY29tXCIpKSB7XG4gICAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIG1ldGhvZDogXCJwYXVzZWRcIiAvL3ZpZGVvIHBsYXkvcGF1c2UgaW4gb25XaW5kb3dNZXNzYWdlIGhhbmRsZXJcblxuICAgICAgfSksIFwiKlwiKTtcbiAgICB9XG4gIH1cblxuICBpc0VtYmVkZGFibGVDZW50ZXIoZWwsIGV2ZW50LCBzY2VuZVgsIHNjZW5lWSkge1xuICAgIHZhciBfYSwgX2I7XG5cbiAgICByZXR1cm4gZWwgJiYgIWV2ZW50LmFsdEtleSAmJiAhZXZlbnQuc2hpZnRLZXkgJiYgIWV2ZW50Lm1ldGFLZXkgJiYgIWV2ZW50LmN0cmxLZXkgJiYgKCgoX2EgPSB0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5lbGVtZW50KSAhPT0gZWwgfHwgKChfYiA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnN0YXRlKSA9PT0gXCJob3ZlclwiIHx8ICF0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpICYmIHNjZW5lWCA+PSBlbC54ICsgZWwud2lkdGggLyAzICYmIHNjZW5lWCA8PSBlbC54ICsgMiAqIGVsLndpZHRoIC8gMyAmJiBzY2VuZVkgPj0gZWwueSArIGVsLmhlaWdodCAvIDMgJiYgc2NlbmVZIDw9IGVsLnkgKyAyICogZWwuaGVpZ2h0IC8gMztcbiAgfVxuXG4gIHJlbmRlckVtYmVkZGFibGVzKCkge1xuICAgIGNvbnN0IHNjYWxlID0gdGhpcy5zdGF0ZS56b29tLnZhbHVlO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRXaWR0aCA9IHRoaXMuc3RhdGUud2lkdGg7XG4gICAgY29uc3Qgbm9ybWFsaXplZEhlaWdodCA9IHRoaXMuc3RhdGUuaGVpZ2h0O1xuICAgIGNvbnN0IGVtYmVkZGFibGVFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkuZmlsdGVyKGVsID0+IGlzRW1iZWRkYWJsZUVsZW1lbnQoZWwpICYmICEhZWwudmFsaWRhdGVkKTtcbiAgICByZXR1cm4gX2pzeChfRnJhZ21lbnQsIHtcbiAgICAgIGNoaWxkcmVuOiBlbWJlZGRhYmxlRWxlbWVudHMubWFwKGVsID0+IHtcbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2YsIF9nLCBfaDtcblxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5XG4gICAgICAgIH0gPSBzY2VuZUNvb3Jkc1RvVmlld3BvcnRDb29yZHMoe1xuICAgICAgICAgIHNjZW5lWDogZWwueCxcbiAgICAgICAgICBzY2VuZVk6IGVsLnlcbiAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIGNvbnN0IGVtYmVkTGluayA9IGdldEVtYmVkTGluayh0b1ZhbGlkVVJMKGVsLmxpbmsgfHwgXCJcIikpO1xuICAgICAgICBjb25zdCBpc1Zpc2libGUgPSBpc0VsZW1lbnRJblZpZXdwb3J0KGVsLCBub3JtYWxpemVkV2lkdGgsIG5vcm1hbGl6ZWRIZWlnaHQsIHRoaXMuc3RhdGUpO1xuICAgICAgICBjb25zdCBpc0FjdGl2ZSA9ICgoX2EgPSB0aGlzLnN0YXRlLmFjdGl2ZUVtYmVkZGFibGUpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5lbGVtZW50KSA9PT0gZWwgJiYgKChfYiA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnN0YXRlKSA9PT0gXCJhY3RpdmVcIjtcbiAgICAgICAgY29uc3QgaXNIb3ZlcmVkID0gKChfYyA9IHRoaXMuc3RhdGUuYWN0aXZlRW1iZWRkYWJsZSkgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLmVsZW1lbnQpID09PSBlbCAmJiAoKF9kID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Quc3RhdGUpID09PSBcImhvdmVyXCI7XG4gICAgICAgIHJldHVybiBfanN4KFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcImV4Y2FsaWRyYXdfX2VtYmVkZGFibGUtY29udGFpbmVyXCIsIHtcbiAgICAgICAgICAgIFwiaXMtaG92ZXJlZFwiOiBpc0hvdmVyZWRcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBpc1Zpc2libGUgPyBgdHJhbnNsYXRlKCR7eCAtIHRoaXMuc3RhdGUub2Zmc2V0TGVmdH1weCwgJHt5IC0gdGhpcy5zdGF0ZS5vZmZzZXRUb3B9cHgpIHNjYWxlKCR7c2NhbGV9KWAgOiBcIm5vbmVcIixcbiAgICAgICAgICAgIGRpc3BsYXk6IGlzVmlzaWJsZSA/IFwiYmxvY2tcIiA6IFwibm9uZVwiLFxuICAgICAgICAgICAgb3BhY2l0eTogZWwub3BhY2l0eSAvIDEwMCxcbiAgICAgICAgICAgIFtcIi0tZW1iZWRkYWJsZS1yYWRpdXNcIl06IGAke2dldENvcm5lclJhZGl1cyhNYXRoLm1pbihlbC53aWR0aCwgZWwuaGVpZ2h0KSwgZWwpfXB4YFxuICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgIGNoaWxkcmVuOiBfanN4cyhcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgIC8vdGhpcyBpcyBhIGhhY2sgdGhhdCBhZGRyZXNzZXMgaXNzZSB3aXRoIGVtYmVkZGVkIGV4Y2FsaWRyYXcuY29tIGVtYmVkZGFibGVcbiAgICAgICAgICAgIC8vaHR0cHM6Ly9naXRodWIuY29tL2V4Y2FsaWRyYXcvZXhjYWxpZHJhdy9wdWxsLzY2OTEjaXNzdWVjb21tZW50LTE2MDczODM5MzhcblxuICAgICAgICAgICAgLypyZWY9eyhyZWYpID0+IHtcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudDtcbiAgICAgICAgICAgICAgY29uc3Qgc2ggPSBjb250YWluZXIuc2Nyb2xsSGVpZ2h0O1xuICAgICAgICAgICAgICBjb25zdCBjaCA9IGNvbnRhaW5lci5jbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICAgIGlmIChzaCAhPT0gY2gpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gYCR7c2h9cHhgO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLmhlaWdodCA9IGAxMDAlYDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfX0qL1xuICAgICAgICAgICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXdfX2VtYmVkZGFibGUtY29udGFpbmVyX19pbm5lclwiLFxuICAgICAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICAgICAgd2lkdGg6IGlzVmlzaWJsZSA/IGAke2VsLndpZHRofXB4YCA6IDAsXG4gICAgICAgICAgICAgIGhlaWdodDogaXNWaXNpYmxlID8gYCR7ZWwuaGVpZ2h0fXB4YCA6IDAsXG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogaXNWaXNpYmxlID8gYHJvdGF0ZSgke2VsLmFuZ2xlfXJhZClgIDogXCJub25lXCIsXG4gICAgICAgICAgICAgIHBvaW50ZXJFdmVudHM6IGlzQWN0aXZlID8gUE9JTlRFUl9FVkVOVFMuZW5hYmxlZCA6IFBPSU5URVJfRVZFTlRTLmRpc2FibGVkXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtpc0hvdmVyZWQgJiYgX2pzeChcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXdfX2VtYmVkZGFibGUtaGludFwiXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgIGNoaWxkcmVuOiB0KFwiYnV0dG9ucy5lbWJlZGRhYmxlSW50ZXJhY3Rpb25CdXR0b25cIilcbiAgICAgICAgICAgIH0pKSwgX2pzeChcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXdfX2VtYmVkZGFibGVfX291dGVyXCIsXG4gICAgICAgICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgcGFkZGluZzogYCR7ZWwuc3Ryb2tlV2lkdGh9cHhgXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgY2hpbGRyZW46IChfZyA9IChfZiA9IChfZSA9IHRoaXMucHJvcHMpLnJlbmRlckVtYmVkZGFibGUpID09PSBudWxsIHx8IF9mID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZi5jYWxsKF9lLCBlbCwgdGhpcy5zdGF0ZSkpICE9PSBudWxsICYmIF9nICE9PSB2b2lkIDAgPyBfZyA6IF9qc3goXCJpZnJhbWVcIiwge1xuICAgICAgICAgICAgICAgIHJlZjogcmVmID0+IHRoaXMudXBkYXRlRW1iZWRkYWJsZVJlZihlbC5pZCwgcmVmKSxcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhd19fZW1iZWRkYWJsZVwiLFxuICAgICAgICAgICAgICAgIHNyY0RvYzogKGVtYmVkTGluayA9PT0gbnVsbCB8fCBlbWJlZExpbmsgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGVtYmVkTGluay50eXBlKSA9PT0gXCJkb2N1bWVudFwiID8gZW1iZWRMaW5rLnNyY2RvYyh0aGlzLnN0YXRlLnRoZW1lKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBzcmM6IChlbWJlZExpbmsgPT09IG51bGwgfHwgZW1iZWRMaW5rID09PSB2b2lkIDAgPyB2b2lkIDAgOiBlbWJlZExpbmsudHlwZSkgIT09IFwiZG9jdW1lbnRcIiA/IChfaCA9IGVtYmVkTGluayA9PT0gbnVsbCB8fCBlbWJlZExpbmsgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGVtYmVkTGluay5saW5rKSAhPT0gbnVsbCAmJiBfaCAhPT0gdm9pZCAwID8gX2ggOiBcIlwiIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xODQ3MDAxNVxuICAgICAgICAgICAgICAgIHNjcm9sbGluZzogXCJub1wiLFxuICAgICAgICAgICAgICAgIHJlZmVycmVyUG9saWN5OiBcIm5vLXJlZmVycmVyLXdoZW4tZG93bmdyYWRlXCIsXG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiRXhjYWxpZHJhdyBFbWJlZGRlZCBDb250ZW50XCIsXG4gICAgICAgICAgICAgICAgYWxsb3c6IFwiYWNjZWxlcm9tZXRlcjsgYXV0b3BsYXk7IGNsaXBib2FyZC13cml0ZTsgZW5jcnlwdGVkLW1lZGlhOyBneXJvc2NvcGU7IHBpY3R1cmUtaW4tcGljdHVyZVwiLFxuICAgICAgICAgICAgICAgIGFsbG93RnVsbFNjcmVlbjogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzYW5kYm94OiBcImFsbG93LXNhbWUtb3JpZ2luIGFsbG93LXNjcmlwdHMgYWxsb3ctZm9ybXMgYWxsb3ctcG9wdXBzIGFsbG93LXBvcHVwcy10by1lc2NhcGUtc2FuZGJveCBhbGxvdy1wcmVzZW50YXRpb24gYWxsb3ctZG93bmxvYWRzXCJcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pKV1cbiAgICAgICAgICB9KSlcbiAgICAgICAgfSksIGVsLmlkKTtcbiAgICAgIH0pXG4gICAgfSk7XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgdmFyIF9hLCBfYiwgX2M7XG5cbiAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuICAgIGNvbnN0IHtcbiAgICAgIHJlbmRlclRvcFJpZ2h0VUksXG4gICAgICByZW5kZXJDdXN0b21TdGF0c1xuICAgIH0gPSB0aGlzLnByb3BzO1xuICAgIGNvbnN0IHZlcnNpb25Ob25jZSA9IHRoaXMuc2NlbmUuZ2V0VmVyc2lvbk5vbmNlKCk7XG4gICAgY29uc3Qge1xuICAgICAgY2FudmFzRWxlbWVudHMsXG4gICAgICB2aXNpYmxlRWxlbWVudHNcbiAgICB9ID0gdGhpcy5yZW5kZXJlci5nZXRSZW5kZXJhYmxlRWxlbWVudHMoe1xuICAgICAgdmVyc2lvbk5vbmNlLFxuICAgICAgem9vbTogdGhpcy5zdGF0ZS56b29tLFxuICAgICAgb2Zmc2V0TGVmdDogdGhpcy5zdGF0ZS5vZmZzZXRMZWZ0LFxuICAgICAgb2Zmc2V0VG9wOiB0aGlzLnN0YXRlLm9mZnNldFRvcCxcbiAgICAgIHNjcm9sbFg6IHRoaXMuc3RhdGUuc2Nyb2xsWCxcbiAgICAgIHNjcm9sbFk6IHRoaXMuc3RhdGUuc2Nyb2xsWSxcbiAgICAgIGhlaWdodDogdGhpcy5zdGF0ZS5oZWlnaHQsXG4gICAgICB3aWR0aDogdGhpcy5zdGF0ZS53aWR0aCxcbiAgICAgIGVkaXRpbmdFbGVtZW50OiB0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50LFxuICAgICAgcGVuZGluZ0ltYWdlRWxlbWVudElkOiB0aGlzLnN0YXRlLnBlbmRpbmdJbWFnZUVsZW1lbnRJZFxuICAgIH0pO1xuICAgIHJldHVybiBfanN4KFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgY2xhc3NOYW1lOiBjbHN4KFwiZXhjYWxpZHJhdyBleGNhbGlkcmF3LWNvbnRhaW5lclwiLCB7XG4gICAgICAgIFwiZXhjYWxpZHJhdy0tdmlldy1tb2RlXCI6IHRoaXMuc3RhdGUudmlld01vZGVFbmFibGVkLFxuICAgICAgICBcImV4Y2FsaWRyYXctLW1vYmlsZVwiOiB0aGlzLmRldmljZS5pc01vYmlsZVxuICAgICAgfSksXG4gICAgICBzdHlsZToge1xuICAgICAgICBbXCItLXVpLXBvaW50ZXJFdmVudHNcIl06IHRoaXMuc3RhdGUuc2VsZWN0aW9uRWxlbWVudCB8fCB0aGlzLnN0YXRlLmRyYWdnaW5nRWxlbWVudCB8fCB0aGlzLnN0YXRlLnJlc2l6aW5nRWxlbWVudCB8fCB0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50ICYmICFpc1RleHRFbGVtZW50KHRoaXMuc3RhdGUuZWRpdGluZ0VsZW1lbnQpID8gUE9JTlRFUl9FVkVOVFMuZGlzYWJsZWQgOiBQT0lOVEVSX0VWRU5UUy5lbmFibGVkXG4gICAgICB9LFxuICAgICAgcmVmOiB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYsXG4gICAgICBvbkRyb3A6IHRoaXMuaGFuZGxlQXBwT25Ecm9wLFxuICAgICAgdGFiSW5kZXg6IDAsXG4gICAgICBvbktleURvd246IHRoaXMucHJvcHMuaGFuZGxlS2V5Ym9hcmRHbG9iYWxseSA/IHVuZGVmaW5lZCA6IHRoaXMub25LZXlEb3duXG4gICAgfSwge1xuICAgICAgY2hpbGRyZW46IF9qc3goQXBwQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgIHZhbHVlOiB0aGlzXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBfanN4KEFwcFByb3BzQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgdmFsdWU6IHRoaXMucHJvcHNcbiAgICAgICAgfSwge1xuICAgICAgICAgIGNoaWxkcmVuOiBfanN4KEV4Y2FsaWRyYXdDb250YWluZXJDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJWYWx1ZVxuICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4KERldmljZUNvbnRleHQuUHJvdmlkZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5kZXZpY2VcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgY2hpbGRyZW46IF9qc3goRXhjYWxpZHJhd1NldEFwcFN0YXRlQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuc2V0QXBwU3RhdGVcbiAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4KEV4Y2FsaWRyYXdBcHBTdGF0ZUNvbnRleHQuUHJvdmlkZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuc3RhdGVcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICBjaGlsZHJlbjogX2pzeHMoRXhjYWxpZHJhd0VsZW1lbnRzQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpXG4gICAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBbX2pzeHMoRXhjYWxpZHJhd0FjdGlvbk1hbmFnZXJDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5hY3Rpb25NYW5hZ2VyXG4gICAgICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW19qc3goTGF5ZXJVSSwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYW52YXM6IHRoaXMuY2FudmFzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3RpdmVDYW52YXM6IHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBTdGF0ZTogdGhpcy5zdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzOiB0aGlzLmZpbGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0QXBwU3RhdGU6IHRoaXMuc2V0QXBwU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb25NYW5hZ2VyOiB0aGlzLmFjdGlvbk1hbmFnZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50czogdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uTG9ja1RvZ2dsZTogdGhpcy50b2dnbGVMb2NrLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25QZW5Nb2RlVG9nZ2xlOiB0aGlzLnRvZ2dsZVBlbk1vZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkhhbmRUb29sVG9nZ2xlOiB0aGlzLm9uSGFuZFRvb2xUb2dnbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYW5nQ29kZTogZ2V0TGFuZ3VhZ2UoKS5jb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyVG9wUmlnaHRVSTogcmVuZGVyVG9wUmlnaHRVSSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckN1c3RvbVN0YXRzOiByZW5kZXJDdXN0b21TdGF0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dFeGl0WmVuTW9kZUJ0bjogdHlwZW9mICgoX2EgPSB0aGlzLnByb3BzKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuemVuTW9kZUVuYWJsZWQpID09PSBcInVuZGVmaW5lZFwiICYmIHRoaXMuc3RhdGUuemVuTW9kZUVuYWJsZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBVSU9wdGlvbnM6IHRoaXMucHJvcHMuVUlPcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25JbWFnZUFjdGlvbjogdGhpcy5vbkltYWdlQWN0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25FeHBvcnRJbWFnZTogdGhpcy5vbkV4cG9ydEltYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyV2VsY29tZVNjcmVlbjogIXRoaXMuc3RhdGUuaXNMb2FkaW5nICYmIHRoaXMuc3RhdGUuc2hvd1dlbGNvbWVTY3JlZW4gJiYgdGhpcy5zdGF0ZS5hY3RpdmVUb29sLnR5cGUgPT09IFwic2VsZWN0aW9uXCIgJiYgIXRoaXMuc3RhdGUuemVuTW9kZUVuYWJsZWQgJiYgIXRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwOiB0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IHRoaXMucHJvcHMuY2hpbGRyZW5cbiAgICAgICAgICAgICAgICAgICAgICB9KSksIF9qc3goXCJkaXZcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXctdGV4dEVkaXRvckNvbnRhaW5lclwiXG4gICAgICAgICAgICAgICAgICAgICAgfSksIF9qc3goXCJkaXZcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXctY29udGV4dE1lbnVDb250YWluZXJcIlxuICAgICAgICAgICAgICAgICAgICAgIH0pLCBfanN4KFwiZGl2XCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogXCJleGNhbGlkcmF3LWV5ZS1kcm9wcGVyLWNvbnRhaW5lclwiXG4gICAgICAgICAgICAgICAgICAgICAgfSksIHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxICYmICF0aGlzLnN0YXRlLmNvbnRleHRNZW51ICYmIHRoaXMuc3RhdGUuc2hvd0h5cGVybGlua1BvcHVwICYmIF9qc3goSHlwZXJsaW5rLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBzZWxlY3RlZEVsZW1lbnRzWzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0QXBwU3RhdGU6IHRoaXMuc2V0QXBwU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkxpbmtPcGVuOiB0aGlzLnByb3BzLm9uTGlua09wZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUb2FzdDogdGhpcy5zZXRUb2FzdFxuICAgICAgICAgICAgICAgICAgICAgIH0sIHNlbGVjdGVkRWxlbWVudHNbMF0uaWQpLCB0aGlzLnN0YXRlLnRvYXN0ICE9PSBudWxsICYmIF9qc3goVG9hc3QsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHRoaXMuc3RhdGUudG9hc3QubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xvc2U6ICgpID0+IHRoaXMuc2V0VG9hc3QobnVsbCksXG4gICAgICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogdGhpcy5zdGF0ZS50b2FzdC5kdXJhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NhYmxlOiB0aGlzLnN0YXRlLnRvYXN0LmNsb3NhYmxlXG4gICAgICAgICAgICAgICAgICAgICAgfSksIHRoaXMuc3RhdGUuY29udGV4dE1lbnUgJiYgX2pzeChDb250ZXh0TWVudSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXM6IHRoaXMuc3RhdGUuY29udGV4dE1lbnUuaXRlbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3A6IHRoaXMuc3RhdGUuY29udGV4dE1lbnUudG9wLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogdGhpcy5zdGF0ZS5jb250ZXh0TWVudS5sZWZ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uTWFuYWdlcjogdGhpcy5hY3Rpb25NYW5hZ2VyXG4gICAgICAgICAgICAgICAgICAgICAgfSksIF9qc3goU3RhdGljQ2FudmFzLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYW52YXM6IHRoaXMuY2FudmFzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmM6IHRoaXMucmMsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50czogY2FudmFzRWxlbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmxlRWxlbWVudHM6IHZpc2libGVFbGVtZW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZlcnNpb25Ob25jZTogdmVyc2lvbk5vbmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uTm9uY2U6IChfYiA9IHRoaXMuc3RhdGUuc2VsZWN0aW9uRWxlbWVudCkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnZlcnNpb25Ob25jZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlOiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcFN0YXRlOiB0aGlzLnN0YXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyQ29uZmlnOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlQ2FjaGU6IHRoaXMuaW1hZ2VDYWNoZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaXNFeHBvcnRpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJHcmlkOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSksIF9qc3goSW50ZXJhY3RpdmVDYW52YXMsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lclJlZjogdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzOiB0aGlzLmludGVyYWN0aXZlQ2FudmFzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudHM6IGNhbnZhc0VsZW1lbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJsZUVsZW1lbnRzOiB2aXNpYmxlRWxlbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRzOiBzZWxlY3RlZEVsZW1lbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmVyc2lvbk5vbmNlOiB2ZXJzaW9uTm9uY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb25Ob25jZTogKF9jID0gdGhpcy5zdGF0ZS5zZWxlY3Rpb25FbGVtZW50KSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MudmVyc2lvbk5vbmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU6IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwU3RhdGU6IHRoaXMuc3RhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJJbnRlcmFjdGl2ZVNjZW5lQ2FsbGJhY2s6IHRoaXMucmVuZGVySW50ZXJhY3RpdmVTY2VuZUNhbGxiYWNrLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlQ2FudmFzUmVmOiB0aGlzLmhhbmRsZUludGVyYWN0aXZlQ2FudmFzUmVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgb25Db250ZXh0TWVudTogdGhpcy5oYW5kbGVDYW52YXNDb250ZXh0TWVudSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uUG9pbnRlck1vdmU6IHRoaXMuaGFuZGxlQ2FudmFzUG9pbnRlck1vdmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBvblBvaW50ZXJVcDogdGhpcy5oYW5kbGVDYW52YXNQb2ludGVyVXAsXG4gICAgICAgICAgICAgICAgICAgICAgICBvblBvaW50ZXJDYW5jZWw6IHRoaXMucmVtb3ZlUG9pbnRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVG91Y2hNb3ZlOiB0aGlzLmhhbmRsZVRvdWNoTW92ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uUG9pbnRlckRvd246IHRoaXMuaGFuZGxlQ2FudmFzUG9pbnRlckRvd24sXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkRvdWJsZUNsaWNrOiB0aGlzLmhhbmRsZUNhbnZhc0RvdWJsZUNsaWNrXG4gICAgICAgICAgICAgICAgICAgICAgfSksIHRoaXMucmVuZGVyRnJhbWVOYW1lcygpXVxuICAgICAgICAgICAgICAgICAgICB9KSksIHRoaXMucmVuZGVyRW1iZWRkYWJsZXMoKV1cbiAgICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICB9KSlcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgIH0pKVxuICAgICAgICB9KSlcbiAgICAgIH0pKVxuICAgIH0pKTtcbiAgfVxuXG4gIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgIHZhciBfYSwgX2I7XG5cbiAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICAgICAgdGhpcy51bm1vdW50ZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclZhbHVlLmNvbnRhaW5lciA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50O1xuXG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IEVOVi5URVNUIHx8IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBcInByb2R1Y3Rpb25cIikge1xuICAgICAgICBjb25zdCBzZXRTdGF0ZSA9IHRoaXMuc2V0U3RhdGUuYmluZCh0aGlzKTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMod2luZG93LmgsIHtcbiAgICAgICAgICBzdGF0ZToge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgc2V0U3RhdGU6IHtcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIHZhbHVlOiAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXRTdGF0ZSguLi5hcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIGFwcDoge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IHRoaXNcbiAgICAgICAgICB9LFxuICAgICAgICAgIGhpc3Rvcnk6IHtcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLmhpc3RvcnlcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNjZW5lLmFkZENhbGxiYWNrKHRoaXMub25TY2VuZVVwZGF0ZWQpO1xuICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVycygpO1xuXG4gICAgICBpZiAodGhpcy5wcm9wcy5hdXRvRm9jdXMgJiYgdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgdGhpcy5mb2N1c0NvbnRhaW5lcigpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQgJiYgLy8gYm91bmRpbmcgcmVjdHMgZG9uJ3Qgd29yayBpbiB0ZXN0cyBzbyB1cGRhdGluZ1xuICAgICAgLy8gdGhlIHN0YXRlIG9uIGluaXQgd291bGQgcmVzdWx0IGluIG1ha2luZyB0aGUgdGVzdCBlbnZpcm8gcnVuXG4gICAgICAvLyBpbiBtb2JpbGUgYnJlYWtwb2ludCAoMCB3aWR0aC9oZWlnaHQpLCBtYWtpbmcgZXZlcnl0aGluZyBmYWlsXG4gICAgICAhaXNUZXN0RW52KCkpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoRGV2aWNlU3RhdGUodGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoXCJSZXNpemVPYnNlcnZlclwiIGluIHdpbmRvdyAmJiAoKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY3VycmVudCkpIHtcbiAgICAgICAgdGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XG4gICAgICAgICAgLy8gcmVjb21wdXRlIGRldmljZSBkaW1lbnNpb25zIHN0YXRlXG4gICAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgICAgdGhpcy5yZWZyZXNoRGV2aWNlU3RhdGUodGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpOyAvLyByZWZyZXNoIG9mZnNldHNcbiAgICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAgICAgICAgIHRoaXMudXBkYXRlRE9NUmVjdCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgKF9iID0gdGhpcy5yZXNpemVPYnNlcnZlcikgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLm9ic2VydmUodGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpO1xuICAgICAgfSBlbHNlIGlmICh3aW5kb3cubWF0Y2hNZWRpYSkge1xuICAgICAgICBjb25zdCBtZFNjcmVlblF1ZXJ5ID0gd2luZG93Lm1hdGNoTWVkaWEoYChtYXgtd2lkdGg6ICR7TVFfTUFYX1dJRFRIX1BPUlRSQUlUfXB4KSwgKG1heC1oZWlnaHQ6ICR7TVFfTUFYX0hFSUdIVF9MQU5EU0NBUEV9cHgpIGFuZCAobWF4LXdpZHRoOiAke01RX01BWF9XSURUSF9MQU5EU0NBUEV9cHgpYCk7XG4gICAgICAgIGNvbnN0IHNtU2NyZWVuUXVlcnkgPSB3aW5kb3cubWF0Y2hNZWRpYShgKG1heC13aWR0aDogJHtNUV9TTV9NQVhfV0lEVEh9cHgpYCk7XG4gICAgICAgIGNvbnN0IGNhbkRldmljZUZpdFNpZGViYXJNZWRpYVF1ZXJ5ID0gd2luZG93Lm1hdGNoTWVkaWEoYChtaW4td2lkdGg6ICR7Ly8gTk9URSB0aGlzIHdvbid0IHVwZGF0ZSBpZiBhIGRpZmZlcmVudCBicmVha3BvaW50IGlzIHN1cHBsaWVkXG4gICAgICAgIC8vIGFmdGVyIG1vdW50XG4gICAgICAgIHRoaXMucHJvcHMuVUlPcHRpb25zLmRvY2tlZFNpZGViYXJCcmVha3BvaW50ICE9IG51bGwgPyB0aGlzLnByb3BzLlVJT3B0aW9ucy5kb2NrZWRTaWRlYmFyQnJlYWtwb2ludCA6IE1RX1JJR0hUX1NJREVCQVJfTUlOX1dJRFRIfXB4KWApO1xuXG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgdGhpcy5kZXZpY2UgPSB1cGRhdGVPYmplY3QodGhpcy5kZXZpY2UsIHtcbiAgICAgICAgICAgIGlzU21TY3JlZW46IHNtU2NyZWVuUXVlcnkubWF0Y2hlcyxcbiAgICAgICAgICAgIGlzTW9iaWxlOiBtZFNjcmVlblF1ZXJ5Lm1hdGNoZXMsXG4gICAgICAgICAgICBjYW5EZXZpY2VGaXRTaWRlYmFyOiBjYW5EZXZpY2VGaXRTaWRlYmFyTWVkaWFRdWVyeS5tYXRjaGVzXG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgbWRTY3JlZW5RdWVyeS5hZGRMaXN0ZW5lcihoYW5kbGVyKTtcblxuICAgICAgICB0aGlzLmRldGFjaElzTW9iaWxlTXFIYW5kbGVyID0gKCkgPT4gbWRTY3JlZW5RdWVyeS5yZW1vdmVMaXN0ZW5lcihoYW5kbGVyKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2VhcmNoUGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoLnNsaWNlKDEpKTtcblxuICAgICAgaWYgKHNlYXJjaFBhcmFtcy5oYXMoXCJ3ZWItc2hhcmUtdGFyZ2V0XCIpKSB7XG4gICAgICAgIC8vIE9idGFpbiBhIGZpbGUgdGhhdCB3YXMgc2hhcmVkIHZpYSB0aGUgV2ViIFNoYXJlIFRhcmdldCBBUEkuXG4gICAgICAgIHRoaXMucmVzdG9yZUZpbGVGcm9tU2hhcmUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudXBkYXRlRE9NUmVjdCh0aGlzLmluaXRpYWxpemVTY2VuZSk7XG4gICAgICB9IC8vIG5vdGUgdGhhdCB0aGlzIGNoZWNrIHNlZW1zIHRvIGFsd2F5cyBwYXNzIGluIGxvY2FsaG9zdFxuXG5cbiAgICAgIGlmIChpc0JyYXZlKCkgJiYgIWlzTWVhc3VyZVRleHRTdXBwb3J0ZWQoKSkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IF9qc3goQnJhdmVNZWFzdXJlVGV4dEVycm9yLCB7fSlcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBjb21wb25lbnRXaWxsVW5tb3VudCgpIHtcbiAgICB2YXIgX2E7XG5cbiAgICB0aGlzLnJlbmRlcmVyLmRlc3Ryb3koKTtcbiAgICB0aGlzLnNjZW5lID0gbmV3IFNjZW5lKCk7XG4gICAgdGhpcy5yZW5kZXJlciA9IG5ldyBSZW5kZXJlcih0aGlzLnNjZW5lKTtcbiAgICB0aGlzLmZpbGVzID0ge307XG4gICAgdGhpcy5pbWFnZUNhY2hlLmNsZWFyKCk7XG4gICAgKF9hID0gdGhpcy5yZXNpemVPYnNlcnZlcikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmRpc2Nvbm5lY3QoKTtcbiAgICB0aGlzLnVubW91bnRlZCA9IHRydWU7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVycygpO1xuICAgIHRoaXMuc2NlbmUuZGVzdHJveSgpO1xuICAgIHRoaXMubGlicmFyeS5kZXN0cm95KCk7XG4gICAgU2hhcGVDYWNoZS5kZXN0cm95KCk7XG4gICAgY2xlYXJUaW1lb3V0KHRvdWNoVGltZW91dCk7XG4gICAgaXNTb21lRWxlbWVudFNlbGVjdGVkLmNsZWFyQ2FjaGUoKTtcbiAgICBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzLmNsZWFyQ2FjaGUoKTtcbiAgICB0b3VjaFRpbWVvdXQgPSAwO1xuICB9XG5cbiAgcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZTtcblxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgdGhpcy5yZW1vdmVQb2ludGVyKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkNPUFksIHRoaXMub25Db3B5KTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlBBU1RFLCB0aGlzLnBhc3RlRnJvbUNsaXBib2FyZCk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5DVVQsIHRoaXMub25DdXQpO1xuICAgIChfYSA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5XSEVFTCwgdGhpcy5vbldoZWVsKTtcbiAgICAoX2IgPSB0aGlzLm5lYXJlc3RTY3JvbGxhYmxlQ29udGFpbmVyKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5TQ1JPTEwsIHRoaXMub25TY3JvbGwpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZRE9XTiwgdGhpcy5vbktleURvd24sIGZhbHNlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULk1PVVNFX01PVkUsIHRoaXMudXBkYXRlQ3VycmVudEN1cnNvclBvc2l0aW9uLCBmYWxzZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5LRVlVUCwgdGhpcy5vbktleVVwKTtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5SRVNJWkUsIHRoaXMub25SZXNpemUsIGZhbHNlKTtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5VTkxPQUQsIHRoaXMub25VbmxvYWQsIGZhbHNlKTtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5CTFVSLCB0aGlzLm9uQmx1ciwgZmFsc2UpO1xuICAgIChfYyA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5EUkFHX09WRVIsIHRoaXMuZGlzYWJsZUV2ZW50LCBmYWxzZSk7XG4gICAgKF9kID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkRST1AsIHRoaXMuZGlzYWJsZUV2ZW50LCBmYWxzZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5HRVNUVVJFX1NUQVJULCB0aGlzLm9uR2VzdHVyZVN0YXJ0LCBmYWxzZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5HRVNUVVJFX0NIQU5HRSwgdGhpcy5vbkdlc3R1cmVDaGFuZ2UsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkdFU1RVUkVfRU5ELCB0aGlzLm9uR2VzdHVyZUVuZCwgZmFsc2UpO1xuICAgIChfZSA9IHRoaXMuZGV0YWNoSXNNb2JpbGVNcUhhbmRsZXIpID09PSBudWxsIHx8IF9lID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZS5jYWxsKHRoaXMpO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULk1FU1NBR0UsIHRoaXMub25XaW5kb3dNZXNzYWdlLCBmYWxzZSk7XG4gIH1cblxuICBhZGRFdmVudExpc3RlbmVycygpIHtcbiAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lO1xuXG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVycygpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULk1FU1NBR0UsIHRoaXMub25XaW5kb3dNZXNzYWdlLCBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCB0aGlzLnJlbW92ZVBvaW50ZXIpOyAvLyAjMzU1M1xuXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5DT1BZLCB0aGlzLm9uQ29weSk7XG4gICAgKF9hID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5hZGRFdmVudExpc3RlbmVyKEVWRU5ULldIRUVMLCB0aGlzLm9uV2hlZWwsIHtcbiAgICAgIHBhc3NpdmU6IGZhbHNlXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5wcm9wcy5oYW5kbGVLZXlib2FyZEdsb2JhbGx5KSB7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULktFWURPV04sIHRoaXMub25LZXlEb3duLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5LRVlVUCwgdGhpcy5vbktleVVwLCB7XG4gICAgICBwYXNzaXZlOiB0cnVlXG4gICAgfSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5NT1VTRV9NT1ZFLCB0aGlzLnVwZGF0ZUN1cnJlbnRDdXJzb3JQb3NpdGlvbik7IC8vIHJlcmVuZGVyIHRleHQgZWxlbWVudHMgb24gZm9udCBsb2FkIHRvIGZpeCAjNjM3ICYmICMxNTUzXG5cbiAgICAoX2MgPSAoX2IgPSBkb2N1bWVudC5mb250cykgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmFkZEV2ZW50TGlzdGVuZXIpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5jYWxsKF9iLCBcImxvYWRpbmdkb25lXCIsIGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IGxvYWRlZEZvbnRGYWNlcyA9IGV2ZW50LmZvbnRmYWNlcztcbiAgICAgIHRoaXMuZm9udHMub25Gb250c0xvYWRlZChsb2FkZWRGb250RmFjZXMpO1xuICAgIH0pOyAvLyBTYWZhcmktb25seSBkZXNrdG9wIHBpbmNoIHpvb21cblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuR0VTVFVSRV9TVEFSVCwgdGhpcy5vbkdlc3R1cmVTdGFydCwgZmFsc2UpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuR0VTVFVSRV9DSEFOR0UsIHRoaXMub25HZXN0dXJlQ2hhbmdlLCBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5HRVNUVVJFX0VORCwgdGhpcy5vbkdlc3R1cmVFbmQsIGZhbHNlKTtcblxuICAgIGlmICh0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUEFTVEUsIHRoaXMucGFzdGVGcm9tQ2xpcGJvYXJkKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKEVWRU5ULkNVVCwgdGhpcy5vbkN1dCk7XG5cbiAgICBpZiAodGhpcy5wcm9wcy5kZXRlY3RTY3JvbGwpIHtcbiAgICAgIHRoaXMubmVhcmVzdFNjcm9sbGFibGVDb250YWluZXIgPSBnZXROZWFyZXN0U2Nyb2xsYWJsZUNvbnRhaW5lcih0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCk7XG4gICAgICB0aGlzLm5lYXJlc3RTY3JvbGxhYmxlQ29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuU0NST0xMLCB0aGlzLm9uU2Nyb2xsKTtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5SRVNJWkUsIHRoaXMub25SZXNpemUsIGZhbHNlKTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5VTkxPQUQsIHRoaXMub25VbmxvYWQsIGZhbHNlKTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5CTFVSLCB0aGlzLm9uQmx1ciwgZmFsc2UpO1xuICAgIChfZCA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5EUkFHX09WRVIsIHRoaXMuZGlzYWJsZUV2ZW50LCBmYWxzZSk7XG4gICAgKF9lID0gdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQpID09PSBudWxsIHx8IF9lID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZS5hZGRFdmVudExpc3RlbmVyKEVWRU5ULkRST1AsIHRoaXMuZGlzYWJsZUV2ZW50LCBmYWxzZSk7XG4gIH1cblxuICBjb21wb25lbnREaWRVcGRhdGUocHJldlByb3BzLCBwcmV2U3RhdGUpIHtcbiAgICB2YXIgX2EsIF9iLCBfYywgX2QsIF9lLCBfZjtcblxuICAgIHRoaXMudXBkYXRlRW1iZWRkYWJsZXMoKTtcblxuICAgIGlmICghdGhpcy5zdGF0ZS5zaG93V2VsY29tZVNjcmVlbiAmJiAhdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKS5sZW5ndGgpIHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBzaG93V2VsY29tZVNjcmVlbjogdHJ1ZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50ICYmIHByZXZQcm9wcy5VSU9wdGlvbnMuZG9ja2VkU2lkZWJhckJyZWFrcG9pbnQgIT09IHRoaXMucHJvcHMuVUlPcHRpb25zLmRvY2tlZFNpZGViYXJCcmVha3BvaW50KSB7XG4gICAgICB0aGlzLnJlZnJlc2hEZXZpY2VTdGF0ZSh0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudCk7XG4gICAgfVxuXG4gICAgaWYgKHByZXZTdGF0ZS5zY3JvbGxYICE9PSB0aGlzLnN0YXRlLnNjcm9sbFggfHwgcHJldlN0YXRlLnNjcm9sbFkgIT09IHRoaXMuc3RhdGUuc2Nyb2xsWSkge1xuICAgICAgKF9iID0gKF9hID0gdGhpcy5wcm9wcykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLm9uU2Nyb2xsQ2hhbmdlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuY2FsbChfYSwgdGhpcy5zdGF0ZS5zY3JvbGxYLCB0aGlzLnN0YXRlLnNjcm9sbFkpO1xuICAgIH1cblxuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkcykubGVuZ3RoICYmIGlzRXJhc2VyQWN0aXZlKHRoaXMuc3RhdGUpKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgYWN0aXZlVG9vbDogdXBkYXRlQWN0aXZlVG9vbCh0aGlzLnN0YXRlLCB7XG4gICAgICAgICAgdHlwZTogXCJzZWxlY3Rpb25cIlxuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImVyYXNlclwiICYmIHByZXZTdGF0ZS50aGVtZSAhPT0gdGhpcy5zdGF0ZS50aGVtZSkge1xuICAgICAgc2V0RXJhc2VyQ3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIHRoaXMuc3RhdGUudGhlbWUpO1xuICAgIH0gLy8gSGlkZSBoeXBlcmxpbmsgcG9wdXAgaWYgc2hvd24gd2hlbiBlbGVtZW50IHR5cGUgaXMgbm90IHNlbGVjdGlvblxuXG5cbiAgICBpZiAocHJldlN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJzZWxlY3Rpb25cIiAmJiB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSAhPT0gXCJzZWxlY3Rpb25cIiAmJiB0aGlzLnN0YXRlLnNob3dIeXBlcmxpbmtQb3B1cCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHNob3dIeXBlcmxpbmtQb3B1cDogZmFsc2VcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChwcmV2UHJvcHMubGFuZ0NvZGUgIT09IHRoaXMucHJvcHMubGFuZ0NvZGUpIHtcbiAgICAgIHRoaXMudXBkYXRlTGFuZ3VhZ2UoKTtcbiAgICB9XG5cbiAgICBpZiAocHJldlByb3BzLnZpZXdNb2RlRW5hYmxlZCAhPT0gdGhpcy5wcm9wcy52aWV3TW9kZUVuYWJsZWQpIHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICB2aWV3TW9kZUVuYWJsZWQ6ICEhdGhpcy5wcm9wcy52aWV3TW9kZUVuYWJsZWRcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChwcmV2U3RhdGUudmlld01vZGVFbmFibGVkICE9PSB0aGlzLnN0YXRlLnZpZXdNb2RlRW5hYmxlZCkge1xuICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVycygpO1xuICAgICAgdGhpcy5kZXNlbGVjdEVsZW1lbnRzKCk7XG4gICAgfVxuXG4gICAgaWYgKHByZXZQcm9wcy56ZW5Nb2RlRW5hYmxlZCAhPT0gdGhpcy5wcm9wcy56ZW5Nb2RlRW5hYmxlZCkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHplbk1vZGVFbmFibGVkOiAhIXRoaXMucHJvcHMuemVuTW9kZUVuYWJsZWRcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChwcmV2UHJvcHMudGhlbWUgIT09IHRoaXMucHJvcHMudGhlbWUgJiYgdGhpcy5wcm9wcy50aGVtZSkge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHRoZW1lOiB0aGlzLnByb3BzLnRoZW1lXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocHJldlByb3BzLmdyaWRNb2RlRW5hYmxlZCAhPT0gdGhpcy5wcm9wcy5ncmlkTW9kZUVuYWJsZWQpIHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBncmlkU2l6ZTogdGhpcy5wcm9wcy5ncmlkTW9kZUVuYWJsZWQgPyBHUklEX1NJWkUgOiBudWxsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9wcy5uYW1lICYmIHByZXZQcm9wcy5uYW1lICE9PSB0aGlzLnByb3BzLm5hbWUpIHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBuYW1lOiB0aGlzLnByb3BzLm5hbWVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIChfYyA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MuY2xhc3NMaXN0LnRvZ2dsZShcInRoZW1lLS1kYXJrXCIsIHRoaXMuc3RhdGUudGhlbWUgPT09IFwiZGFya1wiKTtcblxuICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50ICYmICF0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1t0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmVsZW1lbnRJZF0pIHtcbiAgICAgIC8vIGRlZmVyIHNvIHRoYXQgdGhlIGNvbW1pdFRvSGlzdG9yeSBmbGFnIGlzbid0IHJlc2V0IHZpYSBjdXJyZW50IHVwZGF0ZVxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIC8vIGV4ZWN1dGUgb25seSBpZiB0aGUgY29uZGl0aW9uIHN0aWxsIGhvbGRzIHdoZW4gdGhlIGRlZmVycmVkIGNhbGxiYWNrXG4gICAgICAgIC8vIGV4ZWN1dGVzIChpdCBjYW4gYmUgc2NoZWR1bGVkIG11bHRpcGxlIHRpbWVzIGRlcGVuZGluZyBvbiBob3dcbiAgICAgICAgLy8gbWFueSB0aW1lcyB0aGUgY29tcG9uZW50IHJlbmRlcnMpXG4gICAgICAgIHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgJiYgdGhpcy5hY3Rpb25NYW5hZ2VyLmV4ZWN1dGVBY3Rpb24oYWN0aW9uRmluYWxpemUpO1xuICAgICAgfSk7XG4gICAgfSAvLyBmYWlsc2FmZSBpbiBjYXNlIHRoZSBzdGF0ZSBpcyBiZWluZyB1cGRhdGVkIGluIGluY29ycmVjdCBvcmRlciByZXN1bHRpbmdcbiAgICAvLyBpbiB0aGUgZWRpdGluZ0VsZW1lbnQgYmVpbmcgbm93IGEgZGVsZXRlZCBlbGVtZW50XG5cblxuICAgIGlmICgoX2QgPSB0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50KSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QuaXNEZWxldGVkKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IG51bGxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCAmJiAhdGhpcy5zdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHNbdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQuZWxlbWVudElkXSkge1xuICAgICAgLy8gVG8gbWFrZSBzdXJlIGBzZWxlY3RlZExpbmVhckVsZW1lbnRgIGlzIGluIHN5bmMgd2l0aCBgc2VsZWN0ZWRFbGVtZW50SWRzYCwgaG93ZXZlciB0aGlzIHNob3VsZG4ndCBiZSBuZWVkZWQgb25jZVxuICAgICAgLy8gd2UgaGF2ZSBhIHNpbmdsZSBBUEkgdG8gdXBkYXRlIGBzZWxlY3RlZEVsZW1lbnRJZHNgXG4gICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBudWxsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICBtdWx0aUVsZW1lbnRcbiAgICB9ID0gcHJldlN0YXRlO1xuXG4gICAgaWYgKHByZXZTdGF0ZS5hY3RpdmVUb29sICE9PSB0aGlzLnN0YXRlLmFjdGl2ZVRvb2wgJiYgbXVsdGlFbGVtZW50ICE9IG51bGwgJiYgaXNCaW5kaW5nRW5hYmxlZCh0aGlzLnN0YXRlKSAmJiBpc0JpbmRpbmdFbGVtZW50KG11bHRpRWxlbWVudCwgZmFsc2UpKSB7XG4gICAgICBtYXliZUJpbmRMaW5lYXJFbGVtZW50KG11bHRpRWxlbWVudCwgdGhpcy5zdGF0ZSwgdGhpcy5zY2VuZSwgdHVwbGVUb0Nvb3JzKExpbmVhckVsZW1lbnRFZGl0b3IuZ2V0UG9pbnRBdEluZGV4R2xvYmFsQ29vcmRpbmF0ZXMobXVsdGlFbGVtZW50LCAtMSkpKTtcbiAgICB9XG5cbiAgICB0aGlzLmhpc3RvcnkucmVjb3JkKHRoaXMuc3RhdGUsIHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkpOyAvLyBEbyBub3Qgbm90aWZ5IGNvbnN1bWVycyBpZiB3ZSdyZSBzdGlsbCBsb2FkaW5nIHRoZSBzY2VuZS4gQW1vbmcgb3RoZXJcbiAgICAvLyBwb3RlbnRpYWwgaXNzdWVzLCB0aGlzIGZpeGVzIGEgY2FzZSB3aGVyZSB0aGUgdGFiIGlzbid0IGZvY3VzZWQgZHVyaW5nXG4gICAgLy8gaW5pdCwgd2hpY2ggd291bGQgdHJpZ2dlciBvbkNoYW5nZSB3aXRoIGVtcHR5IGVsZW1lbnRzLCB3aGljaCB3b3VsZCB0aGVuXG4gICAgLy8gb3ZlcnJpZGUgd2hhdGV2ZXIgaXMgaW4gbG9jYWxTdG9yYWdlIGN1cnJlbnRseS5cblxuICAgIGlmICghdGhpcy5zdGF0ZS5pc0xvYWRpbmcpIHtcbiAgICAgIChfZiA9IChfZSA9IHRoaXMucHJvcHMpLm9uQ2hhbmdlKSA9PT0gbnVsbCB8fCBfZiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2YuY2FsbChfZSwgdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKSwgdGhpcy5zdGF0ZSwgdGhpcy5maWxlcyk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHJlc2V0VGFwVHdpY2UoKSB7XG4gICAgZGlkVGFwVHdpY2UgPSBmYWxzZTtcbiAgfVxuXG4gIGFkZFRleHRGcm9tUGFzdGUodGV4dCwgaXNQbGFpblBhc3RlID0gZmFsc2UpIHtcbiAgICBjb25zdCB7XG4gICAgICB4LFxuICAgICAgeVxuICAgIH0gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgY2xpZW50WDogdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi54LFxuICAgICAgY2xpZW50WTogdGhpcy5sYXN0Vmlld3BvcnRQb3NpdGlvbi55XG4gICAgfSwgdGhpcy5zdGF0ZSk7XG4gICAgY29uc3QgdGV4dEVsZW1lbnRQcm9wcyA9IHtcbiAgICAgIHgsXG4gICAgICB5LFxuICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1TdHJva2VDb2xvcixcbiAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUJhY2tncm91bmRDb2xvcixcbiAgICAgIGZpbGxTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbUZpbGxTdHlsZSxcbiAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtU3Ryb2tlV2lkdGgsXG4gICAgICBzdHJva2VTdHlsZTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVN0cm9rZVN0eWxlLFxuICAgICAgcm91bmRuZXNzOiBudWxsLFxuICAgICAgcm91Z2huZXNzOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtUm91Z2huZXNzLFxuICAgICAgb3BhY2l0eTogdGhpcy5zdGF0ZS5jdXJyZW50SXRlbU9wYWNpdHksXG4gICAgICB0ZXh0LFxuICAgICAgZm9udFNpemU6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Gb250U2l6ZSxcbiAgICAgIGZvbnRGYW1pbHk6IHRoaXMuc3RhdGUuY3VycmVudEl0ZW1Gb250RmFtaWx5LFxuICAgICAgdGV4dEFsaWduOiB0aGlzLnN0YXRlLmN1cnJlbnRJdGVtVGV4dEFsaWduLFxuICAgICAgdmVydGljYWxBbGlnbjogREVGQVVMVF9WRVJUSUNBTF9BTElHTixcbiAgICAgIGxvY2tlZDogZmFsc2VcbiAgICB9O1xuICAgIGNvbnN0IExJTkVfR0FQID0gMTA7XG4gICAgbGV0IGN1cnJlbnRZID0geTtcbiAgICBjb25zdCBsaW5lcyA9IGlzUGxhaW5QYXN0ZSA/IFt0ZXh0XSA6IHRleHQuc3BsaXQoXCJcXG5cIik7XG4gICAgY29uc3QgdGV4dEVsZW1lbnRzID0gbGluZXMucmVkdWNlKChhY2MsIGxpbmUsIGlkeCkgPT4ge1xuICAgICAgdmFyIF9hO1xuXG4gICAgICBjb25zdCB0ZXh0ID0gbGluZS50cmltKCk7XG4gICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gZ2V0RGVmYXVsdExpbmVIZWlnaHQodGV4dEVsZW1lbnRQcm9wcy5mb250RmFtaWx5KTtcblxuICAgICAgaWYgKHRleHQubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IHRvcExheWVyRnJhbWUgPSB0aGlzLmdldFRvcExheWVyRnJhbWVBdFNjZW5lQ29vcmRzKHtcbiAgICAgICAgICB4LFxuICAgICAgICAgIHk6IGN1cnJlbnRZXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gbmV3VGV4dEVsZW1lbnQoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0ZXh0RWxlbWVudFByb3BzKSwge1xuICAgICAgICAgIHgsXG4gICAgICAgICAgeTogY3VycmVudFksXG4gICAgICAgICAgdGV4dCxcbiAgICAgICAgICBsaW5lSGVpZ2h0LFxuICAgICAgICAgIGZyYW1lSWQ6IHRvcExheWVyRnJhbWUgPyB0b3BMYXllckZyYW1lLmlkIDogbnVsbFxuICAgICAgICB9KSk7XG4gICAgICAgIGFjYy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICBjdXJyZW50WSArPSBlbGVtZW50LmhlaWdodCArIExJTkVfR0FQO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcHJldkxpbmUgPSAoX2EgPSBsaW5lc1tpZHggLSAxXSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnRyaW0oKTsgLy8gYWRkIHBhcmFncmFwaCBvbmx5IGlmIHByZXZpb3VzIGxpbmUgd2FzIG5vdCBlbXB0eSwgSU9XIGRvbid0IGFkZFxuICAgICAgICAvLyBtb3JlIHRoYW4gb25lIGVtcHR5IGxpbmVcblxuICAgICAgICBpZiAocHJldkxpbmUpIHtcbiAgICAgICAgICBjdXJyZW50WSArPSBnZXRMaW5lSGVpZ2h0SW5QeCh0ZXh0RWxlbWVudFByb3BzLmZvbnRTaXplLCBsaW5lSGVpZ2h0KSArIExJTkVfR0FQO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwgW10pO1xuXG4gICAgaWYgKHRleHRFbGVtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmcmFtZUlkID0gdGV4dEVsZW1lbnRzWzBdLmZyYW1lSWQ7XG5cbiAgICBpZiAoZnJhbWVJZCkge1xuICAgICAgdGhpcy5zY2VuZS5pbnNlcnRFbGVtZW50c0F0SW5kZXgodGV4dEVsZW1lbnRzLCB0aGlzLnNjZW5lLmdldEVsZW1lbnRJbmRleChmcmFtZUlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKFsuLi50aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCAuLi50ZXh0RWxlbWVudHNdKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmZyb21FbnRyaWVzKHRleHRFbGVtZW50cy5tYXAoZWwgPT4gW2VsLmlkLCB0cnVlXSkpLCB0aGlzLnN0YXRlKVxuICAgIH0pO1xuXG4gICAgaWYgKCFpc1BsYWluUGFzdGUgJiYgdGV4dEVsZW1lbnRzLmxlbmd0aCA+IDEgJiYgUExBSU5fUEFTVEVfVE9BU1RfU0hPV04gPT09IGZhbHNlICYmICF0aGlzLmRldmljZS5pc01vYmlsZSkge1xuICAgICAgdGhpcy5zZXRUb2FzdCh7XG4gICAgICAgIG1lc3NhZ2U6IHQoXCJ0b2FzdC5wYXN0ZUFzU2luZ2xlRWxlbWVudFwiLCB7XG4gICAgICAgICAgc2hvcnRjdXQ6IGdldFNob3J0Y3V0S2V5KFwiQ3RybE9yQ21kK1NoaWZ0K1ZcIilcbiAgICAgICAgfSksXG4gICAgICAgIGR1cmF0aW9uOiA1MDAwXG4gICAgICB9KTtcbiAgICAgIFBMQUlOX1BBU1RFX1RPQVNUX1NIT1dOID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmhpc3RvcnkucmVzdW1lUmVjb3JkaW5nKCk7XG4gIH1cblxuICBoYW5kbGVUZXh0V3lzaXd5ZyhlbGVtZW50LCB7XG4gICAgaXNFeGlzdGluZ0VsZW1lbnQgPSBmYWxzZVxuICB9KSB7XG4gICAgY29uc3QgdXBkYXRlRWxlbWVudCA9ICh0ZXh0LCBvcmlnaW5hbFRleHQsIGlzRGVsZXRlZCkgPT4ge1xuICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoWy4uLnRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkubWFwKF9lbGVtZW50ID0+IHtcbiAgICAgICAgaWYgKF9lbGVtZW50LmlkID09PSBlbGVtZW50LmlkICYmIGlzVGV4dEVsZW1lbnQoX2VsZW1lbnQpKSB7XG4gICAgICAgICAgcmV0dXJuIHVwZGF0ZVRleHRFbGVtZW50KF9lbGVtZW50LCB7XG4gICAgICAgICAgICB0ZXh0LFxuICAgICAgICAgICAgaXNEZWxldGVkLFxuICAgICAgICAgICAgb3JpZ2luYWxUZXh0XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gX2VsZW1lbnQ7XG4gICAgICB9KV0pO1xuICAgIH07XG5cbiAgICB0ZXh0V3lzaXd5Zyh7XG4gICAgICBpZDogZWxlbWVudC5pZCxcbiAgICAgIGNhbnZhczogdGhpcy5jYW52YXMsXG4gICAgICBnZXRWaWV3cG9ydENvb3JkczogKHgsIHkpID0+IHtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHg6IHZpZXdwb3J0WCxcbiAgICAgICAgICB5OiB2aWV3cG9ydFlcbiAgICAgICAgfSA9IHNjZW5lQ29vcmRzVG9WaWV3cG9ydENvb3Jkcyh7XG4gICAgICAgICAgc2NlbmVYOiB4LFxuICAgICAgICAgIHNjZW5lWTogeVxuICAgICAgICB9LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgcmV0dXJuIFt2aWV3cG9ydFggLSB0aGlzLnN0YXRlLm9mZnNldExlZnQsIHZpZXdwb3J0WSAtIHRoaXMuc3RhdGUub2Zmc2V0VG9wXTtcbiAgICAgIH0sXG4gICAgICBvbkNoYW5nZTogd2l0aEJhdGNoZWRVcGRhdGVzKHRleHQgPT4ge1xuICAgICAgICB1cGRhdGVFbGVtZW50KHRleHQsIHRleHQsIGZhbHNlKTtcblxuICAgICAgICBpZiAoaXNOb25EZWxldGVkRWxlbWVudChlbGVtZW50KSkge1xuICAgICAgICAgIHVwZGF0ZUJvdW5kRWxlbWVudHMoZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICAgb25TdWJtaXQ6IHdpdGhCYXRjaGVkVXBkYXRlcygoe1xuICAgICAgICB0ZXh0LFxuICAgICAgICB2aWFLZXlib2FyZCxcbiAgICAgICAgb3JpZ2luYWxUZXh0XG4gICAgICB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGlzRGVsZXRlZCA9ICF0ZXh0LnRyaW0oKTtcbiAgICAgICAgdXBkYXRlRWxlbWVudCh0ZXh0LCBvcmlnaW5hbFRleHQsIGlzRGVsZXRlZCk7IC8vIHNlbGVjdCB0aGUgY3JlYXRlZCB0ZXh0IGVsZW1lbnQgb25seSBpZiBzdWJtaXR0aW5nIHZpYSBrZXlib2FyZFxuICAgICAgICAvLyAod2hlbiBzdWJtaXR0aW5nIHZpYSBjbGljayBpdCBzaG91bGQgYWN0IGFzIHNpZ25hbCB0byBkZXNlbGVjdClcblxuICAgICAgICBpZiAoIWlzRGVsZXRlZCAmJiB2aWFLZXlib2FyZCkge1xuICAgICAgICAgIGNvbnN0IGVsZW1lbnRJZFRvU2VsZWN0ID0gZWxlbWVudC5jb250YWluZXJJZCA/IGVsZW1lbnQuY29udGFpbmVySWQgOiBlbGVtZW50LmlkO1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+ICh7XG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyksIHtcbiAgICAgICAgICAgICAgW2VsZW1lbnRJZFRvU2VsZWN0XTogdHJ1ZVxuICAgICAgICAgICAgfSksIHByZXZTdGF0ZSlcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNEZWxldGVkKSB7XG4gICAgICAgICAgZml4QmluZGluZ3NBZnRlckRlbGV0aW9uKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIFtlbGVtZW50XSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzRGVsZXRlZCB8fCBpc0V4aXN0aW5nRWxlbWVudCkge1xuICAgICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgICBlZGl0aW5nRWxlbWVudDogbnVsbFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS5hY3RpdmVUb29sLmxvY2tlZCkge1xuICAgICAgICAgIHNldEN1cnNvckZvclNoYXBlKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5mb2N1c0NvbnRhaW5lcigpO1xuICAgICAgfSksXG4gICAgICBlbGVtZW50LFxuICAgICAgZXhjYWxpZHJhd0NvbnRhaW5lcjogdGhpcy5leGNhbGlkcmF3Q29udGFpbmVyUmVmLmN1cnJlbnQsXG4gICAgICBhcHA6IHRoaXNcbiAgICB9KTsgLy8gZGVzZWxlY3QgYWxsIG90aGVyIGVsZW1lbnRzIHdoZW4gaW5zZXJ0aW5nIHRleHRcblxuICAgIHRoaXMuZGVzZWxlY3RFbGVtZW50cygpOyAvLyBkbyBhbiBpbml0aWFsIHVwZGF0ZSB0byByZS1pbml0aWFsaXplIGVsZW1lbnQgcG9zaXRpb24gc2luY2Ugd2Ugd2VyZVxuICAgIC8vIG1vZGlmeWluZyBlbGVtZW50J3MgeC95IGZvciBzYWtlIG9mIGVkaXRvciAoY2FzZTogc3luY2luZyB0byByZW1vdGUpXG5cbiAgICB1cGRhdGVFbGVtZW50KGVsZW1lbnQudGV4dCwgZWxlbWVudC5vcmlnaW5hbFRleHQsIGZhbHNlKTtcbiAgfVxuXG4gIGRlc2VsZWN0RWxlbWVudHMoKSB7XG4gICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCB0aGlzLnN0YXRlKSxcbiAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IHt9LFxuICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGwsXG4gICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsXG4gICAgfSk7XG4gIH1cblxuICBnZXRUZXh0RWxlbWVudEF0UG9zaXRpb24oeCwgeSkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRBdFBvc2l0aW9uKHgsIHksIHtcbiAgICAgIGluY2x1ZGVCb3VuZFRleHRFbGVtZW50OiB0cnVlXG4gICAgfSk7XG5cbiAgICBpZiAoZWxlbWVudCAmJiBpc1RleHRFbGVtZW50KGVsZW1lbnQpICYmICFlbGVtZW50LmlzRGVsZXRlZCkge1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRFbGVtZW50QXRQb3NpdGlvbih4LCB5LCBvcHRzKSB7XG4gICAgY29uc3QgYWxsSGl0RWxlbWVudHMgPSB0aGlzLmdldEVsZW1lbnRzQXRQb3NpdGlvbih4LCB5LCBvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMuaW5jbHVkZUJvdW5kVGV4dEVsZW1lbnQsIG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5pbmNsdWRlTG9ja2VkRWxlbWVudHMpO1xuXG4gICAgaWYgKGFsbEhpdEVsZW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGlmIChvcHRzID09PSBudWxsIHx8IG9wdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdHMucHJlZmVyU2VsZWN0ZWQpIHtcbiAgICAgICAgZm9yIChsZXQgaW5kZXggPSBhbGxIaXRFbGVtZW50cy5sZW5ndGggLSAxOyBpbmRleCA+IC0xOyBpbmRleC0tKSB7XG4gICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2FsbEhpdEVsZW1lbnRzW2luZGV4XS5pZF0pIHtcbiAgICAgICAgICAgIHJldHVybiBhbGxIaXRFbGVtZW50c1tpbmRleF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVsZW1lbnRXaXRoSGlnaGVzdFpJbmRleCA9IGFsbEhpdEVsZW1lbnRzW2FsbEhpdEVsZW1lbnRzLmxlbmd0aCAtIDFdOyAvLyBJZiB3ZSdyZSBoaXR0aW5nIGVsZW1lbnQgd2l0aCBoaWdoZXN0IHotaW5kZXggb25seSBvbiBpdHMgYm91bmRpbmcgYm94XG4gICAgICAvLyB3aGlsZSBhbHNvIGhpdHRpbmcgb3RoZXIgZWxlbWVudCBmaWd1cmUsIHRoZSBsYXR0ZXIgc2hvdWxkIGJlIGNvbnNpZGVyZWQuXG5cbiAgICAgIHJldHVybiBpc0hpdHRpbmdFbGVtZW50Qm91bmRpbmdCb3hXaXRob3V0SGl0dGluZ0VsZW1lbnQoZWxlbWVudFdpdGhIaWdoZXN0WkluZGV4LCB0aGlzLnN0YXRlLCB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLCB4LCB5KSA/IGFsbEhpdEVsZW1lbnRzW2FsbEhpdEVsZW1lbnRzLmxlbmd0aCAtIDJdIDogZWxlbWVudFdpdGhIaWdoZXN0WkluZGV4O1xuICAgIH1cblxuICAgIGlmIChhbGxIaXRFbGVtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBhbGxIaXRFbGVtZW50c1swXTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGdldEVsZW1lbnRzQXRQb3NpdGlvbih4LCB5LCBpbmNsdWRlQm91bmRUZXh0RWxlbWVudCA9IGZhbHNlLCBpbmNsdWRlTG9ja2VkRWxlbWVudHMgPSBmYWxzZSkge1xuICAgIGNvbnN0IGVsZW1lbnRzID0gaW5jbHVkZUJvdW5kVGV4dEVsZW1lbnQgJiYgaW5jbHVkZUxvY2tlZEVsZW1lbnRzID8gdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSA6IHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCkuZmlsdGVyKGVsZW1lbnQgPT4gKGluY2x1ZGVMb2NrZWRFbGVtZW50cyB8fCAhZWxlbWVudC5sb2NrZWQpICYmIChpbmNsdWRlQm91bmRUZXh0RWxlbWVudCB8fCAhKGlzVGV4dEVsZW1lbnQoZWxlbWVudCkgJiYgZWxlbWVudC5jb250YWluZXJJZCkpKTtcbiAgICByZXR1cm4gZ2V0RWxlbWVudHNBdFBvc2l0aW9uKGVsZW1lbnRzLCBlbGVtZW50ID0+IGhpdFRlc3QoZWxlbWVudCwgdGhpcy5zdGF0ZSwgdGhpcy5mcmFtZU5hbWVCb3VuZHNDYWNoZSwgeCwgeSkpLmZpbHRlcihlbGVtZW50ID0+IHtcbiAgICAgIC8vIGhpdHRpbmcgYSBmcmFtZSdzIGVsZW1lbnQgZnJvbSBvdXRzaWRlIHRoZSBmcmFtZSBpcyBub3QgY29uc2lkZXJlZCBhIGhpdFxuICAgICAgY29uc3QgY29udGFpbmluZ0ZyYW1lID0gZ2V0Q29udGFpbmluZ0ZyYW1lKGVsZW1lbnQpO1xuICAgICAgcmV0dXJuIGNvbnRhaW5pbmdGcmFtZSAmJiB0aGlzLnN0YXRlLmZyYW1lUmVuZGVyaW5nLmVuYWJsZWQgJiYgdGhpcy5zdGF0ZS5mcmFtZVJlbmRlcmluZy5jbGlwID8gaXNDdXJzb3JJbkZyYW1lKHtcbiAgICAgICAgeCxcbiAgICAgICAgeVxuICAgICAgfSwgY29udGFpbmluZ0ZyYW1lKSA6IHRydWU7XG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVIb3ZlclNlbGVjdGVkTGluZWFyRWxlbWVudChsaW5lYXJFbGVtZW50RWRpdG9yLCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZKSB7XG4gICAgY29uc3QgZWxlbWVudCA9IExpbmVhckVsZW1lbnRFZGl0b3IuZ2V0RWxlbWVudChsaW5lYXJFbGVtZW50RWRpdG9yLmVsZW1lbnRJZCk7XG4gICAgY29uc3QgYm91bmRUZXh0RWxlbWVudCA9IGdldEJvdW5kVGV4dEVsZW1lbnQoZWxlbWVudCk7XG5cbiAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQpIHtcbiAgICAgIGxldCBob3ZlclBvaW50SW5kZXggPSAtMTtcbiAgICAgIGxldCBzZWdtZW50TWlkUG9pbnRIb3ZlcmVkQ29vcmRzID0gbnVsbDtcblxuICAgICAgaWYgKGlzSGl0dGluZ0VsZW1lbnROb3RDb25zaWRlcmluZ0JvdW5kaW5nQm94KGVsZW1lbnQsIHRoaXMuc3RhdGUsIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUsIFtzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZXSkpIHtcbiAgICAgICAgaG92ZXJQb2ludEluZGV4ID0gTGluZWFyRWxlbWVudEVkaXRvci5nZXRQb2ludEluZGV4VW5kZXJDdXJzb3IoZWxlbWVudCwgdGhpcy5zdGF0ZS56b29tLCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZKTtcbiAgICAgICAgc2VnbWVudE1pZFBvaW50SG92ZXJlZENvb3JkcyA9IExpbmVhckVsZW1lbnRFZGl0b3IuZ2V0U2VnbWVudE1pZHBvaW50SGl0Q29vcmRzKGxpbmVhckVsZW1lbnRFZGl0b3IsIHtcbiAgICAgICAgICB4OiBzY2VuZVBvaW50ZXJYLFxuICAgICAgICAgIHk6IHNjZW5lUG9pbnRlcllcbiAgICAgICAgfSwgdGhpcy5zdGF0ZSk7XG5cbiAgICAgICAgaWYgKGhvdmVyUG9pbnRJbmRleCA+PSAwIHx8IHNlZ21lbnRNaWRQb2ludEhvdmVyZWRDb29yZHMpIHtcbiAgICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuUE9JTlRFUik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLk1PVkUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHNob3VsZFNob3dCb3VuZGluZ0JveChbZWxlbWVudF0sIHRoaXMuc3RhdGUpICYmIGlzSGl0dGluZ0VsZW1lbnRCb3VuZGluZ0JveFdpdGhvdXRIaXR0aW5nRWxlbWVudChlbGVtZW50LCB0aGlzLnN0YXRlLCB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZKSkge1xuICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuTU9WRSk7XG4gICAgICB9IGVsc2UgaWYgKGJvdW5kVGV4dEVsZW1lbnQgJiYgaGl0VGVzdChib3VuZFRleHRFbGVtZW50LCB0aGlzLnN0YXRlLCB0aGlzLmZyYW1lTmFtZUJvdW5kc0NhY2hlLCBzY2VuZVBvaW50ZXJYLCBzY2VuZVBvaW50ZXJZKSkge1xuICAgICAgICBzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgQ1VSU09SX1RZUEUuTU9WRSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudC5ob3ZlclBvaW50SW5kZXggIT09IGhvdmVyUG9pbnRJbmRleCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQpLCB7XG4gICAgICAgICAgICBob3ZlclBvaW50SW5kZXhcbiAgICAgICAgICB9KVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFMaW5lYXJFbGVtZW50RWRpdG9yLmFyZVBvaW50c0VxdWFsKHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50LnNlZ21lbnRNaWRQb2ludEhvdmVyZWRDb29yZHMsIHNlZ21lbnRNaWRQb2ludEhvdmVyZWRDb29yZHMpKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCksIHtcbiAgICAgICAgICAgIHNlZ21lbnRNaWRQb2ludEhvdmVyZWRDb29yZHNcbiAgICAgICAgICB9KVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc2V0Q3Vyc29yKHRoaXMuaW50ZXJhY3RpdmVDYW52YXMsIENVUlNPUl9UWVBFLkFVVE8pO1xuICAgIH1cbiAgfVxuXG4gIG1heWJlQ2xlYW51cEFmdGVyTWlzc2luZ1BvaW50ZXJVcChldmVudCkge1xuICAgIGlmIChsYXN0UG9pbnRlclVwICE9PSBudWxsKSB7XG4gICAgICAvLyBVbmZvcnR1bmF0ZWx5LCBzb21ldGltZXMgd2UgZG9uJ3QgZ2V0IGEgcG9pbnRlcnVwIGFmdGVyIGEgcG9pbnRlcmRvd24sXG4gICAgICAvLyB0aGlzIGNhbiBoYXBwZW4gd2hlbiBhIGNvbnRleHR1YWwgbWVudSBvciBhbGVydCBpcyB0cmlnZ2VyZWQuIEluIG9yZGVyIHRvIGF2b2lkXG4gICAgICAvLyBiZWluZyBpbiBhIHdlaXJkIHN0YXRlLCB3ZSBjbGVhbiB1cCBvbiB0aGUgbmV4dCBwb2ludGVyZG93blxuICAgICAgbGFzdFBvaW50ZXJVcChldmVudCk7XG4gICAgfVxuICB9XG5cbiAgdXBkYXRlR2VzdHVyZU9uUG9pbnRlckRvd24oZXZlbnQpIHtcbiAgICBnZXN0dXJlLnBvaW50ZXJzLnNldChldmVudC5wb2ludGVySWQsIHtcbiAgICAgIHg6IGV2ZW50LmNsaWVudFgsXG4gICAgICB5OiBldmVudC5jbGllbnRZXG4gICAgfSk7XG5cbiAgICBpZiAoZ2VzdHVyZS5wb2ludGVycy5zaXplID09PSAyKSB7XG4gICAgICBnZXN0dXJlLmxhc3RDZW50ZXIgPSBnZXRDZW50ZXIoZ2VzdHVyZS5wb2ludGVycyk7XG4gICAgICBnZXN0dXJlLmluaXRpYWxTY2FsZSA9IHRoaXMuc3RhdGUuem9vbS52YWx1ZTtcbiAgICAgIGdlc3R1cmUuaW5pdGlhbERpc3RhbmNlID0gZ2V0RGlzdGFuY2UoQXJyYXkuZnJvbShnZXN0dXJlLnBvaW50ZXJzLnZhbHVlcygpKSk7XG4gICAgfVxuICB9XG5cbiAgaW5pdGlhbFBvaW50ZXJEb3duU3RhdGUoZXZlbnQpIHtcbiAgICBjb25zdCBvcmlnaW4gPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoZXZlbnQsIHRoaXMuc3RhdGUpO1xuICAgIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHModGhpcy5zdGF0ZSk7XG4gICAgY29uc3QgW21pblgsIG1pblksIG1heFgsIG1heFldID0gZ2V0Q29tbW9uQm91bmRzKHNlbGVjdGVkRWxlbWVudHMpO1xuICAgIHJldHVybiB7XG4gICAgICBvcmlnaW4sXG4gICAgICB3aXRoQ21kT3JDdHJsOiBldmVudFtLRVlTLkNUUkxfT1JfQ01EXSxcbiAgICAgIG9yaWdpbkluR3JpZDogdHVwbGVUb0Nvb3JzKGdldEdyaWRQb2ludChvcmlnaW4ueCwgb3JpZ2luLnksIGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpKSxcbiAgICAgIHNjcm9sbGJhcnM6IGlzT3ZlclNjcm9sbEJhcnMoY3VycmVudFNjcm9sbEJhcnMsIGV2ZW50LmNsaWVudFggLSB0aGlzLnN0YXRlLm9mZnNldExlZnQsIGV2ZW50LmNsaWVudFkgLSB0aGlzLnN0YXRlLm9mZnNldFRvcCksXG4gICAgICAvLyB3ZSBuZWVkIHRvIGR1cGxpY2F0ZSBiZWNhdXNlIHdlJ2xsIGJlIHVwZGF0aW5nIHRoaXMgc3RhdGVcbiAgICAgIGxhc3RDb29yZHM6IE9iamVjdC5hc3NpZ24oe30sIG9yaWdpbiksXG4gICAgICBvcmlnaW5hbEVsZW1lbnRzOiB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLnJlZHVjZSgoYWNjLCBlbGVtZW50KSA9PiB7XG4gICAgICAgIGFjYy5zZXQoZWxlbWVudC5pZCwgZGVlcENvcHlFbGVtZW50KGVsZW1lbnQpKTtcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sIG5ldyBNYXAoKSksXG4gICAgICByZXNpemU6IHtcbiAgICAgICAgaGFuZGxlVHlwZTogZmFsc2UsXG4gICAgICAgIGlzUmVzaXppbmc6IGZhbHNlLFxuICAgICAgICBvZmZzZXQ6IHtcbiAgICAgICAgICB4OiAwLFxuICAgICAgICAgIHk6IDBcbiAgICAgICAgfSxcbiAgICAgICAgYXJyb3dEaXJlY3Rpb246IFwib3JpZ2luXCIsXG4gICAgICAgIGNlbnRlcjoge1xuICAgICAgICAgIHg6IChtYXhYICsgbWluWCkgLyAyLFxuICAgICAgICAgIHk6IChtYXhZICsgbWluWSkgLyAyXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBoaXQ6IHtcbiAgICAgICAgZWxlbWVudDogbnVsbCxcbiAgICAgICAgYWxsSGl0RWxlbWVudHM6IFtdLFxuICAgICAgICB3YXNBZGRlZFRvU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgaGFzQmVlbkR1cGxpY2F0ZWQ6IGZhbHNlLFxuICAgICAgICBoYXNIaXRDb21tb25Cb3VuZGluZ0JveE9mU2VsZWN0ZWRFbGVtZW50czogdGhpcy5pc0hpdHRpbmdDb21tb25Cb3VuZGluZ0JveE9mU2VsZWN0ZWRFbGVtZW50cyhvcmlnaW4sIHNlbGVjdGVkRWxlbWVudHMpXG4gICAgICB9LFxuICAgICAgZHJhZzoge1xuICAgICAgICBoYXNPY2N1cnJlZDogZmFsc2UsXG4gICAgICAgIG9mZnNldDogbnVsbFxuICAgICAgfSxcbiAgICAgIGV2ZW50TGlzdGVuZXJzOiB7XG4gICAgICAgIG9uTW92ZTogbnVsbCxcbiAgICAgICAgb25VcDogbnVsbCxcbiAgICAgICAgb25LZXlVcDogbnVsbCxcbiAgICAgICAgb25LZXlEb3duOiBudWxsXG4gICAgICB9LFxuICAgICAgYm94U2VsZWN0aW9uOiB7XG4gICAgICAgIGhhc09jY3VycmVkOiBmYWxzZVxuICAgICAgfSxcbiAgICAgIGVsZW1lbnRJZHNUb0VyYXNlOiB7fVxuICAgIH07XG4gIH0gLy8gUmV0dXJucyB3aGV0aGVyIHRoZSBldmVudCBpcyBhIGRyYWdnaW5nIGEgc2Nyb2xsYmFyXG5cblxuICBoYW5kbGVEcmFnZ2luZ1Njcm9sbEJhcihldmVudCwgcG9pbnRlckRvd25TdGF0ZSkge1xuICAgIGlmICghKHBvaW50ZXJEb3duU3RhdGUuc2Nyb2xsYmFycy5pc092ZXJFaXRoZXIgJiYgIXRoaXMuc3RhdGUubXVsdGlFbGVtZW50KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlzRHJhZ2dpbmdTY3JvbGxCYXIgPSB0cnVlO1xuICAgIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy54ID0gZXZlbnQuY2xpZW50WDtcbiAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueSA9IGV2ZW50LmNsaWVudFk7XG4gICAgY29uc3Qgb25Qb2ludGVyTW92ZSA9IHdpdGhCYXRjaGVkVXBkYXRlc1Rocm90dGxlZChldmVudCA9PiB7XG4gICAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQ7XG5cbiAgICAgIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaGFuZGxlUG9pbnRlck1vdmVPdmVyU2Nyb2xsYmFycyhldmVudCwgcG9pbnRlckRvd25TdGF0ZSk7XG4gICAgfSk7XG4gICAgY29uc3Qgb25Qb2ludGVyVXAgPSB3aXRoQmF0Y2hlZFVwZGF0ZXMoKCkgPT4ge1xuICAgICAgaXNEcmFnZ2luZ1Njcm9sbEJhciA9IGZhbHNlO1xuICAgICAgc2V0Q3Vyc29yRm9yU2hhcGUodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcywgdGhpcy5zdGF0ZSk7XG4gICAgICBsYXN0UG9pbnRlclVwID0gbnVsbDtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBjdXJzb3JCdXR0b246IFwidXBcIlxuICAgICAgfSk7XG4gICAgICB0aGlzLnNhdmVQb2ludGVyKGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIFwidXBcIik7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX01PVkUsIG9uUG9pbnRlck1vdmUpO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgb25Qb2ludGVyVXApO1xuICAgICAgb25Qb2ludGVyTW92ZS5mbHVzaCgpO1xuICAgIH0pO1xuICAgIGxhc3RQb2ludGVyVXAgPSBvblBvaW50ZXJVcDtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX01PVkUsIG9uUG9pbnRlck1vdmUpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIG9uUG9pbnRlclVwKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlzQVNlbGVjdGVkRWxlbWVudChoaXRFbGVtZW50KSB7XG4gICAgcmV0dXJuIGhpdEVsZW1lbnQgIT0gbnVsbCAmJiB0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1toaXRFbGVtZW50LmlkXTtcbiAgfVxuXG4gIGlzSGl0dGluZ0NvbW1vbkJvdW5kaW5nQm94T2ZTZWxlY3RlZEVsZW1lbnRzKHBvaW50LCBzZWxlY3RlZEVsZW1lbnRzKSB7XG4gICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gLy8gSG93IG1hbnkgcGl4ZWxzIG9mZiB0aGUgc2hhcGUgYm91bmRhcnkgd2Ugc3RpbGwgY29uc2lkZXIgYSBoaXRcblxuXG4gICAgY29uc3QgdGhyZXNob2xkID0gMTAgLyB0aGlzLnN0YXRlLnpvb20udmFsdWU7XG4gICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IGdldENvbW1vbkJvdW5kcyhzZWxlY3RlZEVsZW1lbnRzKTtcbiAgICByZXR1cm4gcG9pbnQueCA+IHgxIC0gdGhyZXNob2xkICYmIHBvaW50LnggPCB4MiArIHRocmVzaG9sZCAmJiBwb2ludC55ID4geTEgLSB0aHJlc2hvbGQgJiYgcG9pbnQueSA8IHkyICsgdGhyZXNob2xkO1xuICB9XG5cbiAgZ2V0Q3VycmVudEl0ZW1Sb3VuZG5lc3MoZWxlbWVudFR5cGUpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5jdXJyZW50SXRlbVJvdW5kbmVzcyA9PT0gXCJyb3VuZFwiID8ge1xuICAgICAgdHlwZTogaXNVc2luZ0FkYXB0aXZlUmFkaXVzKGVsZW1lbnRUeXBlKSA/IFJPVU5ETkVTUy5BREFQVElWRV9SQURJVVMgOiBST1VORE5FU1MuUFJPUE9SVElPTkFMX1JBRElVU1xuICAgIH0gOiBudWxsO1xuICB9XG5cbiAgb25LZXlEb3duRnJvbVBvaW50ZXJEb3duSGFuZGxlcihwb2ludGVyRG93blN0YXRlKSB7XG4gICAgcmV0dXJuIHdpdGhCYXRjaGVkVXBkYXRlcyhldmVudCA9PiB7XG4gICAgICBpZiAodGhpcy5tYXliZUhhbmRsZVJlc2l6ZShwb2ludGVyRG93blN0YXRlLCBldmVudCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm1heWJlRHJhZ05ld0dlbmVyaWNFbGVtZW50KHBvaW50ZXJEb3duU3RhdGUsIGV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIG9uS2V5VXBGcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpIHtcbiAgICByZXR1cm4gd2l0aEJhdGNoZWRVcGRhdGVzKGV2ZW50ID0+IHtcbiAgICAgIC8vIFByZXZlbnRzIGZvY3VzIGZyb20gZXNjYXBpbmcgZXhjYWxpZHJhdyB0YWJcbiAgICAgIGV2ZW50LmtleSA9PT0gS0VZUy5BTFQgJiYgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgaWYgKHRoaXMubWF5YmVIYW5kbGVSZXNpemUocG9pbnRlckRvd25TdGF0ZSwgZXZlbnQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5tYXliZURyYWdOZXdHZW5lcmljRWxlbWVudChwb2ludGVyRG93blN0YXRlLCBldmVudCk7XG4gICAgfSk7XG4gIH1cblxuICBvblBvaW50ZXJNb3ZlRnJvbVBvaW50ZXJEb3duSGFuZGxlcihwb2ludGVyRG93blN0YXRlKSB7XG4gICAgcmV0dXJuIHdpdGhCYXRjaGVkVXBkYXRlc1Rocm90dGxlZChldmVudCA9PiB7XG4gICAgICB2YXIgX2EsIF9iOyAvLyBXZSBuZWVkIHRvIGluaXRpYWxpemUgZHJhZ09mZnNldFhZIG9ubHkgYWZ0ZXIgd2UndmUgdXBkYXRlZFxuICAgICAgLy8gYHN0YXRlLnNlbGVjdGVkRWxlbWVudElkc2Agb24gcG9pbnRlckRvd24uIERvaW5nIGl0IGhlcmUgaW4gcG9pbnRlck1vdmVcbiAgICAgIC8vIGV2ZW50IGhhbmRsZXIgc2hvdWxkIGhvcGVmdWxseSBlbnN1cmUgd2UncmUgYWxyZWFkeSB3b3JraW5nIHdpdGhcbiAgICAgIC8vIHRoZSB1cGRhdGVkIHN0YXRlLlxuXG5cbiAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLmRyYWcub2Zmc2V0ID09PSBudWxsKSB7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuZHJhZy5vZmZzZXQgPSB0dXBsZVRvQ29vcnMoZ2V0RHJhZ09mZnNldFhZKHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKSwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSkpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQ7XG5cbiAgICAgIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmhhbmRsZVBvaW50ZXJNb3ZlT3ZlclNjcm9sbGJhcnMoZXZlbnQsIHBvaW50ZXJEb3duU3RhdGUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcG9pbnRlckNvb3JkcyA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhldmVudCwgdGhpcy5zdGF0ZSk7XG5cbiAgICAgIGlmIChpc0VyYXNlckFjdGl2ZSh0aGlzLnN0YXRlKSkge1xuICAgICAgICB0aGlzLmhhbmRsZUVyYXNlcihldmVudCwgcG9pbnRlckRvd25TdGF0ZSwgcG9pbnRlckNvb3Jkcyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgW2dyaWRYLCBncmlkWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckNvb3Jkcy54LCBwb2ludGVyQ29vcmRzLnksIGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpOyAvLyBmb3IgYXJyb3dzL2xpbmVzLCBkb24ndCBzdGFydCBkcmFnZ2luZyB1bnRpbCBhIGdpdmVuIHRocmVzaG9sZFxuICAgICAgLy8gdG8gZW5zdXJlIHdlIGRvbid0IGNyZWF0ZSBhIDItcG9pbnQgYXJyb3cgYnkgbWlzdGFrZSB3aGVuXG4gICAgICAvLyB1c2VyIGNsaWNrcyBtb3VzZSBpbiBhIHdheSB0aGF0IGl0IG1vdmVzIGEgdGlueSBiaXQgKHRodXNcbiAgICAgIC8vIHRyaWdnZXJpbmcgcG9pbnRlcm1vdmUpXG5cbiAgICAgIGlmICghcG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkICYmICh0aGlzLnN0YXRlLmFjdGl2ZVRvb2wudHlwZSA9PT0gXCJhcnJvd1wiIHx8IHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcImxpbmVcIikpIHtcbiAgICAgICAgaWYgKGRpc3RhbmNlMmQocG9pbnRlckNvb3Jkcy54LCBwb2ludGVyQ29vcmRzLnksIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnkpIDwgRFJBR0dJTkdfVEhSRVNIT0xEKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLnJlc2l6ZS5pc1Jlc2l6aW5nKSB7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy54ID0gcG9pbnRlckNvb3Jkcy54O1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueSA9IHBvaW50ZXJDb29yZHMueTtcblxuICAgICAgICBpZiAodGhpcy5tYXliZUhhbmRsZVJlc2l6ZShwb2ludGVyRG93blN0YXRlLCBldmVudCkpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgbGluZWFyRWxlbWVudEVkaXRvciA9IHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgfHwgdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQ7XG5cbiAgICAgICAgaWYgKExpbmVhckVsZW1lbnRFZGl0b3Iuc2hvdWxkQWRkTWlkcG9pbnQodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQsIHBvaW50ZXJDb29yZHMsIHRoaXMuc3RhdGUpKSB7XG4gICAgICAgICAgY29uc3QgcmV0ID0gTGluZWFyRWxlbWVudEVkaXRvci5hZGRNaWRwb2ludCh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCwgcG9pbnRlckNvb3JkcywgdGhpcy5zdGF0ZSwgIWV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdKTtcblxuICAgICAgICAgIGlmICghcmV0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSAvLyBTaW5jZSB3ZSBhcmUgcmVhZGluZyBmcm9tIHByZXZpb3VzIHN0YXRlIHdoaWNoIGlzIG5vdCBwb3NzaWJsZSB3aXRoXG4gICAgICAgICAgLy8gYXV0b21hdGljIGJhdGNoaW5nIGluIFJlYWN0IDE4IGhlbmNlIHVzaW5nIGZsdXNoIHN5bmMgdG8gc3luY2hyb25vdXNseVxuICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgc3RhdGUuIENoZWNrIGh0dHBzOi8vZ2l0aHViLmNvbS9leGNhbGlkcmF3L2V4Y2FsaWRyYXcvcHVsbC81NTA4IGZvciBtb3JlIGRldGFpbHMuXG5cblxuICAgICAgICAgIGZsdXNoU3luYygoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSwge1xuICAgICAgICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZTogcmV0LnBvaW50ZXJEb3duU3RhdGUsXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZFBvaW50c0luZGljZXM6IHJldC5zZWxlY3RlZFBvaW50c0luZGljZXNcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgZWRpdGluZ0xpbmVhckVsZW1lbnQ6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCksIHtcbiAgICAgICAgICAgICAgICAgIHBvaW50ZXJEb3duU3RhdGU6IHJldC5wb2ludGVyRG93blN0YXRlLFxuICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRQb2ludHNJbmRpY2VzOiByZXQuc2VsZWN0ZWRQb2ludHNJbmRpY2VzXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKGxpbmVhckVsZW1lbnRFZGl0b3IucG9pbnRlckRvd25TdGF0ZS5zZWdtZW50TWlkcG9pbnQudmFsdWUgIT09IG51bGwgJiYgIWxpbmVhckVsZW1lbnRFZGl0b3IucG9pbnRlckRvd25TdGF0ZS5zZWdtZW50TWlkcG9pbnQuYWRkZWQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkaWREcmFnID0gTGluZWFyRWxlbWVudEVkaXRvci5oYW5kbGVQb2ludERyYWdnaW5nKGV2ZW50LCB0aGlzLnN0YXRlLCBwb2ludGVyQ29vcmRzLngsIHBvaW50ZXJDb29yZHMueSwgKGVsZW1lbnQsIHBvaW50c1NjZW5lQ29vcmRzKSA9PiB7XG4gICAgICAgICAgdGhpcy5tYXliZVN1Z2dlc3RCaW5kaW5nc0ZvckxpbmVhckVsZW1lbnRBdENvb3JkcyhlbGVtZW50LCBwb2ludHNTY2VuZUNvb3Jkcyk7XG4gICAgICAgIH0sIGxpbmVhckVsZW1lbnRFZGl0b3IpO1xuXG4gICAgICAgIGlmIChkaWREcmFnKSB7XG4gICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnggPSBwb2ludGVyQ29vcmRzLng7XG4gICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnkgPSBwb2ludGVyQ29vcmRzLnk7XG4gICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkID0gdHJ1ZTtcblxuICAgICAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50ICYmICF0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LmlzRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICBlZGl0aW5nTGluZWFyRWxlbWVudDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSwge1xuICAgICAgICAgICAgICAgIGlzRHJhZ2dpbmc6IHRydWVcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQuaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCksIHtcbiAgICAgICAgICAgICAgICBpc0RyYWdnaW5nOiB0cnVlXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgaGFzSGl0QVNlbGVjdGVkRWxlbWVudCA9IHBvaW50ZXJEb3duU3RhdGUuaGl0LmFsbEhpdEVsZW1lbnRzLnNvbWUoZWxlbWVudCA9PiB0aGlzLmlzQVNlbGVjdGVkRWxlbWVudChlbGVtZW50KSk7XG4gICAgICBjb25zdCBpc1NlbGVjdGluZ1BvaW50c0luTGluZUVkaXRvciA9IHRoaXMuc3RhdGUuZWRpdGluZ0xpbmVhckVsZW1lbnQgJiYgZXZlbnQuc2hpZnRLZXkgJiYgdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudC5lbGVtZW50SWQgPT09ICgoX2EgPSBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuaWQpO1xuXG4gICAgICBpZiAoKGhhc0hpdEFTZWxlY3RlZEVsZW1lbnQgfHwgcG9pbnRlckRvd25TdGF0ZS5oaXQuaGFzSGl0Q29tbW9uQm91bmRpbmdCb3hPZlNlbGVjdGVkRWxlbWVudHMpICYmICFpc1NlbGVjdGluZ1BvaW50c0luTGluZUVkaXRvcikge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuXG4gICAgICAgIGlmIChzZWxlY3RlZEVsZW1lbnRzLmV2ZXJ5KGVsZW1lbnQgPT4gZWxlbWVudC5sb2NrZWQpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50c0hhc0FGcmFtZSA9IHNlbGVjdGVkRWxlbWVudHMuZmluZChlID0+IGlzRnJhbWVFbGVtZW50KGUpKTtcbiAgICAgICAgY29uc3QgdG9wTGF5ZXJGcmFtZSA9IHRoaXMuZ2V0VG9wTGF5ZXJGcmFtZUF0U2NlbmVDb29yZHMocG9pbnRlckNvb3Jkcyk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGZyYW1lVG9IaWdobGlnaHQ6IHRvcExheWVyRnJhbWUgJiYgIXNlbGVjdGVkRWxlbWVudHNIYXNBRnJhbWUgPyB0b3BMYXllckZyYW1lIDogbnVsbFxuICAgICAgICB9KTsgLy8gTWFya2luZyB0aGF0IGNsaWNrIHdhcyB1c2VkIGZvciBkcmFnZ2luZyB0byBjaGVja1xuICAgICAgICAvLyBpZiBlbGVtZW50cyBzaG91bGQgYmUgZGVzZWxlY3RlZCBvbiBwb2ludGVydXBcblxuICAgICAgICBwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRzQXJlQmVpbmdEcmFnZ2VkOiB0cnVlXG4gICAgICAgIH0pOyAvLyBwcmV2ZW50IGRyYWdnaW5nIGV2ZW4gaWYgd2UncmUgbm8gbG9uZ2VyIGhvbGRpbmcgY21kL2N0cmwgb3RoZXJ3aXNlXG4gICAgICAgIC8vIGl0IHdvdWxkIGhhdmUgd2VpcmQgcmVzdWx0cyAoc3R1ZmYganVtcGluZyBhbGwgb3ZlciB0aGUgc2NyZWVuKVxuICAgICAgICAvLyBDaGVja2luZyBmb3IgZWRpdGluZ0VsZW1lbnQgdG8gYXZvaWQganVtcCB3aGlsZSBlZGl0aW5nIG9uIG1vYmlsZSAjNjUwM1xuXG4gICAgICAgIGlmIChzZWxlY3RlZEVsZW1lbnRzLmxlbmd0aCA+IDAgJiYgIXBvaW50ZXJEb3duU3RhdGUud2l0aENtZE9yQ3RybCAmJiAhdGhpcy5zdGF0ZS5lZGl0aW5nRWxlbWVudCAmJiAoKF9iID0gdGhpcy5zdGF0ZS5hY3RpdmVFbWJlZGRhYmxlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iuc3RhdGUpICE9PSBcImFjdGl2ZVwiKSB7XG4gICAgICAgICAgY29uc3QgW2RyYWdYLCBkcmFnWV0gPSBnZXRHcmlkUG9pbnQocG9pbnRlckNvb3Jkcy54IC0gcG9pbnRlckRvd25TdGF0ZS5kcmFnLm9mZnNldC54LCBwb2ludGVyQ29vcmRzLnkgLSBwb2ludGVyRG93blN0YXRlLmRyYWcub2Zmc2V0LnksIGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpO1xuICAgICAgICAgIGNvbnN0IFtkcmFnRGlzdGFuY2VYLCBkcmFnRGlzdGFuY2VZXSA9IFtNYXRoLmFicyhwb2ludGVyQ29vcmRzLnggLSBwb2ludGVyRG93blN0YXRlLm9yaWdpbi54KSwgTWF0aC5hYnMocG9pbnRlckNvb3Jkcy55IC0gcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSldOyAvLyBXZSBvbmx5IGRyYWcgaW4gb25lIGRpcmVjdGlvbiBpZiBzaGlmdCBpcyBwcmVzc2VkXG5cbiAgICAgICAgICBjb25zdCBsb2NrRGlyZWN0aW9uID0gZXZlbnQuc2hpZnRLZXk7IC8vIHdoZW4gd2UncmUgZWRpdGluZyB0aGUgbmFtZSBvZiBhIGZyYW1lLCB3ZSB3YW50IHRoZSB1c2VyIHRvIGJlXG4gICAgICAgICAgLy8gYWJsZSB0byBzZWxlY3QgYW5kIGludGVyYWN0IHdpdGggdGhlIHRleHQgaW5wdXRcblxuICAgICAgICAgICF0aGlzLnN0YXRlLmVkaXRpbmdGcmFtZSAmJiBkcmFnU2VsZWN0ZWRFbGVtZW50cyhwb2ludGVyRG93blN0YXRlLCBzZWxlY3RlZEVsZW1lbnRzLCBkcmFnWCwgZHJhZ1ksIGxvY2tEaXJlY3Rpb24sIGRyYWdEaXN0YW5jZVgsIGRyYWdEaXN0YW5jZVksIHRoaXMuc3RhdGUsIHRoaXMuc2NlbmUpO1xuICAgICAgICAgIHRoaXMubWF5YmVTdWdnZXN0QmluZGluZ0ZvckFsbChzZWxlY3RlZEVsZW1lbnRzKTsgLy8gV2UgZHVwbGljYXRlIHRoZSBzZWxlY3RlZCBlbGVtZW50IGlmIGFsdCBpcyBwcmVzc2VkIG9uIHBvaW50ZXIgbW92ZVxuXG4gICAgICAgICAgaWYgKGV2ZW50LmFsdEtleSAmJiAhcG9pbnRlckRvd25TdGF0ZS5oaXQuaGFzQmVlbkR1cGxpY2F0ZWQpIHtcbiAgICAgICAgICAgIC8vIE1vdmUgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBlbGVtZW50cyB0byB0aGUgdG9wIG9mIHRoZSB6IGluZGV4IHN0YWNrLCBhbmRcbiAgICAgICAgICAgIC8vIHB1dCB0aGUgZHVwbGljYXRlcyB3aGVyZSB0aGUgc2VsZWN0ZWQgZWxlbWVudHMgdXNlZCB0byBiZS5cbiAgICAgICAgICAgIC8vICh0aGUgb3JpZ2luIHBvaW50IHdoZXJlIHRoZSBkcmFnZ2luZyBzdGFydGVkKVxuICAgICAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5oaXQuaGFzQmVlbkR1cGxpY2F0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3QgbmV4dEVsZW1lbnRzID0gW107XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50c1RvQXBwZW5kID0gW107XG4gICAgICAgICAgICBjb25zdCBncm91cElkTWFwID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgY29uc3Qgb2xkSWRUb0R1cGxpY2F0ZWRJZCA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIGNvbnN0IGhpdEVsZW1lbnQgPSBwb2ludGVyRG93blN0YXRlLmhpdC5lbGVtZW50O1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWRFbGVtZW50SWRzID0gbmV3IFNldCh0aGlzLnNjZW5lLmdldFNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzLFxuICAgICAgICAgICAgICBpbmNsdWRlQm91bmRUZXh0RWxlbWVudDogdHJ1ZSxcbiAgICAgICAgICAgICAgaW5jbHVkZUVsZW1lbnRzSW5GcmFtZXM6IHRydWVcbiAgICAgICAgICAgIH0pLm1hcChlbGVtZW50ID0+IGVsZW1lbnQuaWQpKTtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKTtcblxuICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7XG4gICAgICAgICAgICAgIGlmIChzZWxlY3RlZEVsZW1lbnRJZHMuaGFzKGVsZW1lbnQuaWQpIHx8IC8vIGNhc2U6IHRoZSBzdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMgbWlnaHQgbm90IGhhdmUgYmVlblxuICAgICAgICAgICAgICAvLyB1cGRhdGVkIHlldCBieSB0aGUgdGltZSB0aGlzIG1vdXNlbW92ZSBldmVudCBpcyBmaXJlZFxuICAgICAgICAgICAgICBlbGVtZW50LmlkID09PSAoaGl0RWxlbWVudCA9PT0gbnVsbCB8fCBoaXRFbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBoaXRFbGVtZW50LmlkKSAmJiBwb2ludGVyRG93blN0YXRlLmhpdC53YXNBZGRlZFRvU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZHVwbGljYXRlZEVsZW1lbnQgPSBkdXBsaWNhdGVFbGVtZW50KHRoaXMuc3RhdGUuZWRpdGluZ0dyb3VwSWQsIGdyb3VwSWRNYXAsIGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IFtvcmlnaW5EcmFnWCwgb3JpZ2luRHJhZ1ldID0gZ2V0R3JpZFBvaW50KHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnggLSBwb2ludGVyRG93blN0YXRlLmRyYWcub2Zmc2V0LngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnkgLSBwb2ludGVyRG93blN0YXRlLmRyYWcub2Zmc2V0LnksIGV2ZW50W0tFWVMuQ1RSTF9PUl9DTURdID8gbnVsbCA6IHRoaXMuc3RhdGUuZ3JpZFNpemUpO1xuICAgICAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZHVwbGljYXRlZEVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgICAgIHg6IGR1cGxpY2F0ZWRFbGVtZW50LnggKyAob3JpZ2luRHJhZ1ggLSBkcmFnWCksXG4gICAgICAgICAgICAgICAgICB5OiBkdXBsaWNhdGVkRWxlbWVudC55ICsgKG9yaWdpbkRyYWdZIC0gZHJhZ1kpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbmV4dEVsZW1lbnRzLnB1c2goZHVwbGljYXRlZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGVsZW1lbnRzVG9BcHBlbmQucHVzaChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICBvbGRJZFRvRHVwbGljYXRlZElkLnNldChlbGVtZW50LmlkLCBkdXBsaWNhdGVkRWxlbWVudC5pZCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV4dEVsZW1lbnRzLnB1c2goZWxlbWVudCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbmV4dFNjZW5lRWxlbWVudHMgPSBbLi4ubmV4dEVsZW1lbnRzLCAuLi5lbGVtZW50c1RvQXBwZW5kXTtcbiAgICAgICAgICAgIGJpbmRUZXh0VG9TaGFwZUFmdGVyRHVwbGljYXRpb24obmV4dEVsZW1lbnRzLCBlbGVtZW50c1RvQXBwZW5kLCBvbGRJZFRvRHVwbGljYXRlZElkKTtcbiAgICAgICAgICAgIGZpeEJpbmRpbmdzQWZ0ZXJEdXBsaWNhdGlvbihuZXh0U2NlbmVFbGVtZW50cywgZWxlbWVudHNUb0FwcGVuZCwgb2xkSWRUb0R1cGxpY2F0ZWRJZCwgXCJkdXBsaWNhdGVzU2VydmVBc09sZFwiKTtcbiAgICAgICAgICAgIGJpbmRFbGVtZW50c1RvRnJhbWVzQWZ0ZXJEdXBsaWNhdGlvbihuZXh0U2NlbmVFbGVtZW50cywgZWxlbWVudHNUb0FwcGVuZCwgb2xkSWRUb0R1cGxpY2F0ZWRJZCk7XG4gICAgICAgICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyhuZXh0U2NlbmVFbGVtZW50cyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IC8vIEl0IGlzIHZlcnkgaW1wb3J0YW50IHRvIHJlYWQgdGhpcy5zdGF0ZSB3aXRoaW4gZWFjaCBtb3ZlIGV2ZW50LFxuICAgICAgLy8gb3RoZXJ3aXNlIHdlIHdvdWxkIHJlYWQgYSBzdGFsZSBvbmUhXG5cblxuICAgICAgY29uc3QgZHJhZ2dpbmdFbGVtZW50ID0gdGhpcy5zdGF0ZS5kcmFnZ2luZ0VsZW1lbnQ7XG5cbiAgICAgIGlmICghZHJhZ2dpbmdFbGVtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGRyYWdnaW5nRWxlbWVudC50eXBlID09PSBcImZyZWVkcmF3XCIpIHtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gZHJhZ2dpbmdFbGVtZW50LnBvaW50cztcbiAgICAgICAgY29uc3QgZHggPSBwb2ludGVyQ29vcmRzLnggLSBkcmFnZ2luZ0VsZW1lbnQueDtcbiAgICAgICAgY29uc3QgZHkgPSBwb2ludGVyQ29vcmRzLnkgLSBkcmFnZ2luZ0VsZW1lbnQueTtcbiAgICAgICAgY29uc3QgbGFzdFBvaW50ID0gcG9pbnRzLmxlbmd0aCA+IDAgJiYgcG9pbnRzW3BvaW50cy5sZW5ndGggLSAxXTtcbiAgICAgICAgY29uc3QgZGlzY2FyZFBvaW50ID0gbGFzdFBvaW50ICYmIGxhc3RQb2ludFswXSA9PT0gZHggJiYgbGFzdFBvaW50WzFdID09PSBkeTtcblxuICAgICAgICBpZiAoIWRpc2NhcmRQb2ludCkge1xuICAgICAgICAgIGNvbnN0IHByZXNzdXJlcyA9IGRyYWdnaW5nRWxlbWVudC5zaW11bGF0ZVByZXNzdXJlID8gZHJhZ2dpbmdFbGVtZW50LnByZXNzdXJlcyA6IFsuLi5kcmFnZ2luZ0VsZW1lbnQucHJlc3N1cmVzLCBldmVudC5wcmVzc3VyZV07XG4gICAgICAgICAgbXV0YXRlRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQsIHtcbiAgICAgICAgICAgIHBvaW50czogWy4uLnBvaW50cywgW2R4LCBkeV1dLFxuICAgICAgICAgICAgcHJlc3N1cmVzXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoaXNMaW5lYXJFbGVtZW50KGRyYWdnaW5nRWxlbWVudCkpIHtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgc2VsZWN0ZWRFbGVtZW50c0FyZUJlaW5nRHJhZ2dlZDogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgcG9pbnRzID0gZHJhZ2dpbmdFbGVtZW50LnBvaW50cztcbiAgICAgICAgbGV0IGR4ID0gZ3JpZFggLSBkcmFnZ2luZ0VsZW1lbnQueDtcbiAgICAgICAgbGV0IGR5ID0gZ3JpZFkgLSBkcmFnZ2luZ0VsZW1lbnQueTtcblxuICAgICAgICBpZiAoc2hvdWxkUm90YXRlV2l0aERpc2NyZXRlQW5nbGUoZXZlbnQpICYmIHBvaW50cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAoe1xuICAgICAgICAgICAgd2lkdGg6IGR4LFxuICAgICAgICAgICAgaGVpZ2h0OiBkeVxuICAgICAgICAgIH0gPSBnZXRMb2NrZWRMaW5lYXJDdXJzb3JBbGlnblNpemUoZHJhZ2dpbmdFbGVtZW50LngsIGRyYWdnaW5nRWxlbWVudC55LCBwb2ludGVyQ29vcmRzLngsIHBvaW50ZXJDb29yZHMueSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvaW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICBtdXRhdGVFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwge1xuICAgICAgICAgICAgcG9pbnRzOiBbLi4ucG9pbnRzLCBbZHgsIGR5XV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmIChwb2ludHMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgbXV0YXRlRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQsIHtcbiAgICAgICAgICAgIHBvaW50czogWy4uLnBvaW50cy5zbGljZSgwLCAtMSksIFtkeCwgZHldXVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzQmluZGluZ0VsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCBmYWxzZSkpIHtcbiAgICAgICAgICAvLyBXaGVuIGNyZWF0aW5nIGEgbGluZWFyIGVsZW1lbnQgYnkgZHJhZ2dpbmdcbiAgICAgICAgICB0aGlzLm1heWJlU3VnZ2VzdEJpbmRpbmdzRm9yTGluZWFyRWxlbWVudEF0Q29vcmRzKGRyYWdnaW5nRWxlbWVudCwgW3BvaW50ZXJDb29yZHNdLCB0aGlzLnN0YXRlLnN0YXJ0Qm91bmRFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnggPSBwb2ludGVyQ29vcmRzLng7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUubGFzdENvb3Jkcy55ID0gcG9pbnRlckNvb3Jkcy55O1xuICAgICAgICB0aGlzLm1heWJlRHJhZ05ld0dlbmVyaWNFbGVtZW50KHBvaW50ZXJEb3duU3RhdGUsIGV2ZW50KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlVG9vbC50eXBlID09PSBcInNlbGVjdGlvblwiKSB7XG4gICAgICAgIHBvaW50ZXJEb3duU3RhdGUuYm94U2VsZWN0aW9uLmhhc09jY3VycmVkID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpOyAvLyBib3gtc2VsZWN0IGxpbmUgZWRpdG9yIHBvaW50c1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgTGluZWFyRWxlbWVudEVkaXRvci5oYW5kbGVCb3hTZWxlY3Rpb24oZXZlbnQsIHRoaXMuc3RhdGUsIHRoaXMuc2V0U3RhdGUuYmluZCh0aGlzKSk7IC8vIHJlZ3VsYXIgYm94LXNlbGVjdFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxldCBzaG91bGRSZXVzZVNlbGVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICBpZiAoIWV2ZW50LnNoaWZ0S2V5ICYmIGlzU29tZUVsZW1lbnRTZWxlY3RlZChlbGVtZW50cywgdGhpcy5zdGF0ZSkpIHtcbiAgICAgICAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLndpdGhDbWRPckN0cmwgJiYgcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudCkge1xuICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlKSwge1xuICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczoge1xuICAgICAgICAgICAgICAgICAgW3BvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgcHJldlN0YXRlLCB0aGlzKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzaG91bGRSZXVzZVNlbGVjdGlvbiA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGVsZW1lbnRzV2l0aGluU2VsZWN0aW9uID0gZ2V0RWxlbWVudHNXaXRoaW5TZWxlY3Rpb24oZWxlbWVudHMsIGRyYWdnaW5nRWxlbWVudCk7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4ge1xuICAgICAgICAgICAgY29uc3QgbmV4dFNlbGVjdGVkRWxlbWVudElkcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2hvdWxkUmV1c2VTZWxlY3Rpb24gJiYgcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyksIGVsZW1lbnRzV2l0aGluU2VsZWN0aW9uLnJlZHVjZSgoYWNjLCBlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgIGFjY1tlbGVtZW50LmlkXSA9IHRydWU7XG4gICAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgICB9LCB7fSkpO1xuXG4gICAgICAgICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudCkge1xuICAgICAgICAgICAgICAvLyBpZiB1c2luZyBjdHJsL2NtZCwgc2VsZWN0IHRoZSBoaXRFbGVtZW50IG9ubHkgaWYgd2VcbiAgICAgICAgICAgICAgLy8gaGF2ZW4ndCBib3gtc2VsZWN0ZWQgYW55dGhpbmcgZWxzZVxuICAgICAgICAgICAgICBpZiAoIWVsZW1lbnRzV2l0aGluU2VsZWN0aW9uLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG5leHRTZWxlY3RlZEVsZW1lbnRJZHNbcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudC5pZF0gPSB0cnVlO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW3BvaW50ZXJEb3duU3RhdGUuaGl0LmVsZW1lbnQuaWRdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByZXZTdGF0ZSA9ICFzaG91bGRSZXVzZVNlbGVjdGlvbiA/IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlKSwge1xuICAgICAgICAgICAgICBzZWxlY3RlZEdyb3VwSWRzOiB7fSxcbiAgICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IG51bGxcbiAgICAgICAgICAgIH0pIDogcHJldlN0YXRlO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgc2VsZWN0R3JvdXBzRm9yU2VsZWN0ZWRFbGVtZW50cyh7XG4gICAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBwcmV2U3RhdGUuZWRpdGluZ0dyb3VwSWQsXG4gICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbmV4dFNlbGVjdGVkRWxlbWVudElkc1xuICAgICAgICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgcHJldlN0YXRlLCB0aGlzKSksIHtcbiAgICAgICAgICAgICAgLy8gc2VsZWN0IGxpbmVhciBlbGVtZW50IG9ubHkgd2hlbiB3ZSBoYXZlbid0IGJveC1zZWxlY3RlZCBhbnl0aGluZyBlbHNlXG4gICAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogZWxlbWVudHNXaXRoaW5TZWxlY3Rpb24ubGVuZ3RoID09PSAxICYmIGlzTGluZWFyRWxlbWVudChlbGVtZW50c1dpdGhpblNlbGVjdGlvblswXSkgPyBuZXcgTGluZWFyRWxlbWVudEVkaXRvcihlbGVtZW50c1dpdGhpblNlbGVjdGlvblswXSwgdGhpcy5zY2VuZSkgOiBudWxsLFxuICAgICAgICAgICAgICBzaG93SHlwZXJsaW5rUG9wdXA6IGVsZW1lbnRzV2l0aGluU2VsZWN0aW9uLmxlbmd0aCA9PT0gMSAmJiAoZWxlbWVudHNXaXRoaW5TZWxlY3Rpb25bMF0ubGluayB8fCBpc0VtYmVkZGFibGVFbGVtZW50KGVsZW1lbnRzV2l0aGluU2VsZWN0aW9uWzBdKSkgPyBcImluZm9cIiA6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9IC8vIFJldHVybnMgd2hldGhlciB0aGUgcG9pbnRlciBtb3ZlIGhhcHBlbmVkIG92ZXIgZWl0aGVyIHNjcm9sbGJhclxuXG5cbiAgaGFuZGxlUG9pbnRlck1vdmVPdmVyU2Nyb2xsYmFycyhldmVudCwgcG9pbnRlckRvd25TdGF0ZSkge1xuICAgIGlmIChwb2ludGVyRG93blN0YXRlLnNjcm9sbGJhcnMuaXNPdmVySG9yaXpvbnRhbCkge1xuICAgICAgY29uc3QgeCA9IGV2ZW50LmNsaWVudFg7XG4gICAgICBjb25zdCBkeCA9IHggLSBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueDtcbiAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHtcbiAgICAgICAgc2Nyb2xsWDogdGhpcy5zdGF0ZS5zY3JvbGxYIC0gZHggLyB0aGlzLnN0YXRlLnpvb20udmFsdWVcbiAgICAgIH0pO1xuICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnggPSB4O1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuc2Nyb2xsYmFycy5pc092ZXJWZXJ0aWNhbCkge1xuICAgICAgY29uc3QgeSA9IGV2ZW50LmNsaWVudFk7XG4gICAgICBjb25zdCBkeSA9IHkgLSBwb2ludGVyRG93blN0YXRlLmxhc3RDb29yZHMueTtcbiAgICAgIHRoaXMudHJhbnNsYXRlQ2FudmFzKHtcbiAgICAgICAgc2Nyb2xsWTogdGhpcy5zdGF0ZS5zY3JvbGxZIC0gZHkgLyB0aGlzLnN0YXRlLnpvb20udmFsdWVcbiAgICAgIH0pO1xuICAgICAgcG9pbnRlckRvd25TdGF0ZS5sYXN0Q29vcmRzLnkgPSB5O1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgb25Qb2ludGVyVXBGcm9tUG9pbnRlckRvd25IYW5kbGVyKHBvaW50ZXJEb3duU3RhdGUpIHtcbiAgICByZXR1cm4gd2l0aEJhdGNoZWRVcGRhdGVzKGNoaWxkRXZlbnQgPT4ge1xuICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2Y7XG5cbiAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uTW92ZSkge1xuICAgICAgICBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uTW92ZS5mbHVzaCgpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7XG4gICAgICAgIGRyYWdnaW5nRWxlbWVudCxcbiAgICAgICAgcmVzaXppbmdFbGVtZW50LFxuICAgICAgICBtdWx0aUVsZW1lbnQsXG4gICAgICAgIGFjdGl2ZVRvb2wsXG4gICAgICAgIGlzUmVzaXppbmcsXG4gICAgICAgIGlzUm90YXRpbmdcbiAgICAgIH0gPSB0aGlzLnN0YXRlO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIGlzUmVzaXppbmc6IGZhbHNlLFxuICAgICAgICBpc1JvdGF0aW5nOiBmYWxzZSxcbiAgICAgICAgcmVzaXppbmdFbGVtZW50OiBudWxsLFxuICAgICAgICBzZWxlY3Rpb25FbGVtZW50OiBudWxsLFxuICAgICAgICBmcmFtZVRvSGlnaGxpZ2h0OiBudWxsLFxuICAgICAgICBlbGVtZW50c1RvSGlnaGxpZ2h0OiBudWxsLFxuICAgICAgICBjdXJzb3JCdXR0b246IFwidXBcIixcbiAgICAgICAgLy8gdGV4dCBlbGVtZW50cyBhcmUgcmVzZXQgb24gZmluYWxpemUsIGFuZCByZXNldHRpbmcgb24gcG9pbnRlcnVwXG4gICAgICAgIC8vIG1heSBjYXVzZSBpc3N1ZXMgd2l0aCBkb3VibGUgdGFwc1xuICAgICAgICBlZGl0aW5nRWxlbWVudDogbXVsdGlFbGVtZW50IHx8IGlzVGV4dEVsZW1lbnQodGhpcy5zdGF0ZS5lZGl0aW5nRWxlbWVudCkgPyB0aGlzLnN0YXRlLmVkaXRpbmdFbGVtZW50IDogbnVsbFxuICAgICAgfSk7XG4gICAgICB0aGlzLnNhdmVQb2ludGVyKGNoaWxkRXZlbnQuY2xpZW50WCwgY2hpbGRFdmVudC5jbGllbnRZLCBcInVwXCIpO1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIHNlbGVjdGVkRWxlbWVudHNBcmVCZWluZ0RyYWdnZWQ6IGZhbHNlXG4gICAgICB9KTsgLy8gSGFuZGxlIGVuZCBvZiBkcmFnZ2luZyBhIHBvaW50IG9mIGEgbGluZWFyIGVsZW1lbnQsIG1pZ2h0IGNsb3NlIGEgbG9vcFxuICAgICAgLy8gYW5kIHNldHMgYmluZGluZyBlbGVtZW50XG5cbiAgICAgIGlmICh0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgIGlmICghcG9pbnRlckRvd25TdGF0ZS5ib3hTZWxlY3Rpb24uaGFzT2NjdXJyZWQgJiYgKChfYiA9IChfYSA9IHBvaW50ZXJEb3duU3RhdGUuaGl0KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZWxlbWVudCkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmlkKSAhPT0gdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudC5lbGVtZW50SWQpIHtcbiAgICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgZWRpdGluZ0xpbmVhckVsZW1lbnQgPSBMaW5lYXJFbGVtZW50RWRpdG9yLmhhbmRsZVBvaW50ZXJVcChjaGlsZEV2ZW50LCB0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50LCB0aGlzLnN0YXRlKTtcblxuICAgICAgICAgIGlmIChlZGl0aW5nTGluZWFyRWxlbWVudCAhPT0gdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIGVkaXRpbmdMaW5lYXJFbGVtZW50LFxuICAgICAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkge1xuICAgICAgICBpZiAoKChfZCA9IChfYyA9IHBvaW50ZXJEb3duU3RhdGUuaGl0KSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MuZWxlbWVudCkgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLmlkKSAhPT0gdGhpcy5zdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnQuZWxlbWVudElkKSB7XG4gICAgICAgICAgY29uc3Qgc2VsZWN0ZWRFTGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKTsgLy8gc2V0IHNlbGVjdGVkTGluZWFyRWxlbWVudCB0byBudWxsIGlmIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgZWxlbWVudCBzZWxlY3RlZCBzaW5jZSB3ZSBkb24ndCB3YW50IHRvIHNob3cgbGluZWFyIGVsZW1lbnQgaGFuZGxlc1xuXG4gICAgICAgICAgaWYgKHNlbGVjdGVkRUxlbWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogbnVsbFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IGxpbmVhckVsZW1lbnRFZGl0b3IgPSBMaW5lYXJFbGVtZW50RWRpdG9yLmhhbmRsZVBvaW50ZXJVcChjaGlsZEV2ZW50LCB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgc3RhcnRCaW5kaW5nRWxlbWVudCxcbiAgICAgICAgICAgIGVuZEJpbmRpbmdFbGVtZW50XG4gICAgICAgICAgfSA9IGxpbmVhckVsZW1lbnRFZGl0b3I7XG4gICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuc2NlbmUuZ2V0RWxlbWVudChsaW5lYXJFbGVtZW50RWRpdG9yLmVsZW1lbnRJZCk7XG5cbiAgICAgICAgICBpZiAoaXNCaW5kaW5nRWxlbWVudChlbGVtZW50KSkge1xuICAgICAgICAgICAgYmluZE9yVW5iaW5kTGluZWFyRWxlbWVudChlbGVtZW50LCBzdGFydEJpbmRpbmdFbGVtZW50LCBlbmRCaW5kaW5nRWxlbWVudCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGxpbmVhckVsZW1lbnRFZGl0b3IgIT09IHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIGxpbmVhckVsZW1lbnRFZGl0b3IpLCB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRQb2ludHNJbmRpY2VzOiBudWxsXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsYXN0UG9pbnRlclVwID0gbnVsbDtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfTU9WRSwgcG9pbnRlckRvd25TdGF0ZS5ldmVudExpc3RlbmVycy5vbk1vdmUpO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgcG9pbnRlckRvd25TdGF0ZS5ldmVudExpc3RlbmVycy5vblVwKTtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULktFWURPV04sIHBvaW50ZXJEb3duU3RhdGUuZXZlbnRMaXN0ZW5lcnMub25LZXlEb3duKTtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULktFWVVQLCBwb2ludGVyRG93blN0YXRlLmV2ZW50TGlzdGVuZXJzLm9uS2V5VXApO1xuXG4gICAgICBpZiAodGhpcy5zdGF0ZS5wZW5kaW5nSW1hZ2VFbGVtZW50SWQpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgcGVuZGluZ0ltYWdlRWxlbWVudElkOiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoKGRyYWdnaW5nRWxlbWVudCA9PT0gbnVsbCB8fCBkcmFnZ2luZ0VsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGRyYWdnaW5nRWxlbWVudC50eXBlKSA9PT0gXCJmcmVlZHJhd1wiKSB7XG4gICAgICAgIGNvbnN0IHBvaW50ZXJDb29yZHMgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoY2hpbGRFdmVudCwgdGhpcy5zdGF0ZSk7XG4gICAgICAgIGNvbnN0IHBvaW50cyA9IGRyYWdnaW5nRWxlbWVudC5wb2ludHM7XG4gICAgICAgIGxldCBkeCA9IHBvaW50ZXJDb29yZHMueCAtIGRyYWdnaW5nRWxlbWVudC54O1xuICAgICAgICBsZXQgZHkgPSBwb2ludGVyQ29vcmRzLnkgLSBkcmFnZ2luZ0VsZW1lbnQueTsgLy8gQWxsb3dzIGRvdHMgdG8gYXZvaWQgYmVpbmcgZmxhZ2dlZCBhcyBpbmZpbml0ZWx5IHNtYWxsXG5cbiAgICAgICAgaWYgKGR4ID09PSBwb2ludHNbMF1bMF0gJiYgZHkgPT09IHBvaW50c1swXVsxXSkge1xuICAgICAgICAgIGR5ICs9IDAuMDAwMTtcbiAgICAgICAgICBkeCArPSAwLjAwMDE7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwcmVzc3VyZXMgPSBkcmFnZ2luZ0VsZW1lbnQuc2ltdWxhdGVQcmVzc3VyZSA/IFtdIDogWy4uLmRyYWdnaW5nRWxlbWVudC5wcmVzc3VyZXMsIGNoaWxkRXZlbnQucHJlc3N1cmVdO1xuICAgICAgICBtdXRhdGVFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwge1xuICAgICAgICAgIHBvaW50czogWy4uLnBvaW50cywgW2R4LCBkeV1dLFxuICAgICAgICAgIHByZXNzdXJlcyxcbiAgICAgICAgICBsYXN0Q29tbWl0dGVkUG9pbnQ6IFtkeCwgZHldXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzSW1hZ2VFbGVtZW50KGRyYWdnaW5nRWxlbWVudCkpIHtcbiAgICAgICAgY29uc3QgaW1hZ2VFbGVtZW50ID0gZHJhZ2dpbmdFbGVtZW50O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhpcy5pbml0aWFsaXplSW1hZ2VEaW1lbnNpb25zKGltYWdlRWxlbWVudCk7XG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHtcbiAgICAgICAgICAgICAgW2ltYWdlRWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgIH0sIHRoaXMuc3RhdGUpXG4gICAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5hY3Rpb25NYW5hZ2VyLmV4ZWN1dGVBY3Rpb24oYWN0aW9uRmluYWxpemUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkuZmlsdGVyKGVsID0+IGVsLmlkICE9PSBpbWFnZUVsZW1lbnQuaWQpKTtcbiAgICAgICAgICB0aGlzLmFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25GaW5hbGl6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChpc0xpbmVhckVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50KSkge1xuICAgICAgICBpZiAoZHJhZ2dpbmdFbGVtZW50LnBvaW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgdGhpcy5oaXN0b3J5LnJlc3VtZVJlY29yZGluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcG9pbnRlckNvb3JkcyA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhjaGlsZEV2ZW50LCB0aGlzLnN0YXRlKTtcblxuICAgICAgICBpZiAoIXBvaW50ZXJEb3duU3RhdGUuZHJhZy5oYXNPY2N1cnJlZCAmJiBkcmFnZ2luZ0VsZW1lbnQgJiYgIW11bHRpRWxlbWVudCkge1xuICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50LCB7XG4gICAgICAgICAgICBwb2ludHM6IFsuLi5kcmFnZ2luZ0VsZW1lbnQucG9pbnRzLCBbcG9pbnRlckNvb3Jkcy54IC0gZHJhZ2dpbmdFbGVtZW50LngsIHBvaW50ZXJDb29yZHMueSAtIGRyYWdnaW5nRWxlbWVudC55XV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIG11bHRpRWxlbWVudDogZHJhZ2dpbmdFbGVtZW50LFxuICAgICAgICAgICAgZWRpdGluZ0VsZW1lbnQ6IHRoaXMuc3RhdGUuZHJhZ2dpbmdFbGVtZW50XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAocG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkICYmICFtdWx0aUVsZW1lbnQpIHtcbiAgICAgICAgICBpZiAoaXNCaW5kaW5nRW5hYmxlZCh0aGlzLnN0YXRlKSAmJiBpc0JpbmRpbmdFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwgZmFsc2UpKSB7XG4gICAgICAgICAgICBtYXliZUJpbmRMaW5lYXJFbGVtZW50KGRyYWdnaW5nRWxlbWVudCwgdGhpcy5zdGF0ZSwgdGhpcy5zY2VuZSwgcG9pbnRlckNvb3Jkcyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW10sXG4gICAgICAgICAgICBzdGFydEJvdW5kRWxlbWVudDogbnVsbFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKCFhY3RpdmVUb29sLmxvY2tlZCkge1xuICAgICAgICAgICAgcmVzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyk7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiAoe1xuICAgICAgICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgICAgIGFjdGl2ZVRvb2w6IHVwZGF0ZUFjdGl2ZVRvb2wodGhpcy5zdGF0ZSwge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwic2VsZWN0aW9uXCJcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKSwge1xuICAgICAgICAgICAgICAgIFtkcmFnZ2luZ0VsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgICAgIH0pLCBwcmV2U3RhdGUpLFxuICAgICAgICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IG5ldyBMaW5lYXJFbGVtZW50RWRpdG9yKGRyYWdnaW5nRWxlbWVudCwgdGhpcy5zY2VuZSlcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShwcmV2U3RhdGUgPT4gKHtcbiAgICAgICAgICAgICAgZHJhZ2dpbmdFbGVtZW50OiBudWxsXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWN0aXZlVG9vbC50eXBlICE9PSBcInNlbGVjdGlvblwiICYmIGRyYWdnaW5nRWxlbWVudCAmJiBpc0ludmlzaWJseVNtYWxsRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQpKSB7XG4gICAgICAgIC8vIHJlbW92ZSBpbnZpc2libGUgZWxlbWVudCB3aGljaCB3YXMgYWRkZWQgaW4gb25Qb2ludGVyRG93blxuICAgICAgICB0aGlzLnNjZW5lLnJlcGxhY2VBbGxFbGVtZW50cyh0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLnNsaWNlKDAsIC0xKSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZHJhZ2dpbmdFbGVtZW50KSB7XG4gICAgICAgIGlmIChwb2ludGVyRG93blN0YXRlLmRyYWcuaGFzT2NjdXJyZWQpIHtcbiAgICAgICAgICBjb25zdCBzY2VuZUNvb3JkcyA9IHZpZXdwb3J0Q29vcmRzVG9TY2VuZUNvb3JkcyhjaGlsZEV2ZW50LCB0aGlzLnN0YXRlKTsgLy8gd2hlbiBlZGl0aW5nIHRoZSBwb2ludHMgb2YgYSBsaW5lYXIgZWxlbWVudCwgd2UgY2hlY2sgaWYgdGhlXG4gICAgICAgICAgLy8gbGluZWFyIGVsZW1lbnQgc3RpbGwgaXMgaW4gdGhlIGZyYW1lIGFmdGVyd2FyZHNcbiAgICAgICAgICAvLyBpZiBub3QsIHRoZSBsaW5lYXIgZWxlbWVudCB3aWxsIGJlIHJlbW92ZWQgZnJvbSBpdHMgZnJhbWUgKGlmIGFueSlcblxuICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCAmJiB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudC5pc0RyYWdnaW5nKSB7XG4gICAgICAgICAgICBjb25zdCBsaW5lYXJFbGVtZW50ID0gdGhpcy5zY2VuZS5nZXRFbGVtZW50KHRoaXMuc3RhdGUuc2VsZWN0ZWRMaW5lYXJFbGVtZW50LmVsZW1lbnRJZCk7XG5cbiAgICAgICAgICAgIGlmIChsaW5lYXJFbGVtZW50ID09PSBudWxsIHx8IGxpbmVhckVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGxpbmVhckVsZW1lbnQuZnJhbWVJZCkge1xuICAgICAgICAgICAgICBjb25zdCBmcmFtZSA9IGdldENvbnRhaW5pbmdGcmFtZShsaW5lYXJFbGVtZW50KTtcblxuICAgICAgICAgICAgICBpZiAoZnJhbWUgJiYgbGluZWFyRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGlmICghZWxlbWVudE92ZXJsYXBzV2l0aEZyYW1lKGxpbmVhckVsZW1lbnQsIGZyYW1lKSkge1xuICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIHRoZSBsaW5lYXIgZWxlbWVudCBmcm9tIGFsbCBncm91cHNcbiAgICAgICAgICAgICAgICAgIC8vIGJlZm9yZSByZW1vdmluZyBpdCBmcm9tIHRoZSBmcmFtZSBhcyB3ZWxsXG4gICAgICAgICAgICAgICAgICBtdXRhdGVFbGVtZW50KGxpbmVhckVsZW1lbnQsIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBJZHM6IFtdXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKHJlbW92ZUVsZW1lbnRzRnJvbUZyYW1lKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIFtsaW5lYXJFbGVtZW50XSwgdGhpcy5zdGF0ZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBzZWxlY3RlZCBlbGVtZW50cyBhbmQgZnJhbWVzXG4gICAgICAgICAgICBjb25zdCB0b3BMYXllckZyYW1lID0gdGhpcy5nZXRUb3BMYXllckZyYW1lQXRTY2VuZUNvb3JkcyhzY2VuZUNvb3Jkcyk7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpO1xuICAgICAgICAgICAgbGV0IG5leHRFbGVtZW50cyA9IHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZUdyb3VwSWRzQWZ0ZXJFZGl0aW5nR3JvdXAgPSBlbGVtZW50cyA9PiB7XG4gICAgICAgICAgICAgIGlmIChlbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IGVsZW1lbnQuZ3JvdXBJZHMuaW5kZXhPZih0aGlzLnN0YXRlLmVkaXRpbmdHcm91cElkKTtcbiAgICAgICAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZWxlbWVudCwge1xuICAgICAgICAgICAgICAgICAgICBncm91cElkczogZWxlbWVudC5ncm91cElkcy5zbGljZSgwLCBpbmRleClcbiAgICAgICAgICAgICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBuZXh0RWxlbWVudHMuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50Lmdyb3VwSWRzLmxlbmd0aCAmJiBnZXRFbGVtZW50c0luR3JvdXAobmV4dEVsZW1lbnRzLCBlbGVtZW50Lmdyb3VwSWRzW2VsZW1lbnQuZ3JvdXBJZHMubGVuZ3RoIC0gMV0pLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgICAgICAgICAgICAgZ3JvdXBJZHM6IFtdXG4gICAgICAgICAgICAgICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBudWxsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0b3BMYXllckZyYW1lICYmICF0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1t0b3BMYXllckZyYW1lLmlkXSkge1xuICAgICAgICAgICAgICBjb25zdCBlbGVtZW50c1RvQWRkID0gc2VsZWN0ZWRFbGVtZW50cy5maWx0ZXIoZWxlbWVudCA9PiBlbGVtZW50LmZyYW1lSWQgIT09IHRvcExheWVyRnJhbWUuaWQgJiYgaXNFbGVtZW50SW5GcmFtZShlbGVtZW50LCBuZXh0RWxlbWVudHMsIHRoaXMuc3RhdGUpKTtcblxuICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nR3JvdXBJZCkge1xuICAgICAgICAgICAgICAgIHVwZGF0ZUdyb3VwSWRzQWZ0ZXJFZGl0aW5nR3JvdXAoZWxlbWVudHNUb0FkZCk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBuZXh0RWxlbWVudHMgPSBhZGRFbGVtZW50c1RvRnJhbWUobmV4dEVsZW1lbnRzLCBlbGVtZW50c1RvQWRkLCB0b3BMYXllckZyYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRvcExheWVyRnJhbWUpIHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZWRpdGluZ0dyb3VwSWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50c1RvUmVtb3ZlID0gc2VsZWN0ZWRFbGVtZW50cy5maWx0ZXIoZWxlbWVudCA9PiBlbGVtZW50LmZyYW1lSWQgJiYgIWlzRWxlbWVudEluRnJhbWUoZWxlbWVudCwgbmV4dEVsZW1lbnRzLCB0aGlzLnN0YXRlKSk7XG4gICAgICAgICAgICAgICAgdXBkYXRlR3JvdXBJZHNBZnRlckVkaXRpbmdHcm91cChlbGVtZW50c1RvUmVtb3ZlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXh0RWxlbWVudHMgPSB1cGRhdGVGcmFtZU1lbWJlcnNoaXBPZlNlbGVjdGVkRWxlbWVudHMobmV4dEVsZW1lbnRzLCB0aGlzLnN0YXRlLCB0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKG5leHRFbGVtZW50cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRyYWdnaW5nRWxlbWVudC50eXBlID09PSBcImZyYW1lXCIpIHtcbiAgICAgICAgICBjb25zdCBlbGVtZW50c0luc2lkZUZyYW1lID0gZ2V0RWxlbWVudHNJbk5ld0ZyYW1lKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIGRyYWdnaW5nRWxlbWVudCk7XG4gICAgICAgICAgdGhpcy5zY2VuZS5yZXBsYWNlQWxsRWxlbWVudHMoYWRkRWxlbWVudHNUb0ZyYW1lKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIGVsZW1lbnRzSW5zaWRlRnJhbWUsIGRyYWdnaW5nRWxlbWVudCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgbXV0YXRlRWxlbWVudChkcmFnZ2luZ0VsZW1lbnQsIGdldE5vcm1hbGl6ZWREaW1lbnNpb25zKGRyYWdnaW5nRWxlbWVudCkpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzaXppbmdFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc2l6aW5nRWxlbWVudCAmJiBpc0ludmlzaWJseVNtYWxsRWxlbWVudChyZXNpemluZ0VsZW1lbnQpKSB7XG4gICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCkuZmlsdGVyKGVsID0+IGVsLmlkICE9PSByZXNpemluZ0VsZW1lbnQuaWQpKTtcbiAgICAgIH0gLy8gaGFuZGxlIGZyYW1lIG1lbWJlcnNoaXAgZm9yIHJlc2l6aW5nIGZyYW1lcyBhbmQvb3Igc2VsZWN0ZWQgZWxlbWVudHNcblxuXG4gICAgICBpZiAocG9pbnRlckRvd25TdGF0ZS5yZXNpemUuaXNSZXNpemluZykge1xuICAgICAgICBsZXQgbmV4dEVsZW1lbnRzID0gdXBkYXRlRnJhbWVNZW1iZXJzaGlwT2ZTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc2NlbmUuZ2V0RWxlbWVudHNJbmNsdWRpbmdEZWxldGVkKCksIHRoaXMuc3RhdGUsIHRoaXMpO1xuICAgICAgICBjb25zdCBzZWxlY3RlZEZyYW1lcyA9IHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKS5maWx0ZXIoZWxlbWVudCA9PiBlbGVtZW50LnR5cGUgPT09IFwiZnJhbWVcIik7XG5cbiAgICAgICAgZm9yIChjb25zdCBmcmFtZSBvZiBzZWxlY3RlZEZyYW1lcykge1xuICAgICAgICAgIG5leHRFbGVtZW50cyA9IHJlcGxhY2VBbGxFbGVtZW50c0luRnJhbWUobmV4dEVsZW1lbnRzLCBnZXRFbGVtZW50c0luUmVzaXppbmdGcmFtZSh0aGlzLnNjZW5lLmdldEVsZW1lbnRzSW5jbHVkaW5nRGVsZXRlZCgpLCBmcmFtZSwgdGhpcy5zdGF0ZSksIGZyYW1lLCB0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKG5leHRFbGVtZW50cyk7XG4gICAgICB9IC8vIENvZGUgYmVsb3cgaGFuZGxlcyBzZWxlY3Rpb24gd2hlbiBlbGVtZW50KHMpIHdlcmVuJ3RcbiAgICAgIC8vIGRyYWcgb3IgYWRkZWQgdG8gc2VsZWN0aW9uIG9uIHBvaW50ZXIgZG93biBwaGFzZS5cblxuXG4gICAgICBjb25zdCBoaXRFbGVtZW50ID0gcG9pbnRlckRvd25TdGF0ZS5oaXQuZWxlbWVudDtcblxuICAgICAgaWYgKCgoX2UgPSB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLmVsZW1lbnRJZCkgIT09IChoaXRFbGVtZW50ID09PSBudWxsIHx8IGhpdEVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGhpdEVsZW1lbnQuaWQpICYmIGlzTGluZWFyRWxlbWVudChoaXRFbGVtZW50KSkge1xuICAgICAgICBjb25zdCBzZWxlY3RlZEVMZW1lbnRzID0gdGhpcy5zY2VuZS5nZXRTZWxlY3RlZEVsZW1lbnRzKHRoaXMuc3RhdGUpOyAvLyBzZXQgc2VsZWN0ZWRMaW5lYXJFbGVtZW50IHdoZW4gbm8gb3RoZXIgZWxlbWVudCBzZWxlY3RlZCBleGNlcHRcbiAgICAgICAgLy8gdGhlIG9uZSB3ZSd2ZSBoaXRcblxuICAgICAgICBpZiAoc2VsZWN0ZWRFTGVtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHNlbGVjdGVkTGluZWFyRWxlbWVudDogbmV3IExpbmVhckVsZW1lbnRFZGl0b3IoaGl0RWxlbWVudCwgdGhpcy5zY2VuZSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoaXNFcmFzZXJBY3RpdmUodGhpcy5zdGF0ZSkpIHtcbiAgICAgICAgY29uc3QgZHJhZ2dlZERpc3RhbmNlID0gZGlzdGFuY2UyZCh0aGlzLmxhc3RQb2ludGVyRG93bi5jbGllbnRYLCB0aGlzLmxhc3RQb2ludGVyRG93bi5jbGllbnRZLCB0aGlzLmxhc3RQb2ludGVyVXAuY2xpZW50WCwgdGhpcy5sYXN0UG9pbnRlclVwLmNsaWVudFkpO1xuXG4gICAgICAgIGlmIChkcmFnZ2VkRGlzdGFuY2UgPT09IDApIHtcbiAgICAgICAgICBjb25zdCBzY2VuZVBvaW50ZXIgPSB2aWV3cG9ydENvb3Jkc1RvU2NlbmVDb29yZHMoe1xuICAgICAgICAgICAgY2xpZW50WDogdGhpcy5sYXN0UG9pbnRlclVwLmNsaWVudFgsXG4gICAgICAgICAgICBjbGllbnRZOiB0aGlzLmxhc3RQb2ludGVyVXAuY2xpZW50WVxuICAgICAgICAgIH0sIHRoaXMuc3RhdGUpO1xuICAgICAgICAgIGNvbnN0IGhpdEVsZW1lbnRzID0gdGhpcy5nZXRFbGVtZW50c0F0UG9zaXRpb24oc2NlbmVQb2ludGVyLngsIHNjZW5lUG9pbnRlci55KTtcbiAgICAgICAgICBoaXRFbGVtZW50cy5mb3JFYWNoKGhpdEVsZW1lbnQgPT4gcG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZVtoaXRFbGVtZW50LmlkXSA9IHtcbiAgICAgICAgICAgIGVyYXNlOiB0cnVlLFxuICAgICAgICAgICAgb3BhY2l0eTogaGl0RWxlbWVudC5vcGFjaXR5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVyYXNlRWxlbWVudHMocG9pbnRlckRvd25TdGF0ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSBpZiAoT2JqZWN0LmtleXMocG9pbnRlckRvd25TdGF0ZS5lbGVtZW50SWRzVG9FcmFzZSkubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMucmVzdG9yZVJlYWR5VG9FcmFzZUVsZW1lbnRzKHBvaW50ZXJEb3duU3RhdGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaGl0RWxlbWVudCAmJiAhcG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkICYmICFwb2ludGVyRG93blN0YXRlLmhpdC53YXNBZGRlZFRvU2VsZWN0aW9uICYmICggLy8gaWYgd2UncmUgZWRpdGluZyBhIGxpbmUsIHBvaW50ZXJ1cCBzaG91bGRuJ3Qgc3dpdGNoIHNlbGVjdGlvbiBpZlxuICAgICAgLy8gYm94IHNlbGVjdGVkXG4gICAgICAhdGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCB8fCAhcG9pbnRlckRvd25TdGF0ZS5ib3hTZWxlY3Rpb24uaGFzT2NjdXJyZWQpKSB7XG4gICAgICAgIC8vIHdoZW4gaW5zaWRlIGxpbmUgZWRpdG9yLCBzaGlmdCBzZWxlY3RzIHBvaW50cyBpbnN0ZWFkXG4gICAgICAgIGlmIChjaGlsZEV2ZW50LnNoaWZ0S2V5ICYmICF0aGlzLnN0YXRlLmVkaXRpbmdMaW5lYXJFbGVtZW50KSB7XG4gICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuaWRdKSB7XG4gICAgICAgICAgICBpZiAoaXNTZWxlY3RlZFZpYUdyb3VwKHRoaXMuc3RhdGUsIGhpdEVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoX3ByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dFNlbGVjdGVkRWxlbWVudElkcyA9IE9iamVjdC5hc3NpZ24oe30sIF9wcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKTsgLy8gV2Ugd2FudCB0byB1bnNlbGVjdCBhbGwgZ3JvdXBzIGhpdEVsZW1lbnQgaXMgcGFydCBvZlxuICAgICAgICAgICAgICAgIC8vIGFzIHdlbGwgYXMgYWxsIGVsZW1lbnRzIHRoYXQgYXJlIHBhcnQgb2YgdGhlIGdyb3Vwc1xuICAgICAgICAgICAgICAgIC8vIGhpdEVsZW1lbnQgaXMgcGFydCBvZlxuXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBncm91cGVkRWxlbWVudCBvZiBoaXRFbGVtZW50Lmdyb3VwSWRzLmZsYXRNYXAoZ3JvdXBJZCA9PiBnZXRFbGVtZW50c0luR3JvdXAodGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgZ3JvdXBJZCkpKSB7XG4gICAgICAgICAgICAgICAgICBkZWxldGUgbmV4dFNlbGVjdGVkRWxlbWVudElkc1tncm91cGVkRWxlbWVudC5pZF07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgX3ByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLCBoaXRFbGVtZW50Lmdyb3VwSWRzLm1hcChnSWQgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgW2dJZF06IGZhbHNlXG4gICAgICAgICAgICAgICAgICB9KSkucmVkdWNlKChwcmV2LCBhY2MpID0+IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldiksIGFjYyksIHt9KSksXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKG5leHRTZWxlY3RlZEVsZW1lbnRJZHMsIF9wcmV2U3RhdGUpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgfSk7IC8vIGlmIG5vdCBncmFnZ2luZyBhIGxpbmVhciBlbGVtZW50IHBvaW50IChvdXRzaWRlIGVkaXRvcilcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoISgoX2YgPSB0aGlzLnN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkgPT09IG51bGwgfHwgX2YgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9mLmlzRHJhZ2dpbmcpKSB7XG4gICAgICAgICAgICAgIC8vIHJlbW92ZSBlbGVtZW50IGZyb20gc2VsZWN0aW9uIHdoaWxlXG4gICAgICAgICAgICAgIC8vIGtlZXBpbmcgcHJldiBlbGVtZW50cyBzZWxlY3RlZFxuICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3U2VsZWN0ZWRFbGVtZW50SWRzID0gT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG5ld1NlbGVjdGVkRWxlbWVudElkc1toaXRFbGVtZW50LmlkXTtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdTZWxlY3RlZEVsZW1lbnRzID0gZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCB7XG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG5ld1NlbGVjdGVkRWxlbWVudElkc1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICAgICAgICAgICAgZWRpdGluZ0dyb3VwSWQ6IHByZXZTdGF0ZS5lZGl0aW5nR3JvdXBJZCxcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbmV3U2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgICAgICAgICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgcHJldlN0YXRlLCB0aGlzKSksIHtcbiAgICAgICAgICAgICAgICAgIC8vIHNldCBzZWxlY3RlZExpbmVhckVsZW1lbnQgb25seSBpZiB0aGF0cyB0aGUgb25seSBlbGVtZW50IHNlbGVjdGVkXG4gICAgICAgICAgICAgICAgICBzZWxlY3RlZExpbmVhckVsZW1lbnQ6IG5ld1NlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAxICYmIGlzTGluZWFyRWxlbWVudChuZXdTZWxlY3RlZEVsZW1lbnRzWzBdKSA/IG5ldyBMaW5lYXJFbGVtZW50RWRpdG9yKG5ld1NlbGVjdGVkRWxlbWVudHNbMF0sIHRoaXMuc2NlbmUpIDogcHJldlN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKGhpdEVsZW1lbnQuZnJhbWVJZCAmJiB0aGlzLnN0YXRlLnNlbGVjdGVkRWxlbWVudElkc1toaXRFbGVtZW50LmZyYW1lSWRdKSB7XG4gICAgICAgICAgICAvLyB3aGVuIGhpdEVsZW1lbnQgaXMgcGFydCBvZiBhIHNlbGVjdGVkIGZyYW1lLCBkZXNlbGVjdCB0aGUgZnJhbWVcbiAgICAgICAgICAgIC8vIHRvIGF2b2lkIGZyYW1lIGFuZCBjb250YWluaW5nIGVsZW1lbnRzIHNlbGVjdGVkIHNpbXVsdGFuZW91c2x5XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgICAgIHZhciBfYSwgX2I7XG5cbiAgICAgICAgICAgICAgY29uc3QgbmV4dFNlbGVjdGVkRWxlbWVudElkcyA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgcHJldlN0YXRlLnNlbGVjdGVkRWxlbWVudElkcyksIHtcbiAgICAgICAgICAgICAgICBbaGl0RWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgICAgfSk7IC8vIGRlc2VsZWN0IHRoZSBmcmFtZVxuXG4gICAgICAgICAgICAgIGRlbGV0ZSBuZXh0U2VsZWN0ZWRFbGVtZW50SWRzW2hpdEVsZW1lbnQuZnJhbWVJZF07IC8vIGRlc2VsZWN0IGdyb3VwcyBjb250YWluaW5nIHRoZSBmcmFtZVxuXG4gICAgICAgICAgICAgICgoX2IgPSAoX2EgPSB0aGlzLnNjZW5lLmdldEVsZW1lbnQoaGl0RWxlbWVudC5mcmFtZUlkKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdyb3VwSWRzKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiBbXSkuZmxhdE1hcChnaWQgPT4gZ2V0RWxlbWVudHNJbkdyb3VwKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIGdpZCkpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG5leHRTZWxlY3RlZEVsZW1lbnRJZHNbZWxlbWVudC5pZF07XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBzZWxlY3RHcm91cHNGb3JTZWxlY3RlZEVsZW1lbnRzKHtcbiAgICAgICAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogcHJldlN0YXRlLmVkaXRpbmdHcm91cElkLFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbmV4dFNlbGVjdGVkRWxlbWVudElkc1xuICAgICAgICAgICAgICB9LCB0aGlzLnNjZW5lLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpLCBwcmV2U3RhdGUsIHRoaXMpKSwge1xuICAgICAgICAgICAgICAgIHNob3dIeXBlcmxpbmtQb3B1cDogaGl0RWxlbWVudC5saW5rIHx8IGlzRW1iZWRkYWJsZUVsZW1lbnQoaGl0RWxlbWVudCkgPyBcImluZm9cIiA6IGZhbHNlXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGFkZCBlbGVtZW50IHRvIHNlbGVjdGlvbiB3aGlsZSBrZWVwaW5nIHByZXYgZWxlbWVudHMgc2VsZWN0ZWRcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoX3ByZXZTdGF0ZSA9PiAoe1xuICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgX3ByZXZTdGF0ZS5zZWxlY3RlZEVsZW1lbnRJZHMpLCB7XG4gICAgICAgICAgICAgICAgW2hpdEVsZW1lbnQuaWRdOiB0cnVlXG4gICAgICAgICAgICAgIH0pLCBfcHJldlN0YXRlKVxuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiB7XG4gICAgICAgICAgICB2YXIgX2E7XG5cbiAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sIHNlbGVjdEdyb3Vwc0ZvclNlbGVjdGVkRWxlbWVudHMoe1xuICAgICAgICAgICAgICBlZGl0aW5nR3JvdXBJZDogcHJldlN0YXRlLmVkaXRpbmdHcm91cElkLFxuICAgICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IHtcbiAgICAgICAgICAgICAgICBbaGl0RWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgdGhpcy5zY2VuZS5nZXROb25EZWxldGVkRWxlbWVudHMoKSwgcHJldlN0YXRlLCB0aGlzKSksIHtcbiAgICAgICAgICAgICAgc2VsZWN0ZWRMaW5lYXJFbGVtZW50OiBpc0xpbmVhckVsZW1lbnQoaGl0RWxlbWVudCkgJiYgLy8gRG9uJ3Qgc2V0IGBzZWxlY3RlZExpbmVhckVsZW1lbnRgIGlmIGl0cyBzYW1lIGFzIHRoZSBoaXRFbGVtZW50LCB0aGlzIGlzIG1haW5seSB0byBwcmV2ZW50IHJlc2V0dGluZyB0aGUgYGhvdmVyUG9pbnRJbmRleGAgdG8gLTEuXG4gICAgICAgICAgICAgIC8vIEZ1dHVyZSB3ZSBzaG91bGQgdXBkYXRlIHRoZSBBUEkgdG8gdGFrZSBjYXJlIG9mIHNldHRpbmcgdGhlIGNvcnJlY3QgYGhvdmVyUG9pbnRJbmRleGAgd2hlbiBpbml0aWFsaXplZFxuICAgICAgICAgICAgICAoKF9hID0gcHJldlN0YXRlLnNlbGVjdGVkTGluZWFyRWxlbWVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmVsZW1lbnRJZCkgIT09IGhpdEVsZW1lbnQuaWQgPyBuZXcgTGluZWFyRWxlbWVudEVkaXRvcihoaXRFbGVtZW50LCB0aGlzLnNjZW5lKSA6IHByZXZTdGF0ZS5zZWxlY3RlZExpbmVhckVsZW1lbnRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghcG9pbnRlckRvd25TdGF0ZS5kcmFnLmhhc09jY3VycmVkICYmICF0aGlzLnN0YXRlLmlzUmVzaXppbmcgJiYgKGhpdEVsZW1lbnQgJiYgaXNIaXR0aW5nRWxlbWVudEJvdW5kaW5nQm94V2l0aG91dEhpdHRpbmdFbGVtZW50KGhpdEVsZW1lbnQsIHRoaXMuc3RhdGUsIHRoaXMuZnJhbWVOYW1lQm91bmRzQ2FjaGUsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLngsIHBvaW50ZXJEb3duU3RhdGUub3JpZ2luLnkpIHx8ICFoaXRFbGVtZW50ICYmIHBvaW50ZXJEb3duU3RhdGUuaGl0Lmhhc0hpdENvbW1vbkJvdW5kaW5nQm94T2ZTZWxlY3RlZEVsZW1lbnRzKSkge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5lZGl0aW5nTGluZWFyRWxlbWVudCkge1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgZWRpdGluZ0xpbmVhckVsZW1lbnQ6IG51bGxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBEZXNlbGVjdCBzZWxlY3RlZCBlbGVtZW50c1xuICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7fSwgdGhpcy5zdGF0ZSksXG4gICAgICAgICAgICBzZWxlY3RlZEdyb3VwSWRzOiB7fSxcbiAgICAgICAgICAgIGVkaXRpbmdHcm91cElkOiBudWxsLFxuICAgICAgICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWFjdGl2ZVRvb2wubG9ja2VkICYmIGFjdGl2ZVRvb2wudHlwZSAhPT0gXCJmcmVlZHJhd1wiICYmIGRyYWdnaW5nRWxlbWVudCAmJiBkcmFnZ2luZ0VsZW1lbnQudHlwZSAhPT0gXCJzZWxlY3Rpb25cIikge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHByZXZTdGF0ZSA9PiAoe1xuICAgICAgICAgIHNlbGVjdGVkRWxlbWVudElkczogbWFrZU5leHRTZWxlY3RlZEVsZW1lbnRJZHMoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBwcmV2U3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzKSwge1xuICAgICAgICAgICAgW2RyYWdnaW5nRWxlbWVudC5pZF06IHRydWVcbiAgICAgICAgICB9KSwgcHJldlN0YXRlKSxcbiAgICAgICAgICBzaG93SHlwZXJsaW5rUG9wdXA6IGlzRW1iZWRkYWJsZUVsZW1lbnQoZHJhZ2dpbmdFbGVtZW50KSAmJiAhZHJhZ2dpbmdFbGVtZW50LmxpbmsgPyBcImVkaXRvclwiIDogcHJldlN0YXRlLnNob3dIeXBlcmxpbmtQb3B1cFxuICAgICAgICB9KSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChhY3RpdmVUb29sLnR5cGUgIT09IFwic2VsZWN0aW9uXCIgfHwgaXNTb21lRWxlbWVudFNlbGVjdGVkKHRoaXMuc2NlbmUuZ2V0Tm9uRGVsZXRlZEVsZW1lbnRzKCksIHRoaXMuc3RhdGUpKSB7XG4gICAgICAgIHRoaXMuaGlzdG9yeS5yZXN1bWVSZWNvcmRpbmcoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBvaW50ZXJEb3duU3RhdGUuZHJhZy5oYXNPY2N1cnJlZCB8fCBpc1Jlc2l6aW5nIHx8IGlzUm90YXRpbmcpIHtcbiAgICAgICAgKGlzQmluZGluZ0VuYWJsZWQodGhpcy5zdGF0ZSkgPyBiaW5kT3JVbmJpbmRTZWxlY3RlZEVsZW1lbnRzIDogdW5iaW5kTGluZWFyRWxlbWVudHMpKHRoaXMuc2NlbmUuZ2V0U2VsZWN0ZWRFbGVtZW50cyh0aGlzLnN0YXRlKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICghYWN0aXZlVG9vbC5sb2NrZWQgJiYgYWN0aXZlVG9vbC50eXBlICE9PSBcImZyZWVkcmF3XCIpIHtcbiAgICAgICAgcmVzZXRDdXJzb3IodGhpcy5pbnRlcmFjdGl2ZUNhbnZhcyk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgIGRyYWdnaW5nRWxlbWVudDogbnVsbCxcbiAgICAgICAgICBzdWdnZXN0ZWRCaW5kaW5nczogW10sXG4gICAgICAgICAgYWN0aXZlVG9vbDogdXBkYXRlQWN0aXZlVG9vbCh0aGlzLnN0YXRlLCB7XG4gICAgICAgICAgICB0eXBlOiBcInNlbGVjdGlvblwiXG4gICAgICAgICAgfSlcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBkcmFnZ2luZ0VsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgc3VnZ2VzdGVkQmluZGluZ3M6IFtdXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoaGl0RWxlbWVudCAmJiB0aGlzLmxhc3RQb2ludGVyVXAgJiYgdGhpcy5sYXN0UG9pbnRlckRvd24gJiYgdGhpcy5sYXN0UG9pbnRlclVwLnRpbWVTdGFtcCAtIHRoaXMubGFzdFBvaW50ZXJEb3duLnRpbWVTdGFtcCA8IDMwMCAmJiBnZXN0dXJlLnBvaW50ZXJzLnNpemUgPD0gMSAmJiBpc0VtYmVkZGFibGVFbGVtZW50KGhpdEVsZW1lbnQpICYmIHRoaXMuaXNFbWJlZGRhYmxlQ2VudGVyKGhpdEVsZW1lbnQsIHRoaXMubGFzdFBvaW50ZXJVcCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueCwgcG9pbnRlckRvd25TdGF0ZS5vcmlnaW4ueSkpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVFbWJlZGRhYmxlQ2VudGVyQ2xpY2soaGl0RWxlbWVudCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBtYXliZVN1Z2dlc3RCaW5kaW5nRm9yQWxsKHNlbGVjdGVkRWxlbWVudHMpIHtcbiAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPiA1MCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN1Z2dlc3RlZEJpbmRpbmdzID0gZ2V0RWxpZ2libGVFbGVtZW50c0ZvckJpbmRpbmcoc2VsZWN0ZWRFbGVtZW50cyk7XG4gICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICBzdWdnZXN0ZWRCaW5kaW5nc1xuICAgIH0pO1xuICB9XG5cbiAgY2xlYXJTZWxlY3Rpb24oaGl0RWxlbWVudCkge1xuICAgIHRoaXMuc2V0U3RhdGUocHJldlN0YXRlID0+ICh7XG4gICAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IG1ha2VOZXh0U2VsZWN0ZWRFbGVtZW50SWRzKHt9LCBwcmV2U3RhdGUpLFxuICAgICAgYWN0aXZlRW1iZWRkYWJsZTogbnVsbCxcbiAgICAgIHNlbGVjdGVkR3JvdXBJZHM6IHt9LFxuICAgICAgLy8gQ29udGludWUgZWRpdGluZyB0aGUgc2FtZSBncm91cCBpZiB0aGUgdXNlciBzZWxlY3RlZCBhIGRpZmZlcmVudFxuICAgICAgLy8gZWxlbWVudCBmcm9tIGl0XG4gICAgICBlZGl0aW5nR3JvdXBJZDogcHJldlN0YXRlLmVkaXRpbmdHcm91cElkICYmIGhpdEVsZW1lbnQgIT0gbnVsbCAmJiBpc0VsZW1lbnRJbkdyb3VwKGhpdEVsZW1lbnQsIHByZXZTdGF0ZS5lZGl0aW5nR3JvdXBJZCkgPyBwcmV2U3RhdGUuZWRpdGluZ0dyb3VwSWQgOiBudWxsXG4gICAgfSkpO1xuICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgc2VsZWN0ZWRFbGVtZW50SWRzOiBtYWtlTmV4dFNlbGVjdGVkRWxlbWVudElkcyh7fSwgdGhpcy5zdGF0ZSksXG4gICAgICBhY3RpdmVFbWJlZGRhYmxlOiBudWxsLFxuICAgICAgcHJldmlvdXNTZWxlY3RlZEVsZW1lbnRJZHM6IHRoaXMuc3RhdGUuc2VsZWN0ZWRFbGVtZW50SWRzXG4gICAgfSk7XG4gIH1cblxuICBnZXRUZXh0V3lzaXd5Z1NuYXBwZWRUb0NlbnRlclBvc2l0aW9uKHgsIHksIGFwcFN0YXRlLCBjb250YWluZXIpIHtcbiAgICBpZiAoY29udGFpbmVyKSB7XG4gICAgICBsZXQgZWxlbWVudENlbnRlclggPSBjb250YWluZXIueCArIGNvbnRhaW5lci53aWR0aCAvIDI7XG4gICAgICBsZXQgZWxlbWVudENlbnRlclkgPSBjb250YWluZXIueSArIGNvbnRhaW5lci5oZWlnaHQgLyAyO1xuICAgICAgY29uc3QgZWxlbWVudENlbnRlciA9IGdldENvbnRhaW5lckNlbnRlcihjb250YWluZXIsIGFwcFN0YXRlKTtcblxuICAgICAgaWYgKGVsZW1lbnRDZW50ZXIpIHtcbiAgICAgICAgZWxlbWVudENlbnRlclggPSBlbGVtZW50Q2VudGVyLng7XG4gICAgICAgIGVsZW1lbnRDZW50ZXJZID0gZWxlbWVudENlbnRlci55O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkaXN0YW5jZVRvQ2VudGVyID0gTWF0aC5oeXBvdCh4IC0gZWxlbWVudENlbnRlclgsIHkgLSBlbGVtZW50Q2VudGVyWSk7XG4gICAgICBjb25zdCBpc1NuYXBwZWRUb0NlbnRlciA9IGRpc3RhbmNlVG9DZW50ZXIgPCBURVhUX1RPX0NFTlRFUl9TTkFQX1RIUkVTSE9MRDtcblxuICAgICAgaWYgKGlzU25hcHBlZFRvQ2VudGVyKSB7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICB4OiB2aWV3cG9ydFgsXG4gICAgICAgICAgeTogdmlld3BvcnRZXG4gICAgICAgIH0gPSBzY2VuZUNvb3Jkc1RvVmlld3BvcnRDb29yZHMoe1xuICAgICAgICAgIHNjZW5lWDogZWxlbWVudENlbnRlclgsXG4gICAgICAgICAgc2NlbmVZOiBlbGVtZW50Q2VudGVyWVxuICAgICAgICB9LCBhcHBTdGF0ZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmlld3BvcnRYLFxuICAgICAgICAgIHZpZXdwb3J0WSxcbiAgICAgICAgICBlbGVtZW50Q2VudGVyWCxcbiAgICAgICAgICBlbGVtZW50Q2VudGVyWVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldENhbnZhc09mZnNldHMoKSB7XG4gICAgdmFyIF9hO1xuXG4gICAgaWYgKChfYSA9IHRoaXMuZXhjYWxpZHJhd0NvbnRhaW5lclJlZikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmN1cnJlbnQpIHtcbiAgICAgIGNvbnN0IGV4Y2FsaWRyYXdDb250YWluZXIgPSB0aGlzLmV4Y2FsaWRyYXdDb250YWluZXJSZWYuY3VycmVudDtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgbGVmdCxcbiAgICAgICAgdG9wXG4gICAgICB9ID0gZXhjYWxpZHJhd0NvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9mZnNldExlZnQ6IGxlZnQsXG4gICAgICAgIG9mZnNldFRvcDogdG9wXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBvZmZzZXRMZWZ0OiAwLFxuICAgICAgb2Zmc2V0VG9wOiAwXG4gICAgfTtcbiAgfVxuXG4gIHVwZGF0ZUxhbmd1YWdlKCkge1xuICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gICAgICBjb25zdCBjdXJyZW50TGFuZyA9IGxhbmd1YWdlcy5maW5kKGxhbmcgPT4gbGFuZy5jb2RlID09PSB0aGlzLnByb3BzLmxhbmdDb2RlKSB8fCBkZWZhdWx0TGFuZztcbiAgICAgIHlpZWxkIHNldExhbmd1YWdlKGN1cnJlbnRMYW5nKTtcbiAgICAgIHRoaXMuc2V0QXBwU3RhdGUoe30pO1xuICAgIH0pO1xuICB9XG5cbn1cblxuQXBwLmRlZmF1bHRQcm9wcyA9IHtcbiAgLy8gbmVlZGVkIGZvciB0ZXN0cyB0byBwYXNzIHNpbmNlIHdlIGRpcmVjdGx5IHJlbmRlciBBcHAgaW4gbWFueSB0ZXN0c1xuICBVSU9wdGlvbnM6IERFRkFVTFRfVUlfT1BUSU9OU1xufTtcblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBFTlYuVEVTVCB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gXCJwcm9kdWN0aW9uXCIpIHtcbiAgd2luZG93LmggPSB3aW5kb3cuaCB8fCB7fTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMod2luZG93LmgsIHtcbiAgICBlbGVtZW50czoge1xuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuXG4gICAgICBnZXQoKSB7XG4gICAgICAgIHZhciBfYTtcblxuICAgICAgICByZXR1cm4gKF9hID0gdGhpcy5hcHApID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zY2VuZS5nZXRFbGVtZW50c0luY2x1ZGluZ0RlbGV0ZWQoKTtcbiAgICAgIH0sXG5cbiAgICAgIHNldChlbGVtZW50cykge1xuICAgICAgICB2YXIgX2E7XG5cbiAgICAgICAgcmV0dXJuIChfYSA9IHRoaXMuYXBwKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Euc2NlbmUucmVwbGFjZUFsbEVsZW1lbnRzKGVsZW1lbnRzKTtcbiAgICAgIH1cblxuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFwcDsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../../components/App.tsx\n");
2467
2467
 
2468
2468
  /***/ }),
2469
2469
 
@@ -2540,7 +2540,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2540
2540
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2541
2541
 
2542
2542
  "use strict";
2543
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ColorInput\": () => (/* binding */ ColorInput)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _ColorPicker__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ColorPicker */ \"../../components/ColorPicker/ColorPicker.tsx\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var _colorPickerUtils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./colorPickerUtils */ \"../../components/ColorPicker/colorPickerUtils.ts\");\n/* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../icons */ \"../../components/icons.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../jotai */ \"../../jotai.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../keys */ \"../../keys.ts\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../i18n */ \"../../i18n.ts\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../App */ \"../../components/App.tsx\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../utils */ \"../../utils.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst ColorInput = ({\n color,\n onChange,\n label,\n eyeDropperType\n}) => {\n const device = (0,_App__WEBPACK_IMPORTED_MODULE_10__.useDevice)();\n const [innerValue, setInnerValue] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(color);\n const [activeSection, setActiveColorPickerSection] = (0,jotai__WEBPACK_IMPORTED_MODULE_12__.useAtom)(_colorPickerUtils__WEBPACK_IMPORTED_MODULE_3__.activeColorPickerSectionAtom);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n setInnerValue(color);\n }, [color]);\n const changeColor = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(inputValue => {\n const value = inputValue.toLowerCase();\n const color = (0,_ColorPicker__WEBPACK_IMPORTED_MODULE_2__.getColor)(value);\n\n if (color) {\n onChange(color);\n }\n\n setInnerValue(value);\n }, [onChange]);\n const inputRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);\n const eyeDropperTriggerRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }, [activeSection]);\n const [eyeDropperState, setEyeDropperState] = (0,jotai__WEBPACK_IMPORTED_MODULE_12__.useAtom)(_EyeDropper__WEBPACK_IMPORTED_MODULE_7__.activeEyeDropperAtom, _jotai__WEBPACK_IMPORTED_MODULE_5__.jotaiScope);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n return () => {\n setEyeDropperState(null);\n };\n }, [setEyeDropperState]);\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: \"color-picker__input-label\"\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"color-picker__input-hash\"\n }, {\n children: \"#\"\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"input\", {\n ref: activeSection === \"hex\" ? inputRef : undefined,\n style: {\n border: 0,\n padding: 0\n },\n spellCheck: false,\n className: \"color-picker-input\",\n \"aria-label\": label,\n onChange: event => {\n changeColor(event.target.value);\n },\n value: (innerValue || \"\").replace(/^#/, \"\"),\n onBlur: () => {\n setInnerValue(color);\n },\n tabIndex: -1,\n onFocus: () => setActiveColorPickerSection(\"hex\"),\n onKeyDown: event => {\n var _a;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_6__.KEYS.TAB) {\n return;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_6__.KEYS.ESCAPE) {\n (_a = eyeDropperTriggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();\n }\n\n event.stopPropagation();\n }\n }), !device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n style: {\n width: \"1px\",\n height: \"1.25rem\",\n backgroundColor: \"var(--default-border-color)\"\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n ref: eyeDropperTriggerRef,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"])(\"excalidraw-eye-dropper-trigger\", {\n selected: eyeDropperState\n }),\n onClick: () => setEyeDropperState(s => s ? null : {\n keepOpenOnAlt: false,\n onSelect: color => onChange(color),\n previewType: eyeDropperType\n }),\n title: `${(0,_i18n__WEBPACK_IMPORTED_MODULE_9__.t)(\"labels.eyeDropper\")} — ${_keys__WEBPACK_IMPORTED_MODULE_6__.KEYS.I.toLocaleUpperCase()} or ${(0,_utils__WEBPACK_IMPORTED_MODULE_11__.getShortcutKey)(\"Alt\")} `\n }, {\n children: _icons__WEBPACK_IMPORTED_MODULE_4__.eyeDropperIcon\n }))]\n })]\n }));\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vY29tcG9uZW50cy9Db2xvclBpY2tlci9Db2xvcklucHV0LnRzeC5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBc0Y7QUFDckI7QUFDeEI7QUFDVDtBQUNrQztBQUN4QjtBQUNEO0FBQ1A7QUFDbUI7QUFDN0I7QUFDTztBQUNJO0FBQ1U7QUFDdEM7QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRCxpQkFBaUIsZ0RBQVM7QUFDMUIsc0NBQXNDLCtDQUFRO0FBQzlDLHVEQUF1RCwrQ0FBTyxDQUFDLDJFQUE0QjtBQUMzRixFQUFFLGdEQUFTO0FBQ1g7QUFDQSxHQUFHO0FBQ0gsc0JBQXNCLGtEQUFXO0FBQ2pDO0FBQ0Esa0JBQWtCLHNEQUFROztBQUUxQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0gsbUJBQW1CLDZDQUFNO0FBQ3pCLCtCQUErQiw2Q0FBTTtBQUNyQyxFQUFFLGdEQUFTO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILGdEQUFnRCwrQ0FBTyxDQUFDLDZEQUFvQixFQUFFLDhDQUFVO0FBQ3hGLEVBQUUsZ0RBQVM7QUFDWDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsU0FBUyx1REFBSztBQUNkO0FBQ0EsR0FBRztBQUNILGVBQWUsc0RBQUk7QUFDbkI7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLLElBQUksc0RBQUk7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEIsMkNBQVE7QUFDbEM7QUFDQSxVQUFVLHVCQUF1Qiw4Q0FBVztBQUM1QztBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLLHVCQUF1Qix1REFBSyxDQUFDLHVEQUFTO0FBQzNDLGlCQUFpQixzREFBSTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxHQUFHLHNEQUFJO0FBQ2Q7QUFDQSxtQkFBbUIsZ0RBQUk7QUFDdkI7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Qsa0JBQWtCLHdDQUFDLHVCQUF1QixJQUFJLDJEQUF3QixJQUFJLEtBQUssdURBQWMsU0FBUztBQUN0RyxPQUFPO0FBQ1Asa0JBQWtCLGtEQUFjO0FBQ2hDLE9BQU87QUFDUCxLQUFLO0FBQ0wsR0FBRztBQUNIIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2NvbXBvbmVudHMvQ29sb3JQaWNrZXIvQ29sb3JJbnB1dC50c3g/NGFkZSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBqc3ggYXMgX2pzeCwgRnJhZ21lbnQgYXMgX0ZyYWdtZW50LCBqc3hzIGFzIF9qc3hzIH0gZnJvbSBcInJlYWN0L2pzeC1ydW50aW1lXCI7XG5pbXBvcnQgeyB1c2VDYWxsYmFjaywgdXNlRWZmZWN0LCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBnZXRDb2xvciB9IGZyb20gXCIuL0NvbG9yUGlja2VyXCI7XG5pbXBvcnQgeyB1c2VBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBhY3RpdmVDb2xvclBpY2tlclNlY3Rpb25BdG9tIH0gZnJvbSBcIi4vY29sb3JQaWNrZXJVdGlsc1wiO1xuaW1wb3J0IHsgZXllRHJvcHBlckljb24gfSBmcm9tIFwiLi4vaWNvbnNcIjtcbmltcG9ydCB7IGpvdGFpU2NvcGUgfSBmcm9tIFwiLi4vLi4vam90YWlcIjtcbmltcG9ydCB7IEtFWVMgfSBmcm9tIFwiLi4vLi4va2V5c1wiO1xuaW1wb3J0IHsgYWN0aXZlRXllRHJvcHBlckF0b20gfSBmcm9tIFwiLi4vRXllRHJvcHBlclwiO1xuaW1wb3J0IGNsc3ggZnJvbSBcImNsc3hcIjtcbmltcG9ydCB7IHQgfSBmcm9tIFwiLi4vLi4vaTE4blwiO1xuaW1wb3J0IHsgdXNlRGV2aWNlIH0gZnJvbSBcIi4uL0FwcFwiO1xuaW1wb3J0IHsgZ2V0U2hvcnRjdXRLZXkgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcbmV4cG9ydCBjb25zdCBDb2xvcklucHV0ID0gKHtcbiAgY29sb3IsXG4gIG9uQ2hhbmdlLFxuICBsYWJlbCxcbiAgZXllRHJvcHBlclR5cGVcbn0pID0+IHtcbiAgY29uc3QgZGV2aWNlID0gdXNlRGV2aWNlKCk7XG4gIGNvbnN0IFtpbm5lclZhbHVlLCBzZXRJbm5lclZhbHVlXSA9IHVzZVN0YXRlKGNvbG9yKTtcbiAgY29uc3QgW2FjdGl2ZVNlY3Rpb24sIHNldEFjdGl2ZUNvbG9yUGlja2VyU2VjdGlvbl0gPSB1c2VBdG9tKGFjdGl2ZUNvbG9yUGlja2VyU2VjdGlvbkF0b20pO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIHNldElubmVyVmFsdWUoY29sb3IpO1xuICB9LCBbY29sb3JdKTtcbiAgY29uc3QgY2hhbmdlQ29sb3IgPSB1c2VDYWxsYmFjayhpbnB1dFZhbHVlID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IGlucHV0VmFsdWUudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBjb2xvciA9IGdldENvbG9yKHZhbHVlKTtcblxuICAgIGlmIChjb2xvcikge1xuICAgICAgb25DaGFuZ2UoY29sb3IpO1xuICAgIH1cblxuICAgIHNldElubmVyVmFsdWUodmFsdWUpO1xuICB9LCBbb25DaGFuZ2VdKTtcbiAgY29uc3QgaW5wdXRSZWYgPSB1c2VSZWYobnVsbCk7XG4gIGNvbnN0IGV5ZURyb3BwZXJUcmlnZ2VyUmVmID0gdXNlUmVmKG51bGwpO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChpbnB1dFJlZi5jdXJyZW50KSB7XG4gICAgICBpbnB1dFJlZi5jdXJyZW50LmZvY3VzKCk7XG4gICAgfVxuICB9LCBbYWN0aXZlU2VjdGlvbl0pO1xuICBjb25zdCBbZXllRHJvcHBlclN0YXRlLCBzZXRFeWVEcm9wcGVyU3RhdGVdID0gdXNlQXRvbShhY3RpdmVFeWVEcm9wcGVyQXRvbSwgam90YWlTY29wZSk7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIHNldEV5ZURyb3BwZXJTdGF0ZShudWxsKTtcbiAgICB9O1xuICB9LCBbc2V0RXllRHJvcHBlclN0YXRlXSk7XG4gIHJldHVybiBfanN4cyhcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICBjbGFzc05hbWU6IFwiY29sb3ItcGlja2VyX19pbnB1dC1sYWJlbFwiXG4gIH0sIHtcbiAgICBjaGlsZHJlbjogW19qc3goXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICBjbGFzc05hbWU6IFwiY29sb3ItcGlja2VyX19pbnB1dC1oYXNoXCJcbiAgICB9LCB7XG4gICAgICBjaGlsZHJlbjogXCIjXCJcbiAgICB9KSksIF9qc3goXCJpbnB1dFwiLCB7XG4gICAgICByZWY6IGFjdGl2ZVNlY3Rpb24gPT09IFwiaGV4XCIgPyBpbnB1dFJlZiA6IHVuZGVmaW5lZCxcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIGJvcmRlcjogMCxcbiAgICAgICAgcGFkZGluZzogMFxuICAgICAgfSxcbiAgICAgIHNwZWxsQ2hlY2s6IGZhbHNlLFxuICAgICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlci1pbnB1dFwiLFxuICAgICAgXCJhcmlhLWxhYmVsXCI6IGxhYmVsLFxuICAgICAgb25DaGFuZ2U6IGV2ZW50ID0+IHtcbiAgICAgICAgY2hhbmdlQ29sb3IoZXZlbnQudGFyZ2V0LnZhbHVlKTtcbiAgICAgIH0sXG4gICAgICB2YWx1ZTogKGlubmVyVmFsdWUgfHwgXCJcIikucmVwbGFjZSgvXiMvLCBcIlwiKSxcbiAgICAgIG9uQmx1cjogKCkgPT4ge1xuICAgICAgICBzZXRJbm5lclZhbHVlKGNvbG9yKTtcbiAgICAgIH0sXG4gICAgICB0YWJJbmRleDogLTEsXG4gICAgICBvbkZvY3VzOiAoKSA9PiBzZXRBY3RpdmVDb2xvclBpY2tlclNlY3Rpb24oXCJoZXhcIiksXG4gICAgICBvbktleURvd246IGV2ZW50ID0+IHtcbiAgICAgICAgdmFyIF9hO1xuXG4gICAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuVEFCKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5FU0NBUEUpIHtcbiAgICAgICAgICAoX2EgPSBleWVEcm9wcGVyVHJpZ2dlclJlZi5jdXJyZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZm9jdXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgfVxuICAgIH0pLCAhZGV2aWNlLmlzTW9iaWxlICYmIF9qc3hzKF9GcmFnbWVudCwge1xuICAgICAgY2hpbGRyZW46IFtfanN4KFwiZGl2XCIsIHtcbiAgICAgICAgc3R5bGU6IHtcbiAgICAgICAgICB3aWR0aDogXCIxcHhcIixcbiAgICAgICAgICBoZWlnaHQ6IFwiMS4yNXJlbVwiLFxuICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogXCJ2YXIoLS1kZWZhdWx0LWJvcmRlci1jb2xvcilcIlxuICAgICAgICB9XG4gICAgICB9KSwgX2pzeChcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgcmVmOiBleWVEcm9wcGVyVHJpZ2dlclJlZixcbiAgICAgICAgY2xhc3NOYW1lOiBjbHN4KFwiZXhjYWxpZHJhdy1leWUtZHJvcHBlci10cmlnZ2VyXCIsIHtcbiAgICAgICAgICBzZWxlY3RlZDogZXllRHJvcHBlclN0YXRlXG4gICAgICAgIH0pLFxuICAgICAgICBvbkNsaWNrOiAoKSA9PiBzZXRFeWVEcm9wcGVyU3RhdGUocyA9PiBzID8gbnVsbCA6IHtcbiAgICAgICAgICBrZWVwT3Blbk9uQWx0OiBmYWxzZSxcbiAgICAgICAgICBvblNlbGVjdDogY29sb3IgPT4gb25DaGFuZ2UoY29sb3IpLFxuICAgICAgICAgIHByZXZpZXdUeXBlOiBleWVEcm9wcGVyVHlwZVxuICAgICAgICB9KSxcbiAgICAgICAgdGl0bGU6IGAke3QoXCJsYWJlbHMuZXllRHJvcHBlclwiKX0g4oCUICR7S0VZUy5JLnRvTG9jYWxlVXBwZXJDYXNlKCl9IG9yICR7Z2V0U2hvcnRjdXRLZXkoXCJBbHRcIil9IGBcbiAgICAgIH0sIHtcbiAgICAgICAgY2hpbGRyZW46IGV5ZURyb3BwZXJJY29uXG4gICAgICB9KSldXG4gICAgfSldXG4gIH0pKTtcbn07Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///../../components/ColorPicker/ColorInput.tsx\n");
2543
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ColorInput\": () => (/* binding */ ColorInput)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _ColorPicker__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ColorPicker */ \"../../components/ColorPicker/ColorPicker.tsx\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var _colorPickerUtils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./colorPickerUtils */ \"../../components/ColorPicker/colorPickerUtils.ts\");\n/* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../icons */ \"../../components/icons.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../jotai */ \"../../jotai.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../keys */ \"../../keys.ts\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../i18n */ \"../../i18n.ts\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../App */ \"../../components/App.tsx\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../utils */ \"../../utils.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst ColorInput = ({\n color,\n onChange,\n label,\n colorPickerType\n}) => {\n const device = (0,_App__WEBPACK_IMPORTED_MODULE_10__.useDevice)();\n const [innerValue, setInnerValue] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(color);\n const [activeSection, setActiveColorPickerSection] = (0,jotai__WEBPACK_IMPORTED_MODULE_12__.useAtom)(_colorPickerUtils__WEBPACK_IMPORTED_MODULE_3__.activeColorPickerSectionAtom);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n setInnerValue(color);\n }, [color]);\n const changeColor = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(inputValue => {\n const value = inputValue.toLowerCase();\n const color = (0,_ColorPicker__WEBPACK_IMPORTED_MODULE_2__.getColor)(value);\n\n if (color) {\n onChange(color);\n }\n\n setInnerValue(value);\n }, [onChange]);\n const inputRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);\n const eyeDropperTriggerRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }, [activeSection]);\n const [eyeDropperState, setEyeDropperState] = (0,jotai__WEBPACK_IMPORTED_MODULE_12__.useAtom)(_EyeDropper__WEBPACK_IMPORTED_MODULE_7__.activeEyeDropperAtom, _jotai__WEBPACK_IMPORTED_MODULE_5__.jotaiScope);\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n return () => {\n setEyeDropperState(null);\n };\n }, [setEyeDropperState]);\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: \"color-picker__input-label\"\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"color-picker__input-hash\"\n }, {\n children: \"#\"\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"input\", {\n ref: activeSection === \"hex\" ? inputRef : undefined,\n style: {\n border: 0,\n padding: 0\n },\n spellCheck: false,\n className: \"color-picker-input\",\n \"aria-label\": label,\n onChange: event => {\n changeColor(event.target.value);\n },\n value: (innerValue || \"\").replace(/^#/, \"\"),\n onBlur: () => {\n setInnerValue(color);\n },\n tabIndex: -1,\n onFocus: () => setActiveColorPickerSection(\"hex\"),\n onKeyDown: event => {\n var _a;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_6__.KEYS.TAB) {\n return;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_6__.KEYS.ESCAPE) {\n (_a = eyeDropperTriggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();\n }\n\n event.stopPropagation();\n }\n }), !device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n style: {\n width: \"1px\",\n height: \"1.25rem\",\n backgroundColor: \"var(--default-border-color)\"\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n ref: eyeDropperTriggerRef,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"])(\"excalidraw-eye-dropper-trigger\", {\n selected: eyeDropperState\n }),\n onClick: () => setEyeDropperState(s => s ? null : {\n keepOpenOnAlt: false,\n onSelect: color => onChange(color),\n colorPickerType\n }),\n title: `${(0,_i18n__WEBPACK_IMPORTED_MODULE_9__.t)(\"labels.eyeDropper\")} — ${_keys__WEBPACK_IMPORTED_MODULE_6__.KEYS.I.toLocaleUpperCase()} or ${(0,_utils__WEBPACK_IMPORTED_MODULE_11__.getShortcutKey)(\"Alt\")} `\n }, {\n children: _icons__WEBPACK_IMPORTED_MODULE_4__.eyeDropperIcon\n }))]\n })]\n }));\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vY29tcG9uZW50cy9Db2xvclBpY2tlci9Db2xvcklucHV0LnRzeC5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBc0Y7QUFDckI7QUFDeEI7QUFDVDtBQUNrQztBQUN4QjtBQUNEO0FBQ1A7QUFDbUI7QUFDN0I7QUFDTztBQUNJO0FBQ1U7QUFDdEM7QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRCxpQkFBaUIsZ0RBQVM7QUFDMUIsc0NBQXNDLCtDQUFRO0FBQzlDLHVEQUF1RCwrQ0FBTyxDQUFDLDJFQUE0QjtBQUMzRixFQUFFLGdEQUFTO0FBQ1g7QUFDQSxHQUFHO0FBQ0gsc0JBQXNCLGtEQUFXO0FBQ2pDO0FBQ0Esa0JBQWtCLHNEQUFROztBQUUxQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0gsbUJBQW1CLDZDQUFNO0FBQ3pCLCtCQUErQiw2Q0FBTTtBQUNyQyxFQUFFLGdEQUFTO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILGdEQUFnRCwrQ0FBTyxDQUFDLDZEQUFvQixFQUFFLDhDQUFVO0FBQ3hGLEVBQUUsZ0RBQVM7QUFDWDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsU0FBUyx1REFBSztBQUNkO0FBQ0EsR0FBRztBQUNILGVBQWUsc0RBQUk7QUFDbkI7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLLElBQUksc0RBQUk7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEIsMkNBQVE7QUFDbEM7QUFDQSxVQUFVLHVCQUF1Qiw4Q0FBVztBQUM1QztBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLLHVCQUF1Qix1REFBSyxDQUFDLHVEQUFTO0FBQzNDLGlCQUFpQixzREFBSTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxHQUFHLHNEQUFJO0FBQ2Q7QUFDQSxtQkFBbUIsZ0RBQUk7QUFDdkI7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Qsa0JBQWtCLHdDQUFDLHVCQUF1QixJQUFJLDJEQUF3QixJQUFJLEtBQUssdURBQWMsU0FBUztBQUN0RyxPQUFPO0FBQ1Asa0JBQWtCLGtEQUFjO0FBQ2hDLE9BQU87QUFDUCxLQUFLO0FBQ0wsR0FBRztBQUNIIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2NvbXBvbmVudHMvQ29sb3JQaWNrZXIvQ29sb3JJbnB1dC50c3g/NGFkZSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBqc3ggYXMgX2pzeCwgRnJhZ21lbnQgYXMgX0ZyYWdtZW50LCBqc3hzIGFzIF9qc3hzIH0gZnJvbSBcInJlYWN0L2pzeC1ydW50aW1lXCI7XG5pbXBvcnQgeyB1c2VDYWxsYmFjaywgdXNlRWZmZWN0LCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBnZXRDb2xvciB9IGZyb20gXCIuL0NvbG9yUGlja2VyXCI7XG5pbXBvcnQgeyB1c2VBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBhY3RpdmVDb2xvclBpY2tlclNlY3Rpb25BdG9tIH0gZnJvbSBcIi4vY29sb3JQaWNrZXJVdGlsc1wiO1xuaW1wb3J0IHsgZXllRHJvcHBlckljb24gfSBmcm9tIFwiLi4vaWNvbnNcIjtcbmltcG9ydCB7IGpvdGFpU2NvcGUgfSBmcm9tIFwiLi4vLi4vam90YWlcIjtcbmltcG9ydCB7IEtFWVMgfSBmcm9tIFwiLi4vLi4va2V5c1wiO1xuaW1wb3J0IHsgYWN0aXZlRXllRHJvcHBlckF0b20gfSBmcm9tIFwiLi4vRXllRHJvcHBlclwiO1xuaW1wb3J0IGNsc3ggZnJvbSBcImNsc3hcIjtcbmltcG9ydCB7IHQgfSBmcm9tIFwiLi4vLi4vaTE4blwiO1xuaW1wb3J0IHsgdXNlRGV2aWNlIH0gZnJvbSBcIi4uL0FwcFwiO1xuaW1wb3J0IHsgZ2V0U2hvcnRjdXRLZXkgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcbmV4cG9ydCBjb25zdCBDb2xvcklucHV0ID0gKHtcbiAgY29sb3IsXG4gIG9uQ2hhbmdlLFxuICBsYWJlbCxcbiAgY29sb3JQaWNrZXJUeXBlXG59KSA9PiB7XG4gIGNvbnN0IGRldmljZSA9IHVzZURldmljZSgpO1xuICBjb25zdCBbaW5uZXJWYWx1ZSwgc2V0SW5uZXJWYWx1ZV0gPSB1c2VTdGF0ZShjb2xvcik7XG4gIGNvbnN0IFthY3RpdmVTZWN0aW9uLCBzZXRBY3RpdmVDb2xvclBpY2tlclNlY3Rpb25dID0gdXNlQXRvbShhY3RpdmVDb2xvclBpY2tlclNlY3Rpb25BdG9tKTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBzZXRJbm5lclZhbHVlKGNvbG9yKTtcbiAgfSwgW2NvbG9yXSk7XG4gIGNvbnN0IGNoYW5nZUNvbG9yID0gdXNlQ2FsbGJhY2soaW5wdXRWYWx1ZSA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSBpbnB1dFZhbHVlLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgY29sb3IgPSBnZXRDb2xvcih2YWx1ZSk7XG5cbiAgICBpZiAoY29sb3IpIHtcbiAgICAgIG9uQ2hhbmdlKGNvbG9yKTtcbiAgICB9XG5cbiAgICBzZXRJbm5lclZhbHVlKHZhbHVlKTtcbiAgfSwgW29uQ2hhbmdlXSk7XG4gIGNvbnN0IGlucHV0UmVmID0gdXNlUmVmKG51bGwpO1xuICBjb25zdCBleWVEcm9wcGVyVHJpZ2dlclJlZiA9IHVzZVJlZihudWxsKTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaW5wdXRSZWYuY3VycmVudCkge1xuICAgICAgaW5wdXRSZWYuY3VycmVudC5mb2N1cygpO1xuICAgIH1cbiAgfSwgW2FjdGl2ZVNlY3Rpb25dKTtcbiAgY29uc3QgW2V5ZURyb3BwZXJTdGF0ZSwgc2V0RXllRHJvcHBlclN0YXRlXSA9IHVzZUF0b20oYWN0aXZlRXllRHJvcHBlckF0b20sIGpvdGFpU2NvcGUpO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBzZXRFeWVEcm9wcGVyU3RhdGUobnVsbCk7XG4gICAgfTtcbiAgfSwgW3NldEV5ZURyb3BwZXJTdGF0ZV0pO1xuICByZXR1cm4gX2pzeHMoXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlcl9faW5wdXQtbGFiZWxcIlxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlcl9faW5wdXQtaGFzaFwiXG4gICAgfSwge1xuICAgICAgY2hpbGRyZW46IFwiI1wiXG4gICAgfSkpLCBfanN4KFwiaW5wdXRcIiwge1xuICAgICAgcmVmOiBhY3RpdmVTZWN0aW9uID09PSBcImhleFwiID8gaW5wdXRSZWYgOiB1bmRlZmluZWQsXG4gICAgICBzdHlsZToge1xuICAgICAgICBib3JkZXI6IDAsXG4gICAgICAgIHBhZGRpbmc6IDBcbiAgICAgIH0sXG4gICAgICBzcGVsbENoZWNrOiBmYWxzZSxcbiAgICAgIGNsYXNzTmFtZTogXCJjb2xvci1waWNrZXItaW5wdXRcIixcbiAgICAgIFwiYXJpYS1sYWJlbFwiOiBsYWJlbCxcbiAgICAgIG9uQ2hhbmdlOiBldmVudCA9PiB7XG4gICAgICAgIGNoYW5nZUNvbG9yKGV2ZW50LnRhcmdldC52YWx1ZSk7XG4gICAgICB9LFxuICAgICAgdmFsdWU6IChpbm5lclZhbHVlIHx8IFwiXCIpLnJlcGxhY2UoL14jLywgXCJcIiksXG4gICAgICBvbkJsdXI6ICgpID0+IHtcbiAgICAgICAgc2V0SW5uZXJWYWx1ZShjb2xvcik7XG4gICAgICB9LFxuICAgICAgdGFiSW5kZXg6IC0xLFxuICAgICAgb25Gb2N1czogKCkgPT4gc2V0QWN0aXZlQ29sb3JQaWNrZXJTZWN0aW9uKFwiaGV4XCIpLFxuICAgICAgb25LZXlEb3duOiBldmVudCA9PiB7XG4gICAgICAgIHZhciBfYTtcblxuICAgICAgICBpZiAoZXZlbnQua2V5ID09PSBLRVlTLlRBQikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09IEtFWVMuRVNDQVBFKSB7XG4gICAgICAgICAgKF9hID0gZXllRHJvcHBlclRyaWdnZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmZvY3VzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIH1cbiAgICB9KSwgIWRldmljZS5pc01vYmlsZSAmJiBfanN4cyhfRnJhZ21lbnQsIHtcbiAgICAgIGNoaWxkcmVuOiBbX2pzeChcImRpdlwiLCB7XG4gICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgd2lkdGg6IFwiMXB4XCIsXG4gICAgICAgICAgaGVpZ2h0OiBcIjEuMjVyZW1cIixcbiAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IFwidmFyKC0tZGVmYXVsdC1ib3JkZXItY29sb3IpXCJcbiAgICAgICAgfVxuICAgICAgfSksIF9qc3goXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgIHJlZjogZXllRHJvcHBlclRyaWdnZXJSZWYsXG4gICAgICAgIGNsYXNzTmFtZTogY2xzeChcImV4Y2FsaWRyYXctZXllLWRyb3BwZXItdHJpZ2dlclwiLCB7XG4gICAgICAgICAgc2VsZWN0ZWQ6IGV5ZURyb3BwZXJTdGF0ZVxuICAgICAgICB9KSxcbiAgICAgICAgb25DbGljazogKCkgPT4gc2V0RXllRHJvcHBlclN0YXRlKHMgPT4gcyA/IG51bGwgOiB7XG4gICAgICAgICAga2VlcE9wZW5PbkFsdDogZmFsc2UsXG4gICAgICAgICAgb25TZWxlY3Q6IGNvbG9yID0+IG9uQ2hhbmdlKGNvbG9yKSxcbiAgICAgICAgICBjb2xvclBpY2tlclR5cGVcbiAgICAgICAgfSksXG4gICAgICAgIHRpdGxlOiBgJHt0KFwibGFiZWxzLmV5ZURyb3BwZXJcIil9IOKAlCAke0tFWVMuSS50b0xvY2FsZVVwcGVyQ2FzZSgpfSBvciAke2dldFNob3J0Y3V0S2V5KFwiQWx0XCIpfSBgXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBleWVEcm9wcGVySWNvblxuICAgICAgfSkpXVxuICAgIH0pXVxuICB9KSk7XG59OyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///../../components/ColorPicker/ColorInput.tsx\n");
2544
2544
 
2545
2545
  /***/ }),
2546
2546
 
@@ -2551,7 +2551,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2551
2551
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2552
2552
 
2553
2553
  "use strict";
2554
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ColorPicker\": () => (/* binding */ ColorPicker),\n/* harmony export */ \"getColor\": () => (/* binding */ getColor)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ \"../../utils.ts\");\n/* harmony import */ var _TopPicks__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TopPicks */ \"../../components/ColorPicker/TopPicks.tsx\");\n/* harmony import */ var _Picker__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Picker */ \"../../components/ColorPicker/Picker.tsx\");\n/* harmony import */ var _radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @radix-ui/react-popover */ \"../../../node_modules/@radix-ui/react-popover/dist/index.module.js\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var _colorPickerUtils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./colorPickerUtils */ \"../../components/ColorPicker/colorPickerUtils.ts\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../App */ \"../../components/App.tsx\");\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../colors */ \"../../colors.ts\");\n/* harmony import */ var _PickerHeading__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./PickerHeading */ \"../../components/ColorPicker/PickerHeading.tsx\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../i18n */ \"../../i18n.ts\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../jotai */ \"../../jotai.ts\");\n/* harmony import */ var _ColorInput__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ColorInput */ \"../../components/ColorPicker/ColorInput.tsx\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_12__);\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var _ColorPicker_scss__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./ColorPicker.scss */ \"../../components/ColorPicker/ColorPicker.scss\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst isValidColor = color => {\n const style = new Option().style;\n style.color = color;\n return !!style.color;\n};\n\nconst getColor = color => {\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.isTransparent)(color)) {\n return color;\n } // testing for `#` first fixes a bug on Electron (more specfically, an\n // Obsidian popout window), where a hex color without `#` is (incorrectly)\n // considered valid\n\n\n return isValidColor(`#${color}`) ? `#${color}` : isValidColor(color) ? color : null;\n};\n\nconst ColorPickerPopupContent = ({\n type,\n color,\n onChange,\n label,\n elements,\n palette = _colors__WEBPACK_IMPORTED_MODULE_6__.COLOR_PALETTE,\n updateData\n}) => {\n const [, setActiveColorPickerSection] = (0,jotai__WEBPACK_IMPORTED_MODULE_15__.useAtom)(_colorPickerUtils__WEBPACK_IMPORTED_MODULE_4__.activeColorPickerSectionAtom);\n const [eyeDropperState, setEyeDropperState] = (0,jotai__WEBPACK_IMPORTED_MODULE_15__.useAtom)(_EyeDropper__WEBPACK_IMPORTED_MODULE_13__.activeEyeDropperAtom, _jotai__WEBPACK_IMPORTED_MODULE_10__.jotaiScope);\n const {\n container\n } = (0,_App__WEBPACK_IMPORTED_MODULE_5__.useExcalidrawContainer)();\n const {\n isMobile,\n isLandscape\n } = (0,_App__WEBPACK_IMPORTED_MODULE_5__.useDevice)();\n const eyeDropperType = type === \"canvasBackground\" ? undefined : type === \"elementBackground\" ? \"backgroundColor\" : \"strokeColor\";\n\n const colorInputJSX = eyeDropperType && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_PickerHeading__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_8__.t)(\"colorPicker.hexCode\")\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ColorInput__WEBPACK_IMPORTED_MODULE_11__.ColorInput, {\n color: color,\n label: label,\n onChange: color => {\n onChange(color);\n },\n eyeDropperType: eyeDropperType\n })]\n });\n\n const popoverRef = (0,react__WEBPACK_IMPORTED_MODULE_12__.useRef)(null);\n\n const focusPickerContent = () => {\n var _a, _b;\n\n (_b = (_a = popoverRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(\".color-picker-content\")) === null || _b === void 0 ? void 0 : _b.focus();\n };\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Portal, Object.assign({\n container: container\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Content, Object.assign({\n ref: popoverRef,\n className: \"focus-visible-none\",\n \"data-prevent-outside-click\": true,\n onFocusOutside: event => {\n focusPickerContent();\n event.preventDefault();\n },\n onPointerDownOutside: event => {\n if (eyeDropperState) {\n // prevent from closing if we click outside the popover\n // while eyedropping (e.g. click when clicking the sidebar;\n // the eye-dropper-backdrop is prevented downstream)\n event.preventDefault();\n }\n },\n onCloseAutoFocus: e => {\n e.stopPropagation(); // prevents focusing the trigger\n\n e.preventDefault(); // return focus to excalidraw container unless\n // user focuses an interactive element, such as a button, or\n // enters the text editor by clicking on canvas with the text tool\n\n if (container && !(0,_utils__WEBPACK_IMPORTED_MODULE_1__.isInteractive)(document.activeElement)) {\n container.focus();\n }\n\n updateData({\n openPopup: null\n });\n setActiveColorPickerSection(null);\n },\n side: isMobile && !isLandscape ? \"bottom\" : \"right\",\n align: isMobile && !isLandscape ? \"center\" : \"start\",\n alignOffset: -16,\n sideOffset: 20,\n style: {\n zIndex: \"var(--zIndex-layerUI)\",\n backgroundColor: \"var(--popup-bg-color)\",\n maxWidth: \"208px\",\n maxHeight: window.innerHeight,\n padding: \"12px\",\n borderRadius: \"8px\",\n boxSizing: \"border-box\",\n overflowY: \"auto\",\n boxShadow: \"0px 7px 14px rgba(0, 0, 0, 0.05), 0px 0px 3.12708px rgba(0, 0, 0, 0.0798), 0px 0px 0.931014px rgba(0, 0, 0, 0.1702)\"\n }\n }, {\n children: [palette && eyeDropperType ? (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Picker__WEBPACK_IMPORTED_MODULE_3__.Picker, Object.assign({\n palette: palette,\n color: color,\n onChange: changedColor => {\n onChange(changedColor);\n },\n onEyeDropperToggle: force => {\n setEyeDropperState(state => {\n if (force) {\n state = state || {\n keepOpenOnAlt: true,\n onSelect: onChange,\n previewType: eyeDropperType\n };\n state.keepOpenOnAlt = true;\n return state;\n }\n\n return force === false || state ? null : {\n keepOpenOnAlt: false,\n onSelect: onChange,\n previewType: eyeDropperType\n };\n });\n },\n onEscape: event => {\n if (eyeDropperState) {\n setEyeDropperState(null);\n } else if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.isWritableElement)(event.target)) {\n focusPickerContent();\n } else {\n updateData({\n openPopup: null\n });\n }\n },\n label: label,\n type: type,\n elements: elements,\n updateData: updateData\n }, {\n children: colorInputJSX\n })) : colorInputJSX, (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Arrow, {\n width: 20,\n height: 10,\n style: {\n fill: \"var(--popup-bg-color)\",\n filter: \"drop-shadow(rgba(0, 0, 0, 0.05) 0px 3px 2px)\"\n }\n })]\n }))\n }));\n};\n\nconst ColorPickerTrigger = ({\n label,\n color,\n type\n}) => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Trigger, Object.assign({\n type: \"button\",\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_9__[\"default\"])(\"color-picker__button active-color\", {\n \"is-transparent\": color === \"transparent\" || !color\n }),\n \"aria-label\": label,\n style: color ? {\n \"--swatch-color\": color\n } : undefined,\n title: type === \"elementStroke\" ? (0,_i18n__WEBPACK_IMPORTED_MODULE_8__.t)(\"labels.showStroke\") : (0,_i18n__WEBPACK_IMPORTED_MODULE_8__.t)(\"labels.showBackground\")\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"color-picker__button-outline\"\n })\n }));\n};\n\nconst ColorPicker = ({\n type,\n color,\n onChange,\n label,\n elements,\n palette = _colors__WEBPACK_IMPORTED_MODULE_6__.COLOR_PALETTE,\n topPicks,\n updateData,\n appState\n}) => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n role: \"dialog\",\n \"aria-modal\": \"true\",\n className: \"color-picker-container\"\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_TopPicks__WEBPACK_IMPORTED_MODULE_2__.TopPicks, {\n activeColor: color,\n onChange: onChange,\n type: type,\n topPicks: topPicks\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n style: {\n width: 1,\n height: \"100%\",\n backgroundColor: \"var(--default-border-color)\",\n margin: \"0 auto\"\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Root, Object.assign({\n open: appState.openPopup === type,\n onOpenChange: open => {\n updateData({\n openPopup: open ? type : null\n });\n }\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ColorPickerTrigger, {\n color: color,\n label: label,\n type: type\n }), appState.openPopup === type && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ColorPickerPopupContent, {\n type: type,\n color: color,\n onChange: onChange,\n label: label,\n elements: elements,\n palette: palette,\n updateData: updateData\n })]\n }))]\n }))\n });\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vY29tcG9uZW50cy9Db2xvclBpY2tlci9Db2xvclBpY2tlci50c3guanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBK0Q7QUFDZTtBQUN4QztBQUNKO0FBQ2lCO0FBQ25CO0FBQ2tDO0FBQ1A7QUFDZDtBQUNEO0FBQ2I7QUFDUDtBQUNpQjtBQUNDO0FBQ1g7QUFDc0I7QUFDekI7O0FBRTVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRU87QUFDUCxNQUFNLHFEQUFhO0FBQ25CO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7OztBQUdBLDBCQUEwQixNQUFNLFNBQVMsTUFBTTtBQUMvQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGtEQUFhO0FBQ3pCO0FBQ0EsQ0FBQztBQUNELDBDQUEwQywrQ0FBTyxDQUFDLDJFQUE0QjtBQUM5RSxnREFBZ0QsK0NBQU8sQ0FBQyw4REFBb0IsRUFBRSwrQ0FBVTtBQUN4RjtBQUNBO0FBQ0EsSUFBSSxFQUFFLDREQUFzQjtBQUM1QjtBQUNBO0FBQ0E7QUFDQSxJQUFJLEVBQUUsK0NBQVM7QUFDZjs7QUFFQSwwQ0FBMEMsdURBQUs7QUFDL0MsZUFBZSxzREFBSSxDQUFDLHNEQUFhO0FBQ2pDLGdCQUFnQix3Q0FBQztBQUNqQixLQUFLLEdBQUcsc0RBQUksQ0FBQyxvREFBVTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILHFCQUFxQiw4Q0FBTTs7QUFFM0I7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVMsc0RBQUksQ0FBQyw0REFBYztBQUM1QjtBQUNBLEdBQUc7QUFDSCxjQUFjLHVEQUFLLENBQUMsNkRBQWU7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsNkJBQTZCOztBQUU3Qiw0QkFBNEI7QUFDNUI7QUFDQTs7QUFFQSwwQkFBMEIscURBQWE7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCw2Q0FBNkMsc0RBQUksQ0FBQywyQ0FBTTtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFlBQVksU0FBUyx5REFBaUI7QUFDdEM7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU8sb0JBQW9CLHNEQUFJLENBQUMsMkRBQWE7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTCxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0QsU0FBUyxzREFBSSxDQUFDLDZEQUFlO0FBQzdCO0FBQ0EsZUFBZSxnREFBSTtBQUNuQjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sc0NBQXNDLHdDQUFDLHdCQUF3Qix3Q0FBQztBQUNoRSxHQUFHO0FBQ0gsY0FBYyxzREFBSTtBQUNsQjtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0g7O0FBRU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxrREFBYTtBQUN6QjtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0QsU0FBUyxzREFBSTtBQUNiLGNBQWMsdURBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGlCQUFpQixzREFBSSxDQUFDLCtDQUFRO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxHQUFHLHNEQUFJO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxHQUFHLHVEQUFLLENBQUMsMERBQVk7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxPQUFPO0FBQ1AsbUJBQW1CLHNEQUFJO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBLFNBQVMsa0NBQWtDLHNEQUFJO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUCxLQUFLO0FBQ0wsR0FBRztBQUNIIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2NvbXBvbmVudHMvQ29sb3JQaWNrZXIvQ29sb3JQaWNrZXIudHN4PzdkYjIiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsganN4IGFzIF9qc3gsIGpzeHMgYXMgX2pzeHMgfSBmcm9tIFwicmVhY3QvanN4LXJ1bnRpbWVcIjtcbmltcG9ydCB7IGlzSW50ZXJhY3RpdmUsIGlzVHJhbnNwYXJlbnQsIGlzV3JpdGFibGVFbGVtZW50IH0gZnJvbSBcIi4uLy4uL3V0aWxzXCI7XG5pbXBvcnQgeyBUb3BQaWNrcyB9IGZyb20gXCIuL1RvcFBpY2tzXCI7XG5pbXBvcnQgeyBQaWNrZXIgfSBmcm9tIFwiLi9QaWNrZXJcIjtcbmltcG9ydCAqIGFzIFBvcG92ZXIgZnJvbSBcIkByYWRpeC11aS9yZWFjdC1wb3BvdmVyXCI7XG5pbXBvcnQgeyB1c2VBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBhY3RpdmVDb2xvclBpY2tlclNlY3Rpb25BdG9tIH0gZnJvbSBcIi4vY29sb3JQaWNrZXJVdGlsc1wiO1xuaW1wb3J0IHsgdXNlRGV2aWNlLCB1c2VFeGNhbGlkcmF3Q29udGFpbmVyIH0gZnJvbSBcIi4uL0FwcFwiO1xuaW1wb3J0IHsgQ09MT1JfUEFMRVRURSB9IGZyb20gXCIuLi8uLi9jb2xvcnNcIjtcbmltcG9ydCBQaWNrZXJIZWFkaW5nIGZyb20gXCIuL1BpY2tlckhlYWRpbmdcIjtcbmltcG9ydCB7IHQgfSBmcm9tIFwiLi4vLi4vaTE4blwiO1xuaW1wb3J0IGNsc3ggZnJvbSBcImNsc3hcIjtcbmltcG9ydCB7IGpvdGFpU2NvcGUgfSBmcm9tIFwiLi4vLi4vam90YWlcIjtcbmltcG9ydCB7IENvbG9ySW5wdXQgfSBmcm9tIFwiLi9Db2xvcklucHV0XCI7XG5pbXBvcnQgeyB1c2VSZWYgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IGFjdGl2ZUV5ZURyb3BwZXJBdG9tIH0gZnJvbSBcIi4uL0V5ZURyb3BwZXJcIjtcbmltcG9ydCBcIi4vQ29sb3JQaWNrZXIuc2Nzc1wiO1xuXG5jb25zdCBpc1ZhbGlkQ29sb3IgPSBjb2xvciA9PiB7XG4gIGNvbnN0IHN0eWxlID0gbmV3IE9wdGlvbigpLnN0eWxlO1xuICBzdHlsZS5jb2xvciA9IGNvbG9yO1xuICByZXR1cm4gISFzdHlsZS5jb2xvcjtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRDb2xvciA9IGNvbG9yID0+IHtcbiAgaWYgKGlzVHJhbnNwYXJlbnQoY29sb3IpKSB7XG4gICAgcmV0dXJuIGNvbG9yO1xuICB9IC8vIHRlc3RpbmcgZm9yIGAjYCBmaXJzdCBmaXhlcyBhIGJ1ZyBvbiBFbGVjdHJvbiAobW9yZSBzcGVjZmljYWxseSwgYW5cbiAgLy8gT2JzaWRpYW4gcG9wb3V0IHdpbmRvdyksIHdoZXJlIGEgaGV4IGNvbG9yIHdpdGhvdXQgYCNgIGlzIChpbmNvcnJlY3RseSlcbiAgLy8gY29uc2lkZXJlZCB2YWxpZFxuXG5cbiAgcmV0dXJuIGlzVmFsaWRDb2xvcihgIyR7Y29sb3J9YCkgPyBgIyR7Y29sb3J9YCA6IGlzVmFsaWRDb2xvcihjb2xvcikgPyBjb2xvciA6IG51bGw7XG59O1xuXG5jb25zdCBDb2xvclBpY2tlclBvcHVwQ29udGVudCA9ICh7XG4gIHR5cGUsXG4gIGNvbG9yLFxuICBvbkNoYW5nZSxcbiAgbGFiZWwsXG4gIGVsZW1lbnRzLFxuICBwYWxldHRlID0gQ09MT1JfUEFMRVRURSxcbiAgdXBkYXRlRGF0YVxufSkgPT4ge1xuICBjb25zdCBbLCBzZXRBY3RpdmVDb2xvclBpY2tlclNlY3Rpb25dID0gdXNlQXRvbShhY3RpdmVDb2xvclBpY2tlclNlY3Rpb25BdG9tKTtcbiAgY29uc3QgW2V5ZURyb3BwZXJTdGF0ZSwgc2V0RXllRHJvcHBlclN0YXRlXSA9IHVzZUF0b20oYWN0aXZlRXllRHJvcHBlckF0b20sIGpvdGFpU2NvcGUpO1xuICBjb25zdCB7XG4gICAgY29udGFpbmVyXG4gIH0gPSB1c2VFeGNhbGlkcmF3Q29udGFpbmVyKCk7XG4gIGNvbnN0IHtcbiAgICBpc01vYmlsZSxcbiAgICBpc0xhbmRzY2FwZVxuICB9ID0gdXNlRGV2aWNlKCk7XG4gIGNvbnN0IGV5ZURyb3BwZXJUeXBlID0gdHlwZSA9PT0gXCJjYW52YXNCYWNrZ3JvdW5kXCIgPyB1bmRlZmluZWQgOiB0eXBlID09PSBcImVsZW1lbnRCYWNrZ3JvdW5kXCIgPyBcImJhY2tncm91bmRDb2xvclwiIDogXCJzdHJva2VDb2xvclwiO1xuXG4gIGNvbnN0IGNvbG9ySW5wdXRKU1ggPSBleWVEcm9wcGVyVHlwZSAmJiBfanN4cyhcImRpdlwiLCB7XG4gICAgY2hpbGRyZW46IFtfanN4KFBpY2tlckhlYWRpbmcsIHtcbiAgICAgIGNoaWxkcmVuOiB0KFwiY29sb3JQaWNrZXIuaGV4Q29kZVwiKVxuICAgIH0pLCBfanN4KENvbG9ySW5wdXQsIHtcbiAgICAgIGNvbG9yOiBjb2xvcixcbiAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgIG9uQ2hhbmdlOiBjb2xvciA9PiB7XG4gICAgICAgIG9uQ2hhbmdlKGNvbG9yKTtcbiAgICAgIH0sXG4gICAgICBleWVEcm9wcGVyVHlwZTogZXllRHJvcHBlclR5cGVcbiAgICB9KV1cbiAgfSk7XG5cbiAgY29uc3QgcG9wb3ZlclJlZiA9IHVzZVJlZihudWxsKTtcblxuICBjb25zdCBmb2N1c1BpY2tlckNvbnRlbnQgPSAoKSA9PiB7XG4gICAgdmFyIF9hLCBfYjtcblxuICAgIChfYiA9IChfYSA9IHBvcG92ZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnF1ZXJ5U2VsZWN0b3IoXCIuY29sb3ItcGlja2VyLWNvbnRlbnRcIikpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5mb2N1cygpO1xuICB9O1xuXG4gIHJldHVybiBfanN4KFBvcG92ZXIuUG9ydGFsLCBPYmplY3QuYXNzaWduKHtcbiAgICBjb250YWluZXI6IGNvbnRhaW5lclxuICB9LCB7XG4gICAgY2hpbGRyZW46IF9qc3hzKFBvcG92ZXIuQ29udGVudCwgT2JqZWN0LmFzc2lnbih7XG4gICAgICByZWY6IHBvcG92ZXJSZWYsXG4gICAgICBjbGFzc05hbWU6IFwiZm9jdXMtdmlzaWJsZS1ub25lXCIsXG4gICAgICBcImRhdGEtcHJldmVudC1vdXRzaWRlLWNsaWNrXCI6IHRydWUsXG4gICAgICBvbkZvY3VzT3V0c2lkZTogZXZlbnQgPT4ge1xuICAgICAgICBmb2N1c1BpY2tlckNvbnRlbnQoKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH0sXG4gICAgICBvblBvaW50ZXJEb3duT3V0c2lkZTogZXZlbnQgPT4ge1xuICAgICAgICBpZiAoZXllRHJvcHBlclN0YXRlKSB7XG4gICAgICAgICAgLy8gcHJldmVudCBmcm9tIGNsb3NpbmcgaWYgd2UgY2xpY2sgb3V0c2lkZSB0aGUgcG9wb3ZlclxuICAgICAgICAgIC8vIHdoaWxlIGV5ZWRyb3BwaW5nIChlLmcuIGNsaWNrIHdoZW4gY2xpY2tpbmcgdGhlIHNpZGViYXI7XG4gICAgICAgICAgLy8gdGhlIGV5ZS1kcm9wcGVyLWJhY2tkcm9wIGlzIHByZXZlbnRlZCBkb3duc3RyZWFtKVxuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBvbkNsb3NlQXV0b0ZvY3VzOiBlID0+IHtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTsgLy8gcHJldmVudHMgZm9jdXNpbmcgdGhlIHRyaWdnZXJcblxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIHJldHVybiBmb2N1cyB0byBleGNhbGlkcmF3IGNvbnRhaW5lciB1bmxlc3NcbiAgICAgICAgLy8gdXNlciBmb2N1c2VzIGFuIGludGVyYWN0aXZlIGVsZW1lbnQsIHN1Y2ggYXMgYSBidXR0b24sIG9yXG4gICAgICAgIC8vIGVudGVycyB0aGUgdGV4dCBlZGl0b3IgYnkgY2xpY2tpbmcgb24gY2FudmFzIHdpdGggdGhlIHRleHQgdG9vbFxuXG4gICAgICAgIGlmIChjb250YWluZXIgJiYgIWlzSW50ZXJhY3RpdmUoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkpIHtcbiAgICAgICAgICBjb250YWluZXIuZm9jdXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHVwZGF0ZURhdGEoe1xuICAgICAgICAgIG9wZW5Qb3B1cDogbnVsbFxuICAgICAgICB9KTtcbiAgICAgICAgc2V0QWN0aXZlQ29sb3JQaWNrZXJTZWN0aW9uKG51bGwpO1xuICAgICAgfSxcbiAgICAgIHNpZGU6IGlzTW9iaWxlICYmICFpc0xhbmRzY2FwZSA/IFwiYm90dG9tXCIgOiBcInJpZ2h0XCIsXG4gICAgICBhbGlnbjogaXNNb2JpbGUgJiYgIWlzTGFuZHNjYXBlID8gXCJjZW50ZXJcIiA6IFwic3RhcnRcIixcbiAgICAgIGFsaWduT2Zmc2V0OiAtMTYsXG4gICAgICBzaWRlT2Zmc2V0OiAyMCxcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIHpJbmRleDogXCJ2YXIoLS16SW5kZXgtbGF5ZXJVSSlcIixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBcInZhcigtLXBvcHVwLWJnLWNvbG9yKVwiLFxuICAgICAgICBtYXhXaWR0aDogXCIyMDhweFwiLFxuICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5pbm5lckhlaWdodCxcbiAgICAgICAgcGFkZGluZzogXCIxMnB4XCIsXG4gICAgICAgIGJvcmRlclJhZGl1czogXCI4cHhcIixcbiAgICAgICAgYm94U2l6aW5nOiBcImJvcmRlci1ib3hcIixcbiAgICAgICAgb3ZlcmZsb3dZOiBcImF1dG9cIixcbiAgICAgICAgYm94U2hhZG93OiBcIjBweCA3cHggMTRweCByZ2JhKDAsIDAsIDAsIDAuMDUpLCAwcHggMHB4IDMuMTI3MDhweCByZ2JhKDAsIDAsIDAsIDAuMDc5OCksIDBweCAwcHggMC45MzEwMTRweCByZ2JhKDAsIDAsIDAsIDAuMTcwMilcIlxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBbcGFsZXR0ZSAmJiBleWVEcm9wcGVyVHlwZSA/IF9qc3goUGlja2VyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgcGFsZXR0ZTogcGFsZXR0ZSxcbiAgICAgICAgY29sb3I6IGNvbG9yLFxuICAgICAgICBvbkNoYW5nZTogY2hhbmdlZENvbG9yID0+IHtcbiAgICAgICAgICBvbkNoYW5nZShjaGFuZ2VkQ29sb3IpO1xuICAgICAgICB9LFxuICAgICAgICBvbkV5ZURyb3BwZXJUb2dnbGU6IGZvcmNlID0+IHtcbiAgICAgICAgICBzZXRFeWVEcm9wcGVyU3RhdGUoc3RhdGUgPT4ge1xuICAgICAgICAgICAgaWYgKGZvcmNlKSB7XG4gICAgICAgICAgICAgIHN0YXRlID0gc3RhdGUgfHwge1xuICAgICAgICAgICAgICAgIGtlZXBPcGVuT25BbHQ6IHRydWUsXG4gICAgICAgICAgICAgICAgb25TZWxlY3Q6IG9uQ2hhbmdlLFxuICAgICAgICAgICAgICAgIHByZXZpZXdUeXBlOiBleWVEcm9wcGVyVHlwZVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBzdGF0ZS5rZWVwT3Blbk9uQWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZm9yY2UgPT09IGZhbHNlIHx8IHN0YXRlID8gbnVsbCA6IHtcbiAgICAgICAgICAgICAga2VlcE9wZW5PbkFsdDogZmFsc2UsXG4gICAgICAgICAgICAgIG9uU2VsZWN0OiBvbkNoYW5nZSxcbiAgICAgICAgICAgICAgcHJldmlld1R5cGU6IGV5ZURyb3BwZXJUeXBlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBvbkVzY2FwZTogZXZlbnQgPT4ge1xuICAgICAgICAgIGlmIChleWVEcm9wcGVyU3RhdGUpIHtcbiAgICAgICAgICAgIHNldEV5ZURyb3BwZXJTdGF0ZShudWxsKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGlzV3JpdGFibGVFbGVtZW50KGV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgICAgIGZvY3VzUGlja2VyQ29udGVudCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cGRhdGVEYXRhKHtcbiAgICAgICAgICAgICAgb3BlblBvcHVwOiBudWxsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgZWxlbWVudHM6IGVsZW1lbnRzLFxuICAgICAgICB1cGRhdGVEYXRhOiB1cGRhdGVEYXRhXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBjb2xvcklucHV0SlNYXG4gICAgICB9KSkgOiBjb2xvcklucHV0SlNYLCBfanN4KFBvcG92ZXIuQXJyb3csIHtcbiAgICAgICAgd2lkdGg6IDIwLFxuICAgICAgICBoZWlnaHQ6IDEwLFxuICAgICAgICBzdHlsZToge1xuICAgICAgICAgIGZpbGw6IFwidmFyKC0tcG9wdXAtYmctY29sb3IpXCIsXG4gICAgICAgICAgZmlsdGVyOiBcImRyb3Atc2hhZG93KHJnYmEoMCwgMCwgMCwgMC4wNSkgMHB4IDNweCAycHgpXCJcbiAgICAgICAgfVxuICAgICAgfSldXG4gICAgfSkpXG4gIH0pKTtcbn07XG5cbmNvbnN0IENvbG9yUGlja2VyVHJpZ2dlciA9ICh7XG4gIGxhYmVsLFxuICBjb2xvcixcbiAgdHlwZVxufSkgPT4ge1xuICByZXR1cm4gX2pzeChQb3BvdmVyLlRyaWdnZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgIHR5cGU6IFwiYnV0dG9uXCIsXG4gICAgY2xhc3NOYW1lOiBjbHN4KFwiY29sb3ItcGlja2VyX19idXR0b24gYWN0aXZlLWNvbG9yXCIsIHtcbiAgICAgIFwiaXMtdHJhbnNwYXJlbnRcIjogY29sb3IgPT09IFwidHJhbnNwYXJlbnRcIiB8fCAhY29sb3JcbiAgICB9KSxcbiAgICBcImFyaWEtbGFiZWxcIjogbGFiZWwsXG4gICAgc3R5bGU6IGNvbG9yID8ge1xuICAgICAgXCItLXN3YXRjaC1jb2xvclwiOiBjb2xvclxuICAgIH0gOiB1bmRlZmluZWQsXG4gICAgdGl0bGU6IHR5cGUgPT09IFwiZWxlbWVudFN0cm9rZVwiID8gdChcImxhYmVscy5zaG93U3Ryb2tlXCIpIDogdChcImxhYmVscy5zaG93QmFja2dyb3VuZFwiKVxuICB9LCB7XG4gICAgY2hpbGRyZW46IF9qc3goXCJkaXZcIiwge1xuICAgICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlcl9fYnV0dG9uLW91dGxpbmVcIlxuICAgIH0pXG4gIH0pKTtcbn07XG5cbmV4cG9ydCBjb25zdCBDb2xvclBpY2tlciA9ICh7XG4gIHR5cGUsXG4gIGNvbG9yLFxuICBvbkNoYW5nZSxcbiAgbGFiZWwsXG4gIGVsZW1lbnRzLFxuICBwYWxldHRlID0gQ09MT1JfUEFMRVRURSxcbiAgdG9wUGlja3MsXG4gIHVwZGF0ZURhdGEsXG4gIGFwcFN0YXRlXG59KSA9PiB7XG4gIHJldHVybiBfanN4KFwiZGl2XCIsIHtcbiAgICBjaGlsZHJlbjogX2pzeHMoXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICByb2xlOiBcImRpYWxvZ1wiLFxuICAgICAgXCJhcmlhLW1vZGFsXCI6IFwidHJ1ZVwiLFxuICAgICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlci1jb250YWluZXJcIlxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBbX2pzeChUb3BQaWNrcywge1xuICAgICAgICBhY3RpdmVDb2xvcjogY29sb3IsXG4gICAgICAgIG9uQ2hhbmdlOiBvbkNoYW5nZSxcbiAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgdG9wUGlja3M6IHRvcFBpY2tzXG4gICAgICB9KSwgX2pzeChcImRpdlwiLCB7XG4gICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgd2lkdGg6IDEsXG4gICAgICAgICAgaGVpZ2h0OiBcIjEwMCVcIixcbiAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IFwidmFyKC0tZGVmYXVsdC1ib3JkZXItY29sb3IpXCIsXG4gICAgICAgICAgbWFyZ2luOiBcIjAgYXV0b1wiXG4gICAgICAgIH1cbiAgICAgIH0pLCBfanN4cyhQb3BvdmVyLlJvb3QsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBvcGVuOiBhcHBTdGF0ZS5vcGVuUG9wdXAgPT09IHR5cGUsXG4gICAgICAgIG9uT3BlbkNoYW5nZTogb3BlbiA9PiB7XG4gICAgICAgICAgdXBkYXRlRGF0YSh7XG4gICAgICAgICAgICBvcGVuUG9wdXA6IG9wZW4gPyB0eXBlIDogbnVsbFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBbX2pzeChDb2xvclBpY2tlclRyaWdnZXIsIHtcbiAgICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgICAgbGFiZWw6IGxhYmVsLFxuICAgICAgICAgIHR5cGU6IHR5cGVcbiAgICAgICAgfSksIGFwcFN0YXRlLm9wZW5Qb3B1cCA9PT0gdHlwZSAmJiBfanN4KENvbG9yUGlja2VyUG9wdXBDb250ZW50LCB7XG4gICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgICAgb25DaGFuZ2U6IG9uQ2hhbmdlLFxuICAgICAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgICAgcGFsZXR0ZTogcGFsZXR0ZSxcbiAgICAgICAgICB1cGRhdGVEYXRhOiB1cGRhdGVEYXRhXG4gICAgICAgIH0pXVxuICAgICAgfSkpXVxuICAgIH0pKVxuICB9KTtcbn07Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///../../components/ColorPicker/ColorPicker.tsx\n");
2554
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ColorPicker\": () => (/* binding */ ColorPicker),\n/* harmony export */ \"getColor\": () => (/* binding */ getColor)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils */ \"../../utils.ts\");\n/* harmony import */ var _TopPicks__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TopPicks */ \"../../components/ColorPicker/TopPicks.tsx\");\n/* harmony import */ var _Picker__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Picker */ \"../../components/ColorPicker/Picker.tsx\");\n/* harmony import */ var _radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @radix-ui/react-popover */ \"../../../node_modules/@radix-ui/react-popover/dist/index.module.js\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var _colorPickerUtils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./colorPickerUtils */ \"../../components/ColorPicker/colorPickerUtils.ts\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../App */ \"../../components/App.tsx\");\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../colors */ \"../../colors.ts\");\n/* harmony import */ var _PickerHeading__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./PickerHeading */ \"../../components/ColorPicker/PickerHeading.tsx\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../i18n */ \"../../i18n.ts\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../jotai */ \"../../jotai.ts\");\n/* harmony import */ var _ColorInput__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ColorInput */ \"../../components/ColorPicker/ColorInput.tsx\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_12__);\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var _ColorPicker_scss__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./ColorPicker.scss */ \"../../components/ColorPicker/ColorPicker.scss\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst isValidColor = color => {\n const style = new Option().style;\n style.color = color;\n return !!style.color;\n};\n\nconst getColor = color => {\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.isTransparent)(color)) {\n return color;\n } // testing for `#` first fixes a bug on Electron (more specfically, an\n // Obsidian popout window), where a hex color without `#` is (incorrectly)\n // considered valid\n\n\n return isValidColor(`#${color}`) ? `#${color}` : isValidColor(color) ? color : null;\n};\n\nconst ColorPickerPopupContent = ({\n type,\n color,\n onChange,\n label,\n elements,\n palette = _colors__WEBPACK_IMPORTED_MODULE_6__.COLOR_PALETTE,\n updateData\n}) => {\n const [, setActiveColorPickerSection] = (0,jotai__WEBPACK_IMPORTED_MODULE_15__.useAtom)(_colorPickerUtils__WEBPACK_IMPORTED_MODULE_4__.activeColorPickerSectionAtom);\n const [eyeDropperState, setEyeDropperState] = (0,jotai__WEBPACK_IMPORTED_MODULE_15__.useAtom)(_EyeDropper__WEBPACK_IMPORTED_MODULE_13__.activeEyeDropperAtom, _jotai__WEBPACK_IMPORTED_MODULE_10__.jotaiScope);\n const {\n container\n } = (0,_App__WEBPACK_IMPORTED_MODULE_5__.useExcalidrawContainer)();\n const {\n isMobile,\n isLandscape\n } = (0,_App__WEBPACK_IMPORTED_MODULE_5__.useDevice)();\n\n const colorInputJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_PickerHeading__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_8__.t)(\"colorPicker.hexCode\")\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ColorInput__WEBPACK_IMPORTED_MODULE_11__.ColorInput, {\n color: color,\n label: label,\n onChange: color => {\n onChange(color);\n },\n colorPickerType: type\n })]\n });\n\n const popoverRef = (0,react__WEBPACK_IMPORTED_MODULE_12__.useRef)(null);\n\n const focusPickerContent = () => {\n var _a, _b;\n\n (_b = (_a = popoverRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(\".color-picker-content\")) === null || _b === void 0 ? void 0 : _b.focus();\n };\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Portal, Object.assign({\n container: container\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Content, Object.assign({\n ref: popoverRef,\n className: \"focus-visible-none\",\n \"data-prevent-outside-click\": true,\n onFocusOutside: event => {\n focusPickerContent();\n event.preventDefault();\n },\n onPointerDownOutside: event => {\n if (eyeDropperState) {\n // prevent from closing if we click outside the popover\n // while eyedropping (e.g. click when clicking the sidebar;\n // the eye-dropper-backdrop is prevented downstream)\n event.preventDefault();\n }\n },\n onCloseAutoFocus: e => {\n e.stopPropagation(); // prevents focusing the trigger\n\n e.preventDefault(); // return focus to excalidraw container unless\n // user focuses an interactive element, such as a button, or\n // enters the text editor by clicking on canvas with the text tool\n\n if (container && !(0,_utils__WEBPACK_IMPORTED_MODULE_1__.isInteractive)(document.activeElement)) {\n container.focus();\n }\n\n updateData({\n openPopup: null\n });\n setActiveColorPickerSection(null);\n },\n side: isMobile && !isLandscape ? \"bottom\" : \"right\",\n align: isMobile && !isLandscape ? \"center\" : \"start\",\n alignOffset: -16,\n sideOffset: 20,\n style: {\n zIndex: \"var(--zIndex-layerUI)\",\n backgroundColor: \"var(--popup-bg-color)\",\n maxWidth: \"208px\",\n maxHeight: window.innerHeight,\n padding: \"12px\",\n borderRadius: \"8px\",\n boxSizing: \"border-box\",\n overflowY: \"auto\",\n boxShadow: \"0px 7px 14px rgba(0, 0, 0, 0.05), 0px 0px 3.12708px rgba(0, 0, 0, 0.0798), 0px 0px 0.931014px rgba(0, 0, 0, 0.1702)\"\n }\n }, {\n children: [palette ? (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Picker__WEBPACK_IMPORTED_MODULE_3__.Picker, Object.assign({\n palette: palette,\n color: color,\n onChange: changedColor => {\n onChange(changedColor);\n },\n onEyeDropperToggle: force => {\n setEyeDropperState(state => {\n if (force) {\n state = state || {\n keepOpenOnAlt: true,\n onSelect: onChange,\n colorPickerType: type\n };\n state.keepOpenOnAlt = true;\n return state;\n }\n\n return force === false || state ? null : {\n keepOpenOnAlt: false,\n onSelect: onChange,\n colorPickerType: type\n };\n });\n },\n onEscape: event => {\n if (eyeDropperState) {\n setEyeDropperState(null);\n } else if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.isWritableElement)(event.target)) {\n focusPickerContent();\n } else {\n updateData({\n openPopup: null\n });\n }\n },\n label: label,\n type: type,\n elements: elements,\n updateData: updateData\n }, {\n children: colorInputJSX\n })) : colorInputJSX, (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Arrow, {\n width: 20,\n height: 10,\n style: {\n fill: \"var(--popup-bg-color)\",\n filter: \"drop-shadow(rgba(0, 0, 0, 0.05) 0px 3px 2px)\"\n }\n })]\n }))\n }));\n};\n\nconst ColorPickerTrigger = ({\n label,\n color,\n type\n}) => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Trigger, Object.assign({\n type: \"button\",\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_9__[\"default\"])(\"color-picker__button active-color\", {\n \"is-transparent\": color === \"transparent\" || !color\n }),\n \"aria-label\": label,\n style: color ? {\n \"--swatch-color\": color\n } : undefined,\n title: type === \"elementStroke\" ? (0,_i18n__WEBPACK_IMPORTED_MODULE_8__.t)(\"labels.showStroke\") : (0,_i18n__WEBPACK_IMPORTED_MODULE_8__.t)(\"labels.showBackground\")\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"color-picker__button-outline\"\n })\n }));\n};\n\nconst ColorPicker = ({\n type,\n color,\n onChange,\n label,\n elements,\n palette = _colors__WEBPACK_IMPORTED_MODULE_6__.COLOR_PALETTE,\n topPicks,\n updateData,\n appState\n}) => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n role: \"dialog\",\n \"aria-modal\": \"true\",\n className: \"color-picker-container\"\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_TopPicks__WEBPACK_IMPORTED_MODULE_2__.TopPicks, {\n activeColor: color,\n onChange: onChange,\n type: type,\n topPicks: topPicks\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n style: {\n width: 1,\n height: \"100%\",\n backgroundColor: \"var(--default-border-color)\",\n margin: \"0 auto\"\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_radix_ui_react_popover__WEBPACK_IMPORTED_MODULE_16__.Root, Object.assign({\n open: appState.openPopup === type,\n onOpenChange: open => {\n updateData({\n openPopup: open ? type : null\n });\n }\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ColorPickerTrigger, {\n color: color,\n label: label,\n type: type\n }), appState.openPopup === type && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ColorPickerPopupContent, {\n type: type,\n color: color,\n onChange: onChange,\n label: label,\n elements: elements,\n palette: palette,\n updateData: updateData\n })]\n }))]\n }))\n });\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vY29tcG9uZW50cy9Db2xvclBpY2tlci9Db2xvclBpY2tlci50c3guanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBK0Q7QUFDZTtBQUN4QztBQUNKO0FBQ2lCO0FBQ25CO0FBQ2tDO0FBQ1A7QUFDZDtBQUNEO0FBQ2I7QUFDUDtBQUNpQjtBQUNDO0FBQ1g7QUFDc0I7QUFDekI7O0FBRTVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRU87QUFDUCxNQUFNLHFEQUFhO0FBQ25CO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7OztBQUdBLDBCQUEwQixNQUFNLFNBQVMsTUFBTTtBQUMvQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGtEQUFhO0FBQ3pCO0FBQ0EsQ0FBQztBQUNELDBDQUEwQywrQ0FBTyxDQUFDLDJFQUE0QjtBQUM5RSxnREFBZ0QsK0NBQU8sQ0FBQyw4REFBb0IsRUFBRSwrQ0FBVTtBQUN4RjtBQUNBO0FBQ0EsSUFBSSxFQUFFLDREQUFzQjtBQUM1QjtBQUNBO0FBQ0E7QUFDQSxJQUFJLEVBQUUsK0NBQVM7O0FBRWYsd0JBQXdCLHVEQUFLO0FBQzdCLGVBQWUsc0RBQUksQ0FBQyxzREFBYTtBQUNqQyxnQkFBZ0Isd0NBQUM7QUFDakIsS0FBSyxHQUFHLHNEQUFJLENBQUMsb0RBQVU7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxLQUFLO0FBQ0wsR0FBRzs7QUFFSCxxQkFBcUIsOENBQU07O0FBRTNCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTLHNEQUFJLENBQUMsNERBQWM7QUFDNUI7QUFDQSxHQUFHO0FBQ0gsY0FBYyx1REFBSyxDQUFDLDZEQUFlO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLDZCQUE2Qjs7QUFFN0IsNEJBQTRCO0FBQzVCO0FBQ0E7O0FBRUEsMEJBQTBCLHFEQUFhO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsMkJBQTJCLHNEQUFJLENBQUMsMkNBQU07QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxZQUFZLFNBQVMseURBQWlCO0FBQ3RDO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPLG9CQUFvQixzREFBSSxDQUFDLDJEQUFhO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0wsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFNBQVMsc0RBQUksQ0FBQyw2REFBZTtBQUM3QjtBQUNBLGVBQWUsZ0RBQUk7QUFDbkI7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLHNDQUFzQyx3Q0FBQyx3QkFBd0Isd0NBQUM7QUFDaEUsR0FBRztBQUNILGNBQWMsc0RBQUk7QUFDbEI7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNIOztBQUVPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksa0RBQWE7QUFDekI7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFNBQVMsc0RBQUk7QUFDYixjQUFjLHVEQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxpQkFBaUIsc0RBQUksQ0FBQywrQ0FBUTtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU8sR0FBRyxzREFBSTtBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU8sR0FBRyx1REFBSyxDQUFDLDBEQUFZO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsT0FBTztBQUNQLG1CQUFtQixzREFBSTtBQUN2QjtBQUNBO0FBQ0E7QUFDQSxTQUFTLGtDQUFrQyxzREFBSTtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1AsS0FBSztBQUNMLEdBQUc7QUFDSCIsInNvdXJjZXMiOlsid2VicGFjazovLy8uLi8uLi9jb21wb25lbnRzL0NvbG9yUGlja2VyL0NvbG9yUGlja2VyLnRzeD83ZGIyIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpzeCBhcyBfanN4LCBqc3hzIGFzIF9qc3hzIH0gZnJvbSBcInJlYWN0L2pzeC1ydW50aW1lXCI7XG5pbXBvcnQgeyBpc0ludGVyYWN0aXZlLCBpc1RyYW5zcGFyZW50LCBpc1dyaXRhYmxlRWxlbWVudCB9IGZyb20gXCIuLi8uLi91dGlsc1wiO1xuaW1wb3J0IHsgVG9wUGlja3MgfSBmcm9tIFwiLi9Ub3BQaWNrc1wiO1xuaW1wb3J0IHsgUGlja2VyIH0gZnJvbSBcIi4vUGlja2VyXCI7XG5pbXBvcnQgKiBhcyBQb3BvdmVyIGZyb20gXCJAcmFkaXgtdWkvcmVhY3QtcG9wb3ZlclwiO1xuaW1wb3J0IHsgdXNlQXRvbSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHsgYWN0aXZlQ29sb3JQaWNrZXJTZWN0aW9uQXRvbSB9IGZyb20gXCIuL2NvbG9yUGlja2VyVXRpbHNcIjtcbmltcG9ydCB7IHVzZURldmljZSwgdXNlRXhjYWxpZHJhd0NvbnRhaW5lciB9IGZyb20gXCIuLi9BcHBcIjtcbmltcG9ydCB7IENPTE9SX1BBTEVUVEUgfSBmcm9tIFwiLi4vLi4vY29sb3JzXCI7XG5pbXBvcnQgUGlja2VySGVhZGluZyBmcm9tIFwiLi9QaWNrZXJIZWFkaW5nXCI7XG5pbXBvcnQgeyB0IH0gZnJvbSBcIi4uLy4uL2kxOG5cIjtcbmltcG9ydCBjbHN4IGZyb20gXCJjbHN4XCI7XG5pbXBvcnQgeyBqb3RhaVNjb3BlIH0gZnJvbSBcIi4uLy4uL2pvdGFpXCI7XG5pbXBvcnQgeyBDb2xvcklucHV0IH0gZnJvbSBcIi4vQ29sb3JJbnB1dFwiO1xuaW1wb3J0IHsgdXNlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBhY3RpdmVFeWVEcm9wcGVyQXRvbSB9IGZyb20gXCIuLi9FeWVEcm9wcGVyXCI7XG5pbXBvcnQgXCIuL0NvbG9yUGlja2VyLnNjc3NcIjtcblxuY29uc3QgaXNWYWxpZENvbG9yID0gY29sb3IgPT4ge1xuICBjb25zdCBzdHlsZSA9IG5ldyBPcHRpb24oKS5zdHlsZTtcbiAgc3R5bGUuY29sb3IgPSBjb2xvcjtcbiAgcmV0dXJuICEhc3R5bGUuY29sb3I7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0Q29sb3IgPSBjb2xvciA9PiB7XG4gIGlmIChpc1RyYW5zcGFyZW50KGNvbG9yKSkge1xuICAgIHJldHVybiBjb2xvcjtcbiAgfSAvLyB0ZXN0aW5nIGZvciBgI2AgZmlyc3QgZml4ZXMgYSBidWcgb24gRWxlY3Ryb24gKG1vcmUgc3BlY2ZpY2FsbHksIGFuXG4gIC8vIE9ic2lkaWFuIHBvcG91dCB3aW5kb3cpLCB3aGVyZSBhIGhleCBjb2xvciB3aXRob3V0IGAjYCBpcyAoaW5jb3JyZWN0bHkpXG4gIC8vIGNvbnNpZGVyZWQgdmFsaWRcblxuXG4gIHJldHVybiBpc1ZhbGlkQ29sb3IoYCMke2NvbG9yfWApID8gYCMke2NvbG9yfWAgOiBpc1ZhbGlkQ29sb3IoY29sb3IpID8gY29sb3IgOiBudWxsO1xufTtcblxuY29uc3QgQ29sb3JQaWNrZXJQb3B1cENvbnRlbnQgPSAoe1xuICB0eXBlLFxuICBjb2xvcixcbiAgb25DaGFuZ2UsXG4gIGxhYmVsLFxuICBlbGVtZW50cyxcbiAgcGFsZXR0ZSA9IENPTE9SX1BBTEVUVEUsXG4gIHVwZGF0ZURhdGFcbn0pID0+IHtcbiAgY29uc3QgWywgc2V0QWN0aXZlQ29sb3JQaWNrZXJTZWN0aW9uXSA9IHVzZUF0b20oYWN0aXZlQ29sb3JQaWNrZXJTZWN0aW9uQXRvbSk7XG4gIGNvbnN0IFtleWVEcm9wcGVyU3RhdGUsIHNldEV5ZURyb3BwZXJTdGF0ZV0gPSB1c2VBdG9tKGFjdGl2ZUV5ZURyb3BwZXJBdG9tLCBqb3RhaVNjb3BlKTtcbiAgY29uc3Qge1xuICAgIGNvbnRhaW5lclxuICB9ID0gdXNlRXhjYWxpZHJhd0NvbnRhaW5lcigpO1xuICBjb25zdCB7XG4gICAgaXNNb2JpbGUsXG4gICAgaXNMYW5kc2NhcGVcbiAgfSA9IHVzZURldmljZSgpO1xuXG4gIGNvbnN0IGNvbG9ySW5wdXRKU1ggPSBfanN4cyhcImRpdlwiLCB7XG4gICAgY2hpbGRyZW46IFtfanN4KFBpY2tlckhlYWRpbmcsIHtcbiAgICAgIGNoaWxkcmVuOiB0KFwiY29sb3JQaWNrZXIuaGV4Q29kZVwiKVxuICAgIH0pLCBfanN4KENvbG9ySW5wdXQsIHtcbiAgICAgIGNvbG9yOiBjb2xvcixcbiAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgIG9uQ2hhbmdlOiBjb2xvciA9PiB7XG4gICAgICAgIG9uQ2hhbmdlKGNvbG9yKTtcbiAgICAgIH0sXG4gICAgICBjb2xvclBpY2tlclR5cGU6IHR5cGVcbiAgICB9KV1cbiAgfSk7XG5cbiAgY29uc3QgcG9wb3ZlclJlZiA9IHVzZVJlZihudWxsKTtcblxuICBjb25zdCBmb2N1c1BpY2tlckNvbnRlbnQgPSAoKSA9PiB7XG4gICAgdmFyIF9hLCBfYjtcblxuICAgIChfYiA9IChfYSA9IHBvcG92ZXJSZWYuY3VycmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnF1ZXJ5U2VsZWN0b3IoXCIuY29sb3ItcGlja2VyLWNvbnRlbnRcIikpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5mb2N1cygpO1xuICB9O1xuXG4gIHJldHVybiBfanN4KFBvcG92ZXIuUG9ydGFsLCBPYmplY3QuYXNzaWduKHtcbiAgICBjb250YWluZXI6IGNvbnRhaW5lclxuICB9LCB7XG4gICAgY2hpbGRyZW46IF9qc3hzKFBvcG92ZXIuQ29udGVudCwgT2JqZWN0LmFzc2lnbih7XG4gICAgICByZWY6IHBvcG92ZXJSZWYsXG4gICAgICBjbGFzc05hbWU6IFwiZm9jdXMtdmlzaWJsZS1ub25lXCIsXG4gICAgICBcImRhdGEtcHJldmVudC1vdXRzaWRlLWNsaWNrXCI6IHRydWUsXG4gICAgICBvbkZvY3VzT3V0c2lkZTogZXZlbnQgPT4ge1xuICAgICAgICBmb2N1c1BpY2tlckNvbnRlbnQoKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH0sXG4gICAgICBvblBvaW50ZXJEb3duT3V0c2lkZTogZXZlbnQgPT4ge1xuICAgICAgICBpZiAoZXllRHJvcHBlclN0YXRlKSB7XG4gICAgICAgICAgLy8gcHJldmVudCBmcm9tIGNsb3NpbmcgaWYgd2UgY2xpY2sgb3V0c2lkZSB0aGUgcG9wb3ZlclxuICAgICAgICAgIC8vIHdoaWxlIGV5ZWRyb3BwaW5nIChlLmcuIGNsaWNrIHdoZW4gY2xpY2tpbmcgdGhlIHNpZGViYXI7XG4gICAgICAgICAgLy8gdGhlIGV5ZS1kcm9wcGVyLWJhY2tkcm9wIGlzIHByZXZlbnRlZCBkb3duc3RyZWFtKVxuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBvbkNsb3NlQXV0b0ZvY3VzOiBlID0+IHtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTsgLy8gcHJldmVudHMgZm9jdXNpbmcgdGhlIHRyaWdnZXJcblxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIHJldHVybiBmb2N1cyB0byBleGNhbGlkcmF3IGNvbnRhaW5lciB1bmxlc3NcbiAgICAgICAgLy8gdXNlciBmb2N1c2VzIGFuIGludGVyYWN0aXZlIGVsZW1lbnQsIHN1Y2ggYXMgYSBidXR0b24sIG9yXG4gICAgICAgIC8vIGVudGVycyB0aGUgdGV4dCBlZGl0b3IgYnkgY2xpY2tpbmcgb24gY2FudmFzIHdpdGggdGhlIHRleHQgdG9vbFxuXG4gICAgICAgIGlmIChjb250YWluZXIgJiYgIWlzSW50ZXJhY3RpdmUoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkpIHtcbiAgICAgICAgICBjb250YWluZXIuZm9jdXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHVwZGF0ZURhdGEoe1xuICAgICAgICAgIG9wZW5Qb3B1cDogbnVsbFxuICAgICAgICB9KTtcbiAgICAgICAgc2V0QWN0aXZlQ29sb3JQaWNrZXJTZWN0aW9uKG51bGwpO1xuICAgICAgfSxcbiAgICAgIHNpZGU6IGlzTW9iaWxlICYmICFpc0xhbmRzY2FwZSA/IFwiYm90dG9tXCIgOiBcInJpZ2h0XCIsXG4gICAgICBhbGlnbjogaXNNb2JpbGUgJiYgIWlzTGFuZHNjYXBlID8gXCJjZW50ZXJcIiA6IFwic3RhcnRcIixcbiAgICAgIGFsaWduT2Zmc2V0OiAtMTYsXG4gICAgICBzaWRlT2Zmc2V0OiAyMCxcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIHpJbmRleDogXCJ2YXIoLS16SW5kZXgtbGF5ZXJVSSlcIixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBcInZhcigtLXBvcHVwLWJnLWNvbG9yKVwiLFxuICAgICAgICBtYXhXaWR0aDogXCIyMDhweFwiLFxuICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5pbm5lckhlaWdodCxcbiAgICAgICAgcGFkZGluZzogXCIxMnB4XCIsXG4gICAgICAgIGJvcmRlclJhZGl1czogXCI4cHhcIixcbiAgICAgICAgYm94U2l6aW5nOiBcImJvcmRlci1ib3hcIixcbiAgICAgICAgb3ZlcmZsb3dZOiBcImF1dG9cIixcbiAgICAgICAgYm94U2hhZG93OiBcIjBweCA3cHggMTRweCByZ2JhKDAsIDAsIDAsIDAuMDUpLCAwcHggMHB4IDMuMTI3MDhweCByZ2JhKDAsIDAsIDAsIDAuMDc5OCksIDBweCAwcHggMC45MzEwMTRweCByZ2JhKDAsIDAsIDAsIDAuMTcwMilcIlxuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBbcGFsZXR0ZSA/IF9qc3goUGlja2VyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgcGFsZXR0ZTogcGFsZXR0ZSxcbiAgICAgICAgY29sb3I6IGNvbG9yLFxuICAgICAgICBvbkNoYW5nZTogY2hhbmdlZENvbG9yID0+IHtcbiAgICAgICAgICBvbkNoYW5nZShjaGFuZ2VkQ29sb3IpO1xuICAgICAgICB9LFxuICAgICAgICBvbkV5ZURyb3BwZXJUb2dnbGU6IGZvcmNlID0+IHtcbiAgICAgICAgICBzZXRFeWVEcm9wcGVyU3RhdGUoc3RhdGUgPT4ge1xuICAgICAgICAgICAgaWYgKGZvcmNlKSB7XG4gICAgICAgICAgICAgIHN0YXRlID0gc3RhdGUgfHwge1xuICAgICAgICAgICAgICAgIGtlZXBPcGVuT25BbHQ6IHRydWUsXG4gICAgICAgICAgICAgICAgb25TZWxlY3Q6IG9uQ2hhbmdlLFxuICAgICAgICAgICAgICAgIGNvbG9yUGlja2VyVHlwZTogdHlwZVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBzdGF0ZS5rZWVwT3Blbk9uQWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZm9yY2UgPT09IGZhbHNlIHx8IHN0YXRlID8gbnVsbCA6IHtcbiAgICAgICAgICAgICAga2VlcE9wZW5PbkFsdDogZmFsc2UsXG4gICAgICAgICAgICAgIG9uU2VsZWN0OiBvbkNoYW5nZSxcbiAgICAgICAgICAgICAgY29sb3JQaWNrZXJUeXBlOiB0eXBlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBvbkVzY2FwZTogZXZlbnQgPT4ge1xuICAgICAgICAgIGlmIChleWVEcm9wcGVyU3RhdGUpIHtcbiAgICAgICAgICAgIHNldEV5ZURyb3BwZXJTdGF0ZShudWxsKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGlzV3JpdGFibGVFbGVtZW50KGV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgICAgIGZvY3VzUGlja2VyQ29udGVudCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cGRhdGVEYXRhKHtcbiAgICAgICAgICAgICAgb3BlblBvcHVwOiBudWxsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgZWxlbWVudHM6IGVsZW1lbnRzLFxuICAgICAgICB1cGRhdGVEYXRhOiB1cGRhdGVEYXRhXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBjb2xvcklucHV0SlNYXG4gICAgICB9KSkgOiBjb2xvcklucHV0SlNYLCBfanN4KFBvcG92ZXIuQXJyb3csIHtcbiAgICAgICAgd2lkdGg6IDIwLFxuICAgICAgICBoZWlnaHQ6IDEwLFxuICAgICAgICBzdHlsZToge1xuICAgICAgICAgIGZpbGw6IFwidmFyKC0tcG9wdXAtYmctY29sb3IpXCIsXG4gICAgICAgICAgZmlsdGVyOiBcImRyb3Atc2hhZG93KHJnYmEoMCwgMCwgMCwgMC4wNSkgMHB4IDNweCAycHgpXCJcbiAgICAgICAgfVxuICAgICAgfSldXG4gICAgfSkpXG4gIH0pKTtcbn07XG5cbmNvbnN0IENvbG9yUGlja2VyVHJpZ2dlciA9ICh7XG4gIGxhYmVsLFxuICBjb2xvcixcbiAgdHlwZVxufSkgPT4ge1xuICByZXR1cm4gX2pzeChQb3BvdmVyLlRyaWdnZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgIHR5cGU6IFwiYnV0dG9uXCIsXG4gICAgY2xhc3NOYW1lOiBjbHN4KFwiY29sb3ItcGlja2VyX19idXR0b24gYWN0aXZlLWNvbG9yXCIsIHtcbiAgICAgIFwiaXMtdHJhbnNwYXJlbnRcIjogY29sb3IgPT09IFwidHJhbnNwYXJlbnRcIiB8fCAhY29sb3JcbiAgICB9KSxcbiAgICBcImFyaWEtbGFiZWxcIjogbGFiZWwsXG4gICAgc3R5bGU6IGNvbG9yID8ge1xuICAgICAgXCItLXN3YXRjaC1jb2xvclwiOiBjb2xvclxuICAgIH0gOiB1bmRlZmluZWQsXG4gICAgdGl0bGU6IHR5cGUgPT09IFwiZWxlbWVudFN0cm9rZVwiID8gdChcImxhYmVscy5zaG93U3Ryb2tlXCIpIDogdChcImxhYmVscy5zaG93QmFja2dyb3VuZFwiKVxuICB9LCB7XG4gICAgY2hpbGRyZW46IF9qc3goXCJkaXZcIiwge1xuICAgICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlcl9fYnV0dG9uLW91dGxpbmVcIlxuICAgIH0pXG4gIH0pKTtcbn07XG5cbmV4cG9ydCBjb25zdCBDb2xvclBpY2tlciA9ICh7XG4gIHR5cGUsXG4gIGNvbG9yLFxuICBvbkNoYW5nZSxcbiAgbGFiZWwsXG4gIGVsZW1lbnRzLFxuICBwYWxldHRlID0gQ09MT1JfUEFMRVRURSxcbiAgdG9wUGlja3MsXG4gIHVwZGF0ZURhdGEsXG4gIGFwcFN0YXRlXG59KSA9PiB7XG4gIHJldHVybiBfanN4KFwiZGl2XCIsIHtcbiAgICBjaGlsZHJlbjogX2pzeHMoXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICByb2xlOiBcImRpYWxvZ1wiLFxuICAgICAgXCJhcmlhLW1vZGFsXCI6IFwidHJ1ZVwiLFxuICAgICAgY2xhc3NOYW1lOiBcImNvbG9yLXBpY2tlci1jb250YWluZXJcIlxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBbX2pzeChUb3BQaWNrcywge1xuICAgICAgICBhY3RpdmVDb2xvcjogY29sb3IsXG4gICAgICAgIG9uQ2hhbmdlOiBvbkNoYW5nZSxcbiAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgdG9wUGlja3M6IHRvcFBpY2tzXG4gICAgICB9KSwgX2pzeChcImRpdlwiLCB7XG4gICAgICAgIHN0eWxlOiB7XG4gICAgICAgICAgd2lkdGg6IDEsXG4gICAgICAgICAgaGVpZ2h0OiBcIjEwMCVcIixcbiAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IFwidmFyKC0tZGVmYXVsdC1ib3JkZXItY29sb3IpXCIsXG4gICAgICAgICAgbWFyZ2luOiBcIjAgYXV0b1wiXG4gICAgICAgIH1cbiAgICAgIH0pLCBfanN4cyhQb3BvdmVyLlJvb3QsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBvcGVuOiBhcHBTdGF0ZS5vcGVuUG9wdXAgPT09IHR5cGUsXG4gICAgICAgIG9uT3BlbkNoYW5nZTogb3BlbiA9PiB7XG4gICAgICAgICAgdXBkYXRlRGF0YSh7XG4gICAgICAgICAgICBvcGVuUG9wdXA6IG9wZW4gPyB0eXBlIDogbnVsbFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBbX2pzeChDb2xvclBpY2tlclRyaWdnZXIsIHtcbiAgICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgICAgbGFiZWw6IGxhYmVsLFxuICAgICAgICAgIHR5cGU6IHR5cGVcbiAgICAgICAgfSksIGFwcFN0YXRlLm9wZW5Qb3B1cCA9PT0gdHlwZSAmJiBfanN4KENvbG9yUGlja2VyUG9wdXBDb250ZW50LCB7XG4gICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgICAgb25DaGFuZ2U6IG9uQ2hhbmdlLFxuICAgICAgICAgIGxhYmVsOiBsYWJlbCxcbiAgICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgICAgcGFsZXR0ZTogcGFsZXR0ZSxcbiAgICAgICAgICB1cGRhdGVEYXRhOiB1cGRhdGVEYXRhXG4gICAgICAgIH0pXVxuICAgICAgfSkpXVxuICAgIH0pKVxuICB9KTtcbn07Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///../../components/ColorPicker/ColorPicker.tsx\n");
2555
2555
 
2556
2556
  /***/ }),
2557
2557
 
@@ -2749,7 +2749,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2749
2749
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2750
2750
 
2751
2751
  "use strict";
2752
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"EyeDropper\": () => (/* binding */ EyeDropper),\n/* harmony export */ \"activeEyeDropperAtom\": () => (/* binding */ activeEyeDropperAtom)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../colors */ \"../../colors.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _context_ui_appState__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../context/ui-appState */ \"../../context/ui-appState.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../element/mutateElement */ \"../../element/mutateElement.ts\");\n/* harmony import */ var _hooks_useCreatePortalContainer__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../hooks/useCreatePortalContainer */ \"../../hooks/useCreatePortalContainer.ts\");\n/* harmony import */ var _hooks_useOutsideClick__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../hooks/useOutsideClick */ \"../../hooks/useOutsideClick.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../keys */ \"../../keys.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../scene */ \"../../scene/index.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../scene/Scene */ \"../../scene/Scene.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../scene/ShapeCache */ \"../../scene/ShapeCache.ts\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./App */ \"../../components/App.tsx\");\n/* harmony import */ var _EyeDropper_scss__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./EyeDropper.scss */ \"../../components/EyeDropper.scss\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst activeEyeDropperAtom = (0,jotai__WEBPACK_IMPORTED_MODULE_15__.atom)(null);\nconst EyeDropper = ({\n onCancel,\n onSelect,\n swapPreviewOnAlt,\n previewType\n}) => {\n const eyeDropperContainer = (0,_hooks_useCreatePortalContainer__WEBPACK_IMPORTED_MODULE_7__.useCreatePortalContainer)({\n className: \"excalidraw-eye-dropper-backdrop\",\n parentSelector: \".excalidraw-eye-dropper-container\"\n });\n const appState = (0,_context_ui_appState__WEBPACK_IMPORTED_MODULE_5__.useUIAppState)();\n const elements = (0,_App__WEBPACK_IMPORTED_MODULE_13__.useExcalidrawElements)();\n const app = (0,_App__WEBPACK_IMPORTED_MODULE_13__.useApp)();\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_10__.getSelectedElements)(elements, appState);\n const metaStuffRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)({\n selectedElements,\n app\n });\n metaStuffRef.current.selectedElements = selectedElements;\n metaStuffRef.current.app = app;\n const {\n container: excalidrawContainer\n } = (0,_App__WEBPACK_IMPORTED_MODULE_13__.useExcalidrawContainer)();\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n const colorPreviewDiv = ref.current;\n\n if (!colorPreviewDiv || !app.canvas || !eyeDropperContainer) {\n return;\n }\n\n let isHoldingPointerDown = false;\n const ctx = app.canvas.getContext(\"2d\");\n\n const getCurrentColor = ({\n clientX,\n clientY\n }) => {\n const pixel = ctx.getImageData((clientX - appState.offsetLeft) * window.devicePixelRatio, (clientY - appState.offsetTop) * window.devicePixelRatio, 1, 1).data;\n return (0,_colors__WEBPACK_IMPORTED_MODULE_3__.rgbToHex)(pixel[0], pixel[1], pixel[2]);\n };\n\n const mouseMoveListener = ({\n clientX,\n clientY,\n altKey\n }) => {\n var _a; // FIXME swap offset when the preview gets outside viewport\n\n\n colorPreviewDiv.style.top = `${clientY + 20}px`;\n colorPreviewDiv.style.left = `${clientX + 20}px`;\n const currentColor = getCurrentColor({\n clientX,\n clientY\n });\n\n if (isHoldingPointerDown) {\n for (const element of metaStuffRef.current.selectedElements) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_6__.mutateElement)(element, {\n [altKey && swapPreviewOnAlt ? previewType === \"strokeColor\" ? \"backgroundColor\" : \"strokeColor\" : previewType]: currentColor\n }, false);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_12__.ShapeCache[\"delete\"](element);\n }\n\n (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getScene(metaStuffRef.current.selectedElements[0])) === null || _a === void 0 ? void 0 : _a.informMutation();\n }\n\n colorPreviewDiv.style.background = currentColor;\n };\n\n const pointerDownListener = event => {\n isHoldingPointerDown = true; // NOTE we can't event.preventDefault() as that would stop\n // pointermove events\n\n event.stopImmediatePropagation();\n };\n\n const pointerUpListener = event => {\n isHoldingPointerDown = false; // since we're not preventing default on pointerdown, the focus would\n // goes back to `body` so we want to refocus the editor container instead\n\n excalidrawContainer === null || excalidrawContainer === void 0 ? void 0 : excalidrawContainer.focus();\n event.stopImmediatePropagation();\n event.preventDefault();\n onSelect(getCurrentColor(event), event);\n };\n\n const keyDownListener = event => {\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_9__.KEYS.ESCAPE) {\n event.preventDefault();\n event.stopImmediatePropagation();\n onCancel();\n }\n }; // -------------------------------------------------------------------------\n\n\n eyeDropperContainer.tabIndex = -1; // focus container so we can listen on keydown events\n\n eyeDropperContainer.focus(); // init color preview else it would show only after the first mouse move\n\n mouseMoveListener({\n clientX: metaStuffRef.current.app.lastViewportPosition.x,\n clientY: metaStuffRef.current.app.lastViewportPosition.y,\n altKey: false\n });\n eyeDropperContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.KEYDOWN, keyDownListener);\n eyeDropperContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_DOWN, pointerDownListener);\n eyeDropperContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_UP, pointerUpListener);\n window.addEventListener(\"pointermove\", mouseMoveListener, {\n passive: true\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.BLUR, onCancel);\n return () => {\n isHoldingPointerDown = false;\n eyeDropperContainer.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.KEYDOWN, keyDownListener);\n eyeDropperContainer.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_DOWN, pointerDownListener);\n eyeDropperContainer.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_UP, pointerUpListener);\n window.removeEventListener(\"pointermove\", mouseMoveListener);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.BLUR, onCancel);\n };\n }, [app.canvas, eyeDropperContainer, onCancel, onSelect, swapPreviewOnAlt, previewType, excalidrawContainer, appState.offsetLeft, appState.offsetTop]);\n const ref = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);\n (0,_hooks_useOutsideClick__WEBPACK_IMPORTED_MODULE_8__.useOutsideClick)(ref, () => {\n onCancel();\n }, event => {\n if (event.target.closest(\".excalidraw-eye-dropper-trigger, .excalidraw-eye-dropper-backdrop\")) {\n return true;\n } // consider all other clicks as outside\n\n\n return false;\n });\n\n if (!eyeDropperContainer) {\n return null;\n }\n\n return (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.createPortal)((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n ref: ref,\n className: \"excalidraw-eye-dropper-preview\"\n }), eyeDropperContainer);\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vY29tcG9uZW50cy9FeWVEcm9wcGVyLnRzeC5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFnRDtBQUNuQjtBQUNhO0FBQ0Q7QUFDSjtBQUNBO0FBQ2tCO0FBQ0U7QUFDb0I7QUFDbEI7QUFDNUI7QUFDZ0I7QUFDWjtBQUNjO0FBQzZCO0FBQ25EO0FBQ3BCLDZCQUE2Qiw0Q0FBSTtBQUNqQztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELDhCQUE4Qix5RkFBd0I7QUFDdEQ7QUFDQTtBQUNBLEdBQUc7QUFDSCxtQkFBbUIsbUVBQWE7QUFDaEMsbUJBQW1CLDREQUFxQjtBQUN4QyxjQUFjLDZDQUFNO0FBQ3BCLDJCQUEyQiw0REFBbUI7QUFDOUMsdUJBQXVCLDZDQUFNO0FBQzdCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJLEVBQUUsNkRBQXNCO0FBQzVCLEVBQUUsZ0RBQVM7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxhQUFhLGlEQUFRO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGNBQWM7OztBQUdkLHFDQUFxQyxhQUFhO0FBQ2xELHNDQUFzQyxhQUFhO0FBQ25EO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBLFVBQVUscUVBQWE7QUFDdkI7QUFDQSxXQUFXO0FBQ1gsVUFBVSxvRUFBaUI7QUFDM0I7O0FBRUEsY0FBYyw4REFBYztBQUM1Qjs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbUNBQW1DO0FBQ25DOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxvQ0FBb0M7QUFDcEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdCQUF3Qiw4Q0FBVztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87OztBQUdQLHVDQUF1Qzs7QUFFdkMsaUNBQWlDOztBQUVqQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCx5Q0FBeUMscURBQWE7QUFDdEQseUNBQXlDLDBEQUFrQjtBQUMzRCx5Q0FBeUMsd0RBQWdCO0FBQ3pEO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsNEJBQTRCLGtEQUFVO0FBQ3RDO0FBQ0E7QUFDQSw4Q0FBOEMscURBQWE7QUFDM0QsOENBQThDLDBEQUFrQjtBQUNoRSw4Q0FBOEMsd0RBQWdCO0FBQzlEO0FBQ0EsaUNBQWlDLGtEQUFVO0FBQzNDO0FBQ0EsR0FBRztBQUNILGNBQWMsNkNBQU07QUFDcEIsRUFBRSx1RUFBZTtBQUNqQjtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLHVEQUFZLENBQUMsc0RBQUk7QUFDMUI7QUFDQTtBQUNBLEdBQUc7QUFDSCIsInNvdXJjZXMiOlsid2VicGFjazovLy8uLi8uLi9jb21wb25lbnRzL0V5ZURyb3BwZXIudHN4P2VmMTUiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsganN4IGFzIF9qc3ggfSBmcm9tIFwicmVhY3QvanN4LXJ1bnRpbWVcIjtcbmltcG9ydCB7IGF0b20gfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7IHVzZUVmZmVjdCwgdXNlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBjcmVhdGVQb3J0YWwgfSBmcm9tIFwicmVhY3QtZG9tXCI7XG5pbXBvcnQgeyByZ2JUb0hleCB9IGZyb20gXCIuLi9jb2xvcnNcIjtcbmltcG9ydCB7IEVWRU5UIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgdXNlVUlBcHBTdGF0ZSB9IGZyb20gXCIuLi9jb250ZXh0L3VpLWFwcFN0YXRlXCI7XG5pbXBvcnQgeyBtdXRhdGVFbGVtZW50IH0gZnJvbSBcIi4uL2VsZW1lbnQvbXV0YXRlRWxlbWVudFwiO1xuaW1wb3J0IHsgdXNlQ3JlYXRlUG9ydGFsQ29udGFpbmVyIH0gZnJvbSBcIi4uL2hvb2tzL3VzZUNyZWF0ZVBvcnRhbENvbnRhaW5lclwiO1xuaW1wb3J0IHsgdXNlT3V0c2lkZUNsaWNrIH0gZnJvbSBcIi4uL2hvb2tzL3VzZU91dHNpZGVDbGlja1wiO1xuaW1wb3J0IHsgS0VZUyB9IGZyb20gXCIuLi9rZXlzXCI7XG5pbXBvcnQgeyBnZXRTZWxlY3RlZEVsZW1lbnRzIH0gZnJvbSBcIi4uL3NjZW5lXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL3NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgeyBTaGFwZUNhY2hlIH0gZnJvbSBcIi4uL3NjZW5lL1NoYXBlQ2FjaGVcIjtcbmltcG9ydCB7IHVzZUFwcCwgdXNlRXhjYWxpZHJhd0NvbnRhaW5lciwgdXNlRXhjYWxpZHJhd0VsZW1lbnRzIH0gZnJvbSBcIi4vQXBwXCI7XG5pbXBvcnQgXCIuL0V5ZURyb3BwZXIuc2Nzc1wiO1xuZXhwb3J0IGNvbnN0IGFjdGl2ZUV5ZURyb3BwZXJBdG9tID0gYXRvbShudWxsKTtcbmV4cG9ydCBjb25zdCBFeWVEcm9wcGVyID0gKHtcbiAgb25DYW5jZWwsXG4gIG9uU2VsZWN0LFxuICBzd2FwUHJldmlld09uQWx0LFxuICBwcmV2aWV3VHlwZVxufSkgPT4ge1xuICBjb25zdCBleWVEcm9wcGVyQ29udGFpbmVyID0gdXNlQ3JlYXRlUG9ydGFsQ29udGFpbmVyKHtcbiAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhdy1leWUtZHJvcHBlci1iYWNrZHJvcFwiLFxuICAgIHBhcmVudFNlbGVjdG9yOiBcIi5leGNhbGlkcmF3LWV5ZS1kcm9wcGVyLWNvbnRhaW5lclwiXG4gIH0pO1xuICBjb25zdCBhcHBTdGF0ZSA9IHVzZVVJQXBwU3RhdGUoKTtcbiAgY29uc3QgZWxlbWVudHMgPSB1c2VFeGNhbGlkcmF3RWxlbWVudHMoKTtcbiAgY29uc3QgYXBwID0gdXNlQXBwKCk7XG4gIGNvbnN0IHNlbGVjdGVkRWxlbWVudHMgPSBnZXRTZWxlY3RlZEVsZW1lbnRzKGVsZW1lbnRzLCBhcHBTdGF0ZSk7XG4gIGNvbnN0IG1ldGFTdHVmZlJlZiA9IHVzZVJlZih7XG4gICAgc2VsZWN0ZWRFbGVtZW50cyxcbiAgICBhcHBcbiAgfSk7XG4gIG1ldGFTdHVmZlJlZi5jdXJyZW50LnNlbGVjdGVkRWxlbWVudHMgPSBzZWxlY3RlZEVsZW1lbnRzO1xuICBtZXRhU3R1ZmZSZWYuY3VycmVudC5hcHAgPSBhcHA7XG4gIGNvbnN0IHtcbiAgICBjb250YWluZXI6IGV4Y2FsaWRyYXdDb250YWluZXJcbiAgfSA9IHVzZUV4Y2FsaWRyYXdDb250YWluZXIoKTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBjb2xvclByZXZpZXdEaXYgPSByZWYuY3VycmVudDtcblxuICAgIGlmICghY29sb3JQcmV2aWV3RGl2IHx8ICFhcHAuY2FudmFzIHx8ICFleWVEcm9wcGVyQ29udGFpbmVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IGlzSG9sZGluZ1BvaW50ZXJEb3duID0gZmFsc2U7XG4gICAgY29uc3QgY3R4ID0gYXBwLmNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICBjb25zdCBnZXRDdXJyZW50Q29sb3IgPSAoe1xuICAgICAgY2xpZW50WCxcbiAgICAgIGNsaWVudFlcbiAgICB9KSA9PiB7XG4gICAgICBjb25zdCBwaXhlbCA9IGN0eC5nZXRJbWFnZURhdGEoKGNsaWVudFggLSBhcHBTdGF0ZS5vZmZzZXRMZWZ0KSAqIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLCAoY2xpZW50WSAtIGFwcFN0YXRlLm9mZnNldFRvcCkgKiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywgMSwgMSkuZGF0YTtcbiAgICAgIHJldHVybiByZ2JUb0hleChwaXhlbFswXSwgcGl4ZWxbMV0sIHBpeGVsWzJdKTtcbiAgICB9O1xuXG4gICAgY29uc3QgbW91c2VNb3ZlTGlzdGVuZXIgPSAoe1xuICAgICAgY2xpZW50WCxcbiAgICAgIGNsaWVudFksXG4gICAgICBhbHRLZXlcbiAgICB9KSA9PiB7XG4gICAgICB2YXIgX2E7IC8vIEZJWE1FIHN3YXAgb2Zmc2V0IHdoZW4gdGhlIHByZXZpZXcgZ2V0cyBvdXRzaWRlIHZpZXdwb3J0XG5cblxuICAgICAgY29sb3JQcmV2aWV3RGl2LnN0eWxlLnRvcCA9IGAke2NsaWVudFkgKyAyMH1weGA7XG4gICAgICBjb2xvclByZXZpZXdEaXYuc3R5bGUubGVmdCA9IGAke2NsaWVudFggKyAyMH1weGA7XG4gICAgICBjb25zdCBjdXJyZW50Q29sb3IgPSBnZXRDdXJyZW50Q29sb3Ioe1xuICAgICAgICBjbGllbnRYLFxuICAgICAgICBjbGllbnRZXG4gICAgICB9KTtcblxuICAgICAgaWYgKGlzSG9sZGluZ1BvaW50ZXJEb3duKSB7XG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBtZXRhU3R1ZmZSZWYuY3VycmVudC5zZWxlY3RlZEVsZW1lbnRzKSB7XG4gICAgICAgICAgbXV0YXRlRWxlbWVudChlbGVtZW50LCB7XG4gICAgICAgICAgICBbYWx0S2V5ICYmIHN3YXBQcmV2aWV3T25BbHQgPyBwcmV2aWV3VHlwZSA9PT0gXCJzdHJva2VDb2xvclwiID8gXCJiYWNrZ3JvdW5kQ29sb3JcIiA6IFwic3Ryb2tlQ29sb3JcIiA6IHByZXZpZXdUeXBlXTogY3VycmVudENvbG9yXG4gICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgIFNoYXBlQ2FjaGUuZGVsZXRlKGVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgKF9hID0gU2NlbmUuZ2V0U2NlbmUobWV0YVN0dWZmUmVmLmN1cnJlbnQuc2VsZWN0ZWRFbGVtZW50c1swXSkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5pbmZvcm1NdXRhdGlvbigpO1xuICAgICAgfVxuXG4gICAgICBjb2xvclByZXZpZXdEaXYuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnRDb2xvcjtcbiAgICB9O1xuXG4gICAgY29uc3QgcG9pbnRlckRvd25MaXN0ZW5lciA9IGV2ZW50ID0+IHtcbiAgICAgIGlzSG9sZGluZ1BvaW50ZXJEb3duID0gdHJ1ZTsgLy8gTk9URSB3ZSBjYW4ndCBldmVudC5wcmV2ZW50RGVmYXVsdCgpIGFzIHRoYXQgd291bGQgc3RvcFxuICAgICAgLy8gcG9pbnRlcm1vdmUgZXZlbnRzXG5cbiAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgIH07XG5cbiAgICBjb25zdCBwb2ludGVyVXBMaXN0ZW5lciA9IGV2ZW50ID0+IHtcbiAgICAgIGlzSG9sZGluZ1BvaW50ZXJEb3duID0gZmFsc2U7IC8vIHNpbmNlIHdlJ3JlIG5vdCBwcmV2ZW50aW5nIGRlZmF1bHQgb24gcG9pbnRlcmRvd24sIHRoZSBmb2N1cyB3b3VsZFxuICAgICAgLy8gZ29lcyBiYWNrIHRvIGBib2R5YCBzbyB3ZSB3YW50IHRvIHJlZm9jdXMgdGhlIGVkaXRvciBjb250YWluZXIgaW5zdGVhZFxuXG4gICAgICBleGNhbGlkcmF3Q29udGFpbmVyID09PSBudWxsIHx8IGV4Y2FsaWRyYXdDb250YWluZXIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGV4Y2FsaWRyYXdDb250YWluZXIuZm9jdXMoKTtcbiAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIG9uU2VsZWN0KGdldEN1cnJlbnRDb2xvcihldmVudCksIGV2ZW50KTtcbiAgICB9O1xuXG4gICAgY29uc3Qga2V5RG93bkxpc3RlbmVyID0gZXZlbnQgPT4ge1xuICAgICAgaWYgKGV2ZW50LmtleSA9PT0gS0VZUy5FU0NBUEUpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgIG9uQ2FuY2VsKCk7XG4gICAgICB9XG4gICAgfTsgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbiAgICBleWVEcm9wcGVyQ29udGFpbmVyLnRhYkluZGV4ID0gLTE7IC8vIGZvY3VzIGNvbnRhaW5lciBzbyB3ZSBjYW4gbGlzdGVuIG9uIGtleWRvd24gZXZlbnRzXG5cbiAgICBleWVEcm9wcGVyQ29udGFpbmVyLmZvY3VzKCk7IC8vIGluaXQgY29sb3IgcHJldmlldyBlbHNlIGl0IHdvdWxkIHNob3cgb25seSBhZnRlciB0aGUgZmlyc3QgbW91c2UgbW92ZVxuXG4gICAgbW91c2VNb3ZlTGlzdGVuZXIoe1xuICAgICAgY2xpZW50WDogbWV0YVN0dWZmUmVmLmN1cnJlbnQuYXBwLmxhc3RWaWV3cG9ydFBvc2l0aW9uLngsXG4gICAgICBjbGllbnRZOiBtZXRhU3R1ZmZSZWYuY3VycmVudC5hcHAubGFzdFZpZXdwb3J0UG9zaXRpb24ueSxcbiAgICAgIGFsdEtleTogZmFsc2VcbiAgICB9KTtcbiAgICBleWVEcm9wcGVyQ29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZRE9XTiwga2V5RG93bkxpc3RlbmVyKTtcbiAgICBleWVEcm9wcGVyQ29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9ET1dOLCBwb2ludGVyRG93bkxpc3RlbmVyKTtcbiAgICBleWVEcm9wcGVyQ29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9VUCwgcG9pbnRlclVwTGlzdGVuZXIpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwicG9pbnRlcm1vdmVcIiwgbW91c2VNb3ZlTGlzdGVuZXIsIHtcbiAgICAgIHBhc3NpdmU6IHRydWVcbiAgICB9KTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihFVkVOVC5CTFVSLCBvbkNhbmNlbCk7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGlzSG9sZGluZ1BvaW50ZXJEb3duID0gZmFsc2U7XG4gICAgICBleWVEcm9wcGVyQ29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuS0VZRE9XTiwga2V5RG93bkxpc3RlbmVyKTtcbiAgICAgIGV5ZURyb3BwZXJDb250YWluZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX0RPV04sIHBvaW50ZXJEb3duTGlzdGVuZXIpO1xuICAgICAgZXllRHJvcHBlckNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIHBvaW50ZXJVcExpc3RlbmVyKTtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwicG9pbnRlcm1vdmVcIiwgbW91c2VNb3ZlTGlzdGVuZXIpO1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuQkxVUiwgb25DYW5jZWwpO1xuICAgIH07XG4gIH0sIFthcHAuY2FudmFzLCBleWVEcm9wcGVyQ29udGFpbmVyLCBvbkNhbmNlbCwgb25TZWxlY3QsIHN3YXBQcmV2aWV3T25BbHQsIHByZXZpZXdUeXBlLCBleGNhbGlkcmF3Q29udGFpbmVyLCBhcHBTdGF0ZS5vZmZzZXRMZWZ0LCBhcHBTdGF0ZS5vZmZzZXRUb3BdKTtcbiAgY29uc3QgcmVmID0gdXNlUmVmKG51bGwpO1xuICB1c2VPdXRzaWRlQ2xpY2socmVmLCAoKSA9PiB7XG4gICAgb25DYW5jZWwoKTtcbiAgfSwgZXZlbnQgPT4ge1xuICAgIGlmIChldmVudC50YXJnZXQuY2xvc2VzdChcIi5leGNhbGlkcmF3LWV5ZS1kcm9wcGVyLXRyaWdnZXIsIC5leGNhbGlkcmF3LWV5ZS1kcm9wcGVyLWJhY2tkcm9wXCIpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IC8vIGNvbnNpZGVyIGFsbCBvdGhlciBjbGlja3MgYXMgb3V0c2lkZVxuXG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0pO1xuXG4gIGlmICghZXllRHJvcHBlckNvbnRhaW5lcikge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZVBvcnRhbChfanN4KFwiZGl2XCIsIHtcbiAgICByZWY6IHJlZixcbiAgICBjbGFzc05hbWU6IFwiZXhjYWxpZHJhdy1leWUtZHJvcHBlci1wcmV2aWV3XCJcbiAgfSksIGV5ZURyb3BwZXJDb250YWluZXIpO1xufTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../../components/EyeDropper.tsx\n");
2752
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"EyeDropper\": () => (/* binding */ EyeDropper),\n/* harmony export */ \"activeEyeDropperAtom\": () => (/* binding */ activeEyeDropperAtom)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../colors */ \"../../colors.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _context_ui_appState__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../context/ui-appState */ \"../../context/ui-appState.ts\");\n/* harmony import */ var _hooks_useCreatePortalContainer__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../hooks/useCreatePortalContainer */ \"../../hooks/useCreatePortalContainer.ts\");\n/* harmony import */ var _hooks_useOutsideClick__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../hooks/useOutsideClick */ \"../../hooks/useOutsideClick.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../keys */ \"../../keys.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../scene */ \"../../scene/index.ts\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./App */ \"../../components/App.tsx\");\n/* harmony import */ var _hooks_useStable__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../hooks/useStable */ \"../../hooks/useStable.ts\");\n/* harmony import */ var _EyeDropper_scss__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./EyeDropper.scss */ \"../../components/EyeDropper.scss\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst activeEyeDropperAtom = (0,jotai__WEBPACK_IMPORTED_MODULE_13__.atom)(null);\nconst EyeDropper = ({\n onCancel,\n onChange,\n onSelect,\n colorPickerType\n}) => {\n const eyeDropperContainer = (0,_hooks_useCreatePortalContainer__WEBPACK_IMPORTED_MODULE_6__.useCreatePortalContainer)({\n className: \"excalidraw-eye-dropper-backdrop\",\n parentSelector: \".excalidraw-eye-dropper-container\"\n });\n const appState = (0,_context_ui_appState__WEBPACK_IMPORTED_MODULE_5__.useUIAppState)();\n const elements = (0,_App__WEBPACK_IMPORTED_MODULE_10__.useExcalidrawElements)();\n const app = (0,_App__WEBPACK_IMPORTED_MODULE_10__.useApp)();\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_9__.getSelectedElements)(elements, appState);\n const stableProps = (0,_hooks_useStable__WEBPACK_IMPORTED_MODULE_11__.useStable)({\n app,\n onCancel,\n onChange,\n onSelect,\n selectedElements\n });\n const {\n container: excalidrawContainer\n } = (0,_App__WEBPACK_IMPORTED_MODULE_10__.useExcalidrawContainer)();\n (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(() => {\n const colorPreviewDiv = ref.current;\n\n if (!colorPreviewDiv || !app.canvas || !eyeDropperContainer) {\n return;\n }\n\n let isHoldingPointerDown = false;\n const ctx = app.canvas.getContext(\"2d\");\n\n const getCurrentColor = ({\n clientX,\n clientY\n }) => {\n const pixel = ctx.getImageData((clientX - appState.offsetLeft) * window.devicePixelRatio, (clientY - appState.offsetTop) * window.devicePixelRatio, 1, 1).data;\n return (0,_colors__WEBPACK_IMPORTED_MODULE_3__.rgbToHex)(pixel[0], pixel[1], pixel[2]);\n };\n\n const mouseMoveListener = ({\n clientX,\n clientY,\n altKey\n }) => {\n // FIXME swap offset when the preview gets outside viewport\n colorPreviewDiv.style.top = `${clientY + 20}px`;\n colorPreviewDiv.style.left = `${clientX + 20}px`;\n const currentColor = getCurrentColor({\n clientX,\n clientY\n });\n\n if (isHoldingPointerDown) {\n stableProps.onChange(colorPickerType, currentColor, stableProps.selectedElements, {\n altKey\n });\n }\n\n colorPreviewDiv.style.background = currentColor;\n };\n\n const onCancel = () => {\n stableProps.onCancel();\n };\n\n const onSelect = (color, event) => {\n stableProps.onSelect(color, event);\n };\n\n const pointerDownListener = event => {\n isHoldingPointerDown = true; // NOTE we can't event.preventDefault() as that would stop\n // pointermove events\n\n event.stopImmediatePropagation();\n };\n\n const pointerUpListener = event => {\n isHoldingPointerDown = false; // since we're not preventing default on pointerdown, the focus would\n // goes back to `body` so we want to refocus the editor container instead\n\n excalidrawContainer === null || excalidrawContainer === void 0 ? void 0 : excalidrawContainer.focus();\n event.stopImmediatePropagation();\n event.preventDefault();\n onSelect(getCurrentColor(event), event);\n };\n\n const keyDownListener = event => {\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_8__.KEYS.ESCAPE) {\n event.preventDefault();\n event.stopImmediatePropagation();\n onCancel();\n }\n }; // -------------------------------------------------------------------------\n\n\n eyeDropperContainer.tabIndex = -1; // focus container so we can listen on keydown events\n\n eyeDropperContainer.focus(); // init color preview else it would show only after the first mouse move\n\n mouseMoveListener({\n clientX: stableProps.app.lastViewportPosition.x,\n clientY: stableProps.app.lastViewportPosition.y,\n altKey: false\n });\n eyeDropperContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.KEYDOWN, keyDownListener);\n eyeDropperContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_DOWN, pointerDownListener);\n eyeDropperContainer.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_UP, pointerUpListener);\n window.addEventListener(\"pointermove\", mouseMoveListener, {\n passive: true\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.BLUR, onCancel);\n return () => {\n isHoldingPointerDown = false;\n eyeDropperContainer.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.KEYDOWN, keyDownListener);\n eyeDropperContainer.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_DOWN, pointerDownListener);\n eyeDropperContainer.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.POINTER_UP, pointerUpListener);\n window.removeEventListener(\"pointermove\", mouseMoveListener);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_4__.EVENT.BLUR, onCancel);\n };\n }, [stableProps, app.canvas, eyeDropperContainer, colorPickerType, excalidrawContainer, appState.offsetLeft, appState.offsetTop]);\n const ref = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null);\n (0,_hooks_useOutsideClick__WEBPACK_IMPORTED_MODULE_7__.useOutsideClick)(ref, () => {\n onCancel();\n }, event => {\n if (event.target.closest(\".excalidraw-eye-dropper-trigger, .excalidraw-eye-dropper-backdrop\")) {\n return true;\n } // consider all other clicks as outside\n\n\n return false;\n });\n\n if (!eyeDropperContainer) {\n return null;\n }\n\n return (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.createPortal)((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n ref: ref,\n className: \"excalidraw-eye-dropper-preview\"\n }), eyeDropperContainer);\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vY29tcG9uZW50cy9FeWVEcm9wcGVyLnRzeC5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBZ0Q7QUFDbkI7QUFDb0I7QUFDUjtBQUNKO0FBQ0E7QUFDa0I7QUFDc0I7QUFDbEI7QUFDNUI7QUFDZ0I7QUFDK0I7QUFDL0I7QUFDcEI7QUFDcEIsNkJBQTZCLDRDQUFJO0FBQ2pDO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0QsOEJBQThCLHlGQUF3QjtBQUN0RDtBQUNBO0FBQ0EsR0FBRztBQUNILG1CQUFtQixtRUFBYTtBQUNoQyxtQkFBbUIsNERBQXFCO0FBQ3hDLGNBQWMsNkNBQU07QUFDcEIsMkJBQTJCLDJEQUFtQjtBQUM5QyxzQkFBc0IsNERBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsSUFBSSxFQUFFLDZEQUFzQjtBQUM1QixFQUFFLGdEQUFTO0FBQ1g7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsYUFBYSxpREFBUTtBQUNyQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLHFDQUFxQyxhQUFhO0FBQ2xELHNDQUFzQyxhQUFhO0FBQ25EO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1DQUFtQztBQUNuQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esb0NBQW9DO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3QkFBd0IsOENBQVc7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUCx1Q0FBdUM7O0FBRXZDLGlDQUFpQzs7QUFFakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wseUNBQXlDLHFEQUFhO0FBQ3RELHlDQUF5QywwREFBa0I7QUFDM0QseUNBQXlDLHdEQUFnQjtBQUN6RDtBQUNBO0FBQ0EsS0FBSztBQUNMLDRCQUE0QixrREFBVTtBQUN0QztBQUNBO0FBQ0EsOENBQThDLHFEQUFhO0FBQzNELDhDQUE4QywwREFBa0I7QUFDaEUsOENBQThDLHdEQUFnQjtBQUM5RDtBQUNBLGlDQUFpQyxrREFBVTtBQUMzQztBQUNBLEdBQUc7QUFDSCxjQUFjLDZDQUFNO0FBQ3BCLEVBQUUsdUVBQWU7QUFDakI7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLE1BQU07OztBQUdOO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUEsU0FBUyx1REFBWSxDQUFDLHNEQUFJO0FBQzFCO0FBQ0E7QUFDQSxHQUFHO0FBQ0giLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi4vLi4vY29tcG9uZW50cy9FeWVEcm9wcGVyLnRzeD9lZjE1Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpzeCBhcyBfanN4IH0gZnJvbSBcInJlYWN0L2pzeC1ydW50aW1lXCI7XG5pbXBvcnQgeyBhdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgUmVhY3QsIHsgdXNlRWZmZWN0LCB1c2VSZWYgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IGNyZWF0ZVBvcnRhbCB9IGZyb20gXCJyZWFjdC1kb21cIjtcbmltcG9ydCB7IHJnYlRvSGV4IH0gZnJvbSBcIi4uL2NvbG9yc1wiO1xuaW1wb3J0IHsgRVZFTlQgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyB1c2VVSUFwcFN0YXRlIH0gZnJvbSBcIi4uL2NvbnRleHQvdWktYXBwU3RhdGVcIjtcbmltcG9ydCB7IHVzZUNyZWF0ZVBvcnRhbENvbnRhaW5lciB9IGZyb20gXCIuLi9ob29rcy91c2VDcmVhdGVQb3J0YWxDb250YWluZXJcIjtcbmltcG9ydCB7IHVzZU91dHNpZGVDbGljayB9IGZyb20gXCIuLi9ob29rcy91c2VPdXRzaWRlQ2xpY2tcIjtcbmltcG9ydCB7IEtFWVMgfSBmcm9tIFwiLi4va2V5c1wiO1xuaW1wb3J0IHsgZ2V0U2VsZWN0ZWRFbGVtZW50cyB9IGZyb20gXCIuLi9zY2VuZVwiO1xuaW1wb3J0IHsgdXNlQXBwLCB1c2VFeGNhbGlkcmF3Q29udGFpbmVyLCB1c2VFeGNhbGlkcmF3RWxlbWVudHMgfSBmcm9tIFwiLi9BcHBcIjtcbmltcG9ydCB7IHVzZVN0YWJsZSB9IGZyb20gXCIuLi9ob29rcy91c2VTdGFibGVcIjtcbmltcG9ydCBcIi4vRXllRHJvcHBlci5zY3NzXCI7XG5leHBvcnQgY29uc3QgYWN0aXZlRXllRHJvcHBlckF0b20gPSBhdG9tKG51bGwpO1xuZXhwb3J0IGNvbnN0IEV5ZURyb3BwZXIgPSAoe1xuICBvbkNhbmNlbCxcbiAgb25DaGFuZ2UsXG4gIG9uU2VsZWN0LFxuICBjb2xvclBpY2tlclR5cGVcbn0pID0+IHtcbiAgY29uc3QgZXllRHJvcHBlckNvbnRhaW5lciA9IHVzZUNyZWF0ZVBvcnRhbENvbnRhaW5lcih7XG4gICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXctZXllLWRyb3BwZXItYmFja2Ryb3BcIixcbiAgICBwYXJlbnRTZWxlY3RvcjogXCIuZXhjYWxpZHJhdy1leWUtZHJvcHBlci1jb250YWluZXJcIlxuICB9KTtcbiAgY29uc3QgYXBwU3RhdGUgPSB1c2VVSUFwcFN0YXRlKCk7XG4gIGNvbnN0IGVsZW1lbnRzID0gdXNlRXhjYWxpZHJhd0VsZW1lbnRzKCk7XG4gIGNvbnN0IGFwcCA9IHVzZUFwcCgpO1xuICBjb25zdCBzZWxlY3RlZEVsZW1lbnRzID0gZ2V0U2VsZWN0ZWRFbGVtZW50cyhlbGVtZW50cywgYXBwU3RhdGUpO1xuICBjb25zdCBzdGFibGVQcm9wcyA9IHVzZVN0YWJsZSh7XG4gICAgYXBwLFxuICAgIG9uQ2FuY2VsLFxuICAgIG9uQ2hhbmdlLFxuICAgIG9uU2VsZWN0LFxuICAgIHNlbGVjdGVkRWxlbWVudHNcbiAgfSk7XG4gIGNvbnN0IHtcbiAgICBjb250YWluZXI6IGV4Y2FsaWRyYXdDb250YWluZXJcbiAgfSA9IHVzZUV4Y2FsaWRyYXdDb250YWluZXIoKTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBjb2xvclByZXZpZXdEaXYgPSByZWYuY3VycmVudDtcblxuICAgIGlmICghY29sb3JQcmV2aWV3RGl2IHx8ICFhcHAuY2FudmFzIHx8ICFleWVEcm9wcGVyQ29udGFpbmVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IGlzSG9sZGluZ1BvaW50ZXJEb3duID0gZmFsc2U7XG4gICAgY29uc3QgY3R4ID0gYXBwLmNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICBjb25zdCBnZXRDdXJyZW50Q29sb3IgPSAoe1xuICAgICAgY2xpZW50WCxcbiAgICAgIGNsaWVudFlcbiAgICB9KSA9PiB7XG4gICAgICBjb25zdCBwaXhlbCA9IGN0eC5nZXRJbWFnZURhdGEoKGNsaWVudFggLSBhcHBTdGF0ZS5vZmZzZXRMZWZ0KSAqIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLCAoY2xpZW50WSAtIGFwcFN0YXRlLm9mZnNldFRvcCkgKiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywgMSwgMSkuZGF0YTtcbiAgICAgIHJldHVybiByZ2JUb0hleChwaXhlbFswXSwgcGl4ZWxbMV0sIHBpeGVsWzJdKTtcbiAgICB9O1xuXG4gICAgY29uc3QgbW91c2VNb3ZlTGlzdGVuZXIgPSAoe1xuICAgICAgY2xpZW50WCxcbiAgICAgIGNsaWVudFksXG4gICAgICBhbHRLZXlcbiAgICB9KSA9PiB7XG4gICAgICAvLyBGSVhNRSBzd2FwIG9mZnNldCB3aGVuIHRoZSBwcmV2aWV3IGdldHMgb3V0c2lkZSB2aWV3cG9ydFxuICAgICAgY29sb3JQcmV2aWV3RGl2LnN0eWxlLnRvcCA9IGAke2NsaWVudFkgKyAyMH1weGA7XG4gICAgICBjb2xvclByZXZpZXdEaXYuc3R5bGUubGVmdCA9IGAke2NsaWVudFggKyAyMH1weGA7XG4gICAgICBjb25zdCBjdXJyZW50Q29sb3IgPSBnZXRDdXJyZW50Q29sb3Ioe1xuICAgICAgICBjbGllbnRYLFxuICAgICAgICBjbGllbnRZXG4gICAgICB9KTtcblxuICAgICAgaWYgKGlzSG9sZGluZ1BvaW50ZXJEb3duKSB7XG4gICAgICAgIHN0YWJsZVByb3BzLm9uQ2hhbmdlKGNvbG9yUGlja2VyVHlwZSwgY3VycmVudENvbG9yLCBzdGFibGVQcm9wcy5zZWxlY3RlZEVsZW1lbnRzLCB7XG4gICAgICAgICAgYWx0S2V5XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb2xvclByZXZpZXdEaXYuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnRDb2xvcjtcbiAgICB9O1xuXG4gICAgY29uc3Qgb25DYW5jZWwgPSAoKSA9PiB7XG4gICAgICBzdGFibGVQcm9wcy5vbkNhbmNlbCgpO1xuICAgIH07XG5cbiAgICBjb25zdCBvblNlbGVjdCA9IChjb2xvciwgZXZlbnQpID0+IHtcbiAgICAgIHN0YWJsZVByb3BzLm9uU2VsZWN0KGNvbG9yLCBldmVudCk7XG4gICAgfTtcblxuICAgIGNvbnN0IHBvaW50ZXJEb3duTGlzdGVuZXIgPSBldmVudCA9PiB7XG4gICAgICBpc0hvbGRpbmdQb2ludGVyRG93biA9IHRydWU7IC8vIE5PVEUgd2UgY2FuJ3QgZXZlbnQucHJldmVudERlZmF1bHQoKSBhcyB0aGF0IHdvdWxkIHN0b3BcbiAgICAgIC8vIHBvaW50ZXJtb3ZlIGV2ZW50c1xuXG4gICAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICB9O1xuXG4gICAgY29uc3QgcG9pbnRlclVwTGlzdGVuZXIgPSBldmVudCA9PiB7XG4gICAgICBpc0hvbGRpbmdQb2ludGVyRG93biA9IGZhbHNlOyAvLyBzaW5jZSB3ZSdyZSBub3QgcHJldmVudGluZyBkZWZhdWx0IG9uIHBvaW50ZXJkb3duLCB0aGUgZm9jdXMgd291bGRcbiAgICAgIC8vIGdvZXMgYmFjayB0byBgYm9keWAgc28gd2Ugd2FudCB0byByZWZvY3VzIHRoZSBlZGl0b3IgY29udGFpbmVyIGluc3RlYWRcblxuICAgICAgZXhjYWxpZHJhd0NvbnRhaW5lciA9PT0gbnVsbCB8fCBleGNhbGlkcmF3Q29udGFpbmVyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBleGNhbGlkcmF3Q29udGFpbmVyLmZvY3VzKCk7XG4gICAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBvblNlbGVjdChnZXRDdXJyZW50Q29sb3IoZXZlbnQpLCBldmVudCk7XG4gICAgfTtcblxuICAgIGNvbnN0IGtleURvd25MaXN0ZW5lciA9IGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09IEtFWVMuRVNDQVBFKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICBvbkNhbmNlbCgpO1xuICAgICAgfVxuICAgIH07IC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG4gICAgZXllRHJvcHBlckNvbnRhaW5lci50YWJJbmRleCA9IC0xOyAvLyBmb2N1cyBjb250YWluZXIgc28gd2UgY2FuIGxpc3RlbiBvbiBrZXlkb3duIGV2ZW50c1xuXG4gICAgZXllRHJvcHBlckNvbnRhaW5lci5mb2N1cygpOyAvLyBpbml0IGNvbG9yIHByZXZpZXcgZWxzZSBpdCB3b3VsZCBzaG93IG9ubHkgYWZ0ZXIgdGhlIGZpcnN0IG1vdXNlIG1vdmVcblxuICAgIG1vdXNlTW92ZUxpc3RlbmVyKHtcbiAgICAgIGNsaWVudFg6IHN0YWJsZVByb3BzLmFwcC5sYXN0Vmlld3BvcnRQb3NpdGlvbi54LFxuICAgICAgY2xpZW50WTogc3RhYmxlUHJvcHMuYXBwLmxhc3RWaWV3cG9ydFBvc2l0aW9uLnksXG4gICAgICBhbHRLZXk6IGZhbHNlXG4gICAgfSk7XG4gICAgZXllRHJvcHBlckNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKEVWRU5ULktFWURPV04sIGtleURvd25MaXN0ZW5lcik7XG4gICAgZXllRHJvcHBlckNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfRE9XTiwgcG9pbnRlckRvd25MaXN0ZW5lcik7XG4gICAgZXllRHJvcHBlckNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKEVWRU5ULlBPSU5URVJfVVAsIHBvaW50ZXJVcExpc3RlbmVyKTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInBvaW50ZXJtb3ZlXCIsIG1vdXNlTW92ZUxpc3RlbmVyLCB7XG4gICAgICBwYXNzaXZlOiB0cnVlXG4gICAgfSk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRVZFTlQuQkxVUiwgb25DYW5jZWwpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBpc0hvbGRpbmdQb2ludGVyRG93biA9IGZhbHNlO1xuICAgICAgZXllRHJvcHBlckNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULktFWURPV04sIGtleURvd25MaXN0ZW5lcik7XG4gICAgICBleWVEcm9wcGVyQ29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoRVZFTlQuUE9JTlRFUl9ET1dOLCBwb2ludGVyRG93bkxpc3RlbmVyKTtcbiAgICAgIGV5ZURyb3BwZXJDb250YWluZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcihFVkVOVC5QT0lOVEVSX1VQLCBwb2ludGVyVXBMaXN0ZW5lcik7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInBvaW50ZXJtb3ZlXCIsIG1vdXNlTW92ZUxpc3RlbmVyKTtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKEVWRU5ULkJMVVIsIG9uQ2FuY2VsKTtcbiAgICB9O1xuICB9LCBbc3RhYmxlUHJvcHMsIGFwcC5jYW52YXMsIGV5ZURyb3BwZXJDb250YWluZXIsIGNvbG9yUGlja2VyVHlwZSwgZXhjYWxpZHJhd0NvbnRhaW5lciwgYXBwU3RhdGUub2Zmc2V0TGVmdCwgYXBwU3RhdGUub2Zmc2V0VG9wXSk7XG4gIGNvbnN0IHJlZiA9IHVzZVJlZihudWxsKTtcbiAgdXNlT3V0c2lkZUNsaWNrKHJlZiwgKCkgPT4ge1xuICAgIG9uQ2FuY2VsKCk7XG4gIH0sIGV2ZW50ID0+IHtcbiAgICBpZiAoZXZlbnQudGFyZ2V0LmNsb3Nlc3QoXCIuZXhjYWxpZHJhdy1leWUtZHJvcHBlci10cmlnZ2VyLCAuZXhjYWxpZHJhdy1leWUtZHJvcHBlci1iYWNrZHJvcFwiKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSAvLyBjb25zaWRlciBhbGwgb3RoZXIgY2xpY2tzIGFzIG91dHNpZGVcblxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KTtcblxuICBpZiAoIWV5ZURyb3BwZXJDb250YWluZXIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVQb3J0YWwoX2pzeChcImRpdlwiLCB7XG4gICAgcmVmOiByZWYsXG4gICAgY2xhc3NOYW1lOiBcImV4Y2FsaWRyYXctZXllLWRyb3BwZXItcHJldmlld1wiXG4gIH0pLCBleWVEcm9wcGVyQ29udGFpbmVyKTtcbn07Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///../../components/EyeDropper.tsx\n");
2753
2753
 
2754
2754
  /***/ }),
2755
2755
 
@@ -2881,7 +2881,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2881
2881
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2882
2882
 
2883
2883
  "use strict";
2884
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../element */ \"../../element/index.ts\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../i18n */ \"../../i18n.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../scene */ \"../../scene/index.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils */ \"../../utils.ts\");\n/* harmony import */ var _Actions__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Actions */ \"../../components/Actions.tsx\");\n/* harmony import */ var _ErrorDialog__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ErrorDialog */ \"../../components/ErrorDialog.tsx\");\n/* harmony import */ var _ImageExportDialog__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ImageExportDialog */ \"../../components/ImageExportDialog.tsx\");\n/* harmony import */ var _FixedSideContainer__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./FixedSideContainer */ \"../../components/FixedSideContainer.tsx\");\n/* harmony import */ var _HintViewer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./HintViewer */ \"../../components/HintViewer.tsx\");\n/* harmony import */ var _Island__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Island */ \"../../components/Island.tsx\");\n/* harmony import */ var _LoadingMessage__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./LoadingMessage */ \"../../components/LoadingMessage.tsx\");\n/* harmony import */ var _LockButton__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./LockButton */ \"../../components/LockButton.tsx\");\n/* harmony import */ var _MobileMenu__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./MobileMenu */ \"../../components/MobileMenu.tsx\");\n/* harmony import */ var _PasteChartDialog__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./PasteChartDialog */ \"../../components/PasteChartDialog.tsx\");\n/* harmony import */ var _Section__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./Section */ \"../../components/Section.tsx\");\n/* harmony import */ var _HelpDialog__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./HelpDialog */ \"../../components/HelpDialog.tsx\");\n/* harmony import */ var _Stack__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./Stack */ \"../../components/Stack.tsx\");\n/* harmony import */ var _UserList__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./UserList */ \"../../components/UserList.tsx\");\n/* harmony import */ var _JSONExportDialog__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./JSONExportDialog */ \"../../components/JSONExportDialog.tsx\");\n/* harmony import */ var _PenModeButton__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./PenModeButton */ \"../../components/PenModeButton.tsx\");\n/* harmony import */ var _analytics__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../analytics */ \"../../analytics.ts\");\n/* harmony import */ var _components_App__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../components/App */ \"../../components/App.tsx\");\n/* harmony import */ var _Stats__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./Stats */ \"../../components/Stats.tsx\");\n/* harmony import */ var _actions_actionToggleStats__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../actions/actionToggleStats */ \"../../actions/actionToggleStats.tsx\");\n/* harmony import */ var _footer_Footer__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./footer/Footer */ \"../../components/footer/Footer.tsx\");\n/* harmony import */ var _Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./Sidebar/Sidebar */ \"../../components/Sidebar/Sidebar.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../jotai */ \"../../jotai.ts\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var _main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./main-menu/MainMenu */ \"../../components/main-menu/MainMenu.tsx\");\n/* harmony import */ var _ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./ActiveConfirmDialog */ \"../../components/ActiveConfirmDialog.tsx\");\n/* harmony import */ var _OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./OverwriteConfirm/OverwriteConfirm */ \"../../components/OverwriteConfirm/OverwriteConfirm.tsx\");\n/* harmony import */ var _HandButton__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./HandButton */ \"../../components/HandButton.tsx\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ../appState */ \"../../appState.ts\");\n/* harmony import */ var _context_tunnels__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ../context/tunnels */ \"../../context/tunnels.ts\");\n/* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./icons */ \"../../components/icons.tsx\");\n/* harmony import */ var _context_ui_appState__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../context/ui-appState */ \"../../context/ui-appState.ts\");\n/* harmony import */ var _DefaultSidebar__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./DefaultSidebar */ \"../../components/DefaultSidebar.tsx\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var _LayerUI_scss__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./LayerUI.scss */ \"../../components/LayerUI.scss\");\n/* harmony import */ var _Toolbar_scss__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./Toolbar.scss */ \"../../components/Toolbar.scss\");\nvar __rest = undefined && undefined.__rest || function (s, e) {\n var t = {};\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DefaultMainMenu = ({\n UIOptions\n}) => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"], Object.assign({\n __fallback: true\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.LoadScene, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.SaveToActiveFile, {}), UIOptions.canvasActions.export && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.Export, {}), UIOptions.canvasActions.saveAsImage && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.SaveAsImage, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.Help, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.ClearCanvas, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].Separator, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].Group, Object.assign({\n title: \"Excalidraw links\"\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.Socials, {})\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].Separator, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.ToggleTheme, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.ChangeCanvasBackground, {})]\n }));\n};\n\nconst DefaultOverwriteConfirmDialog = () => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__.OverwriteConfirmDialog, Object.assign({\n __fallback: true\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__.OverwriteConfirmDialog.Actions.SaveToDisk, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__.OverwriteConfirmDialog.Actions.ExportToImage, {})]\n }));\n};\n\nconst LayerUI = ({\n actionManager,\n appState,\n files,\n setAppState,\n elements,\n canvas,\n interactiveCanvas,\n onLockToggle,\n onHandToolToggle,\n onPenModeToggle,\n showExitZenModeBtn,\n renderTopRightUI,\n renderCustomStats,\n UIOptions,\n onImageAction,\n onExportImage,\n renderWelcomeScreen,\n children,\n app\n}) => {\n const device = (0,_components_App__WEBPACK_IMPORTED_MODULE_25__.useDevice)();\n const tunnels = (0,_context_tunnels__WEBPACK_IMPORTED_MODULE_36__.useInitializeTunnels)();\n const [eyeDropperState, setEyeDropperState] = (0,jotai__WEBPACK_IMPORTED_MODULE_43__.useAtom)(_EyeDropper__WEBPACK_IMPORTED_MODULE_40__.activeEyeDropperAtom, _jotai__WEBPACK_IMPORTED_MODULE_30__.jotaiScope);\n\n const renderJSONExportDialog = () => {\n if (!UIOptions.canvasActions.export) {\n return null;\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_JSONExportDialog__WEBPACK_IMPORTED_MODULE_22__.JSONExportDialog, {\n elements: elements,\n appState: appState,\n files: files,\n actionManager: actionManager,\n exportOpts: UIOptions.canvasActions.export,\n canvas: canvas,\n setAppState: setAppState\n });\n };\n\n const renderImageExportDialog = () => {\n if (!UIOptions.canvasActions.saveAsImage) {\n return null;\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ImageExportDialog__WEBPACK_IMPORTED_MODULE_10__.ImageExportDialog, {\n elements: elements,\n appState: appState,\n files: files,\n actionManager: actionManager,\n onExportImage: onExportImage,\n onCloseRequest: () => setAppState({\n openDialog: null\n })\n });\n };\n\n const renderCanvasActions = () => (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n style: {\n position: \"relative\"\n }\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.MainMenuTunnel.Out, {}), renderWelcomeScreen && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.WelcomeScreenMenuHintTunnel.Out, {})]\n }));\n\n const renderSelectedShapeActions = () => (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Section__WEBPACK_IMPORTED_MODULE_18__.Section, Object.assign({\n heading: \"selectedShapeActions\",\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"selected-shape-actions zen-mode-transition\", {\n \"transition-left\": appState.zenModeEnabled\n })\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Island__WEBPACK_IMPORTED_MODULE_13__.Island, Object.assign({\n className: _constants__WEBPACK_IMPORTED_MODULE_3__.CLASSES.SHAPE_ACTIONS_MENU,\n padding: 2,\n style: {\n // we want to make sure this doesn't overflow so subtracting the\n // approximate height of hamburgerMenu + footer\n maxHeight: `${appState.height - 166}px`\n }\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Actions__WEBPACK_IMPORTED_MODULE_8__.SelectedShapeActions, {\n appState: appState,\n elements: elements,\n renderAction: actionManager.renderAction\n })\n }))\n }));\n\n const renderFixedSideContainer = () => {\n var _a;\n\n const shouldRenderSelectedShapeActions = (0,_element__WEBPACK_IMPORTED_MODULE_4__.showSelectedShapeActions)(appState, elements);\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_FixedSideContainer__WEBPACK_IMPORTED_MODULE_11__.FixedSideContainer, Object.assign({\n side: \"top\"\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: \"App-menu App-menu_top\"\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Col, Object.assign({\n gap: 6,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"App-menu_top__left\")\n }, {\n children: [renderCanvasActions(), shouldRenderSelectedShapeActions && renderSelectedShapeActions()]\n })), !appState.viewModeEnabled && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Section__WEBPACK_IMPORTED_MODULE_18__.Section, Object.assign({\n heading: \"shapes\",\n className: \"shapes-section\"\n }, {\n children: heading => (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n style: {\n position: \"relative\"\n }\n }, {\n children: [renderWelcomeScreen && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.WelcomeScreenToolbarHintTunnel.Out, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Col, Object.assign({\n gap: 4,\n align: \"start\"\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Row, Object.assign({\n gap: 1,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"App-toolbar-container\", {\n \"zen-mode\": appState.zenModeEnabled\n })\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_Island__WEBPACK_IMPORTED_MODULE_13__.Island, Object.assign({\n padding: 1,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"App-toolbar\", {\n \"zen-mode\": appState.zenModeEnabled\n })\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_HintViewer__WEBPACK_IMPORTED_MODULE_12__.HintViewer, {\n appState: appState,\n isMobile: device.isMobile,\n device: device,\n app: app\n }), heading, (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Row, Object.assign({\n gap: 1\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_PenModeButton__WEBPACK_IMPORTED_MODULE_23__.PenModeButton, {\n zenModeEnabled: appState.zenModeEnabled,\n checked: appState.penMode,\n onChange: onPenModeToggle,\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.penMode\"),\n penDetected: appState.penDetected\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LockButton__WEBPACK_IMPORTED_MODULE_15__.LockButton, {\n checked: appState.activeTool.locked,\n onChange: onLockToggle,\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.lock\")\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"App-toolbar__divider\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_HandButton__WEBPACK_IMPORTED_MODULE_34__.HandButton, {\n checked: (0,_appState__WEBPACK_IMPORTED_MODULE_35__.isHandToolActive)(appState),\n onChange: () => onHandToolToggle(),\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.hand\"),\n isMobile: true\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Actions__WEBPACK_IMPORTED_MODULE_8__.ShapesSwitcher, {\n appState: appState,\n interactiveCanvas: interactiveCanvas,\n activeTool: appState.activeTool,\n setAppState: setAppState,\n onImageAction: ({\n pointerType\n }) => {\n onImageAction({\n insertOnCanvasDirectly: pointerType !== \"mouse\"\n });\n }\n })]\n }))]\n }))\n }))\n }))]\n }))\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"layer-ui__wrapper__top-right zen-mode-transition\", {\n \"transition-right\": appState.zenModeEnabled\n })\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_UserList__WEBPACK_IMPORTED_MODULE_21__.UserList, {\n collaborators: appState.collaborators\n }), renderTopRightUI === null || renderTopRightUI === void 0 ? void 0 : renderTopRightUI(device.isMobile, appState), !appState.viewModeEnabled && ( // hide button when sidebar docked\n !isSidebarDocked || ((_a = appState.openSidebar) === null || _a === void 0 ? void 0 : _a.name) !== _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.name) && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.DefaultSidebarTriggerTunnel.Out, {})]\n }))]\n }))\n }));\n };\n\n const renderSidebars = () => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_DefaultSidebar__WEBPACK_IMPORTED_MODULE_39__.DefaultSidebar, {\n __fallback: true,\n onDock: docked => {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_24__.trackEvent)(\"sidebar\", `toggleDock (${docked ? \"dock\" : \"undock\"})`, `(${device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n });\n };\n\n const isSidebarDocked = (0,jotai__WEBPACK_IMPORTED_MODULE_43__.useAtomValue)(_Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_29__.isSidebarDockedAtom, _jotai__WEBPACK_IMPORTED_MODULE_30__.jotaiScope);\n\n const layerUIJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: [children, (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DefaultMainMenu, {\n UIOptions: UIOptions\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_DefaultSidebar__WEBPACK_IMPORTED_MODULE_39__.DefaultSidebar.Trigger, Object.assign({\n __fallback: true,\n icon: _icons__WEBPACK_IMPORTED_MODULE_37__.LibraryIcon,\n title: (0,_utils__WEBPACK_IMPORTED_MODULE_7__.capitalizeString)((0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.library\")),\n onToggle: open => {\n if (open) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_24__.trackEvent)(\"sidebar\", `${_constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.name} (open)`, `button (${device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n },\n tab: _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.defaultTab\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.library\")\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DefaultOverwriteConfirmDialog, {}), appState.isLoading && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LoadingMessage__WEBPACK_IMPORTED_MODULE_14__.LoadingMessage, {\n delay: 250\n }), appState.errorMessage && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ErrorDialog__WEBPACK_IMPORTED_MODULE_9__.ErrorDialog, Object.assign({\n onClose: () => setAppState({\n errorMessage: null\n })\n }, {\n children: appState.errorMessage\n })), eyeDropperState && !device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_EyeDropper__WEBPACK_IMPORTED_MODULE_40__.EyeDropper, {\n swapPreviewOnAlt: eyeDropperState.swapPreviewOnAlt,\n previewType: eyeDropperState.previewType,\n onCancel: () => {\n setEyeDropperState(null);\n },\n onSelect: (color, event) => {\n var _a;\n\n setEyeDropperState(state => {\n return (state === null || state === void 0 ? void 0 : state.keepOpenOnAlt) && event.altKey ? state : null;\n });\n (_a = eyeDropperState === null || eyeDropperState === void 0 ? void 0 : eyeDropperState.onSelect) === null || _a === void 0 ? void 0 : _a.call(eyeDropperState, color, event);\n }\n }), appState.openDialog === \"help\" && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_HelpDialog__WEBPACK_IMPORTED_MODULE_19__.HelpDialog, {\n onClose: () => {\n setAppState({\n openDialog: null\n });\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_32__.ActiveConfirmDialog, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.OverwriteConfirmDialogTunnel.Out, {}), renderImageExportDialog(), renderJSONExportDialog(), appState.pasteDialog.shown && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_PasteChartDialog__WEBPACK_IMPORTED_MODULE_17__.PasteChartDialog, {\n setAppState: setAppState,\n appState: appState,\n onClose: () => setAppState({\n pasteDialog: {\n shown: false,\n data: null\n }\n })\n }), device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MobileMenu__WEBPACK_IMPORTED_MODULE_16__.MobileMenu, {\n app: app,\n appState: appState,\n elements: elements,\n actionManager: actionManager,\n renderJSONExportDialog: renderJSONExportDialog,\n renderImageExportDialog: renderImageExportDialog,\n setAppState: setAppState,\n onLockToggle: onLockToggle,\n onHandToolToggle: onHandToolToggle,\n onPenModeToggle: onPenModeToggle,\n interactiveCanvas: interactiveCanvas,\n onImageAction: onImageAction,\n renderTopRightUI: renderTopRightUI,\n renderCustomStats: renderCustomStats,\n renderSidebars: renderSidebars,\n device: device,\n renderWelcomeScreen: renderWelcomeScreen\n }), !device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: \"layer-ui__wrapper\",\n style: appState.openSidebar && isSidebarDocked && device.canDeviceFitSidebar ? {\n width: `calc(100% - ${_constants__WEBPACK_IMPORTED_MODULE_3__.LIBRARY_SIDEBAR_WIDTH}px)`\n } : {}\n }, {\n children: [renderWelcomeScreen && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.WelcomeScreenCenterTunnel.Out, {}), renderFixedSideContainer(), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_footer_Footer__WEBPACK_IMPORTED_MODULE_28__[\"default\"], {\n appState: appState,\n actionManager: actionManager,\n showExitZenModeBtn: showExitZenModeBtn,\n renderWelcomeScreen: renderWelcomeScreen\n }), appState.showStats && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Stats__WEBPACK_IMPORTED_MODULE_26__.Stats, {\n appState: appState,\n setAppState: setAppState,\n elements: elements,\n onClose: () => {\n actionManager.executeAction(_actions_actionToggleStats__WEBPACK_IMPORTED_MODULE_27__.actionToggleStats);\n },\n renderCustomStats: renderCustomStats\n }), appState.scrolledOutside && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"button\", Object.assign({\n className: \"scroll-back-to-content\",\n onClick: () => {\n setAppState(appState => Object.assign({}, (0,_scene__WEBPACK_IMPORTED_MODULE_6__.calculateScrollCenter)(elements, appState)));\n }\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"buttons.scrollBackToContent\")\n }))]\n })), renderSidebars()]\n })]\n });\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_context_ui_appState__WEBPACK_IMPORTED_MODULE_38__.UIAppStateContext.Provider, Object.assign({\n value: appState\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(jotai__WEBPACK_IMPORTED_MODULE_43__.Provider, Object.assign({\n scope: tunnels.jotaiScope\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_context_tunnels__WEBPACK_IMPORTED_MODULE_36__.TunnelsContext.Provider, Object.assign({\n value: tunnels\n }, {\n children: layerUIJSX\n }))\n }))\n }));\n};\n\nconst stripIrrelevantAppStateProps = appState => {\n const {\n suggestedBindings,\n startBoundElement,\n cursorButton,\n scrollX,\n scrollY\n } = appState,\n ret = __rest(appState, [\"suggestedBindings\", \"startBoundElement\", \"cursorButton\", \"scrollX\", \"scrollY\"]);\n\n return ret;\n};\n\nconst areEqual = (prevProps, nextProps) => {\n // short-circuit early\n if (prevProps.children !== nextProps.children) {\n return false;\n }\n\n const {\n canvas: _pC,\n interactiveCanvas: _pIC,\n appState: prevAppState\n } = prevProps,\n prev = __rest(prevProps, [\"canvas\", \"interactiveCanvas\", \"appState\"]);\n\n const {\n canvas: _nC,\n interactiveCanvas: _nIC,\n appState: nextAppState\n } = nextProps,\n next = __rest(nextProps, [\"canvas\", \"interactiveCanvas\", \"appState\"]);\n\n return (0,_utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual)( // asserting AppState because we're being passed the whole AppState\n // but resolve to only the UI-relevant props\n stripIrrelevantAppStateProps(prevAppState), stripIrrelevantAppStateProps(nextAppState), {\n selectedElementIds: _utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual,\n selectedGroupIds: _utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual\n }) && (0,_utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual)(prev, next);\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (react__WEBPACK_IMPORTED_MODULE_2___default().memo(LayerUI, areEqual));//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUFPO0FBQ1AsS0FBSztBQUNMLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUEsU0FBUyxzREFBYztBQUN2QjtBQUNBO0FBQ0Esd0JBQXdCLGtEQUFjO0FBQ3RDLHNCQUFzQixrREFBYztBQUNwQyxHQUFHLEtBQUssc0RBQWM7QUFDdEI7O0FBRUEsaUVBQWUsaURBQVUsbUJBQW1CIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2NvbXBvbmVudHMvTGF5ZXJVSS50c3g/Y2M0MSJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgX19yZXN0ID0gdGhpcyAmJiB0aGlzLl9fcmVzdCB8fCBmdW5jdGlvbiAocywgZSkge1xuICB2YXIgdCA9IHt9O1xuXG4gIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKSB0W3BdID0gc1twXTtcblxuICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpIHRbcFtpXV0gPSBzW3BbaV1dO1xuICB9XG4gIHJldHVybiB0O1xufTtcblxuaW1wb3J0IHsganN4IGFzIF9qc3gsIGpzeHMgYXMgX2pzeHMsIEZyYWdtZW50IGFzIF9GcmFnbWVudCB9IGZyb20gXCJyZWFjdC9qc3gtcnVudGltZVwiO1xuaW1wb3J0IGNsc3ggZnJvbSBcImNsc3hcIjtcbmltcG9ydCBSZWFjdCBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IENMQVNTRVMsIERFRkFVTFRfU0lERUJBUiwgTElCUkFSWV9TSURFQkFSX1dJRFRIIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgc2hvd1NlbGVjdGVkU2hhcGVBY3Rpb25zIH0gZnJvbSBcIi4uL2VsZW1lbnRcIjtcbmltcG9ydCB7IHQgfSBmcm9tIFwiLi4vaTE4blwiO1xuaW1wb3J0IHsgY2FsY3VsYXRlU2Nyb2xsQ2VudGVyIH0gZnJvbSBcIi4uL3NjZW5lXCI7XG5pbXBvcnQgeyBjYXBpdGFsaXplU3RyaW5nLCBpc1NoYWxsb3dFcXVhbCB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgU2VsZWN0ZWRTaGFwZUFjdGlvbnMsIFNoYXBlc1N3aXRjaGVyIH0gZnJvbSBcIi4vQWN0aW9uc1wiO1xuaW1wb3J0IHsgRXJyb3JEaWFsb2cgfSBmcm9tIFwiLi9FcnJvckRpYWxvZ1wiO1xuaW1wb3J0IHsgSW1hZ2VFeHBvcnREaWFsb2cgfSBmcm9tIFwiLi9JbWFnZUV4cG9ydERpYWxvZ1wiO1xuaW1wb3J0IHsgRml4ZWRTaWRlQ29udGFpbmVyIH0gZnJvbSBcIi4vRml4ZWRTaWRlQ29udGFpbmVyXCI7XG5pbXBvcnQgeyBIaW50Vmlld2VyIH0gZnJvbSBcIi4vSGludFZpZXdlclwiO1xuaW1wb3J0IHsgSXNsYW5kIH0gZnJvbSBcIi4vSXNsYW5kXCI7XG5pbXBvcnQgeyBMb2FkaW5nTWVzc2FnZSB9IGZyb20gXCIuL0xvYWRpbmdNZXNzYWdlXCI7XG5pbXBvcnQgeyBMb2NrQnV0dG9uIH0gZnJvbSBcIi4vTG9ja0J1dHRvblwiO1xuaW1wb3J0IHsgTW9iaWxlTWVudSB9IGZyb20gXCIuL01vYmlsZU1lbnVcIjtcbmltcG9ydCB7IFBhc3RlQ2hhcnREaWFsb2cgfSBmcm9tIFwiLi9QYXN0ZUNoYXJ0RGlhbG9nXCI7XG5pbXBvcnQgeyBTZWN0aW9uIH0gZnJvbSBcIi4vU2VjdGlvblwiO1xuaW1wb3J0IHsgSGVscERpYWxvZyB9IGZyb20gXCIuL0hlbHBEaWFsb2dcIjtcbmltcG9ydCBTdGFjayBmcm9tIFwiLi9TdGFja1wiO1xuaW1wb3J0IHsgVXNlckxpc3QgfSBmcm9tIFwiLi9Vc2VyTGlzdFwiO1xuaW1wb3J0IHsgSlNPTkV4cG9ydERpYWxvZyB9IGZyb20gXCIuL0pTT05FeHBvcnREaWFsb2dcIjtcbmltcG9ydCB7IFBlbk1vZGVCdXR0b24gfSBmcm9tIFwiLi9QZW5Nb2RlQnV0dG9uXCI7XG5pbXBvcnQgeyB0cmFja0V2ZW50IH0gZnJvbSBcIi4uL2FuYWx5dGljc1wiO1xuaW1wb3J0IHsgdXNlRGV2aWNlIH0gZnJvbSBcIi4uL2NvbXBvbmVudHMvQXBwXCI7XG5pbXBvcnQgeyBTdGF0cyB9IGZyb20gXCIuL1N0YXRzXCI7XG5pbXBvcnQgeyBhY3Rpb25Ub2dnbGVTdGF0cyB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvblRvZ2dsZVN0YXRzXCI7XG5pbXBvcnQgRm9vdGVyIGZyb20gXCIuL2Zvb3Rlci9Gb290ZXJcIjtcbmltcG9ydCB7IGlzU2lkZWJhckRvY2tlZEF0b20gfSBmcm9tIFwiLi9TaWRlYmFyL1NpZGViYXJcIjtcbmltcG9ydCB7IGpvdGFpU2NvcGUgfSBmcm9tIFwiLi4vam90YWlcIjtcbmltcG9ydCB7IFByb3ZpZGVyLCB1c2VBdG9tLCB1c2VBdG9tVmFsdWUgfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCBNYWluTWVudSBmcm9tIFwiLi9tYWluLW1lbnUvTWFpbk1lbnVcIjtcbmltcG9ydCB7IEFjdGl2ZUNvbmZpcm1EaWFsb2cgfSBmcm9tIFwiLi9BY3RpdmVDb25maXJtRGlhbG9nXCI7XG5pbXBvcnQgeyBPdmVyd3JpdGVDb25maXJtRGlhbG9nIH0gZnJvbSBcIi4vT3ZlcndyaXRlQ29uZmlybS9PdmVyd3JpdGVDb25maXJtXCI7XG5pbXBvcnQgeyBIYW5kQnV0dG9uIH0gZnJvbSBcIi4vSGFuZEJ1dHRvblwiO1xuaW1wb3J0IHsgaXNIYW5kVG9vbEFjdGl2ZSB9IGZyb20gXCIuLi9hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgVHVubmVsc0NvbnRleHQsIHVzZUluaXRpYWxpemVUdW5uZWxzIH0gZnJvbSBcIi4uL2NvbnRleHQvdHVubmVsc1wiO1xuaW1wb3J0IHsgTGlicmFyeUljb24gfSBmcm9tIFwiLi9pY29uc1wiO1xuaW1wb3J0IHsgVUlBcHBTdGF0ZUNvbnRleHQgfSBmcm9tIFwiLi4vY29udGV4dC91aS1hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgRGVmYXVsdFNpZGViYXIgfSBmcm9tIFwiLi9EZWZhdWx0U2lkZWJhclwiO1xuaW1wb3J0IHsgRXllRHJvcHBlciwgYWN0aXZlRXllRHJvcHBlckF0b20gfSBmcm9tIFwiLi9FeWVEcm9wcGVyXCI7XG5pbXBvcnQgXCIuL0xheWVyVUkuc2Nzc1wiO1xuaW1wb3J0IFwiLi9Ub29sYmFyLnNjc3NcIjtcblxuY29uc3QgRGVmYXVsdE1haW5NZW51ID0gKHtcbiAgVUlPcHRpb25zXG59KSA9PiB7XG4gIHJldHVybiBfanN4cyhNYWluTWVudSwgT2JqZWN0LmFzc2lnbih7XG4gICAgX19mYWxsYmFjazogdHJ1ZVxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KE1haW5NZW51LkRlZmF1bHRJdGVtcy5Mb2FkU2NlbmUsIHt9KSwgX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuU2F2ZVRvQWN0aXZlRmlsZSwge30pLCBVSU9wdGlvbnMuY2FudmFzQWN0aW9ucy5leHBvcnQgJiYgX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuRXhwb3J0LCB7fSksIFVJT3B0aW9ucy5jYW52YXNBY3Rpb25zLnNhdmVBc0ltYWdlICYmIF9qc3goTWFpbk1lbnUuRGVmYXVsdEl0ZW1zLlNhdmVBc0ltYWdlLCB7fSksIF9qc3goTWFpbk1lbnUuRGVmYXVsdEl0ZW1zLkhlbHAsIHt9KSwgX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuQ2xlYXJDYW52YXMsIHt9KSwgX2pzeChNYWluTWVudS5TZXBhcmF0b3IsIHt9KSwgX2pzeChNYWluTWVudS5Hcm91cCwgT2JqZWN0LmFzc2lnbih7XG4gICAgICB0aXRsZTogXCJFeGNhbGlkcmF3IGxpbmtzXCJcbiAgICB9LCB7XG4gICAgICBjaGlsZHJlbjogX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuU29jaWFscywge30pXG4gICAgfSkpLCBfanN4KE1haW5NZW51LlNlcGFyYXRvciwge30pLCBfanN4KE1haW5NZW51LkRlZmF1bHRJdGVtcy5Ub2dnbGVUaGVtZSwge30pLCBfanN4KE1haW5NZW51LkRlZmF1bHRJdGVtcy5DaGFuZ2VDYW52YXNCYWNrZ3JvdW5kLCB7fSldXG4gIH0pKTtcbn07XG5cbmNvbnN0IERlZmF1bHRPdmVyd3JpdGVDb25maXJtRGlhbG9nID0gKCkgPT4ge1xuICByZXR1cm4gX2pzeHMoT3ZlcndyaXRlQ29uZmlybURpYWxvZywgT2JqZWN0LmFzc2lnbih7XG4gICAgX19mYWxsYmFjazogdHJ1ZVxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KE92ZXJ3cml0ZUNvbmZpcm1EaWFsb2cuQWN0aW9ucy5TYXZlVG9EaXNrLCB7fSksIF9qc3goT3ZlcndyaXRlQ29uZmlybURpYWxvZy5BY3Rpb25zLkV4cG9ydFRvSW1hZ2UsIHt9KV1cbiAgfSkpO1xufTtcblxuY29uc3QgTGF5ZXJVSSA9ICh7XG4gIGFjdGlvbk1hbmFnZXIsXG4gIGFwcFN0YXRlLFxuICBmaWxlcyxcbiAgc2V0QXBwU3RhdGUsXG4gIGVsZW1lbnRzLFxuICBjYW52YXMsXG4gIGludGVyYWN0aXZlQ2FudmFzLFxuICBvbkxvY2tUb2dnbGUsXG4gIG9uSGFuZFRvb2xUb2dnbGUsXG4gIG9uUGVuTW9kZVRvZ2dsZSxcbiAgc2hvd0V4aXRaZW5Nb2RlQnRuLFxuICByZW5kZXJUb3BSaWdodFVJLFxuICByZW5kZXJDdXN0b21TdGF0cyxcbiAgVUlPcHRpb25zLFxuICBvbkltYWdlQWN0aW9uLFxuICBvbkV4cG9ydEltYWdlLFxuICByZW5kZXJXZWxjb21lU2NyZWVuLFxuICBjaGlsZHJlbixcbiAgYXBwXG59KSA9PiB7XG4gIGNvbnN0IGRldmljZSA9IHVzZURldmljZSgpO1xuICBjb25zdCB0dW5uZWxzID0gdXNlSW5pdGlhbGl6ZVR1bm5lbHMoKTtcbiAgY29uc3QgW2V5ZURyb3BwZXJTdGF0ZSwgc2V0RXllRHJvcHBlclN0YXRlXSA9IHVzZUF0b20oYWN0aXZlRXllRHJvcHBlckF0b20sIGpvdGFpU2NvcGUpO1xuXG4gIGNvbnN0IHJlbmRlckpTT05FeHBvcnREaWFsb2cgPSAoKSA9PiB7XG4gICAgaWYgKCFVSU9wdGlvbnMuY2FudmFzQWN0aW9ucy5leHBvcnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBfanN4KEpTT05FeHBvcnREaWFsb2csIHtcbiAgICAgIGVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgIGZpbGVzOiBmaWxlcyxcbiAgICAgIGFjdGlvbk1hbmFnZXI6IGFjdGlvbk1hbmFnZXIsXG4gICAgICBleHBvcnRPcHRzOiBVSU9wdGlvbnMuY2FudmFzQWN0aW9ucy5leHBvcnQsXG4gICAgICBjYW52YXM6IGNhbnZhcyxcbiAgICAgIHNldEFwcFN0YXRlOiBzZXRBcHBTdGF0ZVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IHJlbmRlckltYWdlRXhwb3J0RGlhbG9nID0gKCkgPT4ge1xuICAgIGlmICghVUlPcHRpb25zLmNhbnZhc0FjdGlvbnMuc2F2ZUFzSW1hZ2UpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBfanN4KEltYWdlRXhwb3J0RGlhbG9nLCB7XG4gICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICBmaWxlczogZmlsZXMsXG4gICAgICBhY3Rpb25NYW5hZ2VyOiBhY3Rpb25NYW5hZ2VyLFxuICAgICAgb25FeHBvcnRJbWFnZTogb25FeHBvcnRJbWFnZSxcbiAgICAgIG9uQ2xvc2VSZXF1ZXN0OiAoKSA9PiBzZXRBcHBTdGF0ZSh7XG4gICAgICAgIG9wZW5EaWFsb2c6IG51bGxcbiAgICAgIH0pXG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgcmVuZGVyQ2FudmFzQWN0aW9ucyA9ICgpID0+IF9qc3hzKFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgIHN0eWxlOiB7XG4gICAgICBwb3NpdGlvbjogXCJyZWxhdGl2ZVwiXG4gICAgfVxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KHR1bm5lbHMuTWFpbk1lbnVUdW5uZWwuT3V0LCB7fSksIHJlbmRlcldlbGNvbWVTY3JlZW4gJiYgX2pzeCh0dW5uZWxzLldlbGNvbWVTY3JlZW5NZW51SGludFR1bm5lbC5PdXQsIHt9KV1cbiAgfSkpO1xuXG4gIGNvbnN0IHJlbmRlclNlbGVjdGVkU2hhcGVBY3Rpb25zID0gKCkgPT4gX2pzeChTZWN0aW9uLCBPYmplY3QuYXNzaWduKHtcbiAgICBoZWFkaW5nOiBcInNlbGVjdGVkU2hhcGVBY3Rpb25zXCIsXG4gICAgY2xhc3NOYW1lOiBjbHN4KFwic2VsZWN0ZWQtc2hhcGUtYWN0aW9ucyB6ZW4tbW9kZS10cmFuc2l0aW9uXCIsIHtcbiAgICAgIFwidHJhbnNpdGlvbi1sZWZ0XCI6IGFwcFN0YXRlLnplbk1vZGVFbmFibGVkXG4gICAgfSlcbiAgfSwge1xuICAgIGNoaWxkcmVuOiBfanN4KElzbGFuZCwgT2JqZWN0LmFzc2lnbih7XG4gICAgICBjbGFzc05hbWU6IENMQVNTRVMuU0hBUEVfQUNUSU9OU19NRU5VLFxuICAgICAgcGFkZGluZzogMixcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoaXMgZG9lc24ndCBvdmVyZmxvdyBzbyBzdWJ0cmFjdGluZyB0aGVcbiAgICAgICAgLy8gYXBwcm94aW1hdGUgaGVpZ2h0IG9mIGhhbWJ1cmdlck1lbnUgKyBmb290ZXJcbiAgICAgICAgbWF4SGVpZ2h0OiBgJHthcHBTdGF0ZS5oZWlnaHQgLSAxNjZ9cHhgXG4gICAgICB9XG4gICAgfSwge1xuICAgICAgY2hpbGRyZW46IF9qc3goU2VsZWN0ZWRTaGFwZUFjdGlvbnMsIHtcbiAgICAgICAgYXBwU3RhdGU6IGFwcFN0YXRlLFxuICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgIHJlbmRlckFjdGlvbjogYWN0aW9uTWFuYWdlci5yZW5kZXJBY3Rpb25cbiAgICAgIH0pXG4gICAgfSkpXG4gIH0pKTtcblxuICBjb25zdCByZW5kZXJGaXhlZFNpZGVDb250YWluZXIgPSAoKSA9PiB7XG4gICAgdmFyIF9hO1xuXG4gICAgY29uc3Qgc2hvdWxkUmVuZGVyU2VsZWN0ZWRTaGFwZUFjdGlvbnMgPSBzaG93U2VsZWN0ZWRTaGFwZUFjdGlvbnMoYXBwU3RhdGUsIGVsZW1lbnRzKTtcbiAgICByZXR1cm4gX2pzeChGaXhlZFNpZGVDb250YWluZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgc2lkZTogXCJ0b3BcIlxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBfanN4cyhcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgY2xhc3NOYW1lOiBcIkFwcC1tZW51IEFwcC1tZW51X3RvcFwiXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBbX2pzeHMoU3RhY2suQ29sLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICBnYXA6IDYsXG4gICAgICAgICAgY2xhc3NOYW1lOiBjbHN4KFwiQXBwLW1lbnVfdG9wX19sZWZ0XCIpXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBjaGlsZHJlbjogW3JlbmRlckNhbnZhc0FjdGlvbnMoKSwgc2hvdWxkUmVuZGVyU2VsZWN0ZWRTaGFwZUFjdGlvbnMgJiYgcmVuZGVyU2VsZWN0ZWRTaGFwZUFjdGlvbnMoKV1cbiAgICAgICAgfSkpLCAhYXBwU3RhdGUudmlld01vZGVFbmFibGVkICYmIF9qc3goU2VjdGlvbiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgaGVhZGluZzogXCJzaGFwZXNcIixcbiAgICAgICAgICBjbGFzc05hbWU6IFwic2hhcGVzLXNlY3Rpb25cIlxuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IGhlYWRpbmcgPT4gX2pzeHMoXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICBwb3NpdGlvbjogXCJyZWxhdGl2ZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtyZW5kZXJXZWxjb21lU2NyZWVuICYmIF9qc3godHVubmVscy5XZWxjb21lU2NyZWVuVG9vbGJhckhpbnRUdW5uZWwuT3V0LCB7fSksIF9qc3goU3RhY2suQ29sLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgZ2FwOiA0LFxuICAgICAgICAgICAgICBhbGlnbjogXCJzdGFydFwiXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4KFN0YWNrLlJvdywgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgZ2FwOiAxLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcIkFwcC10b29sYmFyLWNvbnRhaW5lclwiLCB7XG4gICAgICAgICAgICAgICAgICBcInplbi1tb2RlXCI6IGFwcFN0YXRlLnplbk1vZGVFbmFibGVkXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4cyhJc2xhbmQsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICAgICAgcGFkZGluZzogMSxcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcIkFwcC10b29sYmFyXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgXCJ6ZW4tbW9kZVwiOiBhcHBTdGF0ZS56ZW5Nb2RlRW5hYmxlZFxuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW19qc3goSGludFZpZXdlciwge1xuICAgICAgICAgICAgICAgICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgIGlzTW9iaWxlOiBkZXZpY2UuaXNNb2JpbGUsXG4gICAgICAgICAgICAgICAgICAgIGRldmljZTogZGV2aWNlLFxuICAgICAgICAgICAgICAgICAgICBhcHA6IGFwcFxuICAgICAgICAgICAgICAgICAgfSksIGhlYWRpbmcsIF9qc3hzKFN0YWNrLlJvdywgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgICAgIGdhcDogMVxuICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW19qc3goUGVuTW9kZUJ1dHRvbiwge1xuICAgICAgICAgICAgICAgICAgICAgIHplbk1vZGVFbmFibGVkOiBhcHBTdGF0ZS56ZW5Nb2RlRW5hYmxlZCxcbiAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkOiBhcHBTdGF0ZS5wZW5Nb2RlLFxuICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlOiBvblBlbk1vZGVUb2dnbGUsXG4gICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHQoXCJ0b29sQmFyLnBlbk1vZGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgcGVuRGV0ZWN0ZWQ6IGFwcFN0YXRlLnBlbkRldGVjdGVkXG4gICAgICAgICAgICAgICAgICAgIH0pLCBfanN4KExvY2tCdXR0b24sIHtcbiAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkOiBhcHBTdGF0ZS5hY3RpdmVUb29sLmxvY2tlZCxcbiAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogb25Mb2NrVG9nZ2xlLFxuICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiB0KFwidG9vbEJhci5sb2NrXCIpXG4gICAgICAgICAgICAgICAgICAgIH0pLCBfanN4KFwiZGl2XCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiQXBwLXRvb2xiYXJfX2RpdmlkZXJcIlxuICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChIYW5kQnV0dG9uLCB7XG4gICAgICAgICAgICAgICAgICAgICAgY2hlY2tlZDogaXNIYW5kVG9vbEFjdGl2ZShhcHBTdGF0ZSksXG4gICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U6ICgpID0+IG9uSGFuZFRvb2xUb2dnbGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogdChcInRvb2xCYXIuaGFuZFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICBpc01vYmlsZTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChTaGFwZXNTd2l0Y2hlciwge1xuICAgICAgICAgICAgICAgICAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGl2ZUNhbnZhczogaW50ZXJhY3RpdmVDYW52YXMsXG4gICAgICAgICAgICAgICAgICAgICAgYWN0aXZlVG9vbDogYXBwU3RhdGUuYWN0aXZlVG9vbCxcbiAgICAgICAgICAgICAgICAgICAgICBzZXRBcHBTdGF0ZTogc2V0QXBwU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgb25JbWFnZUFjdGlvbjogKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXJUeXBlXG4gICAgICAgICAgICAgICAgICAgICAgfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgb25JbWFnZUFjdGlvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydE9uQ2FudmFzRGlyZWN0bHk6IHBvaW50ZXJUeXBlICE9PSBcIm1vdXNlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSldXG4gICAgICAgICAgICAgICAgICB9KSldXG4gICAgICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgfSkpXVxuICAgICAgICAgIH0pKVxuICAgICAgICB9KSksIF9qc3hzKFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcImxheWVyLXVpX193cmFwcGVyX190b3AtcmlnaHQgemVuLW1vZGUtdHJhbnNpdGlvblwiLCB7XG4gICAgICAgICAgICBcInRyYW5zaXRpb24tcmlnaHRcIjogYXBwU3RhdGUuemVuTW9kZUVuYWJsZWRcbiAgICAgICAgICB9KVxuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IFtfanN4KFVzZXJMaXN0LCB7XG4gICAgICAgICAgICBjb2xsYWJvcmF0b3JzOiBhcHBTdGF0ZS5jb2xsYWJvcmF0b3JzXG4gICAgICAgICAgfSksIHJlbmRlclRvcFJpZ2h0VUkgPT09IG51bGwgfHwgcmVuZGVyVG9wUmlnaHRVSSA9PT0gdm9pZCAwID8gdm9pZCAwIDogcmVuZGVyVG9wUmlnaHRVSShkZXZpY2UuaXNNb2JpbGUsIGFwcFN0YXRlKSwgIWFwcFN0YXRlLnZpZXdNb2RlRW5hYmxlZCAmJiAoIC8vIGhpZGUgYnV0dG9uIHdoZW4gc2lkZWJhciBkb2NrZWRcbiAgICAgICAgICAhaXNTaWRlYmFyRG9ja2VkIHx8ICgoX2EgPSBhcHBTdGF0ZS5vcGVuU2lkZWJhcikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLm5hbWUpICE9PSBERUZBVUxUX1NJREVCQVIubmFtZSkgJiYgX2pzeCh0dW5uZWxzLkRlZmF1bHRTaWRlYmFyVHJpZ2dlclR1bm5lbC5PdXQsIHt9KV1cbiAgICAgICAgfSkpXVxuICAgICAgfSkpXG4gICAgfSkpO1xuICB9O1xuXG4gIGNvbnN0IHJlbmRlclNpZGViYXJzID0gKCkgPT4ge1xuICAgIHJldHVybiBfanN4KERlZmF1bHRTaWRlYmFyLCB7XG4gICAgICBfX2ZhbGxiYWNrOiB0cnVlLFxuICAgICAgb25Eb2NrOiBkb2NrZWQgPT4ge1xuICAgICAgICB0cmFja0V2ZW50KFwic2lkZWJhclwiLCBgdG9nZ2xlRG9jayAoJHtkb2NrZWQgPyBcImRvY2tcIiA6IFwidW5kb2NrXCJ9KWAsIGAoJHtkZXZpY2UuaXNNb2JpbGUgPyBcIm1vYmlsZVwiIDogXCJkZXNrdG9wXCJ9KWApO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IGlzU2lkZWJhckRvY2tlZCA9IHVzZUF0b21WYWx1ZShpc1NpZGViYXJEb2NrZWRBdG9tLCBqb3RhaVNjb3BlKTtcblxuICBjb25zdCBsYXllclVJSlNYID0gX2pzeHMoX0ZyYWdtZW50LCB7XG4gICAgY2hpbGRyZW46IFtjaGlsZHJlbiwgX2pzeChEZWZhdWx0TWFpbk1lbnUsIHtcbiAgICAgIFVJT3B0aW9uczogVUlPcHRpb25zXG4gICAgfSksIF9qc3goRGVmYXVsdFNpZGViYXIuVHJpZ2dlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICBfX2ZhbGxiYWNrOiB0cnVlLFxuICAgICAgaWNvbjogTGlicmFyeUljb24sXG4gICAgICB0aXRsZTogY2FwaXRhbGl6ZVN0cmluZyh0KFwidG9vbEJhci5saWJyYXJ5XCIpKSxcbiAgICAgIG9uVG9nZ2xlOiBvcGVuID0+IHtcbiAgICAgICAgaWYgKG9wZW4pIHtcbiAgICAgICAgICB0cmFja0V2ZW50KFwic2lkZWJhclwiLCBgJHtERUZBVUxUX1NJREVCQVIubmFtZX0gKG9wZW4pYCwgYGJ1dHRvbiAoJHtkZXZpY2UuaXNNb2JpbGUgPyBcIm1vYmlsZVwiIDogXCJkZXNrdG9wXCJ9KWApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdGFiOiBERUZBVUxUX1NJREVCQVIuZGVmYXVsdFRhYlxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiB0KFwidG9vbEJhci5saWJyYXJ5XCIpXG4gICAgfSkpLCBfanN4KERlZmF1bHRPdmVyd3JpdGVDb25maXJtRGlhbG9nLCB7fSksIGFwcFN0YXRlLmlzTG9hZGluZyAmJiBfanN4KExvYWRpbmdNZXNzYWdlLCB7XG4gICAgICBkZWxheTogMjUwXG4gICAgfSksIGFwcFN0YXRlLmVycm9yTWVzc2FnZSAmJiBfanN4KEVycm9yRGlhbG9nLCBPYmplY3QuYXNzaWduKHtcbiAgICAgIG9uQ2xvc2U6ICgpID0+IHNldEFwcFN0YXRlKHtcbiAgICAgICAgZXJyb3JNZXNzYWdlOiBudWxsXG4gICAgICB9KVxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBhcHBTdGF0ZS5lcnJvck1lc3NhZ2VcbiAgICB9KSksIGV5ZURyb3BwZXJTdGF0ZSAmJiAhZGV2aWNlLmlzTW9iaWxlICYmIF9qc3goRXllRHJvcHBlciwge1xuICAgICAgc3dhcFByZXZpZXdPbkFsdDogZXllRHJvcHBlclN0YXRlLnN3YXBQcmV2aWV3T25BbHQsXG4gICAgICBwcmV2aWV3VHlwZTogZXllRHJvcHBlclN0YXRlLnByZXZpZXdUeXBlLFxuICAgICAgb25DYW5jZWw6ICgpID0+IHtcbiAgICAgICAgc2V0RXllRHJvcHBlclN0YXRlKG51bGwpO1xuICAgICAgfSxcbiAgICAgIG9uU2VsZWN0OiAoY29sb3IsIGV2ZW50KSA9PiB7XG4gICAgICAgIHZhciBfYTtcblxuICAgICAgICBzZXRFeWVEcm9wcGVyU3RhdGUoc3RhdGUgPT4ge1xuICAgICAgICAgIHJldHVybiAoc3RhdGUgPT09IG51bGwgfHwgc3RhdGUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHN0YXRlLmtlZXBPcGVuT25BbHQpICYmIGV2ZW50LmFsdEtleSA/IHN0YXRlIDogbnVsbDtcbiAgICAgICAgfSk7XG4gICAgICAgIChfYSA9IGV5ZURyb3BwZXJTdGF0ZSA9PT0gbnVsbCB8fCBleWVEcm9wcGVyU3RhdGUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGV5ZURyb3BwZXJTdGF0ZS5vblNlbGVjdCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNhbGwoZXllRHJvcHBlclN0YXRlLCBjb2xvciwgZXZlbnQpO1xuICAgICAgfVxuICAgIH0pLCBhcHBTdGF0ZS5vcGVuRGlhbG9nID09PSBcImhlbHBcIiAmJiBfanN4KEhlbHBEaWFsb2csIHtcbiAgICAgIG9uQ2xvc2U6ICgpID0+IHtcbiAgICAgICAgc2V0QXBwU3RhdGUoe1xuICAgICAgICAgIG9wZW5EaWFsb2c6IG51bGxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSksIF9qc3goQWN0aXZlQ29uZmlybURpYWxvZywge30pLCBfanN4KHR1bm5lbHMuT3ZlcndyaXRlQ29uZmlybURpYWxvZ1R1bm5lbC5PdXQsIHt9KSwgcmVuZGVySW1hZ2VFeHBvcnREaWFsb2coKSwgcmVuZGVySlNPTkV4cG9ydERpYWxvZygpLCBhcHBTdGF0ZS5wYXN0ZURpYWxvZy5zaG93biAmJiBfanN4KFBhc3RlQ2hhcnREaWFsb2csIHtcbiAgICAgIHNldEFwcFN0YXRlOiBzZXRBcHBTdGF0ZSxcbiAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgIG9uQ2xvc2U6ICgpID0+IHNldEFwcFN0YXRlKHtcbiAgICAgICAgcGFzdGVEaWFsb2c6IHtcbiAgICAgICAgICBzaG93bjogZmFsc2UsXG4gICAgICAgICAgZGF0YTogbnVsbFxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0pLCBkZXZpY2UuaXNNb2JpbGUgJiYgX2pzeChNb2JpbGVNZW51LCB7XG4gICAgICBhcHA6IGFwcCxcbiAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgIGVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICAgIGFjdGlvbk1hbmFnZXI6IGFjdGlvbk1hbmFnZXIsXG4gICAgICByZW5kZXJKU09ORXhwb3J0RGlhbG9nOiByZW5kZXJKU09ORXhwb3J0RGlhbG9nLFxuICAgICAgcmVuZGVySW1hZ2VFeHBvcnREaWFsb2c6IHJlbmRlckltYWdlRXhwb3J0RGlhbG9nLFxuICAgICAgc2V0QXBwU3RhdGU6IHNldEFwcFN0YXRlLFxuICAgICAgb25Mb2NrVG9nZ2xlOiBvbkxvY2tUb2dnbGUsXG4gICAgICBvbkhhbmRUb29sVG9nZ2xlOiBvbkhhbmRUb29sVG9nZ2xlLFxuICAgICAgb25QZW5Nb2RlVG9nZ2xlOiBvblBlbk1vZGVUb2dnbGUsXG4gICAgICBpbnRlcmFjdGl2ZUNhbnZhczogaW50ZXJhY3RpdmVDYW52YXMsXG4gICAgICBvbkltYWdlQWN0aW9uOiBvbkltYWdlQWN0aW9uLFxuICAgICAgcmVuZGVyVG9wUmlnaHRVSTogcmVuZGVyVG9wUmlnaHRVSSxcbiAgICAgIHJlbmRlckN1c3RvbVN0YXRzOiByZW5kZXJDdXN0b21TdGF0cyxcbiAgICAgIHJlbmRlclNpZGViYXJzOiByZW5kZXJTaWRlYmFycyxcbiAgICAgIGRldmljZTogZGV2aWNlLFxuICAgICAgcmVuZGVyV2VsY29tZVNjcmVlbjogcmVuZGVyV2VsY29tZVNjcmVlblxuICAgIH0pLCAhZGV2aWNlLmlzTW9iaWxlICYmIF9qc3hzKF9GcmFnbWVudCwge1xuICAgICAgY2hpbGRyZW46IFtfanN4cyhcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgY2xhc3NOYW1lOiBcImxheWVyLXVpX193cmFwcGVyXCIsXG4gICAgICAgIHN0eWxlOiBhcHBTdGF0ZS5vcGVuU2lkZWJhciAmJiBpc1NpZGViYXJEb2NrZWQgJiYgZGV2aWNlLmNhbkRldmljZUZpdFNpZGViYXIgPyB7XG4gICAgICAgICAgd2lkdGg6IGBjYWxjKDEwMCUgLSAke0xJQlJBUllfU0lERUJBUl9XSURUSH1weClgXG4gICAgICAgIH0gOiB7fVxuICAgICAgfSwge1xuICAgICAgICBjaGlsZHJlbjogW3JlbmRlcldlbGNvbWVTY3JlZW4gJiYgX2pzeCh0dW5uZWxzLldlbGNvbWVTY3JlZW5DZW50ZXJUdW5uZWwuT3V0LCB7fSksIHJlbmRlckZpeGVkU2lkZUNvbnRhaW5lcigpLCBfanN4KEZvb3Rlciwge1xuICAgICAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgICAgICBhY3Rpb25NYW5hZ2VyOiBhY3Rpb25NYW5hZ2VyLFxuICAgICAgICAgIHNob3dFeGl0WmVuTW9kZUJ0bjogc2hvd0V4aXRaZW5Nb2RlQnRuLFxuICAgICAgICAgIHJlbmRlcldlbGNvbWVTY3JlZW46IHJlbmRlcldlbGNvbWVTY3JlZW5cbiAgICAgICAgfSksIGFwcFN0YXRlLnNob3dTdGF0cyAmJiBfanN4KFN0YXRzLCB7XG4gICAgICAgICAgYXBwU3RhdGU6IGFwcFN0YXRlLFxuICAgICAgICAgIHNldEFwcFN0YXRlOiBzZXRBcHBTdGF0ZSxcbiAgICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgICAgb25DbG9zZTogKCkgPT4ge1xuICAgICAgICAgICAgYWN0aW9uTWFuYWdlci5leGVjdXRlQWN0aW9uKGFjdGlvblRvZ2dsZVN0YXRzKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlbmRlckN1c3RvbVN0YXRzOiByZW5kZXJDdXN0b21TdGF0c1xuICAgICAgICB9KSwgYXBwU3RhdGUuc2Nyb2xsZWRPdXRzaWRlICYmIF9qc3goXCJidXR0b25cIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgY2xhc3NOYW1lOiBcInNjcm9sbC1iYWNrLXRvLWNvbnRlbnRcIixcbiAgICAgICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgICAgICBzZXRBcHBTdGF0ZShhcHBTdGF0ZSA9PiBPYmplY3QuYXNzaWduKHt9LCBjYWxjdWxhdGVTY3JvbGxDZW50ZXIoZWxlbWVudHMsIGFwcFN0YXRlKSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgIGNoaWxkcmVuOiB0KFwiYnV0dG9ucy5zY3JvbGxCYWNrVG9Db250ZW50XCIpXG4gICAgICAgIH0pKV1cbiAgICAgIH0pKSwgcmVuZGVyU2lkZWJhcnMoKV1cbiAgICB9KV1cbiAgfSk7XG5cbiAgcmV0dXJuIF9qc3goVUlBcHBTdGF0ZUNvbnRleHQuUHJvdmlkZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgIHZhbHVlOiBhcHBTdGF0ZVxuICB9LCB7XG4gICAgY2hpbGRyZW46IF9qc3goUHJvdmlkZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgc2NvcGU6IHR1bm5lbHMuam90YWlTY29wZVxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBfanN4KFR1bm5lbHNDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgdmFsdWU6IHR1bm5lbHNcbiAgICAgIH0sIHtcbiAgICAgICAgY2hpbGRyZW46IGxheWVyVUlKU1hcbiAgICAgIH0pKVxuICAgIH0pKVxuICB9KSk7XG59O1xuXG5jb25zdCBzdHJpcElycmVsZXZhbnRBcHBTdGF0ZVByb3BzID0gYXBwU3RhdGUgPT4ge1xuICBjb25zdCB7XG4gICAgc3VnZ2VzdGVkQmluZGluZ3MsXG4gICAgc3RhcnRCb3VuZEVsZW1lbnQsXG4gICAgY3Vyc29yQnV0dG9uLFxuICAgIHNjcm9sbFgsXG4gICAgc2Nyb2xsWVxuICB9ID0gYXBwU3RhdGUsXG4gICAgICAgIHJldCA9IF9fcmVzdChhcHBTdGF0ZSwgW1wic3VnZ2VzdGVkQmluZGluZ3NcIiwgXCJzdGFydEJvdW5kRWxlbWVudFwiLCBcImN1cnNvckJ1dHRvblwiLCBcInNjcm9sbFhcIiwgXCJzY3JvbGxZXCJdKTtcblxuICByZXR1cm4gcmV0O1xufTtcblxuY29uc3QgYXJlRXF1YWwgPSAocHJldlByb3BzLCBuZXh0UHJvcHMpID0+IHtcbiAgLy8gc2hvcnQtY2lyY3VpdCBlYXJseVxuICBpZiAocHJldlByb3BzLmNoaWxkcmVuICE9PSBuZXh0UHJvcHMuY2hpbGRyZW4pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCB7XG4gICAgY2FudmFzOiBfcEMsXG4gICAgaW50ZXJhY3RpdmVDYW52YXM6IF9wSUMsXG4gICAgYXBwU3RhdGU6IHByZXZBcHBTdGF0ZVxuICB9ID0gcHJldlByb3BzLFxuICAgICAgICBwcmV2ID0gX19yZXN0KHByZXZQcm9wcywgW1wiY2FudmFzXCIsIFwiaW50ZXJhY3RpdmVDYW52YXNcIiwgXCJhcHBTdGF0ZVwiXSk7XG5cbiAgY29uc3Qge1xuICAgIGNhbnZhczogX25DLFxuICAgIGludGVyYWN0aXZlQ2FudmFzOiBfbklDLFxuICAgIGFwcFN0YXRlOiBuZXh0QXBwU3RhdGVcbiAgfSA9IG5leHRQcm9wcyxcbiAgICAgICAgbmV4dCA9IF9fcmVzdChuZXh0UHJvcHMsIFtcImNhbnZhc1wiLCBcImludGVyYWN0aXZlQ2FudmFzXCIsIFwiYXBwU3RhdGVcIl0pO1xuXG4gIHJldHVybiBpc1NoYWxsb3dFcXVhbCggLy8gYXNzZXJ0aW5nIEFwcFN0YXRlIGJlY2F1c2Ugd2UncmUgYmVpbmcgcGFzc2VkIHRoZSB3aG9sZSBBcHBTdGF0ZVxuICAvLyBidXQgcmVzb2x2ZSB0byBvbmx5IHRoZSBVSS1yZWxldmFudCBwcm9wc1xuICBzdHJpcElycmVsZXZhbnRBcHBTdGF0ZVByb3BzKHByZXZBcHBTdGF0ZSksIHN0cmlwSXJyZWxldmFudEFwcFN0YXRlUHJvcHMobmV4dEFwcFN0YXRlKSwge1xuICAgIHNlbGVjdGVkRWxlbWVudElkczogaXNTaGFsbG93RXF1YWwsXG4gICAgc2VsZWN0ZWRHcm91cElkczogaXNTaGFsbG93RXF1YWxcbiAgfSkgJiYgaXNTaGFsbG93RXF1YWwocHJldiwgbmV4dCk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBSZWFjdC5tZW1vKExheWVyVUksIGFyZUVxdWFsKTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../../components/LayerUI.tsx\n");
2884
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! clsx */ \"../../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../element */ \"../../element/index.ts\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../i18n */ \"../../i18n.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../scene */ \"../../scene/index.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils */ \"../../utils.ts\");\n/* harmony import */ var _Actions__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Actions */ \"../../components/Actions.tsx\");\n/* harmony import */ var _ErrorDialog__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ErrorDialog */ \"../../components/ErrorDialog.tsx\");\n/* harmony import */ var _ImageExportDialog__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ImageExportDialog */ \"../../components/ImageExportDialog.tsx\");\n/* harmony import */ var _FixedSideContainer__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./FixedSideContainer */ \"../../components/FixedSideContainer.tsx\");\n/* harmony import */ var _HintViewer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./HintViewer */ \"../../components/HintViewer.tsx\");\n/* harmony import */ var _Island__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Island */ \"../../components/Island.tsx\");\n/* harmony import */ var _LoadingMessage__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./LoadingMessage */ \"../../components/LoadingMessage.tsx\");\n/* harmony import */ var _LockButton__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./LockButton */ \"../../components/LockButton.tsx\");\n/* harmony import */ var _MobileMenu__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./MobileMenu */ \"../../components/MobileMenu.tsx\");\n/* harmony import */ var _PasteChartDialog__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./PasteChartDialog */ \"../../components/PasteChartDialog.tsx\");\n/* harmony import */ var _Section__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./Section */ \"../../components/Section.tsx\");\n/* harmony import */ var _HelpDialog__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./HelpDialog */ \"../../components/HelpDialog.tsx\");\n/* harmony import */ var _Stack__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./Stack */ \"../../components/Stack.tsx\");\n/* harmony import */ var _UserList__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./UserList */ \"../../components/UserList.tsx\");\n/* harmony import */ var _JSONExportDialog__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./JSONExportDialog */ \"../../components/JSONExportDialog.tsx\");\n/* harmony import */ var _PenModeButton__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./PenModeButton */ \"../../components/PenModeButton.tsx\");\n/* harmony import */ var _analytics__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../analytics */ \"../../analytics.ts\");\n/* harmony import */ var _components_App__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../components/App */ \"../../components/App.tsx\");\n/* harmony import */ var _Stats__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./Stats */ \"../../components/Stats.tsx\");\n/* harmony import */ var _actions_actionToggleStats__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../actions/actionToggleStats */ \"../../actions/actionToggleStats.tsx\");\n/* harmony import */ var _footer_Footer__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./footer/Footer */ \"../../components/footer/Footer.tsx\");\n/* harmony import */ var _Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./Sidebar/Sidebar */ \"../../components/Sidebar/Sidebar.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../jotai */ \"../../jotai.ts\");\n/* harmony import */ var jotai__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! jotai */ \"../../../node_modules/jotai/esm/index.mjs\");\n/* harmony import */ var _main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./main-menu/MainMenu */ \"../../components/main-menu/MainMenu.tsx\");\n/* harmony import */ var _ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./ActiveConfirmDialog */ \"../../components/ActiveConfirmDialog.tsx\");\n/* harmony import */ var _OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./OverwriteConfirm/OverwriteConfirm */ \"../../components/OverwriteConfirm/OverwriteConfirm.tsx\");\n/* harmony import */ var _HandButton__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./HandButton */ \"../../components/HandButton.tsx\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ../appState */ \"../../appState.ts\");\n/* harmony import */ var _context_tunnels__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ../context/tunnels */ \"../../context/tunnels.ts\");\n/* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./icons */ \"../../components/icons.tsx\");\n/* harmony import */ var _context_ui_appState__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ../context/ui-appState */ \"../../context/ui-appState.ts\");\n/* harmony import */ var _DefaultSidebar__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./DefaultSidebar */ \"../../components/DefaultSidebar.tsx\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./EyeDropper */ \"../../components/EyeDropper.tsx\");\n/* harmony import */ var _LayerUI_scss__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./LayerUI.scss */ \"../../components/LayerUI.scss\");\n/* harmony import */ var _Toolbar_scss__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./Toolbar.scss */ \"../../components/Toolbar.scss\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ../element/mutateElement */ \"../../element/mutateElement.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ../scene/ShapeCache */ \"../../scene/ShapeCache.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ../scene/Scene */ \"../../scene/Scene.ts\");\nvar __rest = undefined && undefined.__rest || function (s, e) {\n var t = {};\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst DefaultMainMenu = ({\n UIOptions\n}) => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"], Object.assign({\n __fallback: true\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.LoadScene, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.SaveToActiveFile, {}), UIOptions.canvasActions.export && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.Export, {}), UIOptions.canvasActions.saveAsImage && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.SaveAsImage, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.Help, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.ClearCanvas, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].Separator, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].Group, Object.assign({\n title: \"Excalidraw links\"\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.Socials, {})\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].Separator, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.ToggleTheme, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_main_menu_MainMenu__WEBPACK_IMPORTED_MODULE_31__[\"default\"].DefaultItems.ChangeCanvasBackground, {})]\n }));\n};\n\nconst DefaultOverwriteConfirmDialog = () => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__.OverwriteConfirmDialog, Object.assign({\n __fallback: true\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__.OverwriteConfirmDialog.Actions.SaveToDisk, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_OverwriteConfirm_OverwriteConfirm__WEBPACK_IMPORTED_MODULE_33__.OverwriteConfirmDialog.Actions.ExportToImage, {})]\n }));\n};\n\nconst LayerUI = ({\n actionManager,\n appState,\n files,\n setAppState,\n elements,\n canvas,\n interactiveCanvas,\n onLockToggle,\n onHandToolToggle,\n onPenModeToggle,\n showExitZenModeBtn,\n renderTopRightUI,\n renderCustomStats,\n UIOptions,\n onImageAction,\n onExportImage,\n renderWelcomeScreen,\n children,\n app\n}) => {\n const device = (0,_components_App__WEBPACK_IMPORTED_MODULE_25__.useDevice)();\n const tunnels = (0,_context_tunnels__WEBPACK_IMPORTED_MODULE_36__.useInitializeTunnels)();\n const [eyeDropperState, setEyeDropperState] = (0,jotai__WEBPACK_IMPORTED_MODULE_46__.useAtom)(_EyeDropper__WEBPACK_IMPORTED_MODULE_40__.activeEyeDropperAtom, _jotai__WEBPACK_IMPORTED_MODULE_30__.jotaiScope);\n\n const renderJSONExportDialog = () => {\n if (!UIOptions.canvasActions.export) {\n return null;\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_JSONExportDialog__WEBPACK_IMPORTED_MODULE_22__.JSONExportDialog, {\n elements: elements,\n appState: appState,\n files: files,\n actionManager: actionManager,\n exportOpts: UIOptions.canvasActions.export,\n canvas: canvas,\n setAppState: setAppState\n });\n };\n\n const renderImageExportDialog = () => {\n if (!UIOptions.canvasActions.saveAsImage) {\n return null;\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ImageExportDialog__WEBPACK_IMPORTED_MODULE_10__.ImageExportDialog, {\n elements: elements,\n appState: appState,\n files: files,\n actionManager: actionManager,\n onExportImage: onExportImage,\n onCloseRequest: () => setAppState({\n openDialog: null\n })\n });\n };\n\n const renderCanvasActions = () => (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n style: {\n position: \"relative\"\n }\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.MainMenuTunnel.Out, {}), renderWelcomeScreen && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.WelcomeScreenMenuHintTunnel.Out, {})]\n }));\n\n const renderSelectedShapeActions = () => (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Section__WEBPACK_IMPORTED_MODULE_18__.Section, Object.assign({\n heading: \"selectedShapeActions\",\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"selected-shape-actions zen-mode-transition\", {\n \"transition-left\": appState.zenModeEnabled\n })\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Island__WEBPACK_IMPORTED_MODULE_13__.Island, Object.assign({\n className: _constants__WEBPACK_IMPORTED_MODULE_3__.CLASSES.SHAPE_ACTIONS_MENU,\n padding: 2,\n style: {\n // we want to make sure this doesn't overflow so subtracting the\n // approximate height of hamburgerMenu + footer\n maxHeight: `${appState.height - 166}px`\n }\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Actions__WEBPACK_IMPORTED_MODULE_8__.SelectedShapeActions, {\n appState: appState,\n elements: elements,\n renderAction: actionManager.renderAction\n })\n }))\n }));\n\n const renderFixedSideContainer = () => {\n var _a;\n\n const shouldRenderSelectedShapeActions = (0,_element__WEBPACK_IMPORTED_MODULE_4__.showSelectedShapeActions)(appState, elements);\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_FixedSideContainer__WEBPACK_IMPORTED_MODULE_11__.FixedSideContainer, Object.assign({\n side: \"top\"\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: \"App-menu App-menu_top\"\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Col, Object.assign({\n gap: 6,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"App-menu_top__left\")\n }, {\n children: [renderCanvasActions(), shouldRenderSelectedShapeActions && renderSelectedShapeActions()]\n })), !appState.viewModeEnabled && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Section__WEBPACK_IMPORTED_MODULE_18__.Section, Object.assign({\n heading: \"shapes\",\n className: \"shapes-section\"\n }, {\n children: heading => (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n style: {\n position: \"relative\"\n }\n }, {\n children: [renderWelcomeScreen && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.WelcomeScreenToolbarHintTunnel.Out, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Col, Object.assign({\n gap: 4,\n align: \"start\"\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Row, Object.assign({\n gap: 1,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"App-toolbar-container\", {\n \"zen-mode\": appState.zenModeEnabled\n })\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_Island__WEBPACK_IMPORTED_MODULE_13__.Island, Object.assign({\n padding: 1,\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"App-toolbar\", {\n \"zen-mode\": appState.zenModeEnabled\n })\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_HintViewer__WEBPACK_IMPORTED_MODULE_12__.HintViewer, {\n appState: appState,\n isMobile: device.isMobile,\n device: device,\n app: app\n }), heading, (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_Stack__WEBPACK_IMPORTED_MODULE_20__[\"default\"].Row, Object.assign({\n gap: 1\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_PenModeButton__WEBPACK_IMPORTED_MODULE_23__.PenModeButton, {\n zenModeEnabled: appState.zenModeEnabled,\n checked: appState.penMode,\n onChange: onPenModeToggle,\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.penMode\"),\n penDetected: appState.penDetected\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LockButton__WEBPACK_IMPORTED_MODULE_15__.LockButton, {\n checked: appState.activeTool.locked,\n onChange: onLockToggle,\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.lock\")\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"App-toolbar__divider\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_HandButton__WEBPACK_IMPORTED_MODULE_34__.HandButton, {\n checked: (0,_appState__WEBPACK_IMPORTED_MODULE_35__.isHandToolActive)(appState),\n onChange: () => onHandToolToggle(),\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.hand\"),\n isMobile: true\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Actions__WEBPACK_IMPORTED_MODULE_8__.ShapesSwitcher, {\n appState: appState,\n interactiveCanvas: interactiveCanvas,\n activeTool: appState.activeTool,\n setAppState: setAppState,\n onImageAction: ({\n pointerType\n }) => {\n onImageAction({\n insertOnCanvasDirectly: pointerType !== \"mouse\"\n });\n }\n })]\n }))]\n }))\n }))\n }))]\n }))\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\"layer-ui__wrapper__top-right zen-mode-transition\", {\n \"transition-right\": appState.zenModeEnabled\n })\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_UserList__WEBPACK_IMPORTED_MODULE_21__.UserList, {\n collaborators: appState.collaborators\n }), renderTopRightUI === null || renderTopRightUI === void 0 ? void 0 : renderTopRightUI(device.isMobile, appState), !appState.viewModeEnabled && ( // hide button when sidebar docked\n !isSidebarDocked || ((_a = appState.openSidebar) === null || _a === void 0 ? void 0 : _a.name) !== _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.name) && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.DefaultSidebarTriggerTunnel.Out, {})]\n }))]\n }))\n }));\n };\n\n const renderSidebars = () => {\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_DefaultSidebar__WEBPACK_IMPORTED_MODULE_39__.DefaultSidebar, {\n __fallback: true,\n onDock: docked => {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_24__.trackEvent)(\"sidebar\", `toggleDock (${docked ? \"dock\" : \"undock\"})`, `(${device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n });\n };\n\n const isSidebarDocked = (0,jotai__WEBPACK_IMPORTED_MODULE_46__.useAtomValue)(_Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_29__.isSidebarDockedAtom, _jotai__WEBPACK_IMPORTED_MODULE_30__.jotaiScope);\n\n const layerUIJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: [children, (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DefaultMainMenu, {\n UIOptions: UIOptions\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_DefaultSidebar__WEBPACK_IMPORTED_MODULE_39__.DefaultSidebar.Trigger, Object.assign({\n __fallback: true,\n icon: _icons__WEBPACK_IMPORTED_MODULE_37__.LibraryIcon,\n title: (0,_utils__WEBPACK_IMPORTED_MODULE_7__.capitalizeString)((0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.library\")),\n onToggle: open => {\n if (open) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_24__.trackEvent)(\"sidebar\", `${_constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.name} (open)`, `button (${device.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n },\n tab: _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.defaultTab\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"toolBar.library\")\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DefaultOverwriteConfirmDialog, {}), appState.isLoading && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LoadingMessage__WEBPACK_IMPORTED_MODULE_14__.LoadingMessage, {\n delay: 250\n }), appState.errorMessage && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ErrorDialog__WEBPACK_IMPORTED_MODULE_9__.ErrorDialog, Object.assign({\n onClose: () => setAppState({\n errorMessage: null\n })\n }, {\n children: appState.errorMessage\n })), eyeDropperState && !device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_EyeDropper__WEBPACK_IMPORTED_MODULE_40__.EyeDropper, {\n colorPickerType: eyeDropperState.colorPickerType,\n onCancel: () => {\n setEyeDropperState(null);\n },\n onChange: (colorPickerType, color, selectedElements, {\n altKey\n }) => {\n var _a;\n\n if (colorPickerType !== \"elementBackground\" && colorPickerType !== \"elementStroke\") {\n return;\n }\n\n if (selectedElements.length) {\n for (const element of selectedElements) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_43__.mutateElement)(element, {\n [altKey && eyeDropperState.swapPreviewOnAlt ? colorPickerType === \"elementBackground\" ? \"strokeColor\" : \"backgroundColor\" : colorPickerType === \"elementBackground\" ? \"backgroundColor\" : \"strokeColor\"]: color\n }, false);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_44__.ShapeCache[\"delete\"](element);\n }\n\n (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_45__[\"default\"].getScene(selectedElements[0])) === null || _a === void 0 ? void 0 : _a.informMutation();\n } else if (colorPickerType === \"elementBackground\") {\n setAppState({\n currentItemBackgroundColor: color\n });\n } else {\n setAppState({\n currentItemStrokeColor: color\n });\n }\n },\n onSelect: (color, event) => {\n var _a;\n\n setEyeDropperState(state => {\n return (state === null || state === void 0 ? void 0 : state.keepOpenOnAlt) && event.altKey ? state : null;\n });\n (_a = eyeDropperState === null || eyeDropperState === void 0 ? void 0 : eyeDropperState.onSelect) === null || _a === void 0 ? void 0 : _a.call(eyeDropperState, color, event);\n }\n }), appState.openDialog === \"help\" && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_HelpDialog__WEBPACK_IMPORTED_MODULE_19__.HelpDialog, {\n onClose: () => {\n setAppState({\n openDialog: null\n });\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_32__.ActiveConfirmDialog, {}), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.OverwriteConfirmDialogTunnel.Out, {}), renderImageExportDialog(), renderJSONExportDialog(), appState.pasteDialog.shown && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_PasteChartDialog__WEBPACK_IMPORTED_MODULE_17__.PasteChartDialog, {\n setAppState: setAppState,\n appState: appState,\n onClose: () => setAppState({\n pasteDialog: {\n shown: false,\n data: null\n }\n })\n }), device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MobileMenu__WEBPACK_IMPORTED_MODULE_16__.MobileMenu, {\n app: app,\n appState: appState,\n elements: elements,\n actionManager: actionManager,\n renderJSONExportDialog: renderJSONExportDialog,\n renderImageExportDialog: renderImageExportDialog,\n setAppState: setAppState,\n onLockToggle: onLockToggle,\n onHandToolToggle: onHandToolToggle,\n onPenModeToggle: onPenModeToggle,\n interactiveCanvas: interactiveCanvas,\n onImageAction: onImageAction,\n renderTopRightUI: renderTopRightUI,\n renderCustomStats: renderCustomStats,\n renderSidebars: renderSidebars,\n device: device,\n renderWelcomeScreen: renderWelcomeScreen\n }), !device.isMobile && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n className: \"layer-ui__wrapper\",\n style: appState.openSidebar && isSidebarDocked && device.canDeviceFitSidebar ? {\n width: `calc(100% - ${_constants__WEBPACK_IMPORTED_MODULE_3__.LIBRARY_SIDEBAR_WIDTH}px)`\n } : {}\n }, {\n children: [renderWelcomeScreen && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(tunnels.WelcomeScreenCenterTunnel.Out, {}), renderFixedSideContainer(), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_footer_Footer__WEBPACK_IMPORTED_MODULE_28__[\"default\"], {\n appState: appState,\n actionManager: actionManager,\n showExitZenModeBtn: showExitZenModeBtn,\n renderWelcomeScreen: renderWelcomeScreen\n }), appState.showStats && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Stats__WEBPACK_IMPORTED_MODULE_26__.Stats, {\n appState: appState,\n setAppState: setAppState,\n elements: elements,\n onClose: () => {\n actionManager.executeAction(_actions_actionToggleStats__WEBPACK_IMPORTED_MODULE_27__.actionToggleStats);\n },\n renderCustomStats: renderCustomStats\n }), appState.scrolledOutside && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"button\", Object.assign({\n className: \"scroll-back-to-content\",\n onClick: () => {\n setAppState(appState => Object.assign({}, (0,_scene__WEBPACK_IMPORTED_MODULE_6__.calculateScrollCenter)(elements, appState)));\n }\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_5__.t)(\"buttons.scrollBackToContent\")\n }))]\n })), renderSidebars()]\n })]\n });\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_context_ui_appState__WEBPACK_IMPORTED_MODULE_38__.UIAppStateContext.Provider, Object.assign({\n value: appState\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(jotai__WEBPACK_IMPORTED_MODULE_46__.Provider, Object.assign({\n scope: tunnels.jotaiScope\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_context_tunnels__WEBPACK_IMPORTED_MODULE_36__.TunnelsContext.Provider, Object.assign({\n value: tunnels\n }, {\n children: layerUIJSX\n }))\n }))\n }));\n};\n\nconst stripIrrelevantAppStateProps = appState => {\n const {\n suggestedBindings,\n startBoundElement,\n cursorButton,\n scrollX,\n scrollY\n } = appState,\n ret = __rest(appState, [\"suggestedBindings\", \"startBoundElement\", \"cursorButton\", \"scrollX\", \"scrollY\"]);\n\n return ret;\n};\n\nconst areEqual = (prevProps, nextProps) => {\n // short-circuit early\n if (prevProps.children !== nextProps.children) {\n return false;\n }\n\n const {\n canvas: _pC,\n interactiveCanvas: _pIC,\n appState: prevAppState\n } = prevProps,\n prev = __rest(prevProps, [\"canvas\", \"interactiveCanvas\", \"appState\"]);\n\n const {\n canvas: _nC,\n interactiveCanvas: _nIC,\n appState: nextAppState\n } = nextProps,\n next = __rest(nextProps, [\"canvas\", \"interactiveCanvas\", \"appState\"]);\n\n return (0,_utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual)( // asserting AppState because we're being passed the whole AppState\n // but resolve to only the UI-relevant props\n stripIrrelevantAppStateProps(prevAppState), stripIrrelevantAppStateProps(nextAppState), {\n selectedElementIds: _utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual,\n selectedGroupIds: _utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual\n }) && (0,_utils__WEBPACK_IMPORTED_MODULE_7__.isShallowEqual)(prev, next);\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (react__WEBPACK_IMPORTED_MODULE_2___default().memo(LayerUI, areEqual));//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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RTtBQUNBLFNBQVM7QUFDVCxvQkFBb0Isd0NBQUM7QUFDckIsU0FBUztBQUNULE9BQU87QUFDUCxLQUFLO0FBQ0wsR0FBRzs7QUFFSCxTQUFTLHNEQUFJLENBQUMsNkVBQTBCO0FBQ3hDO0FBQ0EsR0FBRztBQUNILGNBQWMsc0RBQUksQ0FBQyw0Q0FBUTtBQUMzQjtBQUNBLEtBQUs7QUFDTCxnQkFBZ0Isc0RBQUksQ0FBQyxzRUFBdUI7QUFDNUM7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUEsU0FBUyxzREFBYztBQUN2QjtBQUNBO0FBQ0Esd0JBQXdCLGtEQUFjO0FBQ3RDLHNCQUFzQixrREFBYztBQUNwQyxHQUFHLEtBQUssc0RBQWM7QUFDdEI7O0FBRUEsaUVBQWUsaURBQVUsbUJBQW1CIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2NvbXBvbmVudHMvTGF5ZXJVSS50c3g/Y2M0MSJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgX19yZXN0ID0gdGhpcyAmJiB0aGlzLl9fcmVzdCB8fCBmdW5jdGlvbiAocywgZSkge1xuICB2YXIgdCA9IHt9O1xuXG4gIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKSB0W3BdID0gc1twXTtcblxuICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpIHRbcFtpXV0gPSBzW3BbaV1dO1xuICB9XG4gIHJldHVybiB0O1xufTtcblxuaW1wb3J0IHsganN4IGFzIF9qc3gsIGpzeHMgYXMgX2pzeHMsIEZyYWdtZW50IGFzIF9GcmFnbWVudCB9IGZyb20gXCJyZWFjdC9qc3gtcnVudGltZVwiO1xuaW1wb3J0IGNsc3ggZnJvbSBcImNsc3hcIjtcbmltcG9ydCBSZWFjdCBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IENMQVNTRVMsIERFRkFVTFRfU0lERUJBUiwgTElCUkFSWV9TSURFQkFSX1dJRFRIIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgc2hvd1NlbGVjdGVkU2hhcGVBY3Rpb25zIH0gZnJvbSBcIi4uL2VsZW1lbnRcIjtcbmltcG9ydCB7IHQgfSBmcm9tIFwiLi4vaTE4blwiO1xuaW1wb3J0IHsgY2FsY3VsYXRlU2Nyb2xsQ2VudGVyIH0gZnJvbSBcIi4uL3NjZW5lXCI7XG5pbXBvcnQgeyBjYXBpdGFsaXplU3RyaW5nLCBpc1NoYWxsb3dFcXVhbCB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgU2VsZWN0ZWRTaGFwZUFjdGlvbnMsIFNoYXBlc1N3aXRjaGVyIH0gZnJvbSBcIi4vQWN0aW9uc1wiO1xuaW1wb3J0IHsgRXJyb3JEaWFsb2cgfSBmcm9tIFwiLi9FcnJvckRpYWxvZ1wiO1xuaW1wb3J0IHsgSW1hZ2VFeHBvcnREaWFsb2cgfSBmcm9tIFwiLi9JbWFnZUV4cG9ydERpYWxvZ1wiO1xuaW1wb3J0IHsgRml4ZWRTaWRlQ29udGFpbmVyIH0gZnJvbSBcIi4vRml4ZWRTaWRlQ29udGFpbmVyXCI7XG5pbXBvcnQgeyBIaW50Vmlld2VyIH0gZnJvbSBcIi4vSGludFZpZXdlclwiO1xuaW1wb3J0IHsgSXNsYW5kIH0gZnJvbSBcIi4vSXNsYW5kXCI7XG5pbXBvcnQgeyBMb2FkaW5nTWVzc2FnZSB9IGZyb20gXCIuL0xvYWRpbmdNZXNzYWdlXCI7XG5pbXBvcnQgeyBMb2NrQnV0dG9uIH0gZnJvbSBcIi4vTG9ja0J1dHRvblwiO1xuaW1wb3J0IHsgTW9iaWxlTWVudSB9IGZyb20gXCIuL01vYmlsZU1lbnVcIjtcbmltcG9ydCB7IFBhc3RlQ2hhcnREaWFsb2cgfSBmcm9tIFwiLi9QYXN0ZUNoYXJ0RGlhbG9nXCI7XG5pbXBvcnQgeyBTZWN0aW9uIH0gZnJvbSBcIi4vU2VjdGlvblwiO1xuaW1wb3J0IHsgSGVscERpYWxvZyB9IGZyb20gXCIuL0hlbHBEaWFsb2dcIjtcbmltcG9ydCBTdGFjayBmcm9tIFwiLi9TdGFja1wiO1xuaW1wb3J0IHsgVXNlckxpc3QgfSBmcm9tIFwiLi9Vc2VyTGlzdFwiO1xuaW1wb3J0IHsgSlNPTkV4cG9ydERpYWxvZyB9IGZyb20gXCIuL0pTT05FeHBvcnREaWFsb2dcIjtcbmltcG9ydCB7IFBlbk1vZGVCdXR0b24gfSBmcm9tIFwiLi9QZW5Nb2RlQnV0dG9uXCI7XG5pbXBvcnQgeyB0cmFja0V2ZW50IH0gZnJvbSBcIi4uL2FuYWx5dGljc1wiO1xuaW1wb3J0IHsgdXNlRGV2aWNlIH0gZnJvbSBcIi4uL2NvbXBvbmVudHMvQXBwXCI7XG5pbXBvcnQgeyBTdGF0cyB9IGZyb20gXCIuL1N0YXRzXCI7XG5pbXBvcnQgeyBhY3Rpb25Ub2dnbGVTdGF0cyB9IGZyb20gXCIuLi9hY3Rpb25zL2FjdGlvblRvZ2dsZVN0YXRzXCI7XG5pbXBvcnQgRm9vdGVyIGZyb20gXCIuL2Zvb3Rlci9Gb290ZXJcIjtcbmltcG9ydCB7IGlzU2lkZWJhckRvY2tlZEF0b20gfSBmcm9tIFwiLi9TaWRlYmFyL1NpZGViYXJcIjtcbmltcG9ydCB7IGpvdGFpU2NvcGUgfSBmcm9tIFwiLi4vam90YWlcIjtcbmltcG9ydCB7IFByb3ZpZGVyLCB1c2VBdG9tLCB1c2VBdG9tVmFsdWUgfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCBNYWluTWVudSBmcm9tIFwiLi9tYWluLW1lbnUvTWFpbk1lbnVcIjtcbmltcG9ydCB7IEFjdGl2ZUNvbmZpcm1EaWFsb2cgfSBmcm9tIFwiLi9BY3RpdmVDb25maXJtRGlhbG9nXCI7XG5pbXBvcnQgeyBPdmVyd3JpdGVDb25maXJtRGlhbG9nIH0gZnJvbSBcIi4vT3ZlcndyaXRlQ29uZmlybS9PdmVyd3JpdGVDb25maXJtXCI7XG5pbXBvcnQgeyBIYW5kQnV0dG9uIH0gZnJvbSBcIi4vSGFuZEJ1dHRvblwiO1xuaW1wb3J0IHsgaXNIYW5kVG9vbEFjdGl2ZSB9IGZyb20gXCIuLi9hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgVHVubmVsc0NvbnRleHQsIHVzZUluaXRpYWxpemVUdW5uZWxzIH0gZnJvbSBcIi4uL2NvbnRleHQvdHVubmVsc1wiO1xuaW1wb3J0IHsgTGlicmFyeUljb24gfSBmcm9tIFwiLi9pY29uc1wiO1xuaW1wb3J0IHsgVUlBcHBTdGF0ZUNvbnRleHQgfSBmcm9tIFwiLi4vY29udGV4dC91aS1hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgRGVmYXVsdFNpZGViYXIgfSBmcm9tIFwiLi9EZWZhdWx0U2lkZWJhclwiO1xuaW1wb3J0IHsgRXllRHJvcHBlciwgYWN0aXZlRXllRHJvcHBlckF0b20gfSBmcm9tIFwiLi9FeWVEcm9wcGVyXCI7XG5pbXBvcnQgXCIuL0xheWVyVUkuc2Nzc1wiO1xuaW1wb3J0IFwiLi9Ub29sYmFyLnNjc3NcIjtcbmltcG9ydCB7IG11dGF0ZUVsZW1lbnQgfSBmcm9tIFwiLi4vZWxlbWVudC9tdXRhdGVFbGVtZW50XCI7XG5pbXBvcnQgeyBTaGFwZUNhY2hlIH0gZnJvbSBcIi4uL3NjZW5lL1NoYXBlQ2FjaGVcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vc2NlbmUvU2NlbmVcIjtcblxuY29uc3QgRGVmYXVsdE1haW5NZW51ID0gKHtcbiAgVUlPcHRpb25zXG59KSA9PiB7XG4gIHJldHVybiBfanN4cyhNYWluTWVudSwgT2JqZWN0LmFzc2lnbih7XG4gICAgX19mYWxsYmFjazogdHJ1ZVxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KE1haW5NZW51LkRlZmF1bHRJdGVtcy5Mb2FkU2NlbmUsIHt9KSwgX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuU2F2ZVRvQWN0aXZlRmlsZSwge30pLCBVSU9wdGlvbnMuY2FudmFzQWN0aW9ucy5leHBvcnQgJiYgX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuRXhwb3J0LCB7fSksIFVJT3B0aW9ucy5jYW52YXNBY3Rpb25zLnNhdmVBc0ltYWdlICYmIF9qc3goTWFpbk1lbnUuRGVmYXVsdEl0ZW1zLlNhdmVBc0ltYWdlLCB7fSksIF9qc3goTWFpbk1lbnUuRGVmYXVsdEl0ZW1zLkhlbHAsIHt9KSwgX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuQ2xlYXJDYW52YXMsIHt9KSwgX2pzeChNYWluTWVudS5TZXBhcmF0b3IsIHt9KSwgX2pzeChNYWluTWVudS5Hcm91cCwgT2JqZWN0LmFzc2lnbih7XG4gICAgICB0aXRsZTogXCJFeGNhbGlkcmF3IGxpbmtzXCJcbiAgICB9LCB7XG4gICAgICBjaGlsZHJlbjogX2pzeChNYWluTWVudS5EZWZhdWx0SXRlbXMuU29jaWFscywge30pXG4gICAgfSkpLCBfanN4KE1haW5NZW51LlNlcGFyYXRvciwge30pLCBfanN4KE1haW5NZW51LkRlZmF1bHRJdGVtcy5Ub2dnbGVUaGVtZSwge30pLCBfanN4KE1haW5NZW51LkRlZmF1bHRJdGVtcy5DaGFuZ2VDYW52YXNCYWNrZ3JvdW5kLCB7fSldXG4gIH0pKTtcbn07XG5cbmNvbnN0IERlZmF1bHRPdmVyd3JpdGVDb25maXJtRGlhbG9nID0gKCkgPT4ge1xuICByZXR1cm4gX2pzeHMoT3ZlcndyaXRlQ29uZmlybURpYWxvZywgT2JqZWN0LmFzc2lnbih7XG4gICAgX19mYWxsYmFjazogdHJ1ZVxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KE92ZXJ3cml0ZUNvbmZpcm1EaWFsb2cuQWN0aW9ucy5TYXZlVG9EaXNrLCB7fSksIF9qc3goT3ZlcndyaXRlQ29uZmlybURpYWxvZy5BY3Rpb25zLkV4cG9ydFRvSW1hZ2UsIHt9KV1cbiAgfSkpO1xufTtcblxuY29uc3QgTGF5ZXJVSSA9ICh7XG4gIGFjdGlvbk1hbmFnZXIsXG4gIGFwcFN0YXRlLFxuICBmaWxlcyxcbiAgc2V0QXBwU3RhdGUsXG4gIGVsZW1lbnRzLFxuICBjYW52YXMsXG4gIGludGVyYWN0aXZlQ2FudmFzLFxuICBvbkxvY2tUb2dnbGUsXG4gIG9uSGFuZFRvb2xUb2dnbGUsXG4gIG9uUGVuTW9kZVRvZ2dsZSxcbiAgc2hvd0V4aXRaZW5Nb2RlQnRuLFxuICByZW5kZXJUb3BSaWdodFVJLFxuICByZW5kZXJDdXN0b21TdGF0cyxcbiAgVUlPcHRpb25zLFxuICBvbkltYWdlQWN0aW9uLFxuICBvbkV4cG9ydEltYWdlLFxuICByZW5kZXJXZWxjb21lU2NyZWVuLFxuICBjaGlsZHJlbixcbiAgYXBwXG59KSA9PiB7XG4gIGNvbnN0IGRldmljZSA9IHVzZURldmljZSgpO1xuICBjb25zdCB0dW5uZWxzID0gdXNlSW5pdGlhbGl6ZVR1bm5lbHMoKTtcbiAgY29uc3QgW2V5ZURyb3BwZXJTdGF0ZSwgc2V0RXllRHJvcHBlclN0YXRlXSA9IHVzZUF0b20oYWN0aXZlRXllRHJvcHBlckF0b20sIGpvdGFpU2NvcGUpO1xuXG4gIGNvbnN0IHJlbmRlckpTT05FeHBvcnREaWFsb2cgPSAoKSA9PiB7XG4gICAgaWYgKCFVSU9wdGlvbnMuY2FudmFzQWN0aW9ucy5leHBvcnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBfanN4KEpTT05FeHBvcnREaWFsb2csIHtcbiAgICAgIGVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgIGZpbGVzOiBmaWxlcyxcbiAgICAgIGFjdGlvbk1hbmFnZXI6IGFjdGlvbk1hbmFnZXIsXG4gICAgICBleHBvcnRPcHRzOiBVSU9wdGlvbnMuY2FudmFzQWN0aW9ucy5leHBvcnQsXG4gICAgICBjYW52YXM6IGNhbnZhcyxcbiAgICAgIHNldEFwcFN0YXRlOiBzZXRBcHBTdGF0ZVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IHJlbmRlckltYWdlRXhwb3J0RGlhbG9nID0gKCkgPT4ge1xuICAgIGlmICghVUlPcHRpb25zLmNhbnZhc0FjdGlvbnMuc2F2ZUFzSW1hZ2UpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBfanN4KEltYWdlRXhwb3J0RGlhbG9nLCB7XG4gICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICBmaWxlczogZmlsZXMsXG4gICAgICBhY3Rpb25NYW5hZ2VyOiBhY3Rpb25NYW5hZ2VyLFxuICAgICAgb25FeHBvcnRJbWFnZTogb25FeHBvcnRJbWFnZSxcbiAgICAgIG9uQ2xvc2VSZXF1ZXN0OiAoKSA9PiBzZXRBcHBTdGF0ZSh7XG4gICAgICAgIG9wZW5EaWFsb2c6IG51bGxcbiAgICAgIH0pXG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgcmVuZGVyQ2FudmFzQWN0aW9ucyA9ICgpID0+IF9qc3hzKFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgIHN0eWxlOiB7XG4gICAgICBwb3NpdGlvbjogXCJyZWxhdGl2ZVwiXG4gICAgfVxuICB9LCB7XG4gICAgY2hpbGRyZW46IFtfanN4KHR1bm5lbHMuTWFpbk1lbnVUdW5uZWwuT3V0LCB7fSksIHJlbmRlcldlbGNvbWVTY3JlZW4gJiYgX2pzeCh0dW5uZWxzLldlbGNvbWVTY3JlZW5NZW51SGludFR1bm5lbC5PdXQsIHt9KV1cbiAgfSkpO1xuXG4gIGNvbnN0IHJlbmRlclNlbGVjdGVkU2hhcGVBY3Rpb25zID0gKCkgPT4gX2pzeChTZWN0aW9uLCBPYmplY3QuYXNzaWduKHtcbiAgICBoZWFkaW5nOiBcInNlbGVjdGVkU2hhcGVBY3Rpb25zXCIsXG4gICAgY2xhc3NOYW1lOiBjbHN4KFwic2VsZWN0ZWQtc2hhcGUtYWN0aW9ucyB6ZW4tbW9kZS10cmFuc2l0aW9uXCIsIHtcbiAgICAgIFwidHJhbnNpdGlvbi1sZWZ0XCI6IGFwcFN0YXRlLnplbk1vZGVFbmFibGVkXG4gICAgfSlcbiAgfSwge1xuICAgIGNoaWxkcmVuOiBfanN4KElzbGFuZCwgT2JqZWN0LmFzc2lnbih7XG4gICAgICBjbGFzc05hbWU6IENMQVNTRVMuU0hBUEVfQUNUSU9OU19NRU5VLFxuICAgICAgcGFkZGluZzogMixcbiAgICAgIHN0eWxlOiB7XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoaXMgZG9lc24ndCBvdmVyZmxvdyBzbyBzdWJ0cmFjdGluZyB0aGVcbiAgICAgICAgLy8gYXBwcm94aW1hdGUgaGVpZ2h0IG9mIGhhbWJ1cmdlck1lbnUgKyBmb290ZXJcbiAgICAgICAgbWF4SGVpZ2h0OiBgJHthcHBTdGF0ZS5oZWlnaHQgLSAxNjZ9cHhgXG4gICAgICB9XG4gICAgfSwge1xuICAgICAgY2hpbGRyZW46IF9qc3goU2VsZWN0ZWRTaGFwZUFjdGlvbnMsIHtcbiAgICAgICAgYXBwU3RhdGU6IGFwcFN0YXRlLFxuICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgIHJlbmRlckFjdGlvbjogYWN0aW9uTWFuYWdlci5yZW5kZXJBY3Rpb25cbiAgICAgIH0pXG4gICAgfSkpXG4gIH0pKTtcblxuICBjb25zdCByZW5kZXJGaXhlZFNpZGVDb250YWluZXIgPSAoKSA9PiB7XG4gICAgdmFyIF9hO1xuXG4gICAgY29uc3Qgc2hvdWxkUmVuZGVyU2VsZWN0ZWRTaGFwZUFjdGlvbnMgPSBzaG93U2VsZWN0ZWRTaGFwZUFjdGlvbnMoYXBwU3RhdGUsIGVsZW1lbnRzKTtcbiAgICByZXR1cm4gX2pzeChGaXhlZFNpZGVDb250YWluZXIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgc2lkZTogXCJ0b3BcIlxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBfanN4cyhcImRpdlwiLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgY2xhc3NOYW1lOiBcIkFwcC1tZW51IEFwcC1tZW51X3RvcFwiXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBbX2pzeHMoU3RhY2suQ29sLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICBnYXA6IDYsXG4gICAgICAgICAgY2xhc3NOYW1lOiBjbHN4KFwiQXBwLW1lbnVfdG9wX19sZWZ0XCIpXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBjaGlsZHJlbjogW3JlbmRlckNhbnZhc0FjdGlvbnMoKSwgc2hvdWxkUmVuZGVyU2VsZWN0ZWRTaGFwZUFjdGlvbnMgJiYgcmVuZGVyU2VsZWN0ZWRTaGFwZUFjdGlvbnMoKV1cbiAgICAgICAgfSkpLCAhYXBwU3RhdGUudmlld01vZGVFbmFibGVkICYmIF9qc3goU2VjdGlvbiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgaGVhZGluZzogXCJzaGFwZXNcIixcbiAgICAgICAgICBjbGFzc05hbWU6IFwic2hhcGVzLXNlY3Rpb25cIlxuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IGhlYWRpbmcgPT4gX2pzeHMoXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICBwb3NpdGlvbjogXCJyZWxhdGl2ZVwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwge1xuICAgICAgICAgICAgY2hpbGRyZW46IFtyZW5kZXJXZWxjb21lU2NyZWVuICYmIF9qc3godHVubmVscy5XZWxjb21lU2NyZWVuVG9vbGJhckhpbnRUdW5uZWwuT3V0LCB7fSksIF9qc3goU3RhY2suQ29sLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgICAgICAgZ2FwOiA0LFxuICAgICAgICAgICAgICBhbGlnbjogXCJzdGFydFwiXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4KFN0YWNrLlJvdywgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgZ2FwOiAxLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcIkFwcC10b29sYmFyLWNvbnRhaW5lclwiLCB7XG4gICAgICAgICAgICAgICAgICBcInplbi1tb2RlXCI6IGFwcFN0YXRlLnplbk1vZGVFbmFibGVkXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBfanN4cyhJc2xhbmQsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgICAgICAgICAgcGFkZGluZzogMSxcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcIkFwcC10b29sYmFyXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgXCJ6ZW4tbW9kZVwiOiBhcHBTdGF0ZS56ZW5Nb2RlRW5hYmxlZFxuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW19qc3goSGludFZpZXdlciwge1xuICAgICAgICAgICAgICAgICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgIGlzTW9iaWxlOiBkZXZpY2UuaXNNb2JpbGUsXG4gICAgICAgICAgICAgICAgICAgIGRldmljZTogZGV2aWNlLFxuICAgICAgICAgICAgICAgICAgICBhcHA6IGFwcFxuICAgICAgICAgICAgICAgICAgfSksIGhlYWRpbmcsIF9qc3hzKFN0YWNrLlJvdywgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgICAgIGdhcDogMVxuICAgICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogW19qc3goUGVuTW9kZUJ1dHRvbiwge1xuICAgICAgICAgICAgICAgICAgICAgIHplbk1vZGVFbmFibGVkOiBhcHBTdGF0ZS56ZW5Nb2RlRW5hYmxlZCxcbiAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkOiBhcHBTdGF0ZS5wZW5Nb2RlLFxuICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlOiBvblBlbk1vZGVUb2dnbGUsXG4gICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHQoXCJ0b29sQmFyLnBlbk1vZGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgcGVuRGV0ZWN0ZWQ6IGFwcFN0YXRlLnBlbkRldGVjdGVkXG4gICAgICAgICAgICAgICAgICAgIH0pLCBfanN4KExvY2tCdXR0b24sIHtcbiAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkOiBhcHBTdGF0ZS5hY3RpdmVUb29sLmxvY2tlZCxcbiAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogb25Mb2NrVG9nZ2xlLFxuICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiB0KFwidG9vbEJhci5sb2NrXCIpXG4gICAgICAgICAgICAgICAgICAgIH0pLCBfanN4KFwiZGl2XCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwiQXBwLXRvb2xiYXJfX2RpdmlkZXJcIlxuICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChIYW5kQnV0dG9uLCB7XG4gICAgICAgICAgICAgICAgICAgICAgY2hlY2tlZDogaXNIYW5kVG9vbEFjdGl2ZShhcHBTdGF0ZSksXG4gICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U6ICgpID0+IG9uSGFuZFRvb2xUb2dnbGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogdChcInRvb2xCYXIuaGFuZFwiKSxcbiAgICAgICAgICAgICAgICAgICAgICBpc01vYmlsZTogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICB9KSwgX2pzeChTaGFwZXNTd2l0Y2hlciwge1xuICAgICAgICAgICAgICAgICAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGl2ZUNhbnZhczogaW50ZXJhY3RpdmVDYW52YXMsXG4gICAgICAgICAgICAgICAgICAgICAgYWN0aXZlVG9vbDogYXBwU3RhdGUuYWN0aXZlVG9vbCxcbiAgICAgICAgICAgICAgICAgICAgICBzZXRBcHBTdGF0ZTogc2V0QXBwU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgb25JbWFnZUFjdGlvbjogKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXJUeXBlXG4gICAgICAgICAgICAgICAgICAgICAgfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgb25JbWFnZUFjdGlvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydE9uQ2FudmFzRGlyZWN0bHk6IHBvaW50ZXJUeXBlICE9PSBcIm1vdXNlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSldXG4gICAgICAgICAgICAgICAgICB9KSldXG4gICAgICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgfSkpXVxuICAgICAgICAgIH0pKVxuICAgICAgICB9KSksIF9qc3hzKFwiZGl2XCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgIGNsYXNzTmFtZTogY2xzeChcImxheWVyLXVpX193cmFwcGVyX190b3AtcmlnaHQgemVuLW1vZGUtdHJhbnNpdGlvblwiLCB7XG4gICAgICAgICAgICBcInRyYW5zaXRpb24tcmlnaHRcIjogYXBwU3RhdGUuemVuTW9kZUVuYWJsZWRcbiAgICAgICAgICB9KVxuICAgICAgICB9LCB7XG4gICAgICAgICAgY2hpbGRyZW46IFtfanN4KFVzZXJMaXN0LCB7XG4gICAgICAgICAgICBjb2xsYWJvcmF0b3JzOiBhcHBTdGF0ZS5jb2xsYWJvcmF0b3JzXG4gICAgICAgICAgfSksIHJlbmRlclRvcFJpZ2h0VUkgPT09IG51bGwgfHwgcmVuZGVyVG9wUmlnaHRVSSA9PT0gdm9pZCAwID8gdm9pZCAwIDogcmVuZGVyVG9wUmlnaHRVSShkZXZpY2UuaXNNb2JpbGUsIGFwcFN0YXRlKSwgIWFwcFN0YXRlLnZpZXdNb2RlRW5hYmxlZCAmJiAoIC8vIGhpZGUgYnV0dG9uIHdoZW4gc2lkZWJhciBkb2NrZWRcbiAgICAgICAgICAhaXNTaWRlYmFyRG9ja2VkIHx8ICgoX2EgPSBhcHBTdGF0ZS5vcGVuU2lkZWJhcikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLm5hbWUpICE9PSBERUZBVUxUX1NJREVCQVIubmFtZSkgJiYgX2pzeCh0dW5uZWxzLkRlZmF1bHRTaWRlYmFyVHJpZ2dlclR1bm5lbC5PdXQsIHt9KV1cbiAgICAgICAgfSkpXVxuICAgICAgfSkpXG4gICAgfSkpO1xuICB9O1xuXG4gIGNvbnN0IHJlbmRlclNpZGViYXJzID0gKCkgPT4ge1xuICAgIHJldHVybiBfanN4KERlZmF1bHRTaWRlYmFyLCB7XG4gICAgICBfX2ZhbGxiYWNrOiB0cnVlLFxuICAgICAgb25Eb2NrOiBkb2NrZWQgPT4ge1xuICAgICAgICB0cmFja0V2ZW50KFwic2lkZWJhclwiLCBgdG9nZ2xlRG9jayAoJHtkb2NrZWQgPyBcImRvY2tcIiA6IFwidW5kb2NrXCJ9KWAsIGAoJHtkZXZpY2UuaXNNb2JpbGUgPyBcIm1vYmlsZVwiIDogXCJkZXNrdG9wXCJ9KWApO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGNvbnN0IGlzU2lkZWJhckRvY2tlZCA9IHVzZUF0b21WYWx1ZShpc1NpZGViYXJEb2NrZWRBdG9tLCBqb3RhaVNjb3BlKTtcblxuICBjb25zdCBsYXllclVJSlNYID0gX2pzeHMoX0ZyYWdtZW50LCB7XG4gICAgY2hpbGRyZW46IFtjaGlsZHJlbiwgX2pzeChEZWZhdWx0TWFpbk1lbnUsIHtcbiAgICAgIFVJT3B0aW9uczogVUlPcHRpb25zXG4gICAgfSksIF9qc3goRGVmYXVsdFNpZGViYXIuVHJpZ2dlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICBfX2ZhbGxiYWNrOiB0cnVlLFxuICAgICAgaWNvbjogTGlicmFyeUljb24sXG4gICAgICB0aXRsZTogY2FwaXRhbGl6ZVN0cmluZyh0KFwidG9vbEJhci5saWJyYXJ5XCIpKSxcbiAgICAgIG9uVG9nZ2xlOiBvcGVuID0+IHtcbiAgICAgICAgaWYgKG9wZW4pIHtcbiAgICAgICAgICB0cmFja0V2ZW50KFwic2lkZWJhclwiLCBgJHtERUZBVUxUX1NJREVCQVIubmFtZX0gKG9wZW4pYCwgYGJ1dHRvbiAoJHtkZXZpY2UuaXNNb2JpbGUgPyBcIm1vYmlsZVwiIDogXCJkZXNrdG9wXCJ9KWApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdGFiOiBERUZBVUxUX1NJREVCQVIuZGVmYXVsdFRhYlxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiB0KFwidG9vbEJhci5saWJyYXJ5XCIpXG4gICAgfSkpLCBfanN4KERlZmF1bHRPdmVyd3JpdGVDb25maXJtRGlhbG9nLCB7fSksIGFwcFN0YXRlLmlzTG9hZGluZyAmJiBfanN4KExvYWRpbmdNZXNzYWdlLCB7XG4gICAgICBkZWxheTogMjUwXG4gICAgfSksIGFwcFN0YXRlLmVycm9yTWVzc2FnZSAmJiBfanN4KEVycm9yRGlhbG9nLCBPYmplY3QuYXNzaWduKHtcbiAgICAgIG9uQ2xvc2U6ICgpID0+IHNldEFwcFN0YXRlKHtcbiAgICAgICAgZXJyb3JNZXNzYWdlOiBudWxsXG4gICAgICB9KVxuICAgIH0sIHtcbiAgICAgIGNoaWxkcmVuOiBhcHBTdGF0ZS5lcnJvck1lc3NhZ2VcbiAgICB9KSksIGV5ZURyb3BwZXJTdGF0ZSAmJiAhZGV2aWNlLmlzTW9iaWxlICYmIF9qc3goRXllRHJvcHBlciwge1xuICAgICAgY29sb3JQaWNrZXJUeXBlOiBleWVEcm9wcGVyU3RhdGUuY29sb3JQaWNrZXJUeXBlLFxuICAgICAgb25DYW5jZWw6ICgpID0+IHtcbiAgICAgICAgc2V0RXllRHJvcHBlclN0YXRlKG51bGwpO1xuICAgICAgfSxcbiAgICAgIG9uQ2hhbmdlOiAoY29sb3JQaWNrZXJUeXBlLCBjb2xvciwgc2VsZWN0ZWRFbGVtZW50cywge1xuICAgICAgICBhbHRLZXlcbiAgICAgIH0pID0+IHtcbiAgICAgICAgdmFyIF9hO1xuXG4gICAgICAgIGlmIChjb2xvclBpY2tlclR5cGUgIT09IFwiZWxlbWVudEJhY2tncm91bmRcIiAmJiBjb2xvclBpY2tlclR5cGUgIT09IFwiZWxlbWVudFN0cm9rZVwiKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHNlbGVjdGVkRWxlbWVudHMpIHtcbiAgICAgICAgICAgIG11dGF0ZUVsZW1lbnQoZWxlbWVudCwge1xuICAgICAgICAgICAgICBbYWx0S2V5ICYmIGV5ZURyb3BwZXJTdGF0ZS5zd2FwUHJldmlld09uQWx0ID8gY29sb3JQaWNrZXJUeXBlID09PSBcImVsZW1lbnRCYWNrZ3JvdW5kXCIgPyBcInN0cm9rZUNvbG9yXCIgOiBcImJhY2tncm91bmRDb2xvclwiIDogY29sb3JQaWNrZXJUeXBlID09PSBcImVsZW1lbnRCYWNrZ3JvdW5kXCIgPyBcImJhY2tncm91bmRDb2xvclwiIDogXCJzdHJva2VDb2xvclwiXTogY29sb3JcbiAgICAgICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgICAgIFNoYXBlQ2FjaGUuZGVsZXRlKGVsZW1lbnQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIChfYSA9IFNjZW5lLmdldFNjZW5lKHNlbGVjdGVkRWxlbWVudHNbMF0pKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuaW5mb3JtTXV0YXRpb24oKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb2xvclBpY2tlclR5cGUgPT09IFwiZWxlbWVudEJhY2tncm91bmRcIikge1xuICAgICAgICAgIHNldEFwcFN0YXRlKHtcbiAgICAgICAgICAgIGN1cnJlbnRJdGVtQmFja2dyb3VuZENvbG9yOiBjb2xvclxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNldEFwcFN0YXRlKHtcbiAgICAgICAgICAgIGN1cnJlbnRJdGVtU3Ryb2tlQ29sb3I6IGNvbG9yXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBvblNlbGVjdDogKGNvbG9yLCBldmVudCkgPT4ge1xuICAgICAgICB2YXIgX2E7XG5cbiAgICAgICAgc2V0RXllRHJvcHBlclN0YXRlKHN0YXRlID0+IHtcbiAgICAgICAgICByZXR1cm4gKHN0YXRlID09PSBudWxsIHx8IHN0YXRlID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzdGF0ZS5rZWVwT3Blbk9uQWx0KSAmJiBldmVudC5hbHRLZXkgPyBzdGF0ZSA6IG51bGw7XG4gICAgICAgIH0pO1xuICAgICAgICAoX2EgPSBleWVEcm9wcGVyU3RhdGUgPT09IG51bGwgfHwgZXllRHJvcHBlclN0YXRlID09PSB2b2lkIDAgPyB2b2lkIDAgOiBleWVEcm9wcGVyU3RhdGUub25TZWxlY3QpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jYWxsKGV5ZURyb3BwZXJTdGF0ZSwgY29sb3IsIGV2ZW50KTtcbiAgICAgIH1cbiAgICB9KSwgYXBwU3RhdGUub3BlbkRpYWxvZyA9PT0gXCJoZWxwXCIgJiYgX2pzeChIZWxwRGlhbG9nLCB7XG4gICAgICBvbkNsb3NlOiAoKSA9PiB7XG4gICAgICAgIHNldEFwcFN0YXRlKHtcbiAgICAgICAgICBvcGVuRGlhbG9nOiBudWxsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pLCBfanN4KEFjdGl2ZUNvbmZpcm1EaWFsb2csIHt9KSwgX2pzeCh0dW5uZWxzLk92ZXJ3cml0ZUNvbmZpcm1EaWFsb2dUdW5uZWwuT3V0LCB7fSksIHJlbmRlckltYWdlRXhwb3J0RGlhbG9nKCksIHJlbmRlckpTT05FeHBvcnREaWFsb2coKSwgYXBwU3RhdGUucGFzdGVEaWFsb2cuc2hvd24gJiYgX2pzeChQYXN0ZUNoYXJ0RGlhbG9nLCB7XG4gICAgICBzZXRBcHBTdGF0ZTogc2V0QXBwU3RhdGUsXG4gICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICBvbkNsb3NlOiAoKSA9PiBzZXRBcHBTdGF0ZSh7XG4gICAgICAgIHBhc3RlRGlhbG9nOiB7XG4gICAgICAgICAgc2hvd246IGZhbHNlLFxuICAgICAgICAgIGRhdGE6IG51bGxcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9KSwgZGV2aWNlLmlzTW9iaWxlICYmIF9qc3goTW9iaWxlTWVudSwge1xuICAgICAgYXBwOiBhcHAsXG4gICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICBhY3Rpb25NYW5hZ2VyOiBhY3Rpb25NYW5hZ2VyLFxuICAgICAgcmVuZGVySlNPTkV4cG9ydERpYWxvZzogcmVuZGVySlNPTkV4cG9ydERpYWxvZyxcbiAgICAgIHJlbmRlckltYWdlRXhwb3J0RGlhbG9nOiByZW5kZXJJbWFnZUV4cG9ydERpYWxvZyxcbiAgICAgIHNldEFwcFN0YXRlOiBzZXRBcHBTdGF0ZSxcbiAgICAgIG9uTG9ja1RvZ2dsZTogb25Mb2NrVG9nZ2xlLFxuICAgICAgb25IYW5kVG9vbFRvZ2dsZTogb25IYW5kVG9vbFRvZ2dsZSxcbiAgICAgIG9uUGVuTW9kZVRvZ2dsZTogb25QZW5Nb2RlVG9nZ2xlLFxuICAgICAgaW50ZXJhY3RpdmVDYW52YXM6IGludGVyYWN0aXZlQ2FudmFzLFxuICAgICAgb25JbWFnZUFjdGlvbjogb25JbWFnZUFjdGlvbixcbiAgICAgIHJlbmRlclRvcFJpZ2h0VUk6IHJlbmRlclRvcFJpZ2h0VUksXG4gICAgICByZW5kZXJDdXN0b21TdGF0czogcmVuZGVyQ3VzdG9tU3RhdHMsXG4gICAgICByZW5kZXJTaWRlYmFyczogcmVuZGVyU2lkZWJhcnMsXG4gICAgICBkZXZpY2U6IGRldmljZSxcbiAgICAgIHJlbmRlcldlbGNvbWVTY3JlZW46IHJlbmRlcldlbGNvbWVTY3JlZW5cbiAgICB9KSwgIWRldmljZS5pc01vYmlsZSAmJiBfanN4cyhfRnJhZ21lbnQsIHtcbiAgICAgIGNoaWxkcmVuOiBbX2pzeHMoXCJkaXZcIiwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgIGNsYXNzTmFtZTogXCJsYXllci11aV9fd3JhcHBlclwiLFxuICAgICAgICBzdHlsZTogYXBwU3RhdGUub3BlblNpZGViYXIgJiYgaXNTaWRlYmFyRG9ja2VkICYmIGRldmljZS5jYW5EZXZpY2VGaXRTaWRlYmFyID8ge1xuICAgICAgICAgIHdpZHRoOiBgY2FsYygxMDAlIC0gJHtMSUJSQVJZX1NJREVCQVJfV0lEVEh9cHgpYFxuICAgICAgICB9IDoge31cbiAgICAgIH0sIHtcbiAgICAgICAgY2hpbGRyZW46IFtyZW5kZXJXZWxjb21lU2NyZWVuICYmIF9qc3godHVubmVscy5XZWxjb21lU2NyZWVuQ2VudGVyVHVubmVsLk91dCwge30pLCByZW5kZXJGaXhlZFNpZGVDb250YWluZXIoKSwgX2pzeChGb290ZXIsIHtcbiAgICAgICAgICBhcHBTdGF0ZTogYXBwU3RhdGUsXG4gICAgICAgICAgYWN0aW9uTWFuYWdlcjogYWN0aW9uTWFuYWdlcixcbiAgICAgICAgICBzaG93RXhpdFplbk1vZGVCdG46IHNob3dFeGl0WmVuTW9kZUJ0bixcbiAgICAgICAgICByZW5kZXJXZWxjb21lU2NyZWVuOiByZW5kZXJXZWxjb21lU2NyZWVuXG4gICAgICAgIH0pLCBhcHBTdGF0ZS5zaG93U3RhdHMgJiYgX2pzeChTdGF0cywge1xuICAgICAgICAgIGFwcFN0YXRlOiBhcHBTdGF0ZSxcbiAgICAgICAgICBzZXRBcHBTdGF0ZTogc2V0QXBwU3RhdGUsXG4gICAgICAgICAgZWxlbWVudHM6IGVsZW1lbnRzLFxuICAgICAgICAgIG9uQ2xvc2U6ICgpID0+IHtcbiAgICAgICAgICAgIGFjdGlvbk1hbmFnZXIuZXhlY3V0ZUFjdGlvbihhY3Rpb25Ub2dnbGVTdGF0cyk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICByZW5kZXJDdXN0b21TdGF0czogcmVuZGVyQ3VzdG9tU3RhdHNcbiAgICAgICAgfSksIGFwcFN0YXRlLnNjcm9sbGVkT3V0c2lkZSAmJiBfanN4KFwiYnV0dG9uXCIsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgICAgIGNsYXNzTmFtZTogXCJzY3JvbGwtYmFjay10by1jb250ZW50XCIsXG4gICAgICAgICAgb25DbGljazogKCkgPT4ge1xuICAgICAgICAgICAgc2V0QXBwU3RhdGUoYXBwU3RhdGUgPT4gT2JqZWN0LmFzc2lnbih7fSwgY2FsY3VsYXRlU2Nyb2xsQ2VudGVyKGVsZW1lbnRzLCBhcHBTdGF0ZSkpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICBjaGlsZHJlbjogdChcImJ1dHRvbnMuc2Nyb2xsQmFja1RvQ29udGVudFwiKVxuICAgICAgICB9KSldXG4gICAgICB9KSksIHJlbmRlclNpZGViYXJzKCldXG4gICAgfSldXG4gIH0pO1xuXG4gIHJldHVybiBfanN4KFVJQXBwU3RhdGVDb250ZXh0LlByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICB2YWx1ZTogYXBwU3RhdGVcbiAgfSwge1xuICAgIGNoaWxkcmVuOiBfanN4KFByb3ZpZGVyLCBPYmplY3QuYXNzaWduKHtcbiAgICAgIHNjb3BlOiB0dW5uZWxzLmpvdGFpU2NvcGVcbiAgICB9LCB7XG4gICAgICBjaGlsZHJlbjogX2pzeChUdW5uZWxzQ29udGV4dC5Qcm92aWRlciwgT2JqZWN0LmFzc2lnbih7XG4gICAgICAgIHZhbHVlOiB0dW5uZWxzXG4gICAgICB9LCB7XG4gICAgICAgIGNoaWxkcmVuOiBsYXllclVJSlNYXG4gICAgICB9KSlcbiAgICB9KSlcbiAgfSkpO1xufTtcblxuY29uc3Qgc3RyaXBJcnJlbGV2YW50QXBwU3RhdGVQcm9wcyA9IGFwcFN0YXRlID0+IHtcbiAgY29uc3Qge1xuICAgIHN1Z2dlc3RlZEJpbmRpbmdzLFxuICAgIHN0YXJ0Qm91bmRFbGVtZW50LFxuICAgIGN1cnNvckJ1dHRvbixcbiAgICBzY3JvbGxYLFxuICAgIHNjcm9sbFlcbiAgfSA9IGFwcFN0YXRlLFxuICAgICAgICByZXQgPSBfX3Jlc3QoYXBwU3RhdGUsIFtcInN1Z2dlc3RlZEJpbmRpbmdzXCIsIFwic3RhcnRCb3VuZEVsZW1lbnRcIiwgXCJjdXJzb3JCdXR0b25cIiwgXCJzY3JvbGxYXCIsIFwic2Nyb2xsWVwiXSk7XG5cbiAgcmV0dXJuIHJldDtcbn07XG5cbmNvbnN0IGFyZUVxdWFsID0gKHByZXZQcm9wcywgbmV4dFByb3BzKSA9PiB7XG4gIC8vIHNob3J0LWNpcmN1aXQgZWFybHlcbiAgaWYgKHByZXZQcm9wcy5jaGlsZHJlbiAhPT0gbmV4dFByb3BzLmNoaWxkcmVuKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3Qge1xuICAgIGNhbnZhczogX3BDLFxuICAgIGludGVyYWN0aXZlQ2FudmFzOiBfcElDLFxuICAgIGFwcFN0YXRlOiBwcmV2QXBwU3RhdGVcbiAgfSA9IHByZXZQcm9wcyxcbiAgICAgICAgcHJldiA9IF9fcmVzdChwcmV2UHJvcHMsIFtcImNhbnZhc1wiLCBcImludGVyYWN0aXZlQ2FudmFzXCIsIFwiYXBwU3RhdGVcIl0pO1xuXG4gIGNvbnN0IHtcbiAgICBjYW52YXM6IF9uQyxcbiAgICBpbnRlcmFjdGl2ZUNhbnZhczogX25JQyxcbiAgICBhcHBTdGF0ZTogbmV4dEFwcFN0YXRlXG4gIH0gPSBuZXh0UHJvcHMsXG4gICAgICAgIG5leHQgPSBfX3Jlc3QobmV4dFByb3BzLCBbXCJjYW52YXNcIiwgXCJpbnRlcmFjdGl2ZUNhbnZhc1wiLCBcImFwcFN0YXRlXCJdKTtcblxuICByZXR1cm4gaXNTaGFsbG93RXF1YWwoIC8vIGFzc2VydGluZyBBcHBTdGF0ZSBiZWNhdXNlIHdlJ3JlIGJlaW5nIHBhc3NlZCB0aGUgd2hvbGUgQXBwU3RhdGVcbiAgLy8gYnV0IHJlc29sdmUgdG8gb25seSB0aGUgVUktcmVsZXZhbnQgcHJvcHNcbiAgc3RyaXBJcnJlbGV2YW50QXBwU3RhdGVQcm9wcyhwcmV2QXBwU3RhdGUpLCBzdHJpcElycmVsZXZhbnRBcHBTdGF0ZVByb3BzKG5leHRBcHBTdGF0ZSksIHtcbiAgICBzZWxlY3RlZEVsZW1lbnRJZHM6IGlzU2hhbGxvd0VxdWFsLFxuICAgIHNlbGVjdGVkR3JvdXBJZHM6IGlzU2hhbGxvd0VxdWFsXG4gIH0pICYmIGlzU2hhbGxvd0VxdWFsKHByZXYsIG5leHQpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgUmVhY3QubWVtbyhMYXllclVJLCBhcmVFcXVhbCk7Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///../../components/LayerUI.tsx\n");
2885
2885
 
2886
2886
  /***/ }),
2887
2887
 
@@ -4128,6 +4128,17 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
4128
4128
 
4129
4129
  /***/ }),
4130
4130
 
4131
+ /***/ "../../hooks/useStable.ts":
4132
+ /*!********************************!*\
4133
+ !*** ../../hooks/useStable.ts ***!
4134
+ \********************************/
4135
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4136
+
4137
+ "use strict";
4138
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"useStable\": () => (/* binding */ useStable)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n\nconst useStable = value => {\n const ref = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(value);\n Object.assign(ref.current, value);\n return ref.current;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vLi4vaG9va3MvdXNlU3RhYmxlLnRzLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUErQjtBQUN4QjtBQUNQLGNBQWMsNkNBQU07QUFDcEI7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL2hvb2tzL3VzZVN0YWJsZS50cz9mYmIxIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZVJlZiB9IGZyb20gXCJyZWFjdFwiO1xuZXhwb3J0IGNvbnN0IHVzZVN0YWJsZSA9IHZhbHVlID0+IHtcbiAgY29uc3QgcmVmID0gdXNlUmVmKHZhbHVlKTtcbiAgT2JqZWN0LmFzc2lnbihyZWYuY3VycmVudCwgdmFsdWUpO1xuICByZXR1cm4gcmVmLmN1cnJlbnQ7XG59OyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///../../hooks/useStable.ts\n");
4139
+
4140
+ /***/ }),
4141
+
4131
4142
  /***/ "../../hooks/useTransition.ts":
4132
4143
  /*!************************************!*\
4133
4144
  !*** ../../hooks/useTransition.ts ***!
@@ -4212,7 +4223,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
4212
4223
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4213
4224
 
4214
4225
  "use strict";
4215
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../constants */ \"../../constants.ts\");\n\n\nif (\"development\" !== _constants__WEBPACK_IMPORTED_MODULE_0__.ENV.TEST) {\n /* eslint-disable */\n\n /* global __webpack_public_path__:writable */\n __webpack_require__.p = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${\"@excalidraw/excalidraw\"}@${\"0.16.0\"}/dist/`;\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9wdWJsaWNQYXRoLmpzLmpzIiwibWFwcGluZ3MiOiI7O0FBQXNDOztBQUV0QyxJQUFJLGFBQW9CLEtBQUssZ0RBQVE7QUFDckM7O0FBRUE7QUFDQSxFQUFFLHFCQUF1Qix3REFBd0Qsd0JBQXlCLENBQUMsR0FBRyxRQUE0QixDQUFDO0FBQzNJIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vcHVibGljUGF0aC5qcz8wZTMxIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVOViB9IGZyb20gXCIuLi8uLi9jb25zdGFudHNcIjtcblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBFTlYuVEVTVCkge1xuICAvKiBlc2xpbnQtZGlzYWJsZSAqL1xuXG4gIC8qIGdsb2JhbCBfX3dlYnBhY2tfcHVibGljX3BhdGhfXzp3cml0YWJsZSAqL1xuICBfX3dlYnBhY2tfcHVibGljX3BhdGhfXyA9IHdpbmRvdy5FWENBTElEUkFXX0FTU0VUX1BBVEggfHwgYGh0dHBzOi8vdW5wa2cuY29tLyR7cHJvY2Vzcy5lbnYuVklURV9QS0dfTkFNRX1AJHtwcm9jZXNzLmVudi5WSVRFX1BLR19WRVJTSU9OfS9kaXN0L2A7XG59Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./publicPath.js\n");
4226
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../constants */ \"../../constants.ts\");\n\n\nif (\"development\" !== _constants__WEBPACK_IMPORTED_MODULE_0__.ENV.TEST) {\n /* eslint-disable */\n\n /* global __webpack_public_path__:writable */\n __webpack_require__.p = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${\"@excalidraw/excalidraw\"}@${\"0.16.1\"}/dist/`;\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9wdWJsaWNQYXRoLmpzLmpzIiwibWFwcGluZ3MiOiI7O0FBQXNDOztBQUV0QyxJQUFJLGFBQW9CLEtBQUssZ0RBQVE7QUFDckM7O0FBRUE7QUFDQSxFQUFFLHFCQUF1Qix3REFBd0Qsd0JBQXlCLENBQUMsR0FBRyxRQUE0QixDQUFDO0FBQzNJIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vcHVibGljUGF0aC5qcz8wZTMxIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVOViB9IGZyb20gXCIuLi8uLi9jb25zdGFudHNcIjtcblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBFTlYuVEVTVCkge1xuICAvKiBlc2xpbnQtZGlzYWJsZSAqL1xuXG4gIC8qIGdsb2JhbCBfX3dlYnBhY2tfcHVibGljX3BhdGhfXzp3cml0YWJsZSAqL1xuICBfX3dlYnBhY2tfcHVibGljX3BhdGhfXyA9IHdpbmRvdy5FWENBTElEUkFXX0FTU0VUX1BBVEggfHwgYGh0dHBzOi8vdW5wa2cuY29tLyR7cHJvY2Vzcy5lbnYuVklURV9QS0dfTkFNRX1AJHtwcm9jZXNzLmVudi5WSVRFX1BLR19WRVJTSU9OfS9kaXN0L2A7XG59Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./publicPath.js\n");
4216
4227
 
4217
4228
  /***/ }),
4218
4229
 
@@ -4366,7 +4377,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
4366
4377
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4367
4378
 
4368
4379
  "use strict";
4369
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"SVG_EXPORT_TAG\": () => (/* binding */ SVG_EXPORT_TAG),\n/* harmony export */ \"exportToCanvas\": () => (/* binding */ exportToCanvas),\n/* harmony export */ \"exportToSvg\": () => (/* binding */ exportToSvg),\n/* harmony export */ \"getExportSize\": () => (/* binding */ getExportSize)\n/* harmony export */ });\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var _element_bounds__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element/bounds */ \"../../element/bounds.ts\");\n/* harmony import */ var _renderer_renderScene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../renderer/renderScene */ \"../../renderer/renderScene.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"../../utils.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../appState */ \"../../appState.ts\");\n/* harmony import */ var _data_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../data/json */ \"../../data/json.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../element/image */ \"../../element/image.ts\");\n/* harmony import */ var _Scene__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Scene */ \"../../scene/Scene.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\n\n\n\n\n\n\n\n\n\nconst SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;\nconst exportToCanvas = (elements, appState, files, {\n exportBackground,\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n viewBackgroundColor\n}, createCanvas = (width, height) => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width * appState.exportScale;\n canvas.height = height * appState.exportScale;\n return {\n canvas,\n scale: appState.exportScale\n };\n}) => __awaiter(void 0, void 0, void 0, function* () {\n const [minX, minY, width, height] = getCanvasSize(elements, exportPadding);\n const {\n canvas,\n scale = 1\n } = createCanvas(width, height);\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_5__.getDefaultAppState)();\n const {\n imageCache\n } = yield (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.updateImageCache)({\n imageCache: new Map(),\n fileIds: (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.getInitializedImageElements)(elements).map(element => element.fileId),\n files\n });\n const onlyExportingSingleFrame = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isOnlyExportingSingleFrame)(elements);\n (0,_renderer_renderScene__WEBPACK_IMPORTED_MODULE_2__.renderStaticScene)({\n canvas,\n rc: roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].canvas(canvas),\n elements,\n visibleElements: elements,\n scale,\n appState: Object.assign(Object.assign({}, appState), {\n viewBackgroundColor: exportBackground ? viewBackgroundColor : null,\n scrollX: -minX + (onlyExportingSingleFrame ? 0 : exportPadding),\n scrollY: -minY + (onlyExportingSingleFrame ? 0 : exportPadding),\n zoom: defaultAppState.zoom,\n shouldCacheIgnoreZoom: false,\n theme: appState.exportWithDarkMode ? \"dark\" : \"light\"\n }),\n renderConfig: {\n imageCache,\n renderGrid: false,\n isExporting: true\n }\n });\n return canvas;\n});\nconst exportToSvg = (elements, appState, files, opts) => __awaiter(void 0, void 0, void 0, function* () {\n var _a, _b, _c;\n\n const {\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n viewBackgroundColor,\n exportScale = 1,\n exportEmbedScene\n } = appState;\n let metadata = \"\";\n\n if (exportEmbedScene) {\n try {\n metadata = yield (yield Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ../../src/data/image */ \"../../data/image.ts\"))).encodeSvgMetadata({\n text: (opts === null || opts === void 0 ? void 0 : opts.serializeAsJSON) ? (_a = opts === null || opts === void 0 ? void 0 : opts.serializeAsJSON) === null || _a === void 0 ? void 0 : _a.call(opts) : (0,_data_json__WEBPACK_IMPORTED_MODULE_6__.serializeAsJSON)(elements, appState, files || {}, \"local\")\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n const [minX, minY, width, height] = getCanvasSize(elements, exportPadding); // initialize SVG root\n\n const svgRoot = document.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"svg\");\n svgRoot.setAttribute(\"version\", \"1.1\");\n svgRoot.setAttribute(\"xmlns\", _constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS);\n svgRoot.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svgRoot.setAttribute(\"width\", `${width * exportScale}`);\n svgRoot.setAttribute(\"height\", `${height * exportScale}`);\n\n if (appState.exportWithDarkMode) {\n svgRoot.setAttribute(\"filter\", _constants__WEBPACK_IMPORTED_MODULE_4__.THEME_FILTER);\n }\n\n let assetPath = \"https://excalidraw.com/\"; // Asset path needs to be determined only when using package\n\n if (true) {\n assetPath = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${\"@excalidraw/excalidraw\"}@${({\"VITE_APP_BACKEND_V2_GET_URL\":\"https://json-dev.excalidraw.com/api/v2/\",\"VITE_APP_BACKEND_V2_POST_URL\":\"https://json-dev.excalidraw.com/api/v2/post/\",\"VITE_APP_LIBRARY_URL\":\"https://libraries.excalidraw.com\",\"VITE_APP_LIBRARY_BACKEND\":\"https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries\",\"VITE_APP_WS_SERVER_URL\":\"http://localhost:3002\",\"VITE_APP_PORTAL_URL\":\"\",\"VITE_APP_PLUS_LP\":\"https://plus.excalidraw.com\",\"VITE_APP_PLUS_APP\":\"https://app.excalidraw.com\",\"VITE_APP_FIREBASE_CONFIG\":\"{\\\"apiKey\\\":\\\"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8\\\",\\\"authDomain\\\":\\\"excalidraw-oss-dev.firebaseapp.com\\\",\\\"projectId\\\":\\\"excalidraw-oss-dev\\\",\\\"storageBucket\\\":\\\"excalidraw-oss-dev.appspot.com\\\",\\\"messagingSenderId\\\":\\\"664559512677\\\",\\\"appId\\\":\\\"1:664559512677:web:a385181f2928d328a7aa8c\\\"}\",\"VITE_APP_DEV_ENABLE_SW\":\"\",\"VITE_APP_DEV_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_DISABLE_TRACKING\":\"true\",\"FAST_REFRESH\":\"false\",\"VITE_APP_PORT\":\"3000\",\"VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX\":\"\",\"VITE_APP_COLLAPSE_OVERLAY\":\"true\",\"VITE_APP_ENABLE_ESLINT\":\"true\",\"VITE_PKG_NAME\":\"@excalidraw/excalidraw\",\"VITE_PKG_VERSION\":\"0.16.0\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).PKG_VERSION}`;\n\n if (assetPath === null || assetPath === void 0 ? void 0 : assetPath.startsWith(\"/\")) {\n assetPath = assetPath.replace(\"/\", `${window.location.origin}/`);\n }\n\n assetPath = `${assetPath}/dist/excalidraw-assets/`;\n } // do not apply clipping when we're exporting the whole scene\n\n\n const isExportingWholeCanvas = ((_c = (_b = _Scene__WEBPACK_IMPORTED_MODULE_8__[\"default\"].getScene(elements[0])) === null || _b === void 0 ? void 0 : _b.getNonDeletedElements()) === null || _c === void 0 ? void 0 : _c.length) === elements.length;\n const onlyExportingSingleFrame = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isOnlyExportingSingleFrame)(elements);\n const offsetX = -minX + (onlyExportingSingleFrame ? 0 : exportPadding);\n const offsetY = -minY + (onlyExportingSingleFrame ? 0 : exportPadding);\n const exportingFrame = isExportingWholeCanvas || !onlyExportingSingleFrame ? undefined : elements.find(element => element.type === \"frame\");\n let exportingFrameClipPath = \"\";\n\n if (exportingFrame) {\n const [x1, y1, x2, y2] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getElementAbsoluteCoords)(exportingFrame);\n const cx = (x2 - x1) / 2 - (exportingFrame.x - x1);\n const cy = (y2 - y1) / 2 - (exportingFrame.y - y1);\n exportingFrameClipPath = `<clipPath id=${exportingFrame.id}>\n <rect transform=\"translate(${exportingFrame.x + offsetX} ${exportingFrame.y + offsetY}) rotate(${exportingFrame.angle} ${cx} ${cy})\"\n width=\"${exportingFrame.width}\"\n height=\"${exportingFrame.height}\"\n >\n </rect>\n </clipPath>`;\n }\n\n svgRoot.innerHTML = `\n ${SVG_EXPORT_TAG}\n ${metadata}\n <defs>\n <style class=\"style-fonts\">\n @font-face {\n font-family: \"Virgil\";\n src: url(\"${assetPath}Virgil.woff2\");\n }\n @font-face {\n font-family: \"Cascadia\";\n src: url(\"${assetPath}Cascadia.woff2\");\n }\n </style>\n ${exportingFrameClipPath}\n </defs>\n `; // render background rect\n\n if (appState.exportBackground && viewBackgroundColor) {\n const rect = svgRoot.ownerDocument.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"rect\");\n rect.setAttribute(\"x\", \"0\");\n rect.setAttribute(\"y\", \"0\");\n rect.setAttribute(\"width\", `${width}`);\n rect.setAttribute(\"height\", `${height}`);\n rect.setAttribute(\"fill\", viewBackgroundColor);\n svgRoot.appendChild(rect);\n }\n\n const rsvg = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].svg(svgRoot);\n (0,_renderer_renderScene__WEBPACK_IMPORTED_MODULE_2__.renderSceneToSvg)(elements, rsvg, svgRoot, files || {}, {\n offsetX,\n offsetY,\n exportWithDarkMode: appState.exportWithDarkMode,\n exportingFrameId: (exportingFrame === null || exportingFrame === void 0 ? void 0 : exportingFrame.id) || null,\n renderEmbeddables: opts === null || opts === void 0 ? void 0 : opts.renderEmbeddables\n });\n return svgRoot;\n}); // calculate smallest area to fit the contents in\n\nconst getCanvasSize = (elements, exportPadding) => {\n // we should decide if we are exporting the whole canvas\n // if so, we are not clipping elements in the frame\n // and therefore, we should not do anything special\n var _a, _b;\n\n const isExportingWholeCanvas = ((_b = (_a = _Scene__WEBPACK_IMPORTED_MODULE_8__[\"default\"].getScene(elements[0])) === null || _a === void 0 ? void 0 : _a.getNonDeletedElements()) === null || _b === void 0 ? void 0 : _b.length) === elements.length;\n const onlyExportingSingleFrame = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isOnlyExportingSingleFrame)(elements);\n\n if (!isExportingWholeCanvas || onlyExportingSingleFrame) {\n const frames = elements.filter(element => element.type === \"frame\");\n const exportedFrameIds = frames.reduce((acc, frame) => {\n acc[frame.id] = true;\n return acc;\n }, {}); // elements in a frame do not affect the canvas size if we're not exporting\n // the whole canvas\n\n elements = elements.filter(element => {\n var _a;\n\n return !exportedFrameIds[(_a = element.frameId) !== null && _a !== void 0 ? _a : \"\"];\n });\n }\n\n const [minX, minY, maxX, maxY] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getCommonBounds)(elements);\n const width = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minX, maxX) + (onlyExportingSingleFrame ? 0 : exportPadding * 2);\n const height = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minY, maxY) + (onlyExportingSingleFrame ? 0 : exportPadding * 2);\n return [minX, minY, width, height];\n};\n\nconst getExportSize = (elements, exportPadding, scale) => {\n const [,, width, height] = getCanvasSize(elements, exportPadding).map(dimension => Math.trunc(dimension * scale));\n return [width, height];\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUNBLEtBQUssSUFBSSxHQUFHO0FBQ1o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxtQ0FBbUMsZ0VBQWU7QUFDbEQsZ0JBQWdCLGdEQUFRO0FBQ3hCLGlCQUFpQixnREFBUTtBQUN6QjtBQUNBOztBQUVPO0FBQ1A7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL3NjZW5lL2V4cG9ydC50cz8zZjRlIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2F3YWl0ZXIgPSB0aGlzICYmIHRoaXMuX19hd2FpdGVyIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7XG4gICAgICB0cnkge1xuICAgICAgICBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkge1xuICAgICAgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7XG4gICAgfVxuXG4gICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICB9KTtcbn07XG5cbmltcG9ydCByb3VnaCBmcm9tIFwicm91Z2hqcy9iaW4vcm91Z2hcIjtcbmltcG9ydCB7IGdldENvbW1vbkJvdW5kcywgZ2V0RWxlbWVudEFic29sdXRlQ29vcmRzIH0gZnJvbSBcIi4uL2VsZW1lbnQvYm91bmRzXCI7XG5pbXBvcnQgeyByZW5kZXJTY2VuZVRvU3ZnLCByZW5kZXJTdGF0aWNTY2VuZSB9IGZyb20gXCIuLi9yZW5kZXJlci9yZW5kZXJTY2VuZVwiO1xuaW1wb3J0IHsgZGlzdGFuY2UsIGlzT25seUV4cG9ydGluZ1NpbmdsZUZyYW1lIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VYUE9SVF9QQURESU5HLCBTVkdfTlMsIFRIRU1FX0ZJTFRFUiB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IGdldERlZmF1bHRBcHBTdGF0ZSB9IGZyb20gXCIuLi9hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgc2VyaWFsaXplQXNKU09OIH0gZnJvbSBcIi4uL2RhdGEvanNvblwiO1xuaW1wb3J0IHsgZ2V0SW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnRzLCB1cGRhdGVJbWFnZUNhY2hlIH0gZnJvbSBcIi4uL2VsZW1lbnQvaW1hZ2VcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi9TY2VuZVwiO1xuZXhwb3J0IGNvbnN0IFNWR19FWFBPUlRfVEFHID0gYDwhLS0gc3ZnLXNvdXJjZTpleGNhbGlkcmF3IC0tPmA7XG5leHBvcnQgY29uc3QgZXhwb3J0VG9DYW52YXMgPSAoZWxlbWVudHMsIGFwcFN0YXRlLCBmaWxlcywge1xuICBleHBvcnRCYWNrZ3JvdW5kLFxuICBleHBvcnRQYWRkaW5nID0gREVGQVVMVF9FWFBPUlRfUEFERElORyxcbiAgdmlld0JhY2tncm91bmRDb2xvclxufSwgY3JlYXRlQ2FudmFzID0gKHdpZHRoLCBoZWlnaHQpID0+IHtcbiAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgY2FudmFzLndpZHRoID0gd2lkdGggKiBhcHBTdGF0ZS5leHBvcnRTY2FsZTtcbiAgY2FudmFzLmhlaWdodCA9IGhlaWdodCAqIGFwcFN0YXRlLmV4cG9ydFNjYWxlO1xuICByZXR1cm4ge1xuICAgIGNhbnZhcyxcbiAgICBzY2FsZTogYXBwU3RhdGUuZXhwb3J0U2NhbGVcbiAgfTtcbn0pID0+IF9fYXdhaXRlcih2b2lkIDAsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICBjb25zdCBbbWluWCwgbWluWSwgd2lkdGgsIGhlaWdodF0gPSBnZXRDYW52YXNTaXplKGVsZW1lbnRzLCBleHBvcnRQYWRkaW5nKTtcbiAgY29uc3Qge1xuICAgIGNhbnZhcyxcbiAgICBzY2FsZSA9IDFcbiAgfSA9IGNyZWF0ZUNhbnZhcyh3aWR0aCwgaGVpZ2h0KTtcbiAgY29uc3QgZGVmYXVsdEFwcFN0YXRlID0gZ2V0RGVmYXVsdEFwcFN0YXRlKCk7XG4gIGNvbnN0IHtcbiAgICBpbWFnZUNhY2hlXG4gIH0gPSB5aWVsZCB1cGRhdGVJbWFnZUNhY2hlKHtcbiAgICBpbWFnZUNhY2hlOiBuZXcgTWFwKCksXG4gICAgZmlsZUlkczogZ2V0SW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnRzKGVsZW1lbnRzKS5tYXAoZWxlbWVudCA9PiBlbGVtZW50LmZpbGVJZCksXG4gICAgZmlsZXNcbiAgfSk7XG4gIGNvbnN0IG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA9IGlzT25seUV4cG9ydGluZ1NpbmdsZUZyYW1lKGVsZW1lbnRzKTtcbiAgcmVuZGVyU3RhdGljU2NlbmUoe1xuICAgIGNhbnZhcyxcbiAgICByYzogcm91Z2guY2FudmFzKGNhbnZhcyksXG4gICAgZWxlbWVudHMsXG4gICAgdmlzaWJsZUVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICBzY2FsZSxcbiAgICBhcHBTdGF0ZTogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBhcHBTdGF0ZSksIHtcbiAgICAgIHZpZXdCYWNrZ3JvdW5kQ29sb3I6IGV4cG9ydEJhY2tncm91bmQgPyB2aWV3QmFja2dyb3VuZENvbG9yIDogbnVsbCxcbiAgICAgIHNjcm9sbFg6IC1taW5YICsgKG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA/IDAgOiBleHBvcnRQYWRkaW5nKSxcbiAgICAgIHNjcm9sbFk6IC1taW5ZICsgKG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA/IDAgOiBleHBvcnRQYWRkaW5nKSxcbiAgICAgIHpvb206IGRlZmF1bHRBcHBTdGF0ZS56b29tLFxuICAgICAgc2hvdWxkQ2FjaGVJZ25vcmVab29tOiBmYWxzZSxcbiAgICAgIHRoZW1lOiBhcHBTdGF0ZS5leHBvcnRXaXRoRGFya01vZGUgPyBcImRhcmtcIiA6IFwibGlnaHRcIlxuICAgIH0pLFxuICAgIHJlbmRlckNvbmZpZzoge1xuICAgICAgaW1hZ2VDYWNoZSxcbiAgICAgIHJlbmRlckdyaWQ6IGZhbHNlLFxuICAgICAgaXNFeHBvcnRpbmc6IHRydWVcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gY2FudmFzO1xufSk7XG5leHBvcnQgY29uc3QgZXhwb3J0VG9TdmcgPSAoZWxlbWVudHMsIGFwcFN0YXRlLCBmaWxlcywgb3B0cykgPT4gX19hd2FpdGVyKHZvaWQgMCwgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gIHZhciBfYSwgX2IsIF9jO1xuXG4gIGNvbnN0IHtcbiAgICBleHBvcnRQYWRkaW5nID0gREVGQVVMVF9FWFBPUlRfUEFERElORyxcbiAgICB2aWV3QmFja2dyb3VuZENvbG9yLFxuICAgIGV4cG9ydFNjYWxlID0gMSxcbiAgICBleHBvcnRFbWJlZFNjZW5lXG4gIH0gPSBhcHBTdGF0ZTtcbiAgbGV0IG1ldGFkYXRhID0gXCJcIjtcblxuICBpZiAoZXhwb3J0RW1iZWRTY2VuZSkge1xuICAgIHRyeSB7XG4gICAgICBtZXRhZGF0YSA9IHlpZWxkICh5aWVsZCBpbXBvcnQoXG4gICAgICAvKiB3ZWJwYWNrQ2h1bmtOYW1lOiBcImltYWdlXCIgKi9cbiAgICAgIFwiLi4vLi4vc3JjL2RhdGEvaW1hZ2VcIikpLmVuY29kZVN2Z01ldGFkYXRhKHtcbiAgICAgICAgdGV4dDogKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5zZXJpYWxpemVBc0pTT04pID8gKF9hID0gb3B0cyA9PT0gbnVsbCB8fCBvcHRzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRzLnNlcmlhbGl6ZUFzSlNPTikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNhbGwob3B0cykgOiBzZXJpYWxpemVBc0pTT04oZWxlbWVudHMsIGFwcFN0YXRlLCBmaWxlcyB8fCB7fSwgXCJsb2NhbFwiKVxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IFttaW5YLCBtaW5ZLCB3aWR0aCwgaGVpZ2h0XSA9IGdldENhbnZhc1NpemUoZWxlbWVudHMsIGV4cG9ydFBhZGRpbmcpOyAvLyBpbml0aWFsaXplIFNWRyByb290XG5cbiAgY29uc3Qgc3ZnUm9vdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdfTlMsIFwic3ZnXCIpO1xuICBzdmdSb290LnNldEF0dHJpYnV0ZShcInZlcnNpb25cIiwgXCIxLjFcIik7XG4gIHN2Z1Jvb3Quc2V0QXR0cmlidXRlKFwieG1sbnNcIiwgU1ZHX05TKTtcbiAgc3ZnUm9vdC5zZXRBdHRyaWJ1dGUoXCJ2aWV3Qm94XCIsIGAwIDAgJHt3aWR0aH0gJHtoZWlnaHR9YCk7XG4gIHN2Z1Jvb3Quc2V0QXR0cmlidXRlKFwid2lkdGhcIiwgYCR7d2lkdGggKiBleHBvcnRTY2FsZX1gKTtcbiAgc3ZnUm9vdC5zZXRBdHRyaWJ1dGUoXCJoZWlnaHRcIiwgYCR7aGVpZ2h0ICogZXhwb3J0U2NhbGV9YCk7XG5cbiAgaWYgKGFwcFN0YXRlLmV4cG9ydFdpdGhEYXJrTW9kZSkge1xuICAgIHN2Z1Jvb3Quc2V0QXR0cmlidXRlKFwiZmlsdGVyXCIsIFRIRU1FX0ZJTFRFUik7XG4gIH1cblxuICBsZXQgYXNzZXRQYXRoID0gXCJodHRwczovL2V4Y2FsaWRyYXcuY29tL1wiOyAvLyBBc3NldCBwYXRoIG5lZWRzIHRvIGJlIGRldGVybWluZWQgb25seSB3aGVuIHVzaW5nIHBhY2thZ2VcblxuICBpZiAocHJvY2Vzcy5lbnYuVklURV9JU19FWENBTElEUkFXX05QTV9QQUNLQUdFKSB7XG4gICAgYXNzZXRQYXRoID0gd2luZG93LkVYQ0FMSURSQVdfQVNTRVRfUEFUSCB8fCBgaHR0cHM6Ly91bnBrZy5jb20vJHtwcm9jZXNzLmVudi5WSVRFX1BLR19OQU1FfUAke3Byb2Nlc3MuZW52LlBLR19WRVJTSU9OfWA7XG5cbiAgICBpZiAoYXNzZXRQYXRoID09PSBudWxsIHx8IGFzc2V0UGF0aCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYXNzZXRQYXRoLnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG4gICAgICBhc3NldFBhdGggPSBhc3NldFBhdGgucmVwbGFjZShcIi9cIiwgYCR7d2luZG93LmxvY2F0aW9uLm9yaWdpbn0vYCk7XG4gICAgfVxuXG4gICAgYXNzZXRQYXRoID0gYCR7YXNzZXRQYXRofS9kaXN0L2V4Y2FsaWRyYXctYXNzZXRzL2A7XG4gIH0gLy8gZG8gbm90IGFwcGx5IGNsaXBwaW5nIHdoZW4gd2UncmUgZXhwb3J0aW5nIHRoZSB3aG9sZSBzY2VuZVxuXG5cbiAgY29uc3QgaXNFeHBvcnRpbmdXaG9sZUNhbnZhcyA9ICgoX2MgPSAoX2IgPSBTY2VuZS5nZXRTY2VuZShlbGVtZW50c1swXSkpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5nZXROb25EZWxldGVkRWxlbWVudHMoKSkgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLmxlbmd0aCkgPT09IGVsZW1lbnRzLmxlbmd0aDtcbiAgY29uc3Qgb25seUV4cG9ydGluZ1NpbmdsZUZyYW1lID0gaXNPbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUoZWxlbWVudHMpO1xuICBjb25zdCBvZmZzZXRYID0gLW1pblggKyAob25seUV4cG9ydGluZ1NpbmdsZUZyYW1lID8gMCA6IGV4cG9ydFBhZGRpbmcpO1xuICBjb25zdCBvZmZzZXRZID0gLW1pblkgKyAob25seUV4cG9ydGluZ1NpbmdsZUZyYW1lID8gMCA6IGV4cG9ydFBhZGRpbmcpO1xuICBjb25zdCBleHBvcnRpbmdGcmFtZSA9IGlzRXhwb3J0aW5nV2hvbGVDYW52YXMgfHwgIW9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA/IHVuZGVmaW5lZCA6IGVsZW1lbnRzLmZpbmQoZWxlbWVudCA9PiBlbGVtZW50LnR5cGUgPT09IFwiZnJhbWVcIik7XG4gIGxldCBleHBvcnRpbmdGcmFtZUNsaXBQYXRoID0gXCJcIjtcblxuICBpZiAoZXhwb3J0aW5nRnJhbWUpIHtcbiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gZ2V0RWxlbWVudEFic29sdXRlQ29vcmRzKGV4cG9ydGluZ0ZyYW1lKTtcbiAgICBjb25zdCBjeCA9ICh4MiAtIHgxKSAvIDIgLSAoZXhwb3J0aW5nRnJhbWUueCAtIHgxKTtcbiAgICBjb25zdCBjeSA9ICh5MiAtIHkxKSAvIDIgLSAoZXhwb3J0aW5nRnJhbWUueSAtIHkxKTtcbiAgICBleHBvcnRpbmdGcmFtZUNsaXBQYXRoID0gYDxjbGlwUGF0aCBpZD0ke2V4cG9ydGluZ0ZyYW1lLmlkfT5cbiAgICAgICAgICAgIDxyZWN0IHRyYW5zZm9ybT1cInRyYW5zbGF0ZSgke2V4cG9ydGluZ0ZyYW1lLnggKyBvZmZzZXRYfSAke2V4cG9ydGluZ0ZyYW1lLnkgKyBvZmZzZXRZfSkgcm90YXRlKCR7ZXhwb3J0aW5nRnJhbWUuYW5nbGV9ICR7Y3h9ICR7Y3l9KVwiXG4gICAgICAgICAgd2lkdGg9XCIke2V4cG9ydGluZ0ZyYW1lLndpZHRofVwiXG4gICAgICAgICAgaGVpZ2h0PVwiJHtleHBvcnRpbmdGcmFtZS5oZWlnaHR9XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9yZWN0PlxuICAgICAgICA8L2NsaXBQYXRoPmA7XG4gIH1cblxuICBzdmdSb290LmlubmVySFRNTCA9IGBcbiAgJHtTVkdfRVhQT1JUX1RBR31cbiAgJHttZXRhZGF0YX1cbiAgPGRlZnM+XG4gICAgPHN0eWxlIGNsYXNzPVwic3R5bGUtZm9udHNcIj5cbiAgICAgIEBmb250LWZhY2Uge1xuICAgICAgICBmb250LWZhbWlseTogXCJWaXJnaWxcIjtcbiAgICAgICAgc3JjOiB1cmwoXCIke2Fzc2V0UGF0aH1WaXJnaWwud29mZjJcIik7XG4gICAgICB9XG4gICAgICBAZm9udC1mYWNlIHtcbiAgICAgICAgZm9udC1mYW1pbHk6IFwiQ2FzY2FkaWFcIjtcbiAgICAgICAgc3JjOiB1cmwoXCIke2Fzc2V0UGF0aH1DYXNjYWRpYS53b2ZmMlwiKTtcbiAgICAgIH1cbiAgICA8L3N0eWxlPlxuICAgICR7ZXhwb3J0aW5nRnJhbWVDbGlwUGF0aH1cbiAgPC9kZWZzPlxuICBgOyAvLyByZW5kZXIgYmFja2dyb3VuZCByZWN0XG5cbiAgaWYgKGFwcFN0YXRlLmV4cG9ydEJhY2tncm91bmQgJiYgdmlld0JhY2tncm91bmRDb2xvcikge1xuICAgIGNvbnN0IHJlY3QgPSBzdmdSb290Lm93bmVyRG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFNWR19OUywgXCJyZWN0XCIpO1xuICAgIHJlY3Quc2V0QXR0cmlidXRlKFwieFwiLCBcIjBcIik7XG4gICAgcmVjdC5zZXRBdHRyaWJ1dGUoXCJ5XCIsIFwiMFwiKTtcbiAgICByZWN0LnNldEF0dHJpYnV0ZShcIndpZHRoXCIsIGAke3dpZHRofWApO1xuICAgIHJlY3Quc2V0QXR0cmlidXRlKFwiaGVpZ2h0XCIsIGAke2hlaWdodH1gKTtcbiAgICByZWN0LnNldEF0dHJpYnV0ZShcImZpbGxcIiwgdmlld0JhY2tncm91bmRDb2xvcik7XG4gICAgc3ZnUm9vdC5hcHBlbmRDaGlsZChyZWN0KTtcbiAgfVxuXG4gIGNvbnN0IHJzdmcgPSByb3VnaC5zdmcoc3ZnUm9vdCk7XG4gIHJlbmRlclNjZW5lVG9TdmcoZWxlbWVudHMsIHJzdmcsIHN2Z1Jvb3QsIGZpbGVzIHx8IHt9LCB7XG4gICAgb2Zmc2V0WCxcbiAgICBvZmZzZXRZLFxuICAgIGV4cG9ydFdpdGhEYXJrTW9kZTogYXBwU3RhdGUuZXhwb3J0V2l0aERhcmtNb2RlLFxuICAgIGV4cG9ydGluZ0ZyYW1lSWQ6IChleHBvcnRpbmdGcmFtZSA9PT0gbnVsbCB8fCBleHBvcnRpbmdGcmFtZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogZXhwb3J0aW5nRnJhbWUuaWQpIHx8IG51bGwsXG4gICAgcmVuZGVyRW1iZWRkYWJsZXM6IG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5yZW5kZXJFbWJlZGRhYmxlc1xuICB9KTtcbiAgcmV0dXJuIHN2Z1Jvb3Q7XG59KTsgLy8gY2FsY3VsYXRlIHNtYWxsZXN0IGFyZWEgdG8gZml0IHRoZSBjb250ZW50cyBpblxuXG5jb25zdCBnZXRDYW52YXNTaXplID0gKGVsZW1lbnRzLCBleHBvcnRQYWRkaW5nKSA9PiB7XG4gIC8vIHdlIHNob3VsZCBkZWNpZGUgaWYgd2UgYXJlIGV4cG9ydGluZyB0aGUgd2hvbGUgY2FudmFzXG4gIC8vIGlmIHNvLCB3ZSBhcmUgbm90IGNsaXBwaW5nIGVsZW1lbnRzIGluIHRoZSBmcmFtZVxuICAvLyBhbmQgdGhlcmVmb3JlLCB3ZSBzaG91bGQgbm90IGRvIGFueXRoaW5nIHNwZWNpYWxcbiAgdmFyIF9hLCBfYjtcblxuICBjb25zdCBpc0V4cG9ydGluZ1dob2xlQ2FudmFzID0gKChfYiA9IChfYSA9IFNjZW5lLmdldFNjZW5lKGVsZW1lbnRzWzBdKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IubGVuZ3RoKSA9PT0gZWxlbWVudHMubGVuZ3RoO1xuICBjb25zdCBvbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUgPSBpc09ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZShlbGVtZW50cyk7XG5cbiAgaWYgKCFpc0V4cG9ydGluZ1dob2xlQ2FudmFzIHx8IG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSkge1xuICAgIGNvbnN0IGZyYW1lcyA9IGVsZW1lbnRzLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQudHlwZSA9PT0gXCJmcmFtZVwiKTtcbiAgICBjb25zdCBleHBvcnRlZEZyYW1lSWRzID0gZnJhbWVzLnJlZHVjZSgoYWNjLCBmcmFtZSkgPT4ge1xuICAgICAgYWNjW2ZyYW1lLmlkXSA9IHRydWU7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIHt9KTsgLy8gZWxlbWVudHMgaW4gYSBmcmFtZSBkbyBub3QgYWZmZWN0IHRoZSBjYW52YXMgc2l6ZSBpZiB3ZSdyZSBub3QgZXhwb3J0aW5nXG4gICAgLy8gdGhlIHdob2xlIGNhbnZhc1xuXG4gICAgZWxlbWVudHMgPSBlbGVtZW50cy5maWx0ZXIoZWxlbWVudCA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIHJldHVybiAhZXhwb3J0ZWRGcmFtZUlkc1soX2EgPSBlbGVtZW50LmZyYW1lSWQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IFwiXCJdO1xuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgW21pblgsIG1pblksIG1heFgsIG1heFldID0gZ2V0Q29tbW9uQm91bmRzKGVsZW1lbnRzKTtcbiAgY29uc3Qgd2lkdGggPSBkaXN0YW5jZShtaW5YLCBtYXhYKSArIChvbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUgPyAwIDogZXhwb3J0UGFkZGluZyAqIDIpO1xuICBjb25zdCBoZWlnaHQgPSBkaXN0YW5jZShtaW5ZLCBtYXhZKSArIChvbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUgPyAwIDogZXhwb3J0UGFkZGluZyAqIDIpO1xuICByZXR1cm4gW21pblgsIG1pblksIHdpZHRoLCBoZWlnaHRdO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEV4cG9ydFNpemUgPSAoZWxlbWVudHMsIGV4cG9ydFBhZGRpbmcsIHNjYWxlKSA9PiB7XG4gIGNvbnN0IFssLCB3aWR0aCwgaGVpZ2h0XSA9IGdldENhbnZhc1NpemUoZWxlbWVudHMsIGV4cG9ydFBhZGRpbmcpLm1hcChkaW1lbnNpb24gPT4gTWF0aC50cnVuYyhkaW1lbnNpb24gKiBzY2FsZSkpO1xuICByZXR1cm4gW3dpZHRoLCBoZWlnaHRdO1xufTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../../scene/export.ts\n");
4380
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"SVG_EXPORT_TAG\": () => (/* binding */ SVG_EXPORT_TAG),\n/* harmony export */ \"exportToCanvas\": () => (/* binding */ exportToCanvas),\n/* harmony export */ \"exportToSvg\": () => (/* binding */ exportToSvg),\n/* harmony export */ \"getExportSize\": () => (/* binding */ getExportSize)\n/* harmony export */ });\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var _element_bounds__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element/bounds */ \"../../element/bounds.ts\");\n/* harmony import */ var _renderer_renderScene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../renderer/renderScene */ \"../../renderer/renderScene.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"../../utils.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"../../constants.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../appState */ \"../../appState.ts\");\n/* harmony import */ var _data_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../data/json */ \"../../data/json.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../element/image */ \"../../element/image.ts\");\n/* harmony import */ var _Scene__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Scene */ \"../../scene/Scene.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\n\n\n\n\n\n\n\n\n\nconst SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;\nconst exportToCanvas = (elements, appState, files, {\n exportBackground,\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n viewBackgroundColor\n}, createCanvas = (width, height) => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width * appState.exportScale;\n canvas.height = height * appState.exportScale;\n return {\n canvas,\n scale: appState.exportScale\n };\n}) => __awaiter(void 0, void 0, void 0, function* () {\n const [minX, minY, width, height] = getCanvasSize(elements, exportPadding);\n const {\n canvas,\n scale = 1\n } = createCanvas(width, height);\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_5__.getDefaultAppState)();\n const {\n imageCache\n } = yield (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.updateImageCache)({\n imageCache: new Map(),\n fileIds: (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.getInitializedImageElements)(elements).map(element => element.fileId),\n files\n });\n const onlyExportingSingleFrame = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isOnlyExportingSingleFrame)(elements);\n (0,_renderer_renderScene__WEBPACK_IMPORTED_MODULE_2__.renderStaticScene)({\n canvas,\n rc: roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].canvas(canvas),\n elements,\n visibleElements: elements,\n scale,\n appState: Object.assign(Object.assign({}, appState), {\n viewBackgroundColor: exportBackground ? viewBackgroundColor : null,\n scrollX: -minX + (onlyExportingSingleFrame ? 0 : exportPadding),\n scrollY: -minY + (onlyExportingSingleFrame ? 0 : exportPadding),\n zoom: defaultAppState.zoom,\n shouldCacheIgnoreZoom: false,\n theme: appState.exportWithDarkMode ? \"dark\" : \"light\"\n }),\n renderConfig: {\n imageCache,\n renderGrid: false,\n isExporting: true\n }\n });\n return canvas;\n});\nconst exportToSvg = (elements, appState, files, opts) => __awaiter(void 0, void 0, void 0, function* () {\n var _a, _b, _c;\n\n const {\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n viewBackgroundColor,\n exportScale = 1,\n exportEmbedScene\n } = appState;\n let metadata = \"\";\n\n if (exportEmbedScene) {\n try {\n metadata = yield (yield Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ../../src/data/image */ \"../../data/image.ts\"))).encodeSvgMetadata({\n text: (opts === null || opts === void 0 ? void 0 : opts.serializeAsJSON) ? (_a = opts === null || opts === void 0 ? void 0 : opts.serializeAsJSON) === null || _a === void 0 ? void 0 : _a.call(opts) : (0,_data_json__WEBPACK_IMPORTED_MODULE_6__.serializeAsJSON)(elements, appState, files || {}, \"local\")\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n const [minX, minY, width, height] = getCanvasSize(elements, exportPadding); // initialize SVG root\n\n const svgRoot = document.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"svg\");\n svgRoot.setAttribute(\"version\", \"1.1\");\n svgRoot.setAttribute(\"xmlns\", _constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS);\n svgRoot.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svgRoot.setAttribute(\"width\", `${width * exportScale}`);\n svgRoot.setAttribute(\"height\", `${height * exportScale}`);\n\n if (appState.exportWithDarkMode) {\n svgRoot.setAttribute(\"filter\", _constants__WEBPACK_IMPORTED_MODULE_4__.THEME_FILTER);\n }\n\n let assetPath = \"https://excalidraw.com/\"; // Asset path needs to be determined only when using package\n\n if (true) {\n assetPath = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${\"@excalidraw/excalidraw\"}@${({\"VITE_APP_BACKEND_V2_GET_URL\":\"https://json-dev.excalidraw.com/api/v2/\",\"VITE_APP_BACKEND_V2_POST_URL\":\"https://json-dev.excalidraw.com/api/v2/post/\",\"VITE_APP_LIBRARY_URL\":\"https://libraries.excalidraw.com\",\"VITE_APP_LIBRARY_BACKEND\":\"https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries\",\"VITE_APP_WS_SERVER_URL\":\"http://localhost:3002\",\"VITE_APP_PORTAL_URL\":\"\",\"VITE_APP_PLUS_LP\":\"https://plus.excalidraw.com\",\"VITE_APP_PLUS_APP\":\"https://app.excalidraw.com\",\"VITE_APP_FIREBASE_CONFIG\":\"{\\\"apiKey\\\":\\\"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8\\\",\\\"authDomain\\\":\\\"excalidraw-oss-dev.firebaseapp.com\\\",\\\"projectId\\\":\\\"excalidraw-oss-dev\\\",\\\"storageBucket\\\":\\\"excalidraw-oss-dev.appspot.com\\\",\\\"messagingSenderId\\\":\\\"664559512677\\\",\\\"appId\\\":\\\"1:664559512677:web:a385181f2928d328a7aa8c\\\"}\",\"VITE_APP_DEV_ENABLE_SW\":\"\",\"VITE_APP_DEV_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_DISABLE_TRACKING\":\"true\",\"FAST_REFRESH\":\"false\",\"VITE_APP_PORT\":\"3000\",\"VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX\":\"\",\"VITE_APP_COLLAPSE_OVERLAY\":\"true\",\"VITE_APP_ENABLE_ESLINT\":\"true\",\"VITE_PKG_NAME\":\"@excalidraw/excalidraw\",\"VITE_PKG_VERSION\":\"0.16.1\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).PKG_VERSION}`;\n\n if (assetPath === null || assetPath === void 0 ? void 0 : assetPath.startsWith(\"/\")) {\n assetPath = assetPath.replace(\"/\", `${window.location.origin}/`);\n }\n\n assetPath = `${assetPath}/dist/excalidraw-assets/`;\n } // do not apply clipping when we're exporting the whole scene\n\n\n const isExportingWholeCanvas = ((_c = (_b = _Scene__WEBPACK_IMPORTED_MODULE_8__[\"default\"].getScene(elements[0])) === null || _b === void 0 ? void 0 : _b.getNonDeletedElements()) === null || _c === void 0 ? void 0 : _c.length) === elements.length;\n const onlyExportingSingleFrame = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isOnlyExportingSingleFrame)(elements);\n const offsetX = -minX + (onlyExportingSingleFrame ? 0 : exportPadding);\n const offsetY = -minY + (onlyExportingSingleFrame ? 0 : exportPadding);\n const exportingFrame = isExportingWholeCanvas || !onlyExportingSingleFrame ? undefined : elements.find(element => element.type === \"frame\");\n let exportingFrameClipPath = \"\";\n\n if (exportingFrame) {\n const [x1, y1, x2, y2] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getElementAbsoluteCoords)(exportingFrame);\n const cx = (x2 - x1) / 2 - (exportingFrame.x - x1);\n const cy = (y2 - y1) / 2 - (exportingFrame.y - y1);\n exportingFrameClipPath = `<clipPath id=${exportingFrame.id}>\n <rect transform=\"translate(${exportingFrame.x + offsetX} ${exportingFrame.y + offsetY}) rotate(${exportingFrame.angle} ${cx} ${cy})\"\n width=\"${exportingFrame.width}\"\n height=\"${exportingFrame.height}\"\n >\n </rect>\n </clipPath>`;\n }\n\n svgRoot.innerHTML = `\n ${SVG_EXPORT_TAG}\n ${metadata}\n <defs>\n <style class=\"style-fonts\">\n @font-face {\n font-family: \"Virgil\";\n src: url(\"${assetPath}Virgil.woff2\");\n }\n @font-face {\n font-family: \"Cascadia\";\n src: url(\"${assetPath}Cascadia.woff2\");\n }\n </style>\n ${exportingFrameClipPath}\n </defs>\n `; // render background rect\n\n if (appState.exportBackground && viewBackgroundColor) {\n const rect = svgRoot.ownerDocument.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"rect\");\n rect.setAttribute(\"x\", \"0\");\n rect.setAttribute(\"y\", \"0\");\n rect.setAttribute(\"width\", `${width}`);\n rect.setAttribute(\"height\", `${height}`);\n rect.setAttribute(\"fill\", viewBackgroundColor);\n svgRoot.appendChild(rect);\n }\n\n const rsvg = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].svg(svgRoot);\n (0,_renderer_renderScene__WEBPACK_IMPORTED_MODULE_2__.renderSceneToSvg)(elements, rsvg, svgRoot, files || {}, {\n offsetX,\n offsetY,\n exportWithDarkMode: appState.exportWithDarkMode,\n exportingFrameId: (exportingFrame === null || exportingFrame === void 0 ? void 0 : exportingFrame.id) || null,\n renderEmbeddables: opts === null || opts === void 0 ? void 0 : opts.renderEmbeddables\n });\n return svgRoot;\n}); // calculate smallest area to fit the contents in\n\nconst getCanvasSize = (elements, exportPadding) => {\n // we should decide if we are exporting the whole canvas\n // if so, we are not clipping elements in the frame\n // and therefore, we should not do anything special\n var _a, _b;\n\n const isExportingWholeCanvas = ((_b = (_a = _Scene__WEBPACK_IMPORTED_MODULE_8__[\"default\"].getScene(elements[0])) === null || _a === void 0 ? void 0 : _a.getNonDeletedElements()) === null || _b === void 0 ? void 0 : _b.length) === elements.length;\n const onlyExportingSingleFrame = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.isOnlyExportingSingleFrame)(elements);\n\n if (!isExportingWholeCanvas || onlyExportingSingleFrame) {\n const frames = elements.filter(element => element.type === \"frame\");\n const exportedFrameIds = frames.reduce((acc, frame) => {\n acc[frame.id] = true;\n return acc;\n }, {}); // elements in a frame do not affect the canvas size if we're not exporting\n // the whole canvas\n\n elements = elements.filter(element => {\n var _a;\n\n return !exportedFrameIds[(_a = element.frameId) !== null && _a !== void 0 ? _a : \"\"];\n });\n }\n\n const [minX, minY, maxX, maxY] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getCommonBounds)(elements);\n const width = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minX, maxX) + (onlyExportingSingleFrame ? 0 : exportPadding * 2);\n const height = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minY, maxY) + (onlyExportingSingleFrame ? 0 : exportPadding * 2);\n return [minX, minY, width, height];\n};\n\nconst getExportSize = (elements, exportPadding, scale) => {\n const [,, width, height] = getCanvasSize(elements, exportPadding).map(dimension => Math.trunc(dimension * scale));\n return [width, height];\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUNBLEtBQUssSUFBSSxHQUFHO0FBQ1o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxtQ0FBbUMsZ0VBQWU7QUFDbEQsZ0JBQWdCLGdEQUFRO0FBQ3hCLGlCQUFpQixnREFBUTtBQUN6QjtBQUNBOztBQUVPO0FBQ1A7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4uLy4uL3NjZW5lL2V4cG9ydC50cz8zZjRlIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBfX2F3YWl0ZXIgPSB0aGlzICYmIHRoaXMuX19hd2FpdGVyIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7XG4gICAgICB0cnkge1xuICAgICAgICBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkge1xuICAgICAgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7XG4gICAgfVxuXG4gICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICB9KTtcbn07XG5cbmltcG9ydCByb3VnaCBmcm9tIFwicm91Z2hqcy9iaW4vcm91Z2hcIjtcbmltcG9ydCB7IGdldENvbW1vbkJvdW5kcywgZ2V0RWxlbWVudEFic29sdXRlQ29vcmRzIH0gZnJvbSBcIi4uL2VsZW1lbnQvYm91bmRzXCI7XG5pbXBvcnQgeyByZW5kZXJTY2VuZVRvU3ZnLCByZW5kZXJTdGF0aWNTY2VuZSB9IGZyb20gXCIuLi9yZW5kZXJlci9yZW5kZXJTY2VuZVwiO1xuaW1wb3J0IHsgZGlzdGFuY2UsIGlzT25seUV4cG9ydGluZ1NpbmdsZUZyYW1lIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VYUE9SVF9QQURESU5HLCBTVkdfTlMsIFRIRU1FX0ZJTFRFUiB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IGdldERlZmF1bHRBcHBTdGF0ZSB9IGZyb20gXCIuLi9hcHBTdGF0ZVwiO1xuaW1wb3J0IHsgc2VyaWFsaXplQXNKU09OIH0gZnJvbSBcIi4uL2RhdGEvanNvblwiO1xuaW1wb3J0IHsgZ2V0SW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnRzLCB1cGRhdGVJbWFnZUNhY2hlIH0gZnJvbSBcIi4uL2VsZW1lbnQvaW1hZ2VcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi9TY2VuZVwiO1xuZXhwb3J0IGNvbnN0IFNWR19FWFBPUlRfVEFHID0gYDwhLS0gc3ZnLXNvdXJjZTpleGNhbGlkcmF3IC0tPmA7XG5leHBvcnQgY29uc3QgZXhwb3J0VG9DYW52YXMgPSAoZWxlbWVudHMsIGFwcFN0YXRlLCBmaWxlcywge1xuICBleHBvcnRCYWNrZ3JvdW5kLFxuICBleHBvcnRQYWRkaW5nID0gREVGQVVMVF9FWFBPUlRfUEFERElORyxcbiAgdmlld0JhY2tncm91bmRDb2xvclxufSwgY3JlYXRlQ2FudmFzID0gKHdpZHRoLCBoZWlnaHQpID0+IHtcbiAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgY2FudmFzLndpZHRoID0gd2lkdGggKiBhcHBTdGF0ZS5leHBvcnRTY2FsZTtcbiAgY2FudmFzLmhlaWdodCA9IGhlaWdodCAqIGFwcFN0YXRlLmV4cG9ydFNjYWxlO1xuICByZXR1cm4ge1xuICAgIGNhbnZhcyxcbiAgICBzY2FsZTogYXBwU3RhdGUuZXhwb3J0U2NhbGVcbiAgfTtcbn0pID0+IF9fYXdhaXRlcih2b2lkIDAsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkge1xuICBjb25zdCBbbWluWCwgbWluWSwgd2lkdGgsIGhlaWdodF0gPSBnZXRDYW52YXNTaXplKGVsZW1lbnRzLCBleHBvcnRQYWRkaW5nKTtcbiAgY29uc3Qge1xuICAgIGNhbnZhcyxcbiAgICBzY2FsZSA9IDFcbiAgfSA9IGNyZWF0ZUNhbnZhcyh3aWR0aCwgaGVpZ2h0KTtcbiAgY29uc3QgZGVmYXVsdEFwcFN0YXRlID0gZ2V0RGVmYXVsdEFwcFN0YXRlKCk7XG4gIGNvbnN0IHtcbiAgICBpbWFnZUNhY2hlXG4gIH0gPSB5aWVsZCB1cGRhdGVJbWFnZUNhY2hlKHtcbiAgICBpbWFnZUNhY2hlOiBuZXcgTWFwKCksXG4gICAgZmlsZUlkczogZ2V0SW5pdGlhbGl6ZWRJbWFnZUVsZW1lbnRzKGVsZW1lbnRzKS5tYXAoZWxlbWVudCA9PiBlbGVtZW50LmZpbGVJZCksXG4gICAgZmlsZXNcbiAgfSk7XG4gIGNvbnN0IG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA9IGlzT25seUV4cG9ydGluZ1NpbmdsZUZyYW1lKGVsZW1lbnRzKTtcbiAgcmVuZGVyU3RhdGljU2NlbmUoe1xuICAgIGNhbnZhcyxcbiAgICByYzogcm91Z2guY2FudmFzKGNhbnZhcyksXG4gICAgZWxlbWVudHMsXG4gICAgdmlzaWJsZUVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICBzY2FsZSxcbiAgICBhcHBTdGF0ZTogT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCBhcHBTdGF0ZSksIHtcbiAgICAgIHZpZXdCYWNrZ3JvdW5kQ29sb3I6IGV4cG9ydEJhY2tncm91bmQgPyB2aWV3QmFja2dyb3VuZENvbG9yIDogbnVsbCxcbiAgICAgIHNjcm9sbFg6IC1taW5YICsgKG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA/IDAgOiBleHBvcnRQYWRkaW5nKSxcbiAgICAgIHNjcm9sbFk6IC1taW5ZICsgKG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA/IDAgOiBleHBvcnRQYWRkaW5nKSxcbiAgICAgIHpvb206IGRlZmF1bHRBcHBTdGF0ZS56b29tLFxuICAgICAgc2hvdWxkQ2FjaGVJZ25vcmVab29tOiBmYWxzZSxcbiAgICAgIHRoZW1lOiBhcHBTdGF0ZS5leHBvcnRXaXRoRGFya01vZGUgPyBcImRhcmtcIiA6IFwibGlnaHRcIlxuICAgIH0pLFxuICAgIHJlbmRlckNvbmZpZzoge1xuICAgICAgaW1hZ2VDYWNoZSxcbiAgICAgIHJlbmRlckdyaWQ6IGZhbHNlLFxuICAgICAgaXNFeHBvcnRpbmc6IHRydWVcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gY2FudmFzO1xufSk7XG5leHBvcnQgY29uc3QgZXhwb3J0VG9TdmcgPSAoZWxlbWVudHMsIGFwcFN0YXRlLCBmaWxlcywgb3B0cykgPT4gX19hd2FpdGVyKHZvaWQgMCwgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uKiAoKSB7XG4gIHZhciBfYSwgX2IsIF9jO1xuXG4gIGNvbnN0IHtcbiAgICBleHBvcnRQYWRkaW5nID0gREVGQVVMVF9FWFBPUlRfUEFERElORyxcbiAgICB2aWV3QmFja2dyb3VuZENvbG9yLFxuICAgIGV4cG9ydFNjYWxlID0gMSxcbiAgICBleHBvcnRFbWJlZFNjZW5lXG4gIH0gPSBhcHBTdGF0ZTtcbiAgbGV0IG1ldGFkYXRhID0gXCJcIjtcblxuICBpZiAoZXhwb3J0RW1iZWRTY2VuZSkge1xuICAgIHRyeSB7XG4gICAgICBtZXRhZGF0YSA9IHlpZWxkICh5aWVsZCBpbXBvcnQoXG4gICAgICAvKiB3ZWJwYWNrQ2h1bmtOYW1lOiBcImltYWdlXCIgKi9cbiAgICAgIFwiLi4vLi4vc3JjL2RhdGEvaW1hZ2VcIikpLmVuY29kZVN2Z01ldGFkYXRhKHtcbiAgICAgICAgdGV4dDogKG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5zZXJpYWxpemVBc0pTT04pID8gKF9hID0gb3B0cyA9PT0gbnVsbCB8fCBvcHRzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRzLnNlcmlhbGl6ZUFzSlNPTikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNhbGwob3B0cykgOiBzZXJpYWxpemVBc0pTT04oZWxlbWVudHMsIGFwcFN0YXRlLCBmaWxlcyB8fCB7fSwgXCJsb2NhbFwiKVxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IFttaW5YLCBtaW5ZLCB3aWR0aCwgaGVpZ2h0XSA9IGdldENhbnZhc1NpemUoZWxlbWVudHMsIGV4cG9ydFBhZGRpbmcpOyAvLyBpbml0aWFsaXplIFNWRyByb290XG5cbiAgY29uc3Qgc3ZnUm9vdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdfTlMsIFwic3ZnXCIpO1xuICBzdmdSb290LnNldEF0dHJpYnV0ZShcInZlcnNpb25cIiwgXCIxLjFcIik7XG4gIHN2Z1Jvb3Quc2V0QXR0cmlidXRlKFwieG1sbnNcIiwgU1ZHX05TKTtcbiAgc3ZnUm9vdC5zZXRBdHRyaWJ1dGUoXCJ2aWV3Qm94XCIsIGAwIDAgJHt3aWR0aH0gJHtoZWlnaHR9YCk7XG4gIHN2Z1Jvb3Quc2V0QXR0cmlidXRlKFwid2lkdGhcIiwgYCR7d2lkdGggKiBleHBvcnRTY2FsZX1gKTtcbiAgc3ZnUm9vdC5zZXRBdHRyaWJ1dGUoXCJoZWlnaHRcIiwgYCR7aGVpZ2h0ICogZXhwb3J0U2NhbGV9YCk7XG5cbiAgaWYgKGFwcFN0YXRlLmV4cG9ydFdpdGhEYXJrTW9kZSkge1xuICAgIHN2Z1Jvb3Quc2V0QXR0cmlidXRlKFwiZmlsdGVyXCIsIFRIRU1FX0ZJTFRFUik7XG4gIH1cblxuICBsZXQgYXNzZXRQYXRoID0gXCJodHRwczovL2V4Y2FsaWRyYXcuY29tL1wiOyAvLyBBc3NldCBwYXRoIG5lZWRzIHRvIGJlIGRldGVybWluZWQgb25seSB3aGVuIHVzaW5nIHBhY2thZ2VcblxuICBpZiAocHJvY2Vzcy5lbnYuVklURV9JU19FWENBTElEUkFXX05QTV9QQUNLQUdFKSB7XG4gICAgYXNzZXRQYXRoID0gd2luZG93LkVYQ0FMSURSQVdfQVNTRVRfUEFUSCB8fCBgaHR0cHM6Ly91bnBrZy5jb20vJHtwcm9jZXNzLmVudi5WSVRFX1BLR19OQU1FfUAke3Byb2Nlc3MuZW52LlBLR19WRVJTSU9OfWA7XG5cbiAgICBpZiAoYXNzZXRQYXRoID09PSBudWxsIHx8IGFzc2V0UGF0aCA9PT0gdm9pZCAwID8gdm9pZCAwIDogYXNzZXRQYXRoLnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG4gICAgICBhc3NldFBhdGggPSBhc3NldFBhdGgucmVwbGFjZShcIi9cIiwgYCR7d2luZG93LmxvY2F0aW9uLm9yaWdpbn0vYCk7XG4gICAgfVxuXG4gICAgYXNzZXRQYXRoID0gYCR7YXNzZXRQYXRofS9kaXN0L2V4Y2FsaWRyYXctYXNzZXRzL2A7XG4gIH0gLy8gZG8gbm90IGFwcGx5IGNsaXBwaW5nIHdoZW4gd2UncmUgZXhwb3J0aW5nIHRoZSB3aG9sZSBzY2VuZVxuXG5cbiAgY29uc3QgaXNFeHBvcnRpbmdXaG9sZUNhbnZhcyA9ICgoX2MgPSAoX2IgPSBTY2VuZS5nZXRTY2VuZShlbGVtZW50c1swXSkpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5nZXROb25EZWxldGVkRWxlbWVudHMoKSkgPT09IG51bGwgfHwgX2MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jLmxlbmd0aCkgPT09IGVsZW1lbnRzLmxlbmd0aDtcbiAgY29uc3Qgb25seUV4cG9ydGluZ1NpbmdsZUZyYW1lID0gaXNPbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUoZWxlbWVudHMpO1xuICBjb25zdCBvZmZzZXRYID0gLW1pblggKyAob25seUV4cG9ydGluZ1NpbmdsZUZyYW1lID8gMCA6IGV4cG9ydFBhZGRpbmcpO1xuICBjb25zdCBvZmZzZXRZID0gLW1pblkgKyAob25seUV4cG9ydGluZ1NpbmdsZUZyYW1lID8gMCA6IGV4cG9ydFBhZGRpbmcpO1xuICBjb25zdCBleHBvcnRpbmdGcmFtZSA9IGlzRXhwb3J0aW5nV2hvbGVDYW52YXMgfHwgIW9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSA/IHVuZGVmaW5lZCA6IGVsZW1lbnRzLmZpbmQoZWxlbWVudCA9PiBlbGVtZW50LnR5cGUgPT09IFwiZnJhbWVcIik7XG4gIGxldCBleHBvcnRpbmdGcmFtZUNsaXBQYXRoID0gXCJcIjtcblxuICBpZiAoZXhwb3J0aW5nRnJhbWUpIHtcbiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gZ2V0RWxlbWVudEFic29sdXRlQ29vcmRzKGV4cG9ydGluZ0ZyYW1lKTtcbiAgICBjb25zdCBjeCA9ICh4MiAtIHgxKSAvIDIgLSAoZXhwb3J0aW5nRnJhbWUueCAtIHgxKTtcbiAgICBjb25zdCBjeSA9ICh5MiAtIHkxKSAvIDIgLSAoZXhwb3J0aW5nRnJhbWUueSAtIHkxKTtcbiAgICBleHBvcnRpbmdGcmFtZUNsaXBQYXRoID0gYDxjbGlwUGF0aCBpZD0ke2V4cG9ydGluZ0ZyYW1lLmlkfT5cbiAgICAgICAgICAgIDxyZWN0IHRyYW5zZm9ybT1cInRyYW5zbGF0ZSgke2V4cG9ydGluZ0ZyYW1lLnggKyBvZmZzZXRYfSAke2V4cG9ydGluZ0ZyYW1lLnkgKyBvZmZzZXRZfSkgcm90YXRlKCR7ZXhwb3J0aW5nRnJhbWUuYW5nbGV9ICR7Y3h9ICR7Y3l9KVwiXG4gICAgICAgICAgd2lkdGg9XCIke2V4cG9ydGluZ0ZyYW1lLndpZHRofVwiXG4gICAgICAgICAgaGVpZ2h0PVwiJHtleHBvcnRpbmdGcmFtZS5oZWlnaHR9XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9yZWN0PlxuICAgICAgICA8L2NsaXBQYXRoPmA7XG4gIH1cblxuICBzdmdSb290LmlubmVySFRNTCA9IGBcbiAgJHtTVkdfRVhQT1JUX1RBR31cbiAgJHttZXRhZGF0YX1cbiAgPGRlZnM+XG4gICAgPHN0eWxlIGNsYXNzPVwic3R5bGUtZm9udHNcIj5cbiAgICAgIEBmb250LWZhY2Uge1xuICAgICAgICBmb250LWZhbWlseTogXCJWaXJnaWxcIjtcbiAgICAgICAgc3JjOiB1cmwoXCIke2Fzc2V0UGF0aH1WaXJnaWwud29mZjJcIik7XG4gICAgICB9XG4gICAgICBAZm9udC1mYWNlIHtcbiAgICAgICAgZm9udC1mYW1pbHk6IFwiQ2FzY2FkaWFcIjtcbiAgICAgICAgc3JjOiB1cmwoXCIke2Fzc2V0UGF0aH1DYXNjYWRpYS53b2ZmMlwiKTtcbiAgICAgIH1cbiAgICA8L3N0eWxlPlxuICAgICR7ZXhwb3J0aW5nRnJhbWVDbGlwUGF0aH1cbiAgPC9kZWZzPlxuICBgOyAvLyByZW5kZXIgYmFja2dyb3VuZCByZWN0XG5cbiAgaWYgKGFwcFN0YXRlLmV4cG9ydEJhY2tncm91bmQgJiYgdmlld0JhY2tncm91bmRDb2xvcikge1xuICAgIGNvbnN0IHJlY3QgPSBzdmdSb290Lm93bmVyRG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFNWR19OUywgXCJyZWN0XCIpO1xuICAgIHJlY3Quc2V0QXR0cmlidXRlKFwieFwiLCBcIjBcIik7XG4gICAgcmVjdC5zZXRBdHRyaWJ1dGUoXCJ5XCIsIFwiMFwiKTtcbiAgICByZWN0LnNldEF0dHJpYnV0ZShcIndpZHRoXCIsIGAke3dpZHRofWApO1xuICAgIHJlY3Quc2V0QXR0cmlidXRlKFwiaGVpZ2h0XCIsIGAke2hlaWdodH1gKTtcbiAgICByZWN0LnNldEF0dHJpYnV0ZShcImZpbGxcIiwgdmlld0JhY2tncm91bmRDb2xvcik7XG4gICAgc3ZnUm9vdC5hcHBlbmRDaGlsZChyZWN0KTtcbiAgfVxuXG4gIGNvbnN0IHJzdmcgPSByb3VnaC5zdmcoc3ZnUm9vdCk7XG4gIHJlbmRlclNjZW5lVG9TdmcoZWxlbWVudHMsIHJzdmcsIHN2Z1Jvb3QsIGZpbGVzIHx8IHt9LCB7XG4gICAgb2Zmc2V0WCxcbiAgICBvZmZzZXRZLFxuICAgIGV4cG9ydFdpdGhEYXJrTW9kZTogYXBwU3RhdGUuZXhwb3J0V2l0aERhcmtNb2RlLFxuICAgIGV4cG9ydGluZ0ZyYW1lSWQ6IChleHBvcnRpbmdGcmFtZSA9PT0gbnVsbCB8fCBleHBvcnRpbmdGcmFtZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogZXhwb3J0aW5nRnJhbWUuaWQpIHx8IG51bGwsXG4gICAgcmVuZGVyRW1iZWRkYWJsZXM6IG9wdHMgPT09IG51bGwgfHwgb3B0cyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0cy5yZW5kZXJFbWJlZGRhYmxlc1xuICB9KTtcbiAgcmV0dXJuIHN2Z1Jvb3Q7XG59KTsgLy8gY2FsY3VsYXRlIHNtYWxsZXN0IGFyZWEgdG8gZml0IHRoZSBjb250ZW50cyBpblxuXG5jb25zdCBnZXRDYW52YXNTaXplID0gKGVsZW1lbnRzLCBleHBvcnRQYWRkaW5nKSA9PiB7XG4gIC8vIHdlIHNob3VsZCBkZWNpZGUgaWYgd2UgYXJlIGV4cG9ydGluZyB0aGUgd2hvbGUgY2FudmFzXG4gIC8vIGlmIHNvLCB3ZSBhcmUgbm90IGNsaXBwaW5nIGVsZW1lbnRzIGluIHRoZSBmcmFtZVxuICAvLyBhbmQgdGhlcmVmb3JlLCB3ZSBzaG91bGQgbm90IGRvIGFueXRoaW5nIHNwZWNpYWxcbiAgdmFyIF9hLCBfYjtcblxuICBjb25zdCBpc0V4cG9ydGluZ1dob2xlQ2FudmFzID0gKChfYiA9IChfYSA9IFNjZW5lLmdldFNjZW5lKGVsZW1lbnRzWzBdKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldE5vbkRlbGV0ZWRFbGVtZW50cygpKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IubGVuZ3RoKSA9PT0gZWxlbWVudHMubGVuZ3RoO1xuICBjb25zdCBvbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUgPSBpc09ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZShlbGVtZW50cyk7XG5cbiAgaWYgKCFpc0V4cG9ydGluZ1dob2xlQ2FudmFzIHx8IG9ubHlFeHBvcnRpbmdTaW5nbGVGcmFtZSkge1xuICAgIGNvbnN0IGZyYW1lcyA9IGVsZW1lbnRzLmZpbHRlcihlbGVtZW50ID0+IGVsZW1lbnQudHlwZSA9PT0gXCJmcmFtZVwiKTtcbiAgICBjb25zdCBleHBvcnRlZEZyYW1lSWRzID0gZnJhbWVzLnJlZHVjZSgoYWNjLCBmcmFtZSkgPT4ge1xuICAgICAgYWNjW2ZyYW1lLmlkXSA9IHRydWU7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIHt9KTsgLy8gZWxlbWVudHMgaW4gYSBmcmFtZSBkbyBub3QgYWZmZWN0IHRoZSBjYW52YXMgc2l6ZSBpZiB3ZSdyZSBub3QgZXhwb3J0aW5nXG4gICAgLy8gdGhlIHdob2xlIGNhbnZhc1xuXG4gICAgZWxlbWVudHMgPSBlbGVtZW50cy5maWx0ZXIoZWxlbWVudCA9PiB7XG4gICAgICB2YXIgX2E7XG5cbiAgICAgIHJldHVybiAhZXhwb3J0ZWRGcmFtZUlkc1soX2EgPSBlbGVtZW50LmZyYW1lSWQpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IFwiXCJdO1xuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgW21pblgsIG1pblksIG1heFgsIG1heFldID0gZ2V0Q29tbW9uQm91bmRzKGVsZW1lbnRzKTtcbiAgY29uc3Qgd2lkdGggPSBkaXN0YW5jZShtaW5YLCBtYXhYKSArIChvbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUgPyAwIDogZXhwb3J0UGFkZGluZyAqIDIpO1xuICBjb25zdCBoZWlnaHQgPSBkaXN0YW5jZShtaW5ZLCBtYXhZKSArIChvbmx5RXhwb3J0aW5nU2luZ2xlRnJhbWUgPyAwIDogZXhwb3J0UGFkZGluZyAqIDIpO1xuICByZXR1cm4gW21pblgsIG1pblksIHdpZHRoLCBoZWlnaHRdO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEV4cG9ydFNpemUgPSAoZWxlbWVudHMsIGV4cG9ydFBhZGRpbmcsIHNjYWxlKSA9PiB7XG4gIGNvbnN0IFssLCB3aWR0aCwgaGVpZ2h0XSA9IGdldENhbnZhc1NpemUoZWxlbWVudHMsIGV4cG9ydFBhZGRpbmcpLm1hcChkaW1lbnNpb24gPT4gTWF0aC50cnVuYyhkaW1lbnNpb24gKiBzY2FsZSkpO1xuICByZXR1cm4gW3dpZHRoLCBoZWlnaHRdO1xufTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../../scene/export.ts\n");
4370
4381
 
4371
4382
  /***/ }),
4372
4383