datepicker-inner.component.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. /* tslint:disable: max-file-line-count */
  6. import { Component, EventEmitter, Input, Output } from '@angular/core';
  7. import { DateFormatter } from './date-formatter';
  8. export class DatePickerInnerComponent {
  9. constructor() {
  10. this.selectionDone = new EventEmitter(undefined);
  11. this.update = new EventEmitter(false);
  12. this.activeDateChange = new EventEmitter(undefined);
  13. /* tslint:disable-next-line: no-any*/
  14. this.stepDay = {};
  15. /* tslint:disable-next-line: no-any*/
  16. this.stepMonth = {};
  17. /* tslint:disable-next-line: no-any*/
  18. this.stepYear = {};
  19. this.modes = ['day', 'month', 'year'];
  20. this.dateFormatter = new DateFormatter();
  21. }
  22. /**
  23. * @return {?}
  24. */
  25. get activeDate() {
  26. return this._activeDate;
  27. }
  28. /**
  29. * @param {?} value
  30. * @return {?}
  31. */
  32. set activeDate(value) {
  33. this._activeDate = value;
  34. }
  35. // todo: add formatter value to Date object
  36. /**
  37. * @return {?}
  38. */
  39. ngOnInit() {
  40. // todo: use date for unique value
  41. this.uniqueId = `datepicker--${Math.floor(Math.random() * 10000)}`;
  42. if (this.initDate) {
  43. this.activeDate = this.initDate;
  44. this.selectedDate = new Date(this.activeDate.valueOf());
  45. this.update.emit(this.activeDate);
  46. }
  47. else if (this.activeDate === undefined) {
  48. this.activeDate = new Date();
  49. }
  50. }
  51. // this.refreshView should be called here to reflect the changes on the fly
  52. // tslint:disable-next-line:no-unused-variable
  53. /**
  54. * @param {?} changes
  55. * @return {?}
  56. */
  57. ngOnChanges(changes) {
  58. this.refreshView();
  59. this.checkIfActiveDateGotUpdated(changes.activeDate);
  60. }
  61. // Check if activeDate has been update and then emit the activeDateChange with the new date
  62. /* tslint:disable-next-line: no-any */
  63. /**
  64. * @param {?} activeDate
  65. * @return {?}
  66. */
  67. checkIfActiveDateGotUpdated(activeDate) {
  68. if (activeDate && !activeDate.firstChange) {
  69. /** @type {?} */
  70. const previousValue = activeDate.previousValue;
  71. if (previousValue &&
  72. previousValue instanceof Date &&
  73. previousValue.getTime() !== activeDate.currentValue.getTime()) {
  74. this.activeDateChange.emit(this.activeDate);
  75. }
  76. }
  77. }
  78. /**
  79. * @param {?} handler
  80. * @param {?} type
  81. * @return {?}
  82. */
  83. setCompareHandler(handler, type) {
  84. if (type === 'day') {
  85. this.compareHandlerDay = handler;
  86. }
  87. if (type === 'month') {
  88. this.compareHandlerMonth = handler;
  89. }
  90. if (type === 'year') {
  91. this.compareHandlerYear = handler;
  92. }
  93. }
  94. /**
  95. * @param {?} date1
  96. * @param {?} date2
  97. * @return {?}
  98. */
  99. compare(date1, date2) {
  100. if (date1 === undefined || date2 === undefined) {
  101. return undefined;
  102. }
  103. if (this.datepickerMode === 'day' && this.compareHandlerDay) {
  104. return this.compareHandlerDay(date1, date2);
  105. }
  106. if (this.datepickerMode === 'month' && this.compareHandlerMonth) {
  107. return this.compareHandlerMonth(date1, date2);
  108. }
  109. if (this.datepickerMode === 'year' && this.compareHandlerYear) {
  110. return this.compareHandlerYear(date1, date2);
  111. }
  112. return void 0;
  113. }
  114. /**
  115. * @param {?} handler
  116. * @param {?} type
  117. * @return {?}
  118. */
  119. setRefreshViewHandler(handler, type) {
  120. if (type === 'day') {
  121. this.refreshViewHandlerDay = handler;
  122. }
  123. if (type === 'month') {
  124. this.refreshViewHandlerMonth = handler;
  125. }
  126. if (type === 'year') {
  127. this.refreshViewHandlerYear = handler;
  128. }
  129. }
  130. /**
  131. * @return {?}
  132. */
  133. refreshView() {
  134. if (this.datepickerMode === 'day' && this.refreshViewHandlerDay) {
  135. this.refreshViewHandlerDay();
  136. }
  137. if (this.datepickerMode === 'month' && this.refreshViewHandlerMonth) {
  138. this.refreshViewHandlerMonth();
  139. }
  140. if (this.datepickerMode === 'year' && this.refreshViewHandlerYear) {
  141. this.refreshViewHandlerYear();
  142. }
  143. }
  144. /**
  145. * @param {?} date
  146. * @param {?} format
  147. * @return {?}
  148. */
  149. dateFilter(date, format) {
  150. return this.dateFormatter.format(date, format, this.locale);
  151. }
  152. /* tslint:disable-next-line: no-any*/
  153. /**
  154. * @param {?} dateObject
  155. * @return {?}
  156. */
  157. isActive(dateObject) {
  158. if (this.compare(dateObject.date, this.activeDate) === 0) {
  159. this.activeDateId = dateObject.uid;
  160. return true;
  161. }
  162. return false;
  163. }
  164. /* tslint:disable-next-line: no-any*/
  165. /**
  166. * @param {?} date
  167. * @param {?} format
  168. * @return {?}
  169. */
  170. createDateObject(date, format) {
  171. /* tslint:disable-next-line: no-any*/
  172. /** @type {?} */
  173. const dateObject = {};
  174. dateObject.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  175. dateObject.date = this.fixTimeZone(dateObject.date);
  176. dateObject.label = this.dateFilter(date, format);
  177. dateObject.selected = this.compare(date, this.selectedDate) === 0;
  178. dateObject.disabled = this.isDisabled(date);
  179. dateObject.current = this.compare(date, new Date()) === 0;
  180. dateObject.customClass = this.getCustomClassForDate(dateObject.date);
  181. return dateObject;
  182. }
  183. /* tslint:disable-next-line: no-any*/
  184. /**
  185. * @param {?} arr
  186. * @param {?} size
  187. * @return {?}
  188. */
  189. split(arr, size) {
  190. /* tslint:disable-next-line: no-any*/
  191. /** @type {?} */
  192. const arrays = [];
  193. while (arr.length > 0) {
  194. arrays.push(arr.splice(0, size));
  195. }
  196. return arrays;
  197. }
  198. // Fix a hard-reproducible bug with timezones
  199. // The bug depends on OS, browser, current timezone and current date
  200. // i.e.
  201. // var date = new Date(2014, 0, 1);
  202. // console.log(date.getFullYear(), date.getMonth(), date.getDate(),
  203. // date.getHours()); can result in "2013 11 31 23" because of the bug.
  204. /**
  205. * @param {?} date
  206. * @return {?}
  207. */
  208. fixTimeZone(date) {
  209. /** @type {?} */
  210. const hours = date.getHours();
  211. return new Date(date.getFullYear(), date.getMonth(), date.getDate(), hours === 23 ? hours + 2 : 0);
  212. }
  213. /**
  214. * @param {?} date
  215. * @param {?=} isManual
  216. * @return {?}
  217. */
  218. select(date, isManual = true) {
  219. if (this.datepickerMode === this.minMode) {
  220. if (!this.activeDate) {
  221. this.activeDate = new Date(0, 0, 0, 0, 0, 0, 0);
  222. }
  223. this.activeDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  224. this.activeDate = this.fixTimeZone(this.activeDate);
  225. if (isManual) {
  226. this.selectionDone.emit(this.activeDate);
  227. }
  228. }
  229. else {
  230. this.activeDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  231. this.activeDate = this.fixTimeZone(this.activeDate);
  232. if (isManual) {
  233. this.datepickerMode = this.modes[this.modes.indexOf(this.datepickerMode) - 1];
  234. }
  235. }
  236. this.selectedDate = new Date(this.activeDate.valueOf());
  237. this.update.emit(this.activeDate);
  238. this.refreshView();
  239. }
  240. /**
  241. * @param {?} direction
  242. * @return {?}
  243. */
  244. move(direction) {
  245. /* tslint:disable-next-line: no-any*/
  246. /** @type {?} */
  247. let expectedStep;
  248. if (this.datepickerMode === 'day') {
  249. expectedStep = this.stepDay;
  250. }
  251. if (this.datepickerMode === 'month') {
  252. expectedStep = this.stepMonth;
  253. }
  254. if (this.datepickerMode === 'year') {
  255. expectedStep = this.stepYear;
  256. }
  257. if (expectedStep) {
  258. /** @type {?} */
  259. const year = this.activeDate.getFullYear() + direction * (expectedStep.years || 0);
  260. /** @type {?} */
  261. const month = this.activeDate.getMonth() + direction * (expectedStep.months || 0);
  262. this.activeDate = new Date(year, month, 1);
  263. this.refreshView();
  264. this.activeDateChange.emit(this.activeDate);
  265. }
  266. }
  267. /**
  268. * @param {?} _direction
  269. * @return {?}
  270. */
  271. toggleMode(_direction) {
  272. /** @type {?} */
  273. const direction = _direction || 1;
  274. if ((this.datepickerMode === this.maxMode && direction === 1) ||
  275. (this.datepickerMode === this.minMode && direction === -1)) {
  276. return;
  277. }
  278. this.datepickerMode = this.modes[this.modes.indexOf(this.datepickerMode) + direction];
  279. this.refreshView();
  280. }
  281. /**
  282. * @protected
  283. * @param {?} date
  284. * @return {?}
  285. */
  286. getCustomClassForDate(date) {
  287. if (!this.customClass) {
  288. return '';
  289. }
  290. // todo: build a hash of custom classes, it will work faster
  291. /** @type {?} */
  292. const customClassObject = this.customClass.find((/**
  293. * @param {?} customClass
  294. * @return {?}
  295. */
  296. (customClass) => {
  297. return (customClass.date.valueOf() === date.valueOf() &&
  298. customClass.mode === this.datepickerMode);
  299. }), this);
  300. return customClassObject === undefined ? '' : customClassObject.clazz;
  301. }
  302. /**
  303. * @protected
  304. * @param {?} date1Disabled
  305. * @param {?} date2
  306. * @return {?}
  307. */
  308. compareDateDisabled(date1Disabled, date2) {
  309. if (date1Disabled === undefined || date2 === undefined) {
  310. return undefined;
  311. }
  312. if (date1Disabled.mode === 'day' && this.compareHandlerDay) {
  313. return this.compareHandlerDay(date1Disabled.date, date2);
  314. }
  315. if (date1Disabled.mode === 'month' && this.compareHandlerMonth) {
  316. return this.compareHandlerMonth(date1Disabled.date, date2);
  317. }
  318. if (date1Disabled.mode === 'year' && this.compareHandlerYear) {
  319. return this.compareHandlerYear(date1Disabled.date, date2);
  320. }
  321. return undefined;
  322. }
  323. /**
  324. * @protected
  325. * @param {?} date
  326. * @return {?}
  327. */
  328. isDisabled(date) {
  329. /** @type {?} */
  330. let isDateDisabled = false;
  331. if (this.dateDisabled) {
  332. this.dateDisabled.forEach((/**
  333. * @param {?} disabledDate
  334. * @return {?}
  335. */
  336. (disabledDate) => {
  337. if (this.compareDateDisabled(disabledDate, date) === 0) {
  338. isDateDisabled = true;
  339. }
  340. }));
  341. }
  342. if (this.dayDisabled) {
  343. isDateDisabled =
  344. isDateDisabled ||
  345. this.dayDisabled.indexOf(date.getDay()) > -1;
  346. }
  347. return (isDateDisabled ||
  348. (this.minDate && this.compare(date, this.minDate) < 0) ||
  349. (this.maxDate && this.compare(date, this.maxDate) > 0));
  350. }
  351. }
  352. DatePickerInnerComponent.decorators = [
  353. { type: Component, args: [{
  354. selector: 'datepicker-inner',
  355. template: `
  356. <!--&lt;!&ndash;ng-keydown="keydown($event)"&ndash;&gt;-->
  357. <div *ngIf="datepickerMode" class="well well-sm bg-faded p-a card" role="application" >
  358. <ng-content></ng-content>
  359. </div>
  360. `
  361. }] }
  362. ];
  363. DatePickerInnerComponent.propDecorators = {
  364. locale: [{ type: Input }],
  365. datepickerMode: [{ type: Input }],
  366. startingDay: [{ type: Input }],
  367. yearRange: [{ type: Input }],
  368. minDate: [{ type: Input }],
  369. maxDate: [{ type: Input }],
  370. minMode: [{ type: Input }],
  371. maxMode: [{ type: Input }],
  372. showWeeks: [{ type: Input }],
  373. formatDay: [{ type: Input }],
  374. formatMonth: [{ type: Input }],
  375. formatYear: [{ type: Input }],
  376. formatDayHeader: [{ type: Input }],
  377. formatDayTitle: [{ type: Input }],
  378. formatMonthTitle: [{ type: Input }],
  379. onlyCurrentMonth: [{ type: Input }],
  380. shortcutPropagation: [{ type: Input }],
  381. customClass: [{ type: Input }],
  382. monthColLimit: [{ type: Input }],
  383. yearColLimit: [{ type: Input }],
  384. dateDisabled: [{ type: Input }],
  385. dayDisabled: [{ type: Input }],
  386. initDate: [{ type: Input }],
  387. selectionDone: [{ type: Output }],
  388. update: [{ type: Output }],
  389. activeDateChange: [{ type: Output }],
  390. activeDate: [{ type: Input }]
  391. };
  392. if (false) {
  393. /** @type {?} */
  394. DatePickerInnerComponent.prototype.locale;
  395. /** @type {?} */
  396. DatePickerInnerComponent.prototype.datepickerMode;
  397. /** @type {?} */
  398. DatePickerInnerComponent.prototype.startingDay;
  399. /** @type {?} */
  400. DatePickerInnerComponent.prototype.yearRange;
  401. /** @type {?} */
  402. DatePickerInnerComponent.prototype.minDate;
  403. /** @type {?} */
  404. DatePickerInnerComponent.prototype.maxDate;
  405. /** @type {?} */
  406. DatePickerInnerComponent.prototype.minMode;
  407. /** @type {?} */
  408. DatePickerInnerComponent.prototype.maxMode;
  409. /** @type {?} */
  410. DatePickerInnerComponent.prototype.showWeeks;
  411. /** @type {?} */
  412. DatePickerInnerComponent.prototype.formatDay;
  413. /** @type {?} */
  414. DatePickerInnerComponent.prototype.formatMonth;
  415. /** @type {?} */
  416. DatePickerInnerComponent.prototype.formatYear;
  417. /** @type {?} */
  418. DatePickerInnerComponent.prototype.formatDayHeader;
  419. /** @type {?} */
  420. DatePickerInnerComponent.prototype.formatDayTitle;
  421. /** @type {?} */
  422. DatePickerInnerComponent.prototype.formatMonthTitle;
  423. /** @type {?} */
  424. DatePickerInnerComponent.prototype.onlyCurrentMonth;
  425. /** @type {?} */
  426. DatePickerInnerComponent.prototype.shortcutPropagation;
  427. /** @type {?} */
  428. DatePickerInnerComponent.prototype.customClass;
  429. /** @type {?} */
  430. DatePickerInnerComponent.prototype.monthColLimit;
  431. /** @type {?} */
  432. DatePickerInnerComponent.prototype.yearColLimit;
  433. /** @type {?} */
  434. DatePickerInnerComponent.prototype.dateDisabled;
  435. /** @type {?} */
  436. DatePickerInnerComponent.prototype.dayDisabled;
  437. /** @type {?} */
  438. DatePickerInnerComponent.prototype.initDate;
  439. /** @type {?} */
  440. DatePickerInnerComponent.prototype.selectionDone;
  441. /** @type {?} */
  442. DatePickerInnerComponent.prototype.update;
  443. /** @type {?} */
  444. DatePickerInnerComponent.prototype.activeDateChange;
  445. /** @type {?} */
  446. DatePickerInnerComponent.prototype.stepDay;
  447. /** @type {?} */
  448. DatePickerInnerComponent.prototype.stepMonth;
  449. /** @type {?} */
  450. DatePickerInnerComponent.prototype.stepYear;
  451. /** @type {?} */
  452. DatePickerInnerComponent.prototype.uniqueId;
  453. /**
  454. * @type {?}
  455. * @protected
  456. */
  457. DatePickerInnerComponent.prototype.modes;
  458. /**
  459. * @type {?}
  460. * @protected
  461. */
  462. DatePickerInnerComponent.prototype.dateFormatter;
  463. /**
  464. * @type {?}
  465. * @protected
  466. */
  467. DatePickerInnerComponent.prototype._activeDate;
  468. /**
  469. * @type {?}
  470. * @protected
  471. */
  472. DatePickerInnerComponent.prototype.selectedDate;
  473. /**
  474. * @type {?}
  475. * @protected
  476. */
  477. DatePickerInnerComponent.prototype.activeDateId;
  478. /**
  479. * @type {?}
  480. * @protected
  481. */
  482. DatePickerInnerComponent.prototype.refreshViewHandlerDay;
  483. /**
  484. * @type {?}
  485. * @protected
  486. */
  487. DatePickerInnerComponent.prototype.compareHandlerDay;
  488. /**
  489. * @type {?}
  490. * @protected
  491. */
  492. DatePickerInnerComponent.prototype.refreshViewHandlerMonth;
  493. /**
  494. * @type {?}
  495. * @protected
  496. */
  497. DatePickerInnerComponent.prototype.compareHandlerMonth;
  498. /**
  499. * @type {?}
  500. * @protected
  501. */
  502. DatePickerInnerComponent.prototype.refreshViewHandlerYear;
  503. /**
  504. * @type {?}
  505. * @protected
  506. */
  507. DatePickerInnerComponent.prototype.compareHandlerYear;
  508. }
  509. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci1pbm5lci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtYm9vdHN0cmFwL2RhdGVwaWNrZXIvIiwic291cmNlcyI6WyJkYXRlcGlja2VyLWlubmVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRVAsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBWWpELE1BQU0sT0FBTyx3QkFBd0I7SUFUckM7UUFtQ1ksa0JBQWEsR0FBdUIsSUFBSSxZQUFZLENBQU8sU0FBUyxDQUFDLENBQUM7UUFDdEUsV0FBTSxHQUF1QixJQUFJLFlBQVksQ0FBTyxLQUFLLENBQUMsQ0FBQztRQUMzRCxxQkFBZ0IsR0FBdUIsSUFBSSxZQUFZLENBQU8sU0FBUyxDQUFDLENBQUM7O1FBR25GLFlBQU8sR0FBUSxFQUFFLENBQUM7O1FBRWxCLGNBQVMsR0FBUSxFQUFFLENBQUM7O1FBRXBCLGFBQVEsR0FBUSxFQUFFLENBQUM7UUFJVCxVQUFLLEdBQWEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzNDLGtCQUFhLEdBQWtCLElBQUksYUFBYSxFQUFFLENBQUM7SUFxVS9ELENBQUM7Ozs7SUF6VEMsSUFDSSxVQUFVO1FBQ1osT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzFCLENBQUM7Ozs7O0lBRUQsSUFBSSxVQUFVLENBQUMsS0FBVztRQUN4QixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztJQUMzQixDQUFDOzs7OztJQUdELFFBQVE7UUFDTixrQ0FBa0M7UUFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBSSxlQUFlLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7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RSxvREFBbUY7O0lBR25GLDJDQUFrQjs7SUFFbEIsNkNBQW9COztJQUVwQiw0Q0FBbUI7O0lBRW5CLDRDQUFpQjs7Ozs7SUFFakIseUNBQXFEOzs7OztJQUNyRCxpREFBNkQ7Ozs7O0lBQzdELCtDQUE0Qjs7Ozs7SUFDNUIsZ0RBQTZCOzs7OztJQUM3QixnREFBK0I7Ozs7O0lBRS9CLHlEQUEwQzs7Ozs7SUFDMUMscURBQXNDOzs7OztJQUN0QywyREFBNEM7Ozs7O0lBQzVDLHVEQUF3Qzs7Ozs7SUFDeEMsMERBQTJDOzs7OztJQUMzQyxzREFBdUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiB0c2xpbnQ6ZGlzYWJsZTogbWF4LWZpbGUtbGluZS1jb3VudCAqL1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBEYXRlRm9ybWF0dGVyIH0gZnJvbSAnLi9kYXRlLWZvcm1hdHRlcic7XG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZGF0ZXBpY2tlci1pbm5lcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPCEtLSZsdDshJm5kYXNoO25nLWtleWRvd249XCJrZXlkb3duKCRldmVudClcIiZuZGFzaDsmZ3Q7LS0+XG4gICAgPGRpdiAqbmdJZj1cImRhdGVwaWNrZXJNb2RlXCIgY2xhc3M9XCJ3ZWxsIHdlbGwtc20gYmctZmFkZWQgcC1hIGNhcmRcIiByb2xlPVwiYXBwbGljYXRpb25cIiA+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC9kaXY+XG4gIGBcbn0pXG5leHBvcnQgY2xhc3MgRGF0ZVBpY2tlcklubmVyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuICBASW5wdXQoKSBsb2NhbGU6IHN0cmluZztcbiAgQElucHV0KCkgZGF0ZXBpY2tlck1vZGU6IHN0cmluZztcbiAgQElucHV0KCkgc3RhcnRpbmdEYXk6IG51bWJlcjtcbiAgQElucHV0KCkgeWVhclJhbmdlOiBudW1iZXI7XG5cbiAgQElucHV0KCkgbWluRGF0ZTogRGF0ZTtcbiAgQElucHV0KCkgbWF4RGF0ZTogRGF0ZTtcbiAgQElucHV0KCkgbWluTW9kZTogc3RyaW5nO1xuICBASW5wdXQoKSBtYXhNb2RlOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHNob3dXZWVrczogYm9vbGVhbjtcbiAgQElucHV0KCkgZm9ybWF0RGF5OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGZvcm1hdE1vbnRoOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGZvcm1hdFllYXI6IHN0cmluZztcbiAgQElucHV0KCkgZm9ybWF0RGF5SGVhZGVyOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGZvcm1hdERheVRpdGxlOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGZvcm1hdE1vbnRoVGl0bGU6IHN0cmluZztcbiAgQElucHV0KCkgb25seUN1cnJlbnRNb250aDogYm9vbGVhbjtcbiAgQElucHV0KCkgc2hvcnRjdXRQcm9wYWdhdGlvbjogYm9vbGVhbjtcbiAgQElucHV0KCkgY3VzdG9tQ2xhc3M6IHsgZGF0ZTogRGF0ZTsgbW9kZTogc3RyaW5nOyBjbGF6ejogc3RyaW5nIH1bXTtcbiAgQElucHV0KCkgbW9udGhDb2xMaW1pdDogbnVtYmVyO1xuICBASW5wdXQoKSB5ZWFyQ29sTGltaXQ6IG51bWJlcjtcbiAgQElucHV0KCkgZGF0ZURpc2FibGVkOiB7IGRhdGU6IERhdGU7IG1vZGU6IHN0cmluZyB9W107XG4gIEBJbnB1dCgpIGRheURpc2FibGVkOiBudW1iZXJbXTtcbiAgQElucHV0KCkgaW5pdERhdGU6IERhdGU7XG5cbiAgQE91dHB1dCgpIHNlbGVjdGlvbkRvbmU6IEV2ZW50RW1pdHRlcjxEYXRlPiA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZT4odW5kZWZpbmVkKTtcbiAgQE91dHB1dCgpIHVwZGF0ZTogRXZlbnRFbWl0dGVyPERhdGU+ID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlPihmYWxzZSk7XG4gIEBPdXRwdXQoKSBhY3RpdmVEYXRlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8RGF0ZT4gPSBuZXcgRXZlbnRFbWl0dGVyPERhdGU+KHVuZGVmaW5lZCk7XG5cbiAgLyogdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby1hbnkqL1xuICBzdGVwRGF5OiBhbnkgPSB7fTtcbiAgLyogdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby1hbnkqL1xuICBzdGVwTW9udGg6IGFueSA9IHt9O1xuICAvKiB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG5vLWFueSovXG4gIHN0ZXBZZWFyOiBhbnkgPSB7fTtcblxuICB1bmlxdWVJZDogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCBtb2Rlczogc3RyaW5nW10gPSBbJ2RheScsICdtb250aCcsICd5ZWFyJ107XG4gIHByb3RlY3RlZCBkYXRlRm9ybWF0dGVyOiBEYXRlRm9ybWF0dGVyID0gbmV3IERhdGVGb3JtYXR0ZXIoKTtcbiAgcHJvdGVjdGVkIF9hY3RpdmVEYXRlOiBEYXRlO1xuICBwcm90ZWN0ZWQgc2VsZWN0ZWREYXRlOiBEYXRlO1xuICBwcm90ZWN0ZWQgYWN0aXZlRGF0ZUlkOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIHJlZnJlc2hWaWV3SGFuZGxlckRheTogRnVuY3Rpb247XG4gIHByb3RlY3RlZCBjb21wYXJlSGFuZGxlckRheTogRnVuY3Rpb247XG4gIHByb3RlY3RlZCByZWZyZXNoVmlld0hhbmRsZXJNb250aDogRnVuY3Rpb247XG4gIHByb3RlY3RlZCBjb21wYXJlSGFuZGxlck1vbnRoOiBGdW5jdGlvbjtcbiAgcHJvdGVjdGVkIHJlZnJlc2hWaWV3SGFuZGxlclllYXI6IEZ1bmN0aW9uO1xuICBwcm90ZWN0ZWQgY29tcGFyZUhhbmRsZXJZZWFyOiBGdW5jdGlvbjtcblxuICBASW5wdXQoKVxuICBnZXQgYWN0aXZlRGF0ZSgpOiBEYXRlIHtcbiAgICByZXR1cm4gdGhpcy5fYWN0aXZlRGF0ZTtcbiAgfVxuXG4gIHNldCBhY3RpdmVEYXRlKHZhbHVlOiBEYXRlKSB7XG4gICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gdG9kbzogYWRkIGZvcm1hdHRlciB2YWx1ZSB0byBEYXRlIG9iamVjdFxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyB0b2RvOiB1c2UgZGF0ZSBmb3IgdW5pcXVlIHZhbHVlXG4gICAgdGhpcy51bmlxdWVJZCA9ICBgZGF0ZXBpY2tlci0tJHtNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAxMDAwMCl9YDtcblxuICAgIGlmICh0aGlzLmluaXREYXRlKSB7XG4gICAgICB0aGlzLmFjdGl2ZURhdGUgPSB0aGlzLmluaXREYXRlO1xuICAgICAgdGhpcy5zZWxlY3RlZERhdGUgPSBuZXcgRGF0ZSh0aGlzLmFjdGl2ZURhdGUudmFsdWVPZigpKTtcbiAgICAgIHRoaXMudXBkYXRlLmVtaXQodGhpcy5hY3RpdmVEYXRlKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuYWN0aXZlRGF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmFjdGl2ZURhdGUgPSBuZXcgRGF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHRoaXMucmVmcmVzaFZpZXcgc2hvdWxkIGJlIGNhbGxlZCBoZXJlIHRvIHJlZmxlY3QgdGhlIGNoYW5nZXMgb24gdGhlIGZseVxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tdW51c2VkLXZhcmlhYmxlXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICB0aGlzLnJlZnJlc2hWaWV3KCk7XG4gICAgdGhpcy5jaGVja0lmQWN0aXZlRGF0ZUdvdFVwZGF0ZWQoY2hhbmdlcy5hY3RpdmVEYXRlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGFjdGl2ZURhdGUgaGFzIGJlZW4gdXBkYXRlIGFuZCB0aGVuIGVtaXQgdGhlIGFjdGl2ZURhdGVDaGFuZ2Ugd2l0aCB0aGUgbmV3IGRhdGVcbiAgLyogdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby1hbnkgKi9cbiAgY2hlY2tJZkFjdGl2ZURhdGVHb3RVcGRhdGVkKGFjdGl2ZURhdGU6IGFueSk6IHZvaWQge1xuICAgIGlmIChhY3RpdmVEYXRlICYmICFhY3RpdmVEYXRlLmZpcnN0Q2hhbmdlKSB7XG4gICAgICBjb25zdCBwcmV2aW91c1ZhbHVlID0gYWN0aXZlRGF0ZS5wcmV2aW91c1ZhbHVlO1xuICAgICAgaWYgKFxuICAgICAgICBwcmV2aW91c1ZhbHVlICYmXG4gICAgICAgIHByZXZpb3VzVmFsdWUgaW5zdGFuY2VvZiBEYXRlICYmXG4gICAgICAgIHByZXZpb3VzVmFsdWUuZ2V0VGltZSgpICE9PSBhY3RpdmVEYXRlLmN1cnJlbnRWYWx1ZS5nZXRUaW1lKClcbiAgICAgICkge1xuICAgICAgICB0aGlzLmFjdGl2ZURhdGVDaGFuZ2UuZW1pdCh0aGlzLmFjdGl2ZURhdGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldENvbXBhcmVIYW5kbGVyKGhhbmRsZXI6IEZ1bmN0aW9uLCB0eXBlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodHlwZSA9PT0gJ2RheScpIHtcbiAgICAgIHRoaXMuY29tcGFyZUhhbmRsZXJEYXkgPSBoYW5kbGVyO1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnbW9udGgnKSB7XG4gICAgICB0aGlzLmNvbXBhcmVIYW5kbGVyTW9udGggPSBoYW5kbGVyO1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAneWVhcicpIHtcbiAgICAgIHRoaXMuY29tcGFyZUhhbmRsZXJZZWFyID0gaGFuZGxlcjtcbiAgICB9XG4gIH1cblxuICBjb21wYXJlKGRhdGUxOiBEYXRlLCBkYXRlMjogRGF0ZSk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGRhdGUxID09PSB1bmRlZmluZWQgfHwgZGF0ZTIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gJ2RheScgJiYgdGhpcy5jb21wYXJlSGFuZGxlckRheSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29tcGFyZUhhbmRsZXJEYXkoZGF0ZTEsIGRhdGUyKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gJ21vbnRoJyAmJiB0aGlzLmNvbXBhcmVIYW5kbGVyTW9udGgpIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbXBhcmVIYW5kbGVyTW9udGgoZGF0ZTEsIGRhdGUyKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gJ3llYXInICYmIHRoaXMuY29tcGFyZUhhbmRsZXJZZWFyKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb21wYXJlSGFuZGxlclllYXIoZGF0ZTEsIGRhdGUyKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdm9pZCAwO1xuICB9XG5cbiAgc2V0UmVmcmVzaFZpZXdIYW5kbGVyKGhhbmRsZXI6IEZ1bmN0aW9uLCB0eXBlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodHlwZSA9PT0gJ2RheScpIHtcbiAgICAgIHRoaXMucmVmcmVzaFZpZXdIYW5kbGVyRGF5ID0gaGFuZGxlcjtcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gJ21vbnRoJykge1xuICAgICAgdGhpcy5yZWZyZXNoVmlld0hhbmRsZXJNb250aCA9IGhhbmRsZXI7XG4gICAgfVxuXG4gICAgaWYgKHR5cGUgPT09ICd5ZWFyJykge1xuICAgICAgdGhpcy5yZWZyZXNoVmlld0hhbmRsZXJZZWFyID0gaGFuZGxlcjtcbiAgICB9XG4gIH1cblxuICByZWZyZXNoVmlldygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gJ2RheScgJiYgdGhpcy5yZWZyZXNoVmlld0hhbmRsZXJEYXkpIHtcbiAgICAgIHRoaXMucmVmcmVzaFZpZXdIYW5kbGVyRGF5KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZGF0ZXBpY2tlck1vZGUgPT09ICdtb250aCcgJiYgdGhpcy5yZWZyZXNoVmlld0hhbmRsZXJNb250aCkge1xuICAgICAgdGhpcy5yZWZyZXNoVmlld0hhbmRsZXJNb250aCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRhdGVwaWNrZXJNb2RlID09PSAneWVhcicgJiYgdGhpcy5yZWZyZXNoVmlld0hhbmRsZXJZZWFyKSB7XG4gICAgICB0aGlzLnJlZnJlc2hWaWV3SGFuZGxlclllYXIoKTtcbiAgICB9XG4gIH1cblxuICBkYXRlRmlsdGVyKGRhdGU6IERhdGUsIGZvcm1hdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5kYXRlRm9ybWF0dGVyLmZvcm1hdChkYXRlLCBmb3JtYXQsIHRoaXMubG9jYWxlKTtcbiAgfVxuXG4gIC8qIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tYW55Ki9cbiAgaXNBY3RpdmUoZGF0ZU9iamVjdDogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuY29tcGFyZShkYXRlT2JqZWN0LmRhdGUsIHRoaXMuYWN0aXZlRGF0ZSkgPT09IDApIHtcbiAgICAgIHRoaXMuYWN0aXZlRGF0ZUlkID0gZGF0ZU9iamVjdC51aWQ7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tYW55Ki9cbiAgY3JlYXRlRGF0ZU9iamVjdChkYXRlOiBEYXRlLCBmb3JtYXQ6IHN0cmluZyk6IGFueSB7XG4gICAgLyogdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby1hbnkqL1xuICAgIGNvbnN0IGRhdGVPYmplY3Q6IGFueSA9IHt9O1xuICAgIGRhdGVPYmplY3QuZGF0ZSA9IG5ldyBEYXRlKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgZGF0ZS5nZXREYXRlKClcbiAgICApO1xuICAgIGRhdGVPYmplY3QuZGF0ZSA9IHRoaXMuZml4VGltZVpvbmUoZGF0ZU9iamVjdC5kYXRlKTtcbiAgICBkYXRlT2JqZWN0LmxhYmVsID0gdGhpcy5kYXRlRmlsdGVyKGRhdGUsIGZvcm1hdCk7XG4gICAgZGF0ZU9iamVjdC5zZWxlY3RlZCA9IHRoaXMuY29tcGFyZShkYXRlLCB0aGlzLnNlbGVjdGVkRGF0ZSkgPT09IDA7XG4gICAgZGF0ZU9iamVjdC5kaXNhYmxlZCA9IHRoaXMuaXNEaXNhYmxlZChkYXRlKTtcbiAgICBkYXRlT2JqZWN0LmN1cnJlbnQgPSB0aGlzLmNvbXBhcmUoZGF0ZSwgbmV3IERhdGUoKSkgPT09IDA7XG4gICAgZGF0ZU9iamVjdC5jdXN0b21DbGFzcyA9IHRoaXMuZ2V0Q3VzdG9tQ2xhc3NGb3JEYXRlKGRhdGVPYmplY3QuZGF0ZSk7XG5cbiAgICByZXR1cm4gZGF0ZU9iamVjdDtcbiAgfVxuXG4gIC8qIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tYW55Ki9cbiAgc3BsaXQoYXJyOiBhbnlbXSwgc2l6ZTogbnVtYmVyKTogYW55W10ge1xuICAgIC8qIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tYW55Ki9cbiAgICBjb25zdCBhcnJheXM6IGFueVtdID0gW107XG4gICAgd2hpbGUgKGFyci5sZW5ndGggPiAwKSB7XG4gICAgICBhcnJheXMucHVzaChhcnIuc3BsaWNlKDAsIHNpemUpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJyYXlzO1xuICB9XG5cbiAgLy8gRml4IGEgaGFyZC1yZXByb2R1Y2libGUgYnVnIHdpdGggdGltZXpvbmVzXG4gIC8vIFRoZSBidWcgZGVwZW5kcyBvbiBPUywgYnJvd3NlciwgY3VycmVudCB0aW1lem9uZSBhbmQgY3VycmVudCBkYXRlXG4gIC8vIGkuZS5cbiAgLy8gdmFyIGRhdGUgPSBuZXcgRGF0ZSgyMDE0LCAwLCAxKTtcbiAgLy8gY29uc29sZS5sb2coZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpLFxuICAvLyBkYXRlLmdldEhvdXJzKCkpOyBjYW4gcmVzdWx0IGluIFwiMjAxMyAxMSAzMSAyM1wiIGJlY2F1c2Ugb2YgdGhlIGJ1Zy5cbiAgZml4VGltZVpvbmUoZGF0ZTogRGF0ZSk6IERhdGUge1xuICAgIGNvbnN0IGhvdXJzID0gZGF0ZS5nZXRIb3VycygpO1xuXG4gICAgcmV0dXJuIG5ldyBEYXRlKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgZGF0ZS5nZXREYXRlKCksXG4gICAgICBob3VycyA9PT0gMjMgPyBob3VycyArIDIgOiAwXG4gICAgKTtcbiAgfVxuXG4gIHNlbGVjdChkYXRlOiBEYXRlLCBpc01hbnVhbCA9IHRydWUpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gdGhpcy5taW5Nb2RlKSB7XG4gICAgICBpZiAoIXRoaXMuYWN0aXZlRGF0ZSkge1xuICAgICAgICB0aGlzLmFjdGl2ZURhdGUgPSBuZXcgRGF0ZSgwLCAwLCAwLCAwLCAwLCAwLCAwKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hY3RpdmVEYXRlID0gbmV3IERhdGUoXG4gICAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgICBkYXRlLmdldERhdGUoKVxuICAgICAgKTtcbiAgICAgIHRoaXMuYWN0aXZlRGF0ZSA9IHRoaXMuZml4VGltZVpvbmUodGhpcy5hY3RpdmVEYXRlKTtcbiAgICAgIGlmIChpc01hbnVhbCkge1xuICAgICAgICB0aGlzLnNlbGVjdGlvbkRvbmUuZW1pdCh0aGlzLmFjdGl2ZURhdGUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFjdGl2ZURhdGUgPSBuZXcgRGF0ZShcbiAgICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgICBkYXRlLmdldE1vbnRoKCksXG4gICAgICAgIGRhdGUuZ2V0RGF0ZSgpXG4gICAgICApO1xuICAgICAgdGhpcy5hY3RpdmVEYXRlID0gdGhpcy5maXhUaW1lWm9uZSh0aGlzLmFjdGl2ZURhdGUpO1xuICAgICAgaWYgKGlzTWFudWFsKSB7XG4gICAgICAgIHRoaXMuZGF0ZXBpY2tlck1vZGUgPSB0aGlzLm1vZGVzW1xuICAgICAgICAgIHRoaXMubW9kZXMuaW5kZXhPZih0aGlzLmRhdGVwaWNrZXJNb2RlKSAtIDFcbiAgICAgICAgXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IG5ldyBEYXRlKHRoaXMuYWN0aXZlRGF0ZS52YWx1ZU9mKCkpO1xuICAgIHRoaXMudXBkYXRlLmVtaXQodGhpcy5hY3RpdmVEYXRlKTtcbiAgICB0aGlzLnJlZnJlc2hWaWV3KCk7XG4gIH1cblxuICBtb3ZlKGRpcmVjdGlvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgLyogdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby1hbnkqL1xuICAgIGxldCBleHBlY3RlZFN0ZXA6IGFueTtcbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gJ2RheScpIHtcbiAgICAgIGV4cGVjdGVkU3RlcCA9IHRoaXMuc3RlcERheTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gJ21vbnRoJykge1xuICAgICAgZXhwZWN0ZWRTdGVwID0gdGhpcy5zdGVwTW9udGg7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZGF0ZXBpY2tlck1vZGUgPT09ICd5ZWFyJykge1xuICAgICAgZXhwZWN0ZWRTdGVwID0gdGhpcy5zdGVwWWVhcjtcbiAgICB9XG5cbiAgICBpZiAoZXhwZWN0ZWRTdGVwKSB7XG4gICAgICBjb25zdCB5ZWFyID1cbiAgICAgICAgdGhpcy5hY3RpdmVEYXRlLmdldEZ1bGxZZWFyKCkgKyBkaXJlY3Rpb24gKiAoZXhwZWN0ZWRTdGVwLnllYXJzIHx8IDApO1xuICAgICAgY29uc3QgbW9udGggPVxuICAgICAgICB0aGlzLmFjdGl2ZURhdGUuZ2V0TW9udGgoKSArIGRpcmVjdGlvbiAqIChleHBlY3RlZFN0ZXAubW9udGhzIHx8IDApO1xuICAgICAgdGhpcy5hY3RpdmVEYXRlID0gbmV3IERhdGUoeWVhciwgbW9udGgsIDEpO1xuXG4gICAgICB0aGlzLnJlZnJlc2hWaWV3KCk7XG4gICAgICB0aGlzLmFjdGl2ZURhdGVDaGFuZ2UuZW1pdCh0aGlzLmFjdGl2ZURhdGUpO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZU1vZGUoX2RpcmVjdGlvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgZGlyZWN0aW9uID0gX2RpcmVjdGlvbiB8fCAxO1xuXG4gICAgaWYgKFxuICAgICAgKHRoaXMuZGF0ZXBpY2tlck1vZGUgPT09IHRoaXMubWF4TW9kZSAmJiBkaXJlY3Rpb24gPT09IDEpIHx8XG4gICAgICAodGhpcy5kYXRlcGlja2VyTW9kZSA9PT0gdGhpcy5taW5Nb2RlICYmIGRpcmVjdGlvbiA9PT0gLTEpXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kYXRlcGlja2VyTW9kZSA9IHRoaXMubW9kZXNbXG4gICAgICB0aGlzLm1vZGVzLmluZGV4T2YodGhpcy5kYXRlcGlja2VyTW9kZSkgKyBkaXJlY3Rpb25cbiAgICBdO1xuICAgIHRoaXMucmVmcmVzaFZpZXcoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRDdXN0b21DbGFzc0ZvckRhdGUoZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLmN1c3RvbUNsYXNzKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIC8vIHRvZG86IGJ1aWxkIGEgaGFzaCBvZiBjdXN0b20gY2xhc3NlcywgaXQgd2lsbCB3b3JrIGZhc3RlclxuICAgIGNvbnN0IGN1c3RvbUNsYXNzT2JqZWN0OiB7XG4gICAgICBkYXRlOiBEYXRlO1xuICAgICAgbW9kZTogc3RyaW5nO1xuICAgICAgY2xheno6IHN0cmluZztcbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG5vLWFueSAqL1xuICAgIH0gPSB0aGlzLmN1c3RvbUNsYXNzLmZpbmQoKGN1c3RvbUNsYXNzOiBhbnkpID0+IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGN1c3RvbUNsYXNzLmRhdGUudmFsdWVPZigpID09PSBkYXRlLnZhbHVlT2YoKSAmJlxuICAgICAgICBjdXN0b21DbGFzcy5tb2RlID09PSB0aGlzLmRhdGVwaWNrZXJNb2RlXG4gICAgICApO1xuICAgIH0sIHRoaXMpO1xuXG4gICAgcmV0dXJuIGN1c3RvbUNsYXNzT2JqZWN0ID09PSB1bmRlZmluZWQgPyAnJyA6IGN1c3RvbUNsYXNzT2JqZWN0LmNsYXp6O1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbXBhcmVEYXRlRGlzYWJsZWQoXG4gICAgZGF0ZTFEaXNhYmxlZDogeyBkYXRlOiBEYXRlOyBtb2RlOiBzdHJpbmcgfSxcbiAgICBkYXRlMjogRGF0ZVxuICApOiBudW1iZXIge1xuICAgIGlmIChkYXRlMURpc2FibGVkID09PSB1bmRlZmluZWQgfHwgZGF0ZTIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoZGF0ZTFEaXNhYmxlZC5tb2RlID09PSAnZGF5JyAmJiB0aGlzLmNvbXBhcmVIYW5kbGVyRGF5KSB7XG4gICAgICByZXR1cm4gdGhpcy5jb21wYXJlSGFuZGxlckRheShkYXRlMURpc2FibGVkLmRhdGUsIGRhdGUyKTtcbiAgICB9XG5cbiAgICBpZiAoZGF0ZTFEaXNhYmxlZC5tb2RlID09PSAnbW9udGgnICYmIHRoaXMuY29tcGFyZUhhbmRsZXJNb250aCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29tcGFyZUhhbmRsZXJNb250aChkYXRlMURpc2FibGVkLmRhdGUsIGRhdGUyKTtcbiAgICB9XG5cbiAgICBpZiAoZGF0ZTFEaXNhYmxlZC5tb2RlID09PSAneWVhcicgJiYgdGhpcy5jb21wYXJlSGFuZGxlclllYXIpIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbXBhcmVIYW5kbGVyWWVhcihkYXRlMURpc2FibGVkLmRhdGUsIGRhdGUyKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJvdGVjdGVkIGlzRGlzYWJsZWQoZGF0ZTogRGF0ZSk6IGJvb2xlYW4ge1xuICAgIGxldCBpc0RhdGVEaXNhYmxlZCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmRhdGVEaXNhYmxlZCkge1xuICAgICAgdGhpcy5kYXRlRGlzYWJsZWQuZm9yRWFjaChcbiAgICAgICAgKGRpc2FibGVkRGF0ZTogeyBkYXRlOiBEYXRlOyBtb2RlOiBzdHJpbmcgfSkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLmNvbXBhcmVEYXRlRGlzYWJsZWQoZGlzYWJsZWREYXRlLCBkYXRlKSA9PT0gMCkge1xuICAgICAgICAgICAgaXNEYXRlRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5kYXlEaXNhYmxlZCkge1xuICAgICAgaXNEYXRlRGlzYWJsZWQgPVxuICAgICAgICBpc0RhdGVEaXNhYmxlZCB8fFxuICAgICAgICB0aGlzLmRheURpc2FibGVkLmluZGV4T2YoZGF0ZS5nZXREYXkoKSkgPiAtMTtcbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgaXNEYXRlRGlzYWJsZWQgfHxcbiAgICAgICh0aGlzLm1pbkRhdGUgJiYgdGhpcy5jb21wYXJlKGRhdGUsIHRoaXMubWluRGF0ZSkgPCAwKSB8fFxuICAgICAgKHRoaXMubWF4RGF0ZSAmJiB0aGlzLmNvbXBhcmUoZGF0ZSwgdGhpcy5tYXhEYXRlKSA+IDApXG4gICAgKTtcbiAgfVxufVxuIl19