TimeTrex/interface/html5/dist/BaseViewController.bundle.js

1 line
883 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(self.webpackChunktimetrex=self.webpackChunktimetrex||[]).push([["BaseViewController","paging-Paging2"],{5583:(__unused_webpack_module,__unused_webpack_exports,__webpack_require__)=>{eval("/* provided dependency */ var jQuery = __webpack_require__(9755);\n( function( $ ) {\n\n\t$.fn.Paging2 = function( options ) {\n\t\tvar opts = $.extend( {}, $.fn.Paging2.defaults, options );\n\t\tvar $this = this;\n\t\tvar pager_data;\n\t\tvar start;\n\t\tvar last;\n\t\tvar next;\n\t\tvar end;\n\t\tvar paging_selector;\n\t\tvar left_buttons_div;\n\t\tvar right_buttons_div;\n\n\t\tvar left_buttons_enable;\n\t\tvar right_buttons_enable;\n\n\t\tthis.getPagerData = function() {\n\t\t\treturn pager_data;\n\t\t},\n\n\t\t\tthis.setPagerData = function( value ) {\n\n\t\t\t\tpager_data = value;\n\n\t\t\t\tif ( !pager_data ) {\n\t\t\t\t\t$( this.css( 'display', 'none' ) );\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\t$( this.css( 'display', 'block' ) );\n\t\t\t\t}\n\n\t\t\t\t$( paging_selector ).empty();\n\n\t\t\t\tvar len = pager_data.last_page_number;\n\n\t\t\t\tif ( len === -1 ) {\n\t\t\t\t\t$( paging_selector ).append( '<option value=\"' + 1 + '\">' + 1 + '</option>' );\n\t\t\t\t} else {\n\t\t\t\t\tfor ( var i = 1; i <= len; i++ ) {\n\t\t\t\t\t\t$( paging_selector ).append( '<option value=\"' + i + '\">' + i + '</option>' );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$( $( paging_selector ).find( 'option' ) ).filter( function() {\n\t\t\t\t\tvar current_value = parseInt( $( this ).attr( 'value' ) );\n\n\t\t\t\t\treturn current_value === pager_data.current_page;\n\t\t\t\t} ).prop( 'selected', true ).prop( 'selected', true );\n\n\t\t\t\tif ( pager_data.is_last_page === true ) {\n\t\t\t\t\tright_buttons_div.addClass( 'disabled' );\n\t\t\t\t\tright_buttons_div.addClass( 'disabled-image' );\n\t\t\t\t\tright_buttons_enable = false;\n\t\t\t\t} else {\n\t\t\t\t\tright_buttons_div.removeClass( 'disabled' );\n\t\t\t\t\tright_buttons_div.removeClass( 'disabled-image' );\n\t\t\t\t\tright_buttons_enable = true;\n\t\t\t\t}\n\n\t\t\t\tif ( pager_data.is_first_page ) {\n\t\t\t\t\tleft_buttons_div.addClass( 'disabled' );\n\t\t\t\t\tleft_buttons_div.addClass( 'disabled-image' );\n\t\t\t\t\tleft_buttons_enable = false;\n\n\t\t\t\t} else {\n\t\t\t\t\tleft_buttons_div.removeClass( 'disabled' );\n\t\t\t\t\tleft_buttons_div.removeClass( 'disabled-image' );\n\t\t\t\t\tleft_buttons_enable = true;\n\t\t\t\t}\n\n\t\t\t\tif ( len === -1 || ( pager_data.is_first_page && pager_data.is_last_page ) ) {\n\n\t\t\t\t\tleft_buttons_div.addClass( 'disabled' );\n\t\t\t\t\tleft_buttons_div.addClass( 'disabled-image' );\n\t\t\t\t\tleft_buttons_enable = false;\n\t\t\t\t\tright_buttons_div.addClass( 'disabled' );\n\t\t\t\t\tright_buttons_div.addClass( 'disabled-image' );\n\t\t\t\t\tright_buttons_enable = false;\n\n\t\t\t\t\t$this.hide();\n\t\t\t\t} else {\n\t\t\t\t\t$this.show();\n\t\t\t\t}\n\n\t\t\t};\n\n\t\tthis.each( function() {\n\n\t\t\tvar o = $.meta ? $.extend( {}, opts, $( this ).data() ) : opts;\n\n\t\t\tvar pages_label = $( this ).find( '.page-label-span' );\n\n\t\t\tpages_label.text( $.i18n._( 'Page' ) );\n\n\t\t\tleft_buttons_div = $( this ).find( '.left-buttons-div' );\n\t\t\tright_buttons_div = $( this ).find( '.right-buttons-div' );\n\n\t\t\tstart = $( this ).find( '.start' );\n\t\t\tlast = $( this ).find( '.last' );\n\t\t\tnext = $( this ).find( '.next' );\n\t\t\tend = $( this ).find( '.end' );\n\t\t\tpaging_selector = $( this ).find( '.paging-selector' );\n\n\t\t\tstart.text( $.i18n._( 'Start' ) );\n\t\t\tlast.text( $.i18n._( 'Previous' ) );\n\n\t\t\tnext.text( $.i18n._( 'Next' ) );\n\t\t\tend.text( $.i18n._( 'End' ) );\n\n\t\t\t$( this ).hide();\n\n\t\t\tstart.click( function() {\n\t\t\t\tif ( left_buttons_enable ) {\n\t\t\t\t\t$this.trigger( 'paging', ['start'] );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tlast.click( function() {\n\t\t\t\tif ( left_buttons_enable ) {\n\t\t\t\t\t$this.trigger( 'paging', ['last'] );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tnext.click( function() {\n\t\t\t\tif ( right_buttons_enable ) {\n\t\t\t\t\t$this.trigger( 'paging', ['next'] );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tend.click( function() {\n\t\t\t\tif ( right_buttons_enable ) {\n\t\t\t\t\t$this.trigger( 'paging', ['end'] );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t$( paging_selector ).change( $.proxy( function() {\n\n\t\t\t\t$( paging_selector ).find( 'option:selected' ).each( function() {\n\t\t\t\t\tvar page_number = $( this ).attr( 'value' );\n\t\t\t\t\t$this.trigger( 'paging', ['go_to', page_number] );\n\t\t\t\t} );\n\n\t\t\t}, this ) );\n\n\t\t} );\n\n\t\treturn this;\n\n\t};\n\n\t$.fn.Paging2.defaults = {};\n\t$.fn.Paging2.html = {\n\t\tpaging: `<div class=\"paging-div\"><span class=\"paging-span\">CLICK TO SHOW MORE</span></div>`,\n\t\tpaging2: `\n\t\t\t<div class=\"paging-2-div\">\n\t\t\t\t<div class=\"left-buttons-div\">\n\t\t\t\t\t<span class=\"double-left-arrow pi pi-angle-double-left\" title=\"Start\"></span>\n\t\t\t\t\t<span class=\"paging-2-span start\"></span>\n\t\t\t\t\t<span class=\"left-arrow pi pi-angle-left\"></span>\n\t\t\t\t\t<span class=\"paging-2-span last\"></span>\n\t\t\t\t</div>\n\t\t\t\t<span class=\"page-label-span\"></span>\n\t\t\t\t<select class=\"t-select paging-selector\">\n\t\t\t\t</select>\n\t\t\t\t<div class=\"right-buttons-div\">\n\t\t\t\t\t<span class=\"paging-2-span next\"></span>\n\t\t\t\t\t<span class=\"right-arrow pi pi-angle-right\"></span>\n\t\t\t\t\t<span class=\"paging-2-span end\"></span>\n\t\t\t\t\t<span class=\"double-right-arrow pi pi-angle-double-right\"></span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t};\n\n} )\n( jQuery );//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNTU4My5qcyIsIm1hcHBpbmdzIjoiO0FBQUE7O0FBRUE7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTixzQkFBc0IsVUFBVTtBQUNoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBOztBQUVBLGdDQUFnQzs7QUFFaEM7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTixJQUFJOztBQUVKLElBQUk7O0FBRUo7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0YsRUFBRSxNQUFNIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vaW50ZXJmYWNlL2h0bWw1L2dsb2JhbC93aWRnZXRzL3BhZ2luZy9QYWdpbmcyLmpzPzM3MTciXSwic291cmNlc0NvbnRlbnQiOlsiKCBmdW5jdGlvbiggJCApIHtcblxuXHQkLmZuLlBhZ2luZzIgPSBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0XHR2YXIgb3B0cyA9ICQuZXh0ZW5kKCB7fSwgJC5mbi5QYWdpbmcyLmRlZmF1bHRzLCBvcHRpb25zICk7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgcGFnZXJfZGF0YTtcblx0XHR2YXIgc3RhcnQ7XG5cdFx0dmFyIGxhc3Q7XG5cdFx0dmFyIG5leHQ7XG5cdFx0dmFyIGVuZDtcblx0XHR2YXIgcGFnaW5nX3NlbGVjdG9yO1xuXHRcdHZhciBsZWZ0X2J1dHRvbnNfZGl2O1xuXHRcdHZhciByaWdodF9idXR0b25zX2RpdjtcblxuXHRcdHZhciBsZWZ0X2J1dHRvbnNfZW5hYmxlO1xuXHRcdHZhciByaWdodF9idXR0b25zX2VuYWJsZTtcblxuXHRcdHRoaXMuZ2V0UGFnZXJEYXRhID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gcGFnZXJfZGF0YTtcblx0XHR9LFxuXG5cdFx0XHR0aGlzLnNldFBhZ2VyRGF0YSA9IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblxuXHRcdFx0XHRwYWdlcl9kYXRhID0gdmFsdWU7XG5cblx0XHRcdFx0aWYgKCAhcGFnZXJfZGF0YSApIHtcblx0XHRcdFx0XHQkKCB0aGlzLmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKSApO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkKCB0aGlzLmNzcyggJ2Rpc3BsYXknLCAnYmxvY2snICkgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQoIHBhZ2luZ19zZWxlY3RvciApLmVtcHR5KCk7XG5cblx0XHRcdFx0dmFyIGxlbiA9IHBhZ2VyX2RhdGEubGFzdF9wYWdlX251bWJlcjtcblxuXHRcdFx0XHRpZiAoIGxlbiA9PT0gLTEgKSB7XG5cdFx0XHRcdFx0JCggcGFnaW5nX3NlbGVjdG9yICkuYXBwZW5kKCAnPG9wdGlvbiB2YWx1ZT1cIicgKyAxICsgJ1wiPicgKyAxICsgJzwvb3B0aW9uPicgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRmb3IgKCB2YXIgaSA9IDE7IGkgPD0gbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0XHQkKCBwYWdpbmdfc2VsZWN0b3IgKS5hcHBlbmQoICc8b3B0aW9uIHZhbHVlPVwiJyArIGkgKyAnXCI+JyArIGkgKyAnPC9vcHRpb24+JyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQoICQoIHBhZ2luZ19zZWxlY3RvciApLmZpbmQoICdvcHRpb24nICkgKS5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciBjdXJyZW50X3ZhbHVlID0gcGFyc2VJbnQoICQoIHRoaXMgKS5hdHRyKCAndmFsdWUnICkgKTtcblxuXHRcdFx0XHRcdHJldHVybiBjdXJyZW50X3ZhbHVlID09PSBwYWdlcl9kYXRhLmN1cnJlbnRfcGFnZTtcblx0XHRcdFx0fSApLnByb3AoICdzZWxlY3RlZCcsIHRydWUgKS5wcm9wKCAnc2VsZWN0ZWQnLCB0cnVlICk7XG5cblx0XHRcdFx0aWYgKCBwYWdlcl9kYXRhLmlzX2xhc3RfcGFnZSA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRyaWdodF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2LmFkZENsYXNzKCAnZGlzYWJsZWQtaW1hZ2UnICk7XG5cdFx0XHRcdFx0cmlnaHRfYnV0dG9uc19lbmFibGUgPSBmYWxzZTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyaWdodF9idXR0b25zX2Rpdi5yZW1vdmVDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2LnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQtaW1hZ2UnICk7XG5cdFx0XHRcdFx0cmlnaHRfYnV0dG9uc19lbmFibGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBwYWdlcl9kYXRhLmlzX2ZpcnN0X3BhZ2UgKSB7XG5cdFx0XHRcdFx0bGVmdF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdGxlZnRfYnV0dG9uc19kaXYuYWRkQ2xhc3MoICdkaXNhYmxlZC1pbWFnZScgKTtcblx0XHRcdFx0XHRsZWZ0X2J1dHRvbnNfZW5hYmxlID0gZmFsc2U7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsZWZ0X2J1dHRvbnNfZGl2LnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHRcdFx0bGVmdF9idXR0b25zX2Rpdi5yZW1vdmVDbGFzcyggJ2Rpc2FibGVkLWltYWdlJyApO1xuXHRcdFx0XHRcdGxlZnRfYnV0dG9uc19lbmFibGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBsZW4gPT09IC0xIHx8ICggcGFnZXJfZGF0YS5pc19maXJzdF9wYWdlICYmIHBhZ2VyX2RhdGEuaXNfbGFzdF9wYWdlICkgKSB7XG5cblx0XHRcdFx0XHRsZWZ0X2J1dHRvbnNfZGl2LmFkZENsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHRcdFx0bGVmdF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkLWltYWdlJyApO1xuXHRcdFx0XHRcdGxlZnRfYnV0dG9uc19lbmFibGUgPSBmYWxzZTtcblx0XHRcdFx0XHRyaWdodF9idXR0b25zX2Rpdi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2LmFkZENsYXNzKCAnZGlzYWJsZWQtaW1hZ2UnICk7XG5cdFx0XHRcdFx0cmlnaHRfYnV0dG9uc19lbmFibGUgPSBmYWxzZTtcblxuXHRcdFx0XHRcdCR0aGlzLmhpZGUoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5zaG93KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fTtcblxuXHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBvID0gJC5tZXRhID8gJC5leHRlbmQoIHt9LCBvcHRzLCAkKCB0aGlzICkuZGF0YSgpICkgOiBvcHRzO1xuXG5cdFx0XHR2YXIgcGFnZXNfbGFiZWwgPSAkKCB0aGlzICkuZmluZCggJy5wYWdlLWxhYmVsLXNwYW4nICk7XG5cblx0XHRcdHBhZ2VzX2xhYmVsLnRleHQoICQuaTE4bi5fKCAnUGFnZScgKSApO1xuXG5cdFx0XHRsZWZ0X2J1dHRvbnNfZGl2ID0gJCggdGhpcyApLmZpbmQoICcubGVmdC1idXR0b25zLWRpdicgKTtcblx0XHRcdHJpZ2h0X2J1dHRvbnNfZGl2ID0gJCggdGhpcyApLmZpbmQoICcucmlnaHQtYnV0dG9ucy1kaXYnICk7XG5cblx0XHRcdHN0YXJ0ID0gJCggdGhpcyApLmZpbmQoICcuc3RhcnQnICk7XG5cdFx0XHRsYXN0ID0gJCggdGhpcyApLmZpbmQoICcubGFzdCcgKTtcblx0XHRcdG5leHQgPSAkKCB0aGlzICkuZmluZCggJy5uZXh0JyApO1xuXHRcdFx0ZW5kID0gJCggdGhpcyApLmZpbmQoICcuZW5kJyApO1xuXHRcdFx0cGFnaW5nX3NlbGVjdG9yID0gJCggdGhpcyApLmZpbmQoICcucGFnaW5nLXNlbGVjdG9yJyApO1xuXG5cdFx0XHRzdGFydC50ZXh0KCAkLmkxOG4uXyggJ1N0YXJ0JyApICk7XG5cdFx0XHRsYXN0LnRleHQoICQuaTE4bi5fKCAnUHJldmlvdXMnICkgKTtcblxuXHRcdFx0bmV4dC50ZXh0KCAkLmkxOG4uXyggJ05leHQnICkgKTtcblx0XHRcdGVuZC50ZXh0KCAkLmkxOG4uXyggJ0VuZCcgKSApO1xuXG5cdFx0XHQkKCB0aGlzICkuaGlkZSgpO1xuXG5cdFx0XHRzdGFydC5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGVmdF9idXR0b25zX2VuYWJsZSApIHtcblx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCAncGFnaW5nJywgWydzdGFydCddICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0bGFzdC5jbGljayggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGVmdF9idXR0b25zX2VuYWJsZSApIHtcblx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCAncGFnaW5nJywgWydsYXN0J10gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0XHRuZXh0LmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCByaWdodF9idXR0b25zX2VuYWJsZSApIHtcblx0XHRcdFx0XHQkdGhpcy50cmlnZ2VyKCAncGFnaW5nJywgWyduZXh0J10gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0XHRlbmQuY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHJpZ2h0X2J1dHRvbnNfZW5hYmxlICkge1xuXHRcdFx0XHRcdCR0aGlzLnRyaWdnZXIoICdwYWdpbmcnLCBbJ2VuZCddICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0JCggcGFnaW5nX3NlbGVjdG9yICkuY2hhbmdlKCAkLnByb3h5KCBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHQkKCBwYWdpbmdfc2VsZWN0b3IgKS5maW5kKCAnb3B0aW9uOnNlbGVjdGVkJyApLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciBwYWdlX251bWJlciA9ICQoIHRoaXMgKS5hdHRyKCAndmFsdWUnICk7XG5cdFx0XHRcdFx0JHRoaXMudHJpZ2dlciggJ3BhZ2luZycsIFsnZ29fdG8nLCBwYWdlX251bWJlcl0gKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9LCB0aGlzICkgKTtcblxuXHRcdH0gKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH07XG5cblx0JC5mbi5QYWdpbmcyLmRlZmF1bHRzID0ge307XG5cdCQuZm4uUGFnaW5nMi5odG1sID0ge1xuXHRcdHBhZ2luZzogYDxkaXYgY2xhc3M9XCJwYWdpbmctZGl2XCI+PHNwYW4gY2xhc3M9XCJwYWdpbmctc3BhblwiPkNMSUNLIFRPIFNIT1cgTU9SRTwvc3Bhbj48L2Rpdj5gLFxuXHRcdHBhZ2luZzI6IGBcblx0XHRcdDxkaXYgY2xhc3M9XCJwYWdpbmctMi1kaXZcIj5cblx0XHRcdFx0PGRpdiBjbGFzcz1cImxlZnQtYnV0dG9ucy1kaXZcIj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cImRvdWJsZS1sZWZ0LWFycm93IHBpIHBpLWFuZ2xlLWRvdWJsZS1sZWZ0XCIgdGl0bGU9XCJTdGFydFwiPjwvc3Bhbj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cInBhZ2luZy0yLXNwYW4gc3RhcnRcIj48L3NwYW4+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJsZWZ0LWFycm93IHBpIHBpLWFuZ2xlLWxlZnRcIj48L3NwYW4+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJwYWdpbmctMi1zcGFuIGxhc3RcIj48L3NwYW4+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8c3BhbiBjbGFzcz1cInBhZ2UtbGFiZWwtc3BhblwiPjwvc3Bhbj5cblx0XHRcdFx0PHNlbGVjdCBjbGFzcz1cInQtc2VsZWN0IHBhZ2luZy1zZWxlY3RvclwiPlxuXHRcdFx0XHQ8L3NlbGVjdD5cblx0XHRcdFx0PGRpdiBjbGFzcz1cInJpZ2h0LWJ1dHRvbnMtZGl2XCI+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJwYWdpbmctMi1zcGFuIG5leHRcIj48L3NwYW4+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJyaWdodC1hcnJvdyBwaSBwaS1hbmdsZS1yaWdodFwiPjwvc3Bhbj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cInBhZ2luZy0yLXNwYW4gZW5kXCI+PC9zcGFuPlxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzPVwiZG91YmxlLXJpZ2h0LWFycm93IHBpIHBpLWFuZ2xlLWRvdWJsZS1yaWdodFwiPjwvc3Bhbj5cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQ8L2Rpdj5cblx0XHRgXG5cdH07XG5cbn0gKVxuKCBqUXVlcnkgKTsiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///5583\n")},121:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BaseViewController\": () => (/* binding */ BaseViewController)\n/* harmony export */ });\n/* harmony import */ var _views_TTBackboneView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6739);\n/* harmony import */ var _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7526);\n/* harmony import */ var _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2548);\n/* harmony import */ var _global_widgets_paging_Paging2_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5583);\n/* harmony import */ var _global_widgets_paging_Paging2_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_global_widgets_paging_Paging2_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _global_Global__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9490);\n/* harmony import */ var _services_HtmlTemplates__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4578);\n/* provided dependency */ var _ = __webpack_require__(9050);\n/* provided dependency */ var $ = __webpack_require__(9755);\n/* provided dependency */ var jQuery = __webpack_require__(9755);\n\n\n // TODO: duplicated in merged js files.\n\n\n\n\nwindow.FormItemType = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType; // TODO: Eventually refactor to import only where these are used.\nwindow.WidgetNamesDic = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic; // TODO: Eventually refactor to import only where these are used.\n\n/* jshint ignore:start */\n\n//Don't check this file for now. Too many issues.\nclass BaseViewController extends _views_TTBackboneView__WEBPACK_IMPORTED_MODULE_0__.TTBackboneView {\n\tconstructor( options = {} ) {\n\t\t_.defaults( options, {\n\t\t\treal_this: null, //For super call in second level sub class\n\n\t\t\tsub_view_mode: false,\n\n\t\t\tedit_only_mode: false,\n\n\t\t\tcan_cache_controller: true, //if allow to cache current controller\n\n\t\t\tpermission_id: '',\n\t\t\tapi: null,\n\t\t\tuser_generic_data_api: null,\n\t\t\tall_columns: [],\n\t\t\tdisplay_columns: [],\n\t\t\tdefault_display_columns: [],\n\t\t\tscript_name: '',\n\t\t\tfilter_data: null, //current Filter data get from Search panel\n\t\t\ttemp_basic_filter_data: null,\n\t\t\ttemp_adv_filter_data: null,\n\t\t\tsortData: null, //Current Sort data get from search panel\n\t\t\tselect_layout: null,\n\t\t\tlayout_changed: false,\n\t\t\tsearch_panel: null,\n\t\t\tgrid: null,\n\t\t\tcontext_menu_name: '',\n\t\t\tnavigation_label: '',\n\t\t\tcontext_menu_array: [],\n\t\t\tt_grid_header_array: [],\n\n\t\t\t//Column Selector in search panel\n\t\t\tcolumn_selector: null,\n\n\t\t\tsort_by_selector: null,\n\n\t\t\tsave_search_as_input: null,\n\n\t\t\tprevious_saved_layout_selector: null,\n\n\t\t\tprevious_saved_layout_div: null,\n\n\t\t\tneed_select_layout_name: '', //Set this when save new layout to choose the new layout\n\n\t\t\tsearch_fields: null,\n\n\t\t\tbasic_search_field_ui_dic: {}, //Save AwesomeBox when they created\n\n\t\t\tadv_search_field_ui_dic: {}, //Save AwesomeBox when they created\n\n\t\t\tedit_view_ui_dic: {},\n\n\t\t\tedit_view_ui_validation_field_dic: {},\n\n\t\t\tedit_view_form_item_dic: {}, //Whole FormItem\n\n\t\t\tedit_view_error_ui_dic: {},\n\n\t\t\tedit_view: null,\n\n\t\t\tedit_view_tab: null,\n\n\t\t\tcurrent_edit_record: null, //Current edit record\n\n\t\t\trefresh_id: null, //Set this to refresh one record in grid view.\n\n\t\t\tnavigation: null, // Navigation widget in edit view\n\n\t\t\tis_mass_editing: false, //Set when mass edit\n\n\t\t\tis_viewing: false,\n\t\t\tis_viewing_detail: false,\n\t\t\tis_edit: false,\n\t\t\tis_add: false,\n\n\t\t\tunique_columns: [], //Set when Mass edit, mark which fields need to be disable\n\n\t\t\tlinked_fields: [],\n\n\t\t\tmass_edit_record_ids: [], // Mass edit records\n\n\t\t\tedit_view_tabs: [],\n\n\t\t\trefresh_sub_view: false,\n\n\t\t\tparent_key: null, //default filter when search\n\n\t\t\tparent_value: null, //default filter when search\n\n\t\t\tparent_edit_record: null,\n\n\t\t\ttotal_display_span: null,\n\n\t\t\tpaging_widget: null,\n\n\t\t\tpaging_widget_2: null, //Put in the bottom of data grid\n\n\t\t\tpager_data: null,\n\n\t\t\tviewId: null,\n\n\t\t\tinit_options_complete: false,\n\n\t\t\tno_result_box: null, // No Result Found Black cover when no result in grid\n\n\t\t\ttable_name_key: null,\n\n\t\t\tsub_log_view_controller: null,\n\n\t\t\tparent_view_controller: null, //Add this to call parent_view_controll cancel action when cancel from sub view\n\n\t\t\tui_id: '',\n\n\t\t\tis_changed: false, // Track if modified any fields in edit view\n\n\t\t\tconfirm_on_exit: false, //confirm before leaving the edit view even if no changes have been made\n\n\t\t\tedit_view_tpl: '', //Edit view html name\n\n\t\t\tsubMenuNavMap: null,\n\n\t\t\ttrySetGridSizeWhenTabShow: false, // Set sub view grid size when tab show instead when tab select\n\n\t\t\tcopied_record_id: '', // When copy as new, save copied reord's id\n\n\t\t\tcustom_field_api: null,\n\n\t\t\tlast_select_ids: null,\n\n\t\t\tsaving_layout_in_layout_tab: false, //Mark if save layout from Saved and layout tab. if so, don't switch tabs when set values to search panel\n\n\t\t\tneed_switch_to_context_menu: false,\n\n\t\t\tshow_search_tab: true,\n\n\t\t\tgrid_total_width: null,\n\n\t\t\tshow_warning_when_validation: false,\n\n\t\t\tpulse_time_dic: false,\n\n\t\t\tedit_view_close_icon: null,\n\n\t\t\tenable_validation: true,\n\n\t\t\t// _required_files: null,\n\n\t\t\ttab_model: null, //Tab definitions and a map to their callbacks.\n\n\t\t\tgrid_parent: null,\n\n\t\t\tcustom_fields: []\n\t\t} );\n\t\tsuper( options );\n\t}\n\n\t// getRequiredFiles() {\n\t// \t//override in child class\n\t// \treturn [];\n\t// }\n\n\t/**\n\t * When changing this function, you need to look for all occurences of this function because it was needed in several bases\n\t * BaseViewController, HomeViewController, BaseWizardController, QuickPunchBaseViewControler\n\t *\n\t * @returns {Array}\n\t */\n\t// filterRequiredFiles() {\n\t// \tDebug.Warn( 'Deprecated requirejs function. Replace usage immediately with webpack loaders.', 'BaseViewController.js', 'BaseViewController', 'filterRequiredFiles', 2 );\n\t//\n\t// \tvar retval = [];\n\t// \tvar required_files;\n\t//\n\t// \tif ( typeof this._required_files == 'object' ) {\n\t// \t\trequired_files = this._required_files;\n\t// \t} else {\n\t// \t\trequired_files = this.getRequiredFiles();\n\t// \t}\n\t//\n\t// \tif ( required_files && required_files[0] ) {\n\t// \t\tretval = required_files;\n\t// \t} else {\n\t// \t\tfor ( var edition_id in required_files ) {\n\t// \t\t\tif ( Global.getProductEdition() >= edition_id ) {\n\t// \t\t\t\tretval = retval.concat( required_files[edition_id] );\n\t// \t\t\t}\n\t// \t\t}\n\t// \t}\n\t//\n\t// \tDebug.Arr( retval, 'RETVAL', 'BaseViewController.js', 'BaseViewController', 'filterRequiredFiles', 10 );\n\t// \treturn retval;\n\t// }\n\n\tpreInit() {\n\t\t//override in child class\n\t}\n\n\tinitialize( options ) {\n\t\tDebug.Text( 'INITIALIZE', 'BaseViewController.js', 'BaseViewController', 'initialize', 10 );\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setUINotready */ .x.setUINotready();\n\n\t\tsuper.initialize( options );\n\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.add( 'BaseViewController', 'initialize' );\n\t\t//trigger readystate update\n\t\tTTPromise.wait();\n\n\t\tvar $this = this;\n\t\tthis.layout_changed = false;\n\t\t// var required_files = this.filterRequiredFiles();\n\n\t\t// __non_webpack_require__( required_files, function() { // This is to prevent conflict with the Webpack Node require calls.\n\t\t// Debug.Warn( 'Deprecated requirejs function. Replace usage immediately with webpack loaders.', 'BaseViewController.js', 'BaseViewController', 'initialize', 2 );\n\n\t\tsetTimeout(function() { // #2662 This setTimeout is essential in keeping the code flow the same as when this code block has a requirejs callback. Otherwise it causes issues in many areas like Audit logs going blank, as the subview postInit function is called before its set in afterLoadView().\n\n\t\t\t$this.preInit( options );\n\n\t\t\t$this.options = options;\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.can_cache_controller ) ) {\n\t\t\t\t$this.can_cache_controller = $this.options.can_cache_controller;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.edit_only_mode ) ) {\n\t\t\t\t$this.edit_only_mode = $this.options.edit_only_mode;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.sub_view_mode ) ) {\n\t\t\t\t$this.sub_view_mode = $this.options.sub_view_mode;\n\t\t\t} else {\n\t\t\t\t$this.sub_view_mode = false;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.parent_view ) ) {\n\t\t\t\t$this.parent_view = $this.options.parent_view;\n\t\t\t}\n\n\t\t\tif ( $this.options && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.options.parent_view_controller ) ) {\n\t\t\t\t$this.parent_view_controller = $this.options.parent_view_controller;\n\t\t\t}\n\n\t\t\tif ( !$this.edit_only_mode ) {\n\n\t\t\t\tif ( $this.can_cache_controller ) {\n\t\t\t\t\tif ( !$this.sub_view_mode ) {\n\t\t\t\t\t\tLocalCacheData.current_open_primary_controller = $this;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLocalCacheData.current_open_sub_controller = $this;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//Reset main container id so it won't duplicate when in sub view. Like Audit view.\n\t\t\t\tvar root_container = $( $this.el );\n\t\t\t\tvar new_id = root_container.attr( 'id' ) + '_' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRandomNum */ .x.getRandomNum();\n\t\t\t\troot_container.attr( 'id', new_id );\n\t\t\t\t$this.el = '#' + new_id;\n\t\t\t\t$this.ui_id = new_id;\n\n\t\t\t\t$this.user_generic_data_api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APIUserGenericData */ .y.APIUserGenericData;\n\n\t\t\t\t$this.total_display_span = $( $( $this.el ).find( '.total-number-span' )[0] );\n\n\t\t\t\t//$this shouldn't be displayed as it caused \"flashing\" of text and it wasn't translated either.\n\t\t\t\t//if ( $this.total_display_span ) {\n\t\t\t\t//$this.total_display_span.text( 'Displaying 0 - 0 of 0 total. Selected: 0' );\n\t\t\t\t//}\n\n\t\t\t\t//JS load Optimize\n\t\t\t\tif ( LocalCacheData.loadViewRequiredJSReady ) {\n\t\t\t\t\t//Init paging widget, next step, add widget to UI and bind events in setSelectLayout\n\t\t\t\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\t\t\t\t$this.paging_widget = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.PAGING );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.paging_widget = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.PAGING_2 );\n\t\t\t\t\t\t$this.paging_widget_2 = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.PAGING_2 );\n\t\t\t\t\t\t$this.paging_widget = $this.paging_widget.Paging2();\n\t\t\t\t\t\t$this.paging_widget_2 = $this.paging_widget_2.Paging2();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$this.ui_id = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRandomNum */ .x.getRandomNum();\n\t\t\t}\n\n\t\t\t//init all dic or array, or it will extends last viewcontroller's value. Why?\n\t\t\t$this.sub_log_view_controller = null;\n\t\t\t$this.edit_view_ui_dic = {};\n\t\t\t$this.edit_view_ui_validation_field_dic = {};\n\t\t\t$this.basic_search_field_ui_dic = {};\n\t\t\t$this.adv_search_field_ui_dic = {};\n\t\t\t$this.edit_view_tabs = [];\n\n\t\t\t$this.custom_field_api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APICustomField */ .y.APICustomField;\n\n\t\t\t$this.initKeyboardEvent(); // register keyboard events if it's a main view\n\n\t\t\t$this.init( options );\n\t\t\t$this.postInit( options );\n\n\t\t\tTTPromise.resolve( 'BaseViewController', 'initialize' );\n\t\t\tTTPromise.resolve( 'init', 'init' );\n\t\t}, 1);\n\t}\n\n\tinit() {\n\t\t//override in child class\n\t}\n\n\tpostInit() {\n\t\t//override in child class\n\t}\n\n\tinitKeyboardEvent() {\n\n\t\tvar $this = this;\n\t\tif ( this.sub_view_mode || this.edit_only_mode ) {\n\t\t\treturn;\n\t\t}\n\n//\t\t$( this.el ).unbind( 'keydown' ).bind( 'keydown', function( e ) {\n//\n//\t\t\tif ( e.keyCode === 13 && !$this.search_panel.isCollapsed() ) {\n//\t\t\t\t$this.onSearch();\n//\t\t\t}\n//\n//\t\t} );\n\n\t\t$( this.el ).unbind( 'keyup' ).bind( 'keydown', function( e ) {\n\n\t\t\tif ( e.keyCode === 13 && $this.search_panel && !$this.search_panel.isCollapsed() ) {\n\n\t\t\t\t$this.onSearch();\n\t\t\t\t$( ':focus' ).blur(); //Make focus out of current view. pevent search too much when user keep click enter\n\t\t\t}\n\t\t} );\n\t}\n\n\t//Speical permission check for views, need override\n\tinitPermission() {\n\t}\n\n\t//Set this when setDefault menu\n\tsetTotalDisplaySpan() {\n\t\tif ( !this.total_display_span ) {\n\t\t\treturn;\n\t\t}\n\t\tvar totalRows;\n\t\tvar start;\n\t\tvar end;\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = 0;\n\t\t//Uncaught TypeError: Cannot read property 'length' of undefined\n\t\tif ( grid_selected_id_array ) {\n\t\t\tgrid_selected_length = grid_selected_id_array.length;\n\t\t}\n\n\t\tvar items_pre_page = 100;\n\t\tif ( LocalCacheData.getLoginUserPreference() ) {\n\t\t\tvar items_per_page = parseInt( LocalCacheData.getLoginUserPreference().items_per_page );\n\t\t}\n\n\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\tif ( this.pager_data ) {\n\t\t\t\ttotalRows = this.pager_data.total_rows;\n\t\t\t\tstart = 1;\n\t\t\t\tend = this.grid.getData().length;\n\t\t\t} else {\n\t\t\t\ttotalRows = 0;\n\t\t\t\tstart = 0;\n\t\t\t\tend = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.pager_data ) {\n\t\t\t\ttotalRows = this.pager_data.total_rows;\n\t\t\t\tstart = 0;\n\t\t\t\tend = 0;\n\n\t\t\t\tif ( this.pager_data.last_page_number > 1 ) {\n\t\t\t\t\tif ( !this.pager_data.is_last_page ) {\n\n\t\t\t\t\t\tstart = ( this.pager_data.current_page - 1 ) * items_per_page + 1;\n\t\t\t\t\t\tend = start + items_per_page - 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstart = ( this.pager_data.current_page - 1 ) * items_per_page + 1;\n\t\t\t\t\t\tend = totalRows;\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tstart = 1;\n\t\t\t\t\tend = totalRows;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\ttotalRows = 0;\n\t\t\t\tstart = 0;\n\t\t\t\tend = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Counting pages can be disabled, in which case totalRows returns FALSE unless the user is on the last page.\n\t\tvar totalInfo = start + ' - ' + end;\n\t\tif ( totalRows !== false ) {\n\t\t\ttotalInfo = totalInfo + ' ' + $.i18n._( 'of' ) + ' ' + totalRows + ' ' + $.i18n._( 'total' ) + '.';\n\t\t}\n\n\t\tthis.total_display_span.text( $.i18n._( 'Displaying' ) + ' ' + totalInfo + ' [ ' + $.i18n._( 'Selected' ) + ': ' + grid_selected_length + ' ]' );\n\t}\n\n\tisContextIconDisabled( id ) {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tif ( context_menu_array[i].id === id ) {\n\t\t\t\tif ( context_btn.disabled || ( context_btn.hasOwnProperty( 'visible' ) && !context_btn.visible ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true; //Cannot find context menu button, return true as if button is disabled / cannot be used.\n\t}\n\n\tgetViewModeErrorMessage() {\n\t\t//Change error message depending on if edit context menu icon is available or not.\n\t\tif ( this.isContextIconDisabled( 'edit' ) ) {\n\t\t\treturn _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.view_mode_message */ .x.view_mode_message;\n\t\t}\n\n\t\treturn _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.view_mode_message */ .x.view_mode_message + ', ' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.view_mode_edit_message */ .x.view_mode_edit_message;\n\t}\n\n\t//Set right click menu for list view grid\n\tinitRightClickMenu( target_type ) {\n\t\t//Error: Object doesn't support property or method 'contextMenu' in /interface/html5/views/BaseViewController.js?v=7.4.6-20141027-132733 line 393\n\t\tif ( !$.hasOwnProperty( 'contextMenu' ) ) {\n\t\t\treturn;\n\t\t}\n\t\tvar $this = this;\n\n\t\tvar selector = '';\n\n\t\tswitch ( target_type ) {\n\t\t\tcase RightClickMenuType.LISTVIEW:\n\t\t\t\tselector = '#gbox_' + this.ui_id + '_grid';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.EDITVIEW:\n\t\t\t\tselector = '#' + this.ui_id + '_edit_view_tab';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.NORESULTBOX:\n\t\t\t\tselector = '#' + this.ui_id + '_no_result_box';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.ABSENCE_GRID:\n\t\t\t\tselector = '#' + this.ui_id + '_absence_grid';\n\t\t\t\tbreak;\n\t\t\tcase RightClickMenuType.VIEW_ICON:\n\t\t\t\tselector = '#' + 'view_html';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tselector = '#gbox_' + this.ui_id + '_grid';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( $( selector ).length == 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar items = this.getRightClickMenuItems();\n\n\t\tif ( !items || $.isEmptyObject( items ) ) {\n\t\t\treturn;\n\t\t}\n\t\t$.contextMenu( 'destroy', selector );\n\t\t$.contextMenu( {\n\t\t\tselector: selector,\n\t\t\tcallback: function( key, options ) {\n\t\t\t\t$this.onContextMenuClick( null, key );\n\t\t\t},\n\n\t\t\tonContextMenu: function() {\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\titems: items\n\t\t} );\n\t}\n\n\tgetRightClickMenuItems() {\n\t\tvar $this = this;\n\n\t\tvar items = {};\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar context_btn = context_menu_array[i];\n\n\t\t\tif ( context_btn.visible === false || context_btn.action_group_header || context_btn.separator || !context_btn.show_on_right_click ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar label = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.htmlDecode */ .x.htmlDecode( context_btn.label.replace( '<br>', ' ' ) );\n\t\t\tvar id = context_btn.id;\n\n\t\t\titems[id] = {\n\t\t\t\tname: label,\n\t\t\t\tdisabled: function( key ) {\n\t\t\t\t\treturn $this.isContextIconDisabled( key );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\treturn items;\n\t}\n\n\t//Don't initOptions if edit_only_mode. Do it in sub views\n\tinitData() {\n\t\tvar $this = this;\n\n\t\t//Work around to init sub view after tab is shown.\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.removeViewTab */ .x.removeViewTab( this.viewId );\n\t\tProgressBar.showOverlay();\n\t\tif ( !$this.edit_only_mode ) {\n\n\t\t\t//Various views expect search fields to be built already, such as initOptions() in PunchesViewController or getAllColumns() in ScheduleViewController.\n\t\t\t//Because of that we need to wait for resolution of getCustomFields promise to avoid exceptions and breaking views.\n\t\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\t\t$this.initOptions();\n\t\t\t\t$this.getAllColumns( function() {\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t//When on a sub view mode tab we want to disable certain context menu buttons of the parent view.\n\t\t\t//This is to help prevent users from using context menu buttons for the wrong view and deleting/copying records they did not intend to use.\n\t\t\tthis.onSubViewModeDisableParentContextMenuButtons();\n\t\t}\n\t}\n\n\tinitLayout() {\n\t\tvar $this = this;\n\t\t$this.getAllLayouts( function() {\n\t\t\t$this.getDefaultDisplayColumns( function() {\n\t\t\t\t$this.setSelectLayout();\n\t\t\t\t//$this.setGridColumnsWidth(); //This is done in setSelectLayout() and searchDone(), so no point in doing it multiple times.\n\t\t\t\t$this.search();\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// edit_only_mode call this when open edit view. Not in initData\n\tinitOptions() {\n\t}\n\n\t// TODO: Consolidate id and menu container into one function.\n\t/**\n\t * Determine what id, mount point, and menu type are needed to create the context menu for a specific view/edit view, based on the current view state. Main, Edit View, Sub View etc.\n\t */\n\tdetermineContextMenuMountAttributes() {\n\t\tvar return_object = {\n\t\t\tid: null,\n\t\t\tparent_mount_point: null,\n\t\t\tmenu_type: null,\n\t\t\tparent_id: null\n\t\t};\n\n\t\t// Figure out parent type\n\n\t\t/* Be aware that if something is incorrectly matched here, it may try to match with a wrong menu, or existing other menu,\n\t\t * and thus may have the side effect of closing the wrong menu when a window is closed.\n\t\t * If that symptom happens, check the matching here.\n\t\t */\n\n\t\t// You can see an extensive list in setCurrentEditViewState().\n\t\tif( this.is_add\n\t\t\t|| this.is_viewing\n\t\t\t|| this.is_viewing_detail //Cannot use just LocalCacheData.current_doing_context_action === 'view_detail' as it gets overwritten to cancel.\n\t\t\t|| this.is_edit\n\t\t\t|| this.is_mass_editing\n\t\t\t|| this.is_mass_adding // Not tested, but as all the others from setCurrentEditViewState are now here, might as well add it.\n\t\t\t|| this.edit_only_mode\n\t\t\t|| LocalCacheData.current_doing_context_action === 'view_detail' //With is_viewing_detail we may no longer need this condition.\n\t\t\t|| LocalCacheData.current_doing_context_action === 'delete'\n\t\t) {\n\t\t\treturn_object = this.parseContextMenuEditViewAttributes();\n\t\t} else if( $( this.el ).parents( '.edit-view-tab-outside-sub-view' ).length > 0 && this.ui_id ) {\n\t\t\t// Using this approach rather than this.sub_view_mode, as some views have edit views still showing as subviews.\n\t\t\t// #VueContextMenu#SubViews# Old approach can be found in BaseVC.parseCustomContextModelForSubViews but its better to control it from here in one place.\n\t\t\t// These matches would previously match to main_view, but subviews should be different to main views.\n\t\t\treturn_object = this.parseContextMenuEditSubViewTabAttributes();\n\t\t}\n\t\telse if( this.ui_id ) {\n\t\t\treturn_object = this.parseContextMenuMainViewAttributes();\n\t\t} else {\n\t\t\t// If each view has a unique context menu, then this should never happen, as context menu should only be initiated once.\n\t\t\t// However, there are many cases where tabs repeatedly call this.buildContextMenu, whilst keeping the same view controller, so this is now a warning rather than an error.\n\t\t\tDebug.Error( 'Error: View state for '+ this.viewId +' ('+ this.ui_id +') does not match options.', 'BaseViewController.js', 'BaseViewController', 'determineContextMenuMountAttributes', 1 );\n\t\t}\n\n\t\t// Regardless of editview/main type above, there are some occasions when it detects as main menu, but its still within tabs.\n\t\t// Here it would be Edit View -> Tabs -> Subview. For example Attendance->Accrual Balance -> View.\n\t\t// The top icons are edit view for AccrualBalanceView.\n\t\t// The icons within Accrual tab are seen as a main menu for AccrualView.\n\t\t// Lets add these occurances into another type.\n\n\t\t// Get ID\n\t\treturn_object.id = ContextMenuManager.generateMenuId( return_object.menu_type, return_object.parent_id );\n\n\t\treturn return_object;\n\t}\n\n\tparseContextMenuEditViewAttributes() {\n\t\t// Designed to be overriden by views if behaviour needs to be different.\n\t\t// All the edit_view style windows. Although the edit_only ones have a slightly different this.ui_id value, but the code is the same.\n\t\tif( !this.edit_view_tab ) {\n\t\t\t// If mount point IS needed (not just menu ID), then this is a bug. Check if buildContextMenu is not called before edit_view_tab populated (common in views overriding BaseView functions like openEditView.\n\t\t\tDebug.Text( 'Warning: Unable to get full context menu mount data, edit_view_tab missing. Might be ok if mount point not needed. Check if buildContextMenu is not called before edit_view_tab populated (common in views overriding BaseView functions like openEditView ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 10 );\n\t\t}\n\t\tif( !this.ui_id ) {\n\t\t\tDebug.Error( 'Warning: Unable to get full context menu mount data, ui_id missing. ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 1 );\n\t\t}\n\t\treturn {\n\t\t\tparent_mount_point: this.edit_view_tab, // Note: When this function is called, the edit_view_tab might not be built yet, so parent mount could be null, thats ok if mount point not needed yet.\n\t\t\tparent_id: this.ui_id + '_edit_view_tab',\n\t\t\tmenu_type: 'editview_contextmenu',\n\t\t}\n\t}\n\tparseContextMenuMainViewAttributes() {\n\t\t// Designed to be overriden by views if behaviour needs to be different.\n\t\t// Main views\n\n\t\tif( !this.ui_id ) {\n\t\t\tDebug.Error( 'Warning: Unable to get full context menu mount data, ui_id missing. ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 1 );\n\t\t}\n\n\t\treturn {\n\t\t\tparent_mount_point: $( this.el ),\n\t\t\tparent_id: this.ui_id,\n\t\t\tmenu_type: 'listview_contextmenu',\n\t\t}\n\t}\n\n\tparseContextMenuEditSubViewTabAttributes() {\n\t\t// Designed to be overriden by views if behaviour needs to be different.\n\t\t// Based on main_contextmenu\n\n\t\tif( !this.ui_id ) {\n\t\t\tDebug.Error( 'Warning: Unable to get full context menu mount data, ui_id missing. ('+ this.viewId +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'parseContextMenuEditViewAttributes', 1 );\n\t\t}\n\n\t\treturn {\n\t\t\tparent_mount_point: $( this.el ),\n\t\t\tparent_id: this.ui_id,\n\t\t\tmenu_type: 'subview_contextmenu',\n\t\t}\n\t}\n\n\tgetDefaultContextMenuModel() {\n\n\t\tvar default_context_menu_model = {\n\t\t\t'groups': {\n\t\t\t\t'editor': {\n\t\t\t\t\tlabel: $.i18n._( 'Editor' ),\n\t\t\t\t\tid: 'editor',\n\t\t\t\t\tsort_order: 1000\n\t\t\t\t},\n\t\t\t\t'navigation': {\n\t\t\t\t\tlabel: $.i18n._( 'Navigation' ),\n\t\t\t\t\tid: 'navigation',\n\t\t\t\t\tsort_order: 8000\n\t\t\t\t},\n\t\t\t\t'other': {\n\t\t\t\t\tlabel: $.i18n._( 'Other' ),\n\t\t\t\t\tid: 'other',\n\t\t\t\t\tsort_order: 9000\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t'icons': {}\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['add'] = {\n\t\t\tlabel: $.i18n._( 'New' ),\n\t\t\tid: 'add',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-add_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1000\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['view'] = {\n\t\t\tlabel: $.i18n._( 'View' ),\n\t\t\tid: 'view',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-visibility_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1010\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['edit'] = {\n\t\t\tlabel: $.i18n._( 'Edit' ),\n\t\t\tid: 'edit',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-edit_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1020,\n\t\t\t//min_width: '85' /* Match with mass_edit so they can toggle without moving any menu items in UI */\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['mass_edit'] = {\n\t\t\tlabel: $.i18n._( 'Mass Edit' ),\n\t\t\tid: 'mass_edit',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-edit_note_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tvisible: false, // Ensures Mass Edit is not shown at start together with Edit. We only want one or the other.\n\t\t\tsort_order: 1030,\n\t\t\t//min_width: '85' /* Match with edit so they can toggle without moving any menu items in UI */\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['delete_icon'] = {\n\t\t\tlabel: $.i18n._( 'Delete' ),\n\t\t\tid: 'delete_icon',\n\t\t\taction_group: 'delete',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-delete_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1040\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['delete_and_next'] = {\n\t\t\tlabel: $.i18n._( 'Delete & Next' ),\n\t\t\tid: 'delete_and_next',\n\t\t\taction_group: 'delete',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-delete_black_24dp',\n\t\t\tsort_order: 1050\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['copy'] = {\n\t\t\tlabel: $.i18n._( 'Copy' ),\n\t\t\tid: 'copy',\n\t\t\taction_group: 'copy',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-content_copy_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1060\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['copy_as_new'] = {\n\t\t\tlabel: $.i18n._( 'Copy as New' ),\n\t\t\tid: 'copy_as_new',\n\t\t\taction_group: 'copy',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-content_copy_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1070\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save'] = {\n\t\t\tlabel: $.i18n._( 'Save' ),\n\t\t\tid: 'save',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tshow_on_right_click: true,\n\t\t\tsort_order: 1080\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_continue'] = {\n\t\t\tlabel: $.i18n._( 'Save & Continue' ),\n\t\t\tid: 'save_and_continue',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1090\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_next'] = {\n\t\t\tlabel: $.i18n._( 'Save & Next' ),\n\t\t\tid: 'save_and_next',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1100\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_copy'] = {\n\t\t\tlabel: $.i18n._( 'Save & Copy' ),\n\t\t\tid: 'save_and_copy',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1110\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['save_and_new'] = {\n\t\t\tlabel: $.i18n._( 'Save & New' ),\n\t\t\tid: 'save_and_new',\n\t\t\taction_group: 'save',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-save_black_24dp',\n\t\t\tsort_order: 1120\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['cancel'] = {\n\t\t\tlabel: $.i18n._( 'Cancel' ),\n\t\t\tid: 'cancel',\n\t\t\tgroup: 'editor',\n\t\t\tvue_icon: 'tticon tticon-cancel_black_24dp',\n\t\t\tsort_order: 1130\n\t\t};\n\n\t\tdefault_context_menu_model['icons']['export_excel'] = {\n\t\t\tlabel: $.i18n._( 'Export' ),\n\t\t\tid: 'export_excel',\n\t\t\tmenu_align: 'right',\n\t\t\taction_group: 'import_export',\n\t\t\tgroup: 'other',\n\t\t\tvue_icon: 'tticon tticon-file_upload_black_24dp',\n\t\t\tsort_order: 9000,\n\t\t\tmenu_force_active: true\n\t\t};\n\n\t\treturn default_context_menu_model;\n\t}\n\n\t// Overriden by ViewControllers with custom context menus.\n\tgetCustomContextMenuModel() {\n\t\tvar context_menu_model = {\n\t\t\tgroups: {},\n\t\t\texclude: [],\n\t\t\tinclude: ['default']\n\t\t};\n\n\t\treturn context_menu_model;\n\t}\n\tparseCustomContextModelForEditViews( context_menu_model ) {\n\n\t\t// #VueContextMenu# - Commenting out logic below as we want to have the menu type logic in one place (BaseVC.determineContextMenuMountAttributes)\n\t\t// if( this.is_add\n\t\t// \t|| this.is_viewing\n\t\t// \t|| this.is_edit\n\t\t// \t|| this.is_mass_editing\n\t\t// \t|| this.is_mass_adding // Not tested, but as all the others from setCurrentEditViewState are now here, might as well add it.\n\t\t// \t|| this.edit_only_mode\n\t\t// \t|| LocalCacheData.current_doing_context_action === 'view_detail'\n\t\t// ) {\n\t\tif( this.determineContextMenuMountAttributes().menu_type === 'editview_contextmenu' ) {\n\t\t\tcontext_menu_model.include.push( 'cancel' );\n\t\t}\n\n\t\treturn context_menu_model;\n\t}\n\tparseCustomContextModelForSubViews( context_menu_model ) {\n\t\t// If a view does not want this, override the function in that view and just return the untouched object.\n\t\t// #VueContextMenu#SubViews# Commenting out the logic below as we should just have the controlling logic in one place (BaseVC.determineContextMenuMountAttributes)\n\n\t\t// if( this.determineContextMenuMountAttributes().menu_type === 'subview_contextmenu'\n\t\t// \t|| (this.sub_view_mode\n\t\t// \t&& !this.is_edit\n\t\t// \t&& !this.is_viewing\n\t\t// \t&& LocalCacheData.current_doing_context_action !== 'view' // To ensure view state is carried forward across subview loads, as Accrual Balance -> Accrual View record results in this.is_viewing === false.\n\t\t// \t&& LocalCacheData.current_doing_context_action !== 'edit' // Note: See if these last 2 checks are still needed after subview_contextmenu check addition.\n\t\t// )) { // TODO: Does not seem to work for Audit log, as is_viewing is deliberately set to false.\n\t\tif( this.determineContextMenuMountAttributes().menu_type === 'subview_contextmenu' ) {\n\t\t\tcontext_menu_model.exclude.push( 'cancel' ); // Needed as subview grid menus dont need to be able to close the current window; the main context menu should do that.\n\t\t}\n\n\t\treturn context_menu_model;\n\t}\n\n\tbuildContextMenuModels() {\n\t\t// Note: Currently icons might still be hidden by the permissions code, due to the 'invisible-image' class, especially with this.edit_only_mode. See BaseViewController.setDefaultMenuAddIcon() as an example.\n\n\t\tlet icon_count = 1;\n\t\tlet context_menu_model = this.getCustomContextMenuModel();\n\n\t\t// Override for edit views.\n\t\tcontext_menu_model = this.parseCustomContextModelForEditViews( context_menu_model );\n\n\t\t// Override for subviews, as we want to remove Cancel. This is global, perhaps refactor into the individual getCustomContextMenuModel but that means duplicating the code in 100+ places.\n\t\tcontext_menu_model = this.parseCustomContextModelForSubViews( context_menu_model );\n\n\t\tif ( context_menu_model && ( context_menu_model.include || context_menu_model.exclude ) ) {\n\t\t\t//Context Menu\n\n\t\t\tlet default_context_menu_model = this.getDefaultContextMenuModel();\n\n\t\t\tlet final_context_menu_model = { 'icons': {}, 'groups': {} };\n\n\t\t\tif ( !context_menu_model.groups ) {\n\t\t\t\tcontext_menu_model.groups = {};\n\t\t\t}\n\n\t\t\t//Default to including all default icons.\n\t\t\tif ( !context_menu_model.include ) {\n\t\t\t\tcontext_menu_model.include = ['default'];\n\t\t\t}\n\n\t\t\t//If we don't include default, assume we want to include all default icons.\n\t\t\tif ( context_menu_model.include.indexOf( 'default' ) === -1 ) {\n\t\t\t\tcontext_menu_model.include.unshift( 'default' ); // Add to front, so custom icons can override a default icon id.\n\t\t\t}\n\n\t\t\t//Assign default groups.\n\t\t\tfor ( let x in default_context_menu_model.groups ) {\n\t\t\t\tdefault_context_menu_model.groups[x].sub_menus = [];\n\n\t\t\t\tfinal_context_menu_model.groups[x] = default_context_menu_model.groups[x];\n\t\t\t}\n\n\t\t\tfor ( let x in context_menu_model.groups ) {\n\t\t\t\tcontext_menu_model.groups[x].sub_menus = [];\n\n\t\t\t\tfinal_context_menu_model.groups[x] = context_menu_model.groups[x];\n\t\t\t}\n\n\t\t\t//Filter groups/icons\n\t\t\tif ( context_menu_model.hasOwnProperty( 'include' ) ) {\n\t\t\t\tif ( context_menu_model.include.constructor !== Array ) {\n\t\t\t\t\tcontext_menu_model.include = Array( context_menu_model.include );\n\t\t\t\t}\n\n\t\t\t\tfor ( let i in context_menu_model.include ) {\n\t\t\t\t\tlet current_include_element = context_menu_model.include[i];\n\t\t\t\t\tif( context_menu_model.include.hasOwnProperty( i )) {\n\t\t\t\t\t\tif ( current_include_element == 'default' ) {\n\t\t\t\t\t\t\tDebug.Text( 'Including All Default Icons...', 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 11 );\n\n\t\t\t\t\t\t\tfor ( let x in default_context_menu_model.icons ) {\n\t\t\t\t\t\t\t\taddIconToFinalModel( default_context_menu_model.icons[x] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ( typeof current_include_element !== 'object' && default_context_menu_model.icons[current_include_element] ) {\n\t\t\t\t\t\t\t\taddIconToFinalModel( default_context_menu_model.icons[current_include_element] );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\taddIconToFinalModel( current_include_element );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction addIconToFinalModel( icon ) {\n\t\t\t\tif( !icon.sort_order && icon.group ) {\n\t\t\t\t\ticon.sort_order = final_context_menu_model.groups[ icon.group ].sort_order; // Rather than setting the default to 1000, lets set it to the start of the icon's group, so it appears in roughly the right area of the menu. Fixes e.g. TimeSheet & Export in Employee->Employees.\n\t\t\t\t}\n\t\t\t\t// TODO: Also need scenario for when there is no sort_order and no group. Currently this is caught as a console error via checks in ContextMenuManager.convertBackBoneMenuModelToPrimeVue.sort_compare\n\n\t\t\t\ticon.add_order = icon_count; // rather than calculating length each time, just track additions, as all icons should be added through here anyway.\n\t\t\t\tfinal_context_menu_model.icons[icon.id] = icon;\n\t\t\t\ticon_count++;\n\n\t\t\t\treturn icon;\n\t\t\t}\n\n\t\t\t// #2644 Include array is a mix of icon id strings and objects, this function flattens it to an array of strings for id comparision.\n\t\t\tfunction flattenMixedIdObjectArray( array ) {\n\t\t\t\treturn array.map( function( item ) {\n\t\t\t\t\treturn item.id || item;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tlet tmp_included_icon_ids = flattenMixedIdObjectArray( context_menu_model.include );\n\n\t\t\t//Must go after include, so they can include a few icons, then exclude all.\n\t\t\tif ( context_menu_model.hasOwnProperty( 'exclude' ) ) {\n\t\t\t\tif ( context_menu_model.exclude.constructor !== Array ) {\n\t\t\t\t\tcontext_menu_model.exclude = Array( context_menu_model.exclude );\n\t\t\t\t}\n\n\t\t\t\tfor ( let j in context_menu_model.exclude ) {\n\t\t\t\t\tif( context_menu_model.exclude.hasOwnProperty( j )) {\n\t\t\t\t\t\tif ( context_menu_model.exclude[j] == 'default' ) {\n\t\t\t\t\t\t\tDebug.Text( 'Excluding All Default Icons...', 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 10 );\n\n\t\t\t\t\t\t\tfor ( let x in default_context_menu_model.icons ) {\n\t\t\t\t\t\t\t\tif ( tmp_included_icon_ids.indexOf( x ) === -1 ) { //Make sure we don't exclude one that is included. Compare against flattened/extracted include array, otherwise types do not match and all default icons are removed regardless if they exist in include.\n\t\t\t\t\t\t\t\t\tif ( final_context_menu_model.icons[x] ) {\n\t\t\t\t\t\t\t\t\t\tdelete final_context_menu_model.icons[x];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlet exclude_icon_id = context_menu_model.exclude[j];\n\t\t\t\t\t\t\tif ( final_context_menu_model.icons[exclude_icon_id] ) {\n\t\t\t\t\t\t\t\tdelete final_context_menu_model.icons[exclude_icon_id];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Build Menu\n\t\t\tlet groups = {};\n\t\t\tfor ( let x in final_context_menu_model.groups ) {\n\t\t\t\tgroups[x] = final_context_menu_model.groups[x];\n\t\t\t\tDebug.Text( 'Creating Ribbon Menu Group: ' + final_context_menu_model.groups[x].label, 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 11 );\n\t\t\t}\n\n\t\t\tfor ( let x in final_context_menu_model.icons ) {\n\n\t\t\t\t//Replace group string with object.\n\t\t\t\tif ( final_context_menu_model.icons[x] && final_context_menu_model.icons[x].group ) {\n\t\t\t\t\tif ( final_context_menu_model.icons[x].group.constructor === String ) {\n\t\t\t\t\t\tfinal_context_menu_model.icons[x].group = groups[final_context_menu_model.icons[x].group];\n\t\t\t\t\t} else if ( typeof final_context_menu_model.icons[x].group === 'object' ) {\n\t\t\t\t\t\t//The 2nd time the edit view is opened, icons manually passed in through 'include' already have the groups converted to objects, but the icons don't appear until we re-assign the group object again.\n\t\t\t\t\t\tfinal_context_menu_model.icons[x].group = groups[final_context_menu_model.icons[x].group.get( 'id' )];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( final_context_menu_model.icons[x].hasOwnProperty( 'permission_result' ) == false ) {\n\t\t\t\t\tfinal_context_menu_model.icons[x].permission_result = true;\n\t\t\t\t}\n\t\t\t\tif ( !final_context_menu_model.icons[x].hasOwnProperty( 'permission' ) == false ) {\n\t\t\t\t\tfinal_context_menu_model.icons[x].permission = null;\n\t\t\t\t}\n\n\t\t\t\tDebug.Text( 'Creating Ribbon Menu Icon: ' + final_context_menu_model.icons[x].label, 'BaseViewController.js', 'BaseViewController', 'buildContextMenuModels', 11 );\n\n/*\t\t\t\t// TODO: This not an ideal way to do it, but not worth changing until a bigger refactor of the context menu is done at a later date.\n\t\t\t\tif ( final_context_menu_model.icons[x].items && final_context_menu_model.icons[x].items.length > 0 ) {\n\t\t\t\t\t// We use item to store the pre conversion and post conversion data. Therefore we must re-assign to a temp var, and reset.\n\t\t\t\t\tlet items_to_add = final_context_menu_model.icons[x].items;\n\n\t\t\t\t\t// Still store the original items so that the new Vue Menu can parse these.\n\t\t\t\t\tfinal_context_menu_model.icons[x].original_items = items_to_add;\n\n\t\t\t\t\t// Reset the items attribute to an empty array, ready for RibbonSubMenuNavItem to use later on. Still needs clearing to empty array in ContextMenuManager once the ribbonmenu is done with it.\n\t\t\t\t\tfinal_context_menu_model.icons[x].items = [];\n\t\t\t\t}*/\n\t\t\t}\n\n\t\t\t// #VueContextMenu# Pass the final context menu model to the Vue context menu.\n\t\t\tContextMenuManager.buildContextMenuModelFromBackbone( this.determineContextMenuMountAttributes().id, final_context_menu_model, this );\n\n\t\t} else {\n\t\t\t//Legacy fallback when no context menu model is defined.\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.sendErrorReport */ .x.sendErrorReport( 'ContextMenuModel error. No valid contextmenu model defined.' );\n\t\t}\n\t}\n\n\tunmountContextMenu() {\n\t\t// This should be able to handle various menu's as the determine menu id function will identify the right menu (view, edit etc)\n\t\tContextMenuManager.unmountContextMenu( this.determineContextMenuMountAttributes().id );\n\t}\n\n\tbuildContextMenu( setFocus ) {\n\t\tif ( this.current_edit_record && this.edit_only_mode == true && LocalCacheData.current_open_edit_only_controller && LocalCacheData.current_open_edit_only_controller.viewId != LocalCacheData.current_open_edit_only_controller.viewId ) { // #2542 - prevent early menu setup for views that have not been loaded into memory yet.\n\t\t\treturn null;\n\t\t}\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( setFocus ) ) {\n\t\t\tsetFocus = true;\n\t\t}\n\n\t\tif ( !this.sub_view_mode ) {\n\t\t\tLocalCacheData.current_open_sub_controller = null; //Clean sub controller if current view is a main view\n\t\t} else {\n\t\t\t//When on a sub view mode tab we want to disable certain context menu buttons of the parent view.\n\t\t\t//This is to help prevent users from using context menu buttons for the wrong view and deleting/copying records they did not intend to use.\n\t\t\tthis.onSubViewModeDisableParentContextMenuButtons();\n\t\t}\n\n\t\t// Vue Context Menu initialization - #2838\n\t\t// Checks for existing menu, because for an edit_view, we dont want to start a new menu, we want to re-use it.\n\t\t// Otherwise we end up treating edit menus like new views, which is more complex given the html templates (report edit views are unique, as we now have a common template).\n\t\tlet menu_attributes = this.determineContextMenuMountAttributes();\n\n\t\tif( ContextMenuManager.getMenu( menu_attributes.id ) === undefined ) {\n\t\t\t// #VueContextMenu#Dynamic-EditView\n\t\t\tContextMenuManager.createAndMountMenu( menu_attributes.id, menu_attributes.parent_mount_point, this );\n\n\t\t\tif( menu_attributes && menu_attributes.parent_mount_point ) {\n\t\t\t\t// #VueContextMenu#context-border creation to put a border around a context menu and the contents it relates to. This will help users understand which context menu belongs to what if there is more than one menu on the page.\n\t\t\t\tvar context_parent = menu_attributes.parent_mount_point; // $('.edit-view-tab-bar');\n\t\t\t\tvar context_label = this.context_menu_name;\n\n\t\t\t\tcontext_parent.prepend('<span class=\"context-border-label\">'+ context_label +'</span>');\n\t\t\t\tcontext_parent.wrapInner('<div class=\"context-border\"></div>');\n\t\t\t} else {\n\t\t\t\t// If mount point is null, then this is a bug. Check if buildContextMenu is not called before edit_view_tab populated (common in views overriding BaseView functions like openEditView.\n\t\t\t\tDebug.Error( 'Error creating context-border for '+this.viewId+' ('+ menu_attributes.id +'/'+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 10 );\n\t\t\t}\n\n\t\t\t// if( ( this.is_add || this.is_edit || this.edit_only_mode ) && this.edit_view_tab || LocalCacheData.current_doing_context_action === 'view_detail' ) { // REMEMBER TO UPDATE determineContextMenuMountAttributes!!\n\t\t\t// \t// #VueContextMenu#Dynamic-EditView - Consolidate this, as View is now in 1 place, and EditView in 2 places. <-- #TODO: is this comment still valid? Search the tag.\n\t\t\t// \t// Pop-up edit views, which overlay across an unrelated view ( appear anywhere basically ).\n\t\t\t// \tthis.context_edit_only_menu_id = ContextMenuManager.createAndMountMenu( menu_attributes.id, this.edit_view_tab, this );\n\t\t\t// } else if( this.ui_id ) {\n\t\t\t// \t// Normal Views\n\t\t\t// \tthis.context_menu_id = ContextMenuManager.createAndMountMenu( menu_attributes.id, $( $this.el ), this );\n\t\t\t// } else {\n\t\t\t// \t// If each view has a unique context menu, then this should never happen, as context menu should only be initiated once.\n\t\t\t// \t// However, there are many cases where tabs repeatedly call this.buildContextMenu, whilst keeping the same view controller, so this is now a warning rather than an error.\n\t\t\t// \tDebug.Error( 'Error during context menu mount. View state for ( '+ this.viewId +' ) does not match options.', 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 1 );\n\t\t\t// }\n\t\t} else {\n\t\t\t// This might be normal for situations like closing Edit Views, where the menu will already exist in the main view.\n\t\t\tDebug.Warn( 'Context Menu Manager ('+ menu_attributes.id +') already exists for: '+ this.viewId +' ('+ this.ui_id +')', 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 10 );\n\t\t}\n\n\t\tthis.buildContextMenuModels();\n\t\tLocalCacheData.currentShownContextMenuName = this.context_menu_name ? this.context_menu_name : menu_attributes.parent_id;\n\n\t}\n\n\tgetContextMenuGroupByName( menu, name, name_prefix ) {\n\t\tvar group;\n\t\tif ( name_prefix == undefined ) {\n\t\t\tname_prefix = this.viewId;\n\t\t}\n\n\t\tfor ( var i = 0; i < menu.attributes.sub_menu_groups.length; i++ ) {\n\t\t\tif ( menu.attributes.sub_menu_groups[i].id == name_prefix + name ) {\n\t\t\t\tgroup = menu.attributes.sub_menu_groups[i];\n\t\t\t}\n\t\t}\n\n\t\treturn group;\n\t}\n\n\tonReportMenuClick( id ) {\n\t}\n\n\t//Overridden in ReportBaseViewController.\n\tonContextMenuClick( context_btn, menu_name ) {\n\t\t// Vue notes: Luckily when Vue calls this menu, it does not need context_btn, as most places that use this function have the Global.isSet( menu_name ) check to just use menu_name as the id. However, MessageControlVC does use it.\n\t\tvar id;\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( menu_name ) ) {\n\t\t\tid = menu_name;\n\t\t} else {\n\n\t\t\tif ( context_btn.disabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tProgressBar.showOverlay();\n\t\t//This flag is turned off in ProgressBarManager::closeOverlay, or 2 seconds whichever happens first. Use 2 seconds as overseas users could see intermittant 2 second latencies and double click Save icons.\n\t\tif ( window.clickProcessing == true ) {\n\t\t\treturn;\n\t\t} else {\n\t\t\twindow.clickProcessing = true;\n\t\t\twindow.clickProcessingHandle = window.setTimeout( function() {\n\t\t\t\t//FIXME: Check to see if the progress bar is visible because a API call is taking a long time, and if so keep the overlay up longer.\n\t\t\t\tif ( window.clickProcessing == true ) {\n\t\t\t\t\twindow.clickProcessing = false;\n\t\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\t\tTTPromise.wait();\n\t\t\t\t}\n\t\t\t}, _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.calcDebounceWaitTimeBasedOnNetwork */ .x.calcDebounceWaitTimeBasedOnNetwork( 2000 ) );\n\t\t}\n\n\t\t//Debug.Text( 'Context Menu Click: '+ id, 'BaseViewController.js', 'BaseViewController', 'onContextMenuClick', 10 );\n\n\t\t/**\n\t\t * Here where you see ProgressBar.showOverlay() it is how we prevent doubleclick from firing two single clicks\n\t\t */\n\n\t\tswitch ( id ) {\n\t\t\tcase 'add':\n\t\t\t\tthis.onAddClick();\n\t\t\t\tbreak;\n\t\t\tcase 'view':\n\t\t\t\tthis.onViewClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save':\n\t\t\t\tthis.onSaveClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_next':\n\t\t\t\tthis.onSaveAndNextClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_continue':\n\t\t\t\tthis.onSaveAndContinue();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_new':\n\t\t\t\tthis.onSaveAndNewClick();\n\t\t\t\tbreak;\n\t\t\tcase 'save_and_copy':\n\t\t\t\tthis.onSaveAndCopy();\n\t\t\t\tbreak;\n\t\t\tcase 'edit':\n\t\t\t\tthis.onEditClick();\n\t\t\t\tbreak;\n\t\t\tcase 'mass_edit':\n\t\t\t\tthis.onMassEditClick();\n\t\t\t\tbreak;\n\t\t\tcase 'delete_icon':\n\t\t\t\tthis.onDeleteClick();\n\t\t\t\tbreak;\n\t\t\tcase 'delete_and_next':\n\t\t\t\tthis.onDeleteAndNextClick();\n\t\t\t\tbreak;\n\t\t\tcase 'copy':\n\t\t\t\tthis.onCopyClick();\n\t\t\t\tbreak;\n\t\t\tcase 'copy_as_new':\n\t\t\t\tthis.onCopyAsNewClick();\n\t\t\t\tbreak;\n\t\t\tcase 'cancel':\n\t\t\t\tthis.onCancelClick();\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\tbreak;\n\t\t\tcase 'export_excel':\n\t\t\t\tthis.onExportClick( 'export' + this.api.key_name );\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\tbreak;\n\t\t\tcase 'map':\n\t\t\t\tthis.onMapClick();\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.onCustomContextClick( id, context_btn );\n\t\t\t\tProgressBar.closeOverlay(); //FIXME: This may be closing the overlay too soon, allowing double-clicks to get through. For example when in Request Authorizations and hammer clicking \"Authorize\".\n\t\t\t\t//Debug.Text( 'Context Menu Click: '+ id +' Overlay closing...', 'BaseViewController.js', 'BaseViewController', 'onContextMenuClick', 10 );\n\t\t\t\tbreak;\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsContextMenuClick */ .x.triggerAnalyticsContextMenuClick( context_btn, menu_name );\n\t}\n\n\tonCustomContextClick( id ) {\n\t\treturn false; //FALSE tells onContextMenuClick() to keep processing.\n\t}\n\n\tonNavigationClick( id ) {\n\t\tthis.onContextMenuClick( id );\n\t}\n\n\tgetCurrentAPI() {\n\t\treturn this.api;\n\t}\n\n\tsetCurrentEditViewState( state ) {\n\t\tthis.is_viewing = false;\n\t\tthis.is_viewing_detail = false; //Clicked \"View Detail\" on audit log. Separate logic from regular view.\n\t\tthis.is_edit = false;\n\t\tthis.is_add = false;\n\t\tthis.is_mass_editing = false;\n\t\tthis.is_mass_adding = false;\n\t\tswitch ( state ) {\n\t\t\tcase 'view':\n\t\t\t\tthis.is_viewing = true;\n\t\t\t\tbreak;\n\t\t\tcase 'view_detail':\n\t\t\t\tthis.is_viewing_detail = true;\n\t\t\t\tbreak;\n\t\t\tcase 'new':\n\t\t\t\tthis.is_add = true;\n\t\t\t\tbreak;\n\t\t\tcase 'edit':\n\t\t\t\tthis.is_edit = true;\n\t\t\t\tbreak;\n\t\t\tcase 'mass_edit':\n\t\t\t\tthis.is_mass_editing = true;\n\t\t\t\tbreak;\n\t\t\t// case 'mass_add':\n\t\t\t// \t//this.is_add = true;\n\t\t\t// \tthis.is_mass_adding = true;\n\t\t\t// \tbreak;\n\n\t\t}\n\n\t\tLocalCacheData.previous_doing_context_action = LocalCacheData.current_doing_context_action;\n\t\tLocalCacheData.current_doing_context_action = state;\n\t}\n\n\trevertEditViewState() {\n\t\tthis.setCurrentEditViewState( LocalCacheData.previous_doing_context_action ? LocalCacheData.previous_doing_context_action : '' );\n\t}\n\n\tonAddClick( show_save_and_continue ) {\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\t$this.openEditView();\n\t\t//Error: Uncaught TypeError: undefined is not a function in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-111140 line 897\n\t\tif ( $this.api && typeof $this.api['get' + $this.api.key_name + 'DefaultData'] === 'function' ) {\n\t\t\t$this.api['get' + $this.api.key_name + 'DefaultData']( {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.onAddResult( result );\n\t\t\t\t\tif ( show_save_and_continue ) {\n\t\t\t\t\t\t//Issue #3111 - If user is on a subview the tab will appear blank and the Save and Continue button will not show unless user switches to another tab.\n\t\t\t\t\t\t//Because of that when coming from a \"Save & New\" action, we need to make sure to show the Save and Continue button.\n\t\t\t\t\t\t$this.showSaveAndContinueButton();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tonAddResult( result ) {\n\t\tvar $this = this;\n\t\tvar result_data = {};\n\n\t\tif ( result.getResult ) {\n\t\t\tresult_data = result.getResult();\n\t\t} else {\n\t\t\t//if not an api result, assume object is already the result of a call to getResult() and we will use it verbatim.\n\t\t\t//useful for passing in default values when adding new records before this function is called.\n\t\t\tresult_data = result;\n\t\t}\n\n\t\tif ( !result_data || result_data === true ) {\n\t\t\tresult_data = [];\n\t\t}\n\n\t\tresult_data.company = LocalCacheData.current_company.name;\n\n\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t}\n\n\t\t$this.current_edit_record = result_data;\n\t\t$this.initEditView();\n\t}\n\n\tonDeleteAndNextClick() {\n\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.delete_confirm_message */ .x.delete_confirm_message, null, function( result ) {\n\t\t\t// Using an anonymous function instead of reference, to ensure during debugging it is clear this function is called from DeleteAndNext, and not just Delete.\n\t\t\tthis.doDeleteClick( result, 'delete_and_next' );\n\t\t}.bind( this ) );\n\t}\n\n\tresetNavigationSourceData() {\n\t}\n\n\tgetDeleteSelectedRecordId() {\n\t\tvar retval = [];\n\t\tif ( this.edit_view && this.current_edit_record ) {\n\t\t\tretval.push( this.current_edit_record.id );\n\t\t} else {\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray().slice(); //Use .slice() to make a copy of the IDs.\n\t\t\tif ( grid_selected_id_array.length ) {\n\t\t\t\tretval = grid_selected_id_array;\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\n\t\t}\n\t\treturn retval;\n\t}\n\n\tdoDeleteClick( result, delete_type ) {\n\t\tif ( result ) {\n\t\t\tProgressBar.showOverlay();\n\t\t\tvar remove_ids = this.getDeleteSelectedRecordId();\n\t\t\tif ( remove_ids === [] ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.setCurrentEditViewState( delete_type ? delete_type : 'delete' );\n\t\t\treturn this.doDeleteAPICall( remove_ids );\n\n\t\t} else {\n\t\t\tProgressBar.closeOverlay();\n\t\t}\n\t}\n\n\tdoDeleteAPICall( remove_ids, callback ) {\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tif ( !callback ) {\n\t\t\tcallback = {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tthis.onDeleteResult( result, remove_ids );\n\t\t\t\t}.bind( this )\n\t\t\t};\n\t\t}\n\t\treturn current_api['delete' + current_api.key_name]( remove_ids, callback );\n\t}\n\n\tonDeleteClick() {\n\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.delete_confirm_message */ .x.delete_confirm_message, null, this.doDeleteClick.bind( this ) );\n\t}\n\n\tonDeleteResult( result, remove_ids ) {\n\t\tvar $this = this;\n\t\tProgressBar.closeOverlay();\n\t\tif ( result.isValid() ) {\n\n\t\t\tif ( LocalCacheData.current_doing_context_action === 'delete_and_next' ) {\n\t\t\t\t// store the index of the current item, before refreshing the search and losing the current context due to the deleted records\n\t\t\t\t$this.refresh_id = this.navigation.getNextSelectItemId();\n\n\t\t\t\t// refresh the grid to get the current dataset now that records have been deleted\n\t\t\t\t$this.search( false, null, null, function( result ) {\n\t\t\t\t\tvar current_grid_source = result.getResult();\n\n\t\t\t\t\tif ( $.type( current_grid_source ) !== 'array' || current_grid_source.length < 1 ) {\n\t\t\t\t\t\t// if after delete, there are no more records in the search, close edit view\n\t\t\t\t\t\t$this.removeEditView();\n\t\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t\t\t// TODO: Should the above not simulate a cancel click? Could be an area for further refactor.\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// there are still records, load the new data\n\t\t\t\t\t\t$this.navigation.setSourceData( current_grid_source );\n\t\t\t\t\t\t$this.navigation.setPagerData( $this.pager_data );\n\n\t\t\t\t\t\t// if there is a valid id on the next record to load, do it\n\t\t\t\t\t\tif ( $this.refresh_id ) {\n\t\t\t\t\t\t\t$this.onRightOrLeftArrowClickCallBack( $this.refresh_id );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// no valid next record, simulate a cancel click.\n\t\t\t\t\t\t\t$this.onCancelClick();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.onDeleteAndNextDone( result );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.search();\n\t\t\t\t$this.onDeleteDone( result );\n\t\t\t\tif ( $this.edit_view && LocalCacheData.current_doing_context_action === 'delete' ) {\n\t\t\t\t\t$this.removeEditView();\n\t\t\t\t\t$this.setDefaultMenu();\n\t\t\t\t} else if ( !$this.edit_view ) {\n\t\t\t\t\t$this.setCurrentEditViewState( '' );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// If some valid records were deleted, we need to refresh the search grid.\n\t\t\tif ( result.getRecordDetails().valid && result.getRecordDetails().valid > 0 ) {\n\t\t\t\t$this.search();\n\t\t\t}\n\t\t\t$this.revertEditViewState();\n\t\t\tTAlertManager.showErrorAlert( result );\n\t\t}\n\t}\n\n\tremoveDeletedRows( remove_ids ) {\n\t\tvar $this = this;\n\t\t$.each( remove_ids, function( index, value ) {\n\t\t\t$this.grid.grid.deleteRow( value );\n\t\t\t$this.paging_widget.minus();\n\n\t\t} );\n//\n//\t\tif ( this.grid.getGridParam( 'data' ).length === 0 ) {\n//\t\t\tthis.search();\n//\t\t}\n\n//\t\tthis.search();\n\n//\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n//\t\tvar grid_selected_length = grid_selected_id_array.length;\n//\n//\t\tif ( grid_selected_length === 0 ) {\n//\t\t\tthis.search();\n//\t\t}\n\t}\n\n\tclearNavigationData() {\n\t\tif ( this.navigation && this.navigation.setSourceData ) {\n\t\t\tthis.navigation.setSourceData( null );\n\t\t}\n\t}\n\n\tonSaveAndCopy( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_add = true;\n\t\tthis.is_changed = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_copy';\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.uniformVariable( record );\n\n\t\tthis.clearNavigationData();\n\t\tthis.api['set' + this.api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndCopyResult( result );\n\t\t\t\t$this.clearSubViewControllers();\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndCopyResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t$this.refresh_id = result_data;\n\t\t\t}\n\t\t\t$this.search( false );\n\t\t\t$this.onCopyAsNewClick();\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result );\n\n\t\t}\n\t}\n\n\tonSaveAndNewClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.uniformVariable( record );\n\t\tthis.api['set' + this.api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndNewResult( result );\n\t\t\t\tif ( $this.sub_view_mode ) {\n\t\t\t\t\t$this.clearSubViewControllers( false );\n\t\t\t\t} else {\n\t\t\t\t\t$this.clearSubViewControllers( true );\n\t\t\t\t\t$this.showSaveAndContinueButton();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndNewResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\n\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) { // as new\n\t\t\t\t$this.refresh_id = result_data;\n\t\t\t}\n\n\t\t\t$this.saveInsideEditorData( function() {\n\t\t\t\t$this.search( false );\n\t\t\t\t$this.onAddClick( true );\n\t\t\t} );\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result );\n\n\t\t}\n\t}\n\n\tonSaveAndContinue( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\t//Setting is_add false too early can cause determineContextMenuMountAttributes() to have unexpected side effects. However not setting it here might have other side effects.\n\t\t//$this.is_add = false;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_continue';\n\t\tvar record = this.current_edit_record;\n\t\trecord = this.uniformVariable( record );\n\n\t\tthis.doSaveAPICall( record, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndContinueResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndContinueResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\n\t\t\t} else if ( result_data && TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t$this.refresh_id = result_data;\n\n\t\t\t}\n\n\t\t\t$this.saveInsideEditorData( function() {\n\t\t\t\t$this.search( false );\n\t\t\t\t$this.onEditClick( $this.refresh_id, true );\n\t\t\t\t$this.onSaveAndContinueDone( result );\n\t\t\t} );\n\n\t\t} else {\n\t\t\t$this.setErrorTips( result );\n\t\t\t$this.setErrorMenu();\n\t\t}\n\t}\n\n\tonSaveAndNextClick( ignoreWarning ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\t\tthis.is_add = false;\n\t\tthis.is_changed = false;\n\n\t\tvar current_api = this.getCurrentAPI();\n\t\tvar record = this.current_edit_record;\n\t\tLocalCacheData.current_doing_context_action = 'save_and_next';\n\t\trecord = this.uniformVariable( record );\n\t\tcurrent_api['set' + current_api.key_name]( record, false, ignoreWarning, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onSaveAndNextResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveAndNextResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t} else if ( result_data && TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t$this.refresh_id = result_data;\n\t\t\t}\n\n\t\t\t$this.saveInsideEditorData( function() {\n\t\t\t\t$this.onRightArrowClick();\n\t\t\t\t$this.search( false );\n\t\t\t\t$this.onSaveAndNextDone( result );\n\t\t\t} );\n\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result );\n\n\t\t}\n\t}\n\n\tuniformVariable( records ) {\n\t\treturn records;\n\t}\n\n\tsaveInsideEditorData( callback ) {\n\t\t//override this stub function where neeed. Brought in to consolidate those view controllers that used this.\n\t\t/* Dev Note: #2644 If issues happen, read this:\n\t\t * Functions such as onSaveAndNextResult() had a saveInsideEditorData call, but the base view did not, but the rest of the function was the same.\n\t\t * During refactor of these functions like save and next result into the base view, a stub of saveInsideEditor had to be created as it was not there previously.\n\t\t */\n\n\t\tif ( callback ) {\n\t\t\tcallback();\n\t\t}\n\t}\n\n\tgetChangedFields() {\n\t\tvar retval = {};\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.isChecked ) ) {\n\t\t\t\tif ( widget.isChecked() && widget.getEnabled() ) {\n\t\t\t\t\tretval[key] = this.current_edit_record[key]; // Note: Some view controllers use widget.getValue() instead of current_edit_record[key]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\t// overridden in view controllers where needed\n\t// this base version will simply extract and duplicate current edit record if an array of user_id's exist\n\t// parent function should check to confirm this.is_mass_adding is true\n\tbuildMassAddRecord( record ) {\n\t\tvar retval;\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( record.user_id ) && record.user_id.length > 0 ) {\n\t\t\tretval = [];\n\t\t\t$.each( this.current_edit_record.user_id, function( index, value ) {\n\n\t\t\t\tvar commonRecord = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( record );\n\t\t\t\tcommonRecord.user_id = value;\n\t\t\t\tretval.push( commonRecord );\n\n\t\t\t} );\n\t\t} else {\n\t\t\tretval = record;\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tbuildMassEditSaveRecord( mass_edit_record_ids, changed_fields ) {\n\t\tvar $this = this;\n\t\tvar mass_records = [];\n\n\t\t$.each( mass_edit_record_ids, function( index, value ) {\n\t\t\tvar common_record = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( changed_fields );\n\t\t\tcommon_record.id = value;\n\t\t\tcommon_record = $this.uniformVariable( common_record );\n\t\t\tmass_records.push( common_record );\n\t\t} );\n\n\t\treturn mass_records;\n\t}\n\n\tonSaveClick( ignoreWarning ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( ignoreWarning ) ) {\n\t\t\tignoreWarning = false;\n\t\t}\n\n\t\tvar record;\n\t\t//Setting is_add false too early can cause determineContextMenuMountAttributes() to have unexpected side effects. However not setting it here might have other side effects.\n\t\t//this.is_add = false;\n\t\tLocalCacheData.current_doing_context_action = 'save';\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tvar changed_fields = this.getChangedFields();\n\t\t\trecord = this.buildMassEditSaveRecord( this.mass_edit_record_ids, changed_fields );\n\n\t\t} else if ( this.is_mass_adding ) {\n\t\t\trecord = this.buildMassAddRecord( this.current_edit_record );\n\n\t\t} else {\n\t\t\trecord = this.current_edit_record;\n\t\t\trecord = this.uniformVariable( record );\n\t\t}\n\n\t\tthis.doSaveAPICall( record, ignoreWarning );\n\t}\n\n\tdoSaveAPICall( record, ignoreWarning, callback ) {\n\t\tvar current_api = this.getCurrentAPI();\n\n\t\tif ( !callback ) {\n\t\t\tcallback = {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tthis.onSaveResult( result );\n\t\t\t\t}.bind( this )\n\t\t\t};\n\t\t}\n\n\t\t//current_api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\treturn current_api['set' + current_api.key_name]( record, false, ignoreWarning, callback );\n\t}\n\n\tonSaveResult( result ) {\n\t\tvar $this = this;\n\t\tif ( result.isValid() ) {\n\t\t\t//Setting is_add false too early can cause determineContextMenuMountAttributes() to have unexpected side effects. However not setting it here might have other side effects.\n\t\t\t//$this.is_add = false;\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( !this.edit_only_mode ) {\n\t\t\t\tif ( result_data === true && $this.current_edit_record && $this.current_edit_record.id ) {\n\t\t\t\t\t$this.refresh_id = $this.current_edit_record.id;\n\t\t\t\t} else if ( TTUUID.isUUID( result_data ) && result_data != TTUUID.zero_id && result_data != TTUUID.not_exist_id ) {\n\t\t\t\t\t$this.refresh_id = result_data;\n\t\t\t\t} else {\n\t\t\t\t\t$this.refresh_id = null;\n\t\t\t\t}\n\n\t\t\t\t$this.search();\n\t\t\t}\n\n\t\t\tvar on_save_done_result = $this.onSaveDone( result ); //post hook for onSaveResult\n\t\t\tif ( on_save_done_result == undefined || on_save_done_result == true ) {\n\t\t\t\t$this.removeEditView();\n\t\t\t}\n\t\t} else {\n\t\t\t$this.setErrorTips( result );\n\t\t\t$this.setErrorMenu();\n\t\t}\n\t}\n\n\t//post hook for onSaveResult\n\tonSaveDone( result ) {\n\t\treturn true;\n\t}\n\n\tonSaveAndContinueDone( result ) {\n\t}\n\n\tonSaveAndNextDone( result ) {\n\t}\n\n\tonDeleteDone( result ) {\n\t\tthis.removeDeletedRows();\n\t}\n\n\tonDeleteAndNextDone( result ) {\n\t}\n\n\tonMassEditClick() {\n\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'mass_edit' );\n\t\t$this.openEditView();\n\t\tvar filter = {};\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\t\tthis.mass_edit_record_ids = [];\n\n\t\t$.each( grid_selected_id_array, function( index, value ) {\n\t\t\t$this.mass_edit_record_ids.push( value );\n\t\t} );\n\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_data.id = this.mass_edit_record_ids;\n\n\t\tthis.api['getCommon' + this.api.key_name + 'Data']( filter, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\tif ( !result_data ) {\n\t\t\t\t\tresult_data = [];\n\t\t\t\t}\n\n\t\t\t\t$this.api['getOptions']( 'unique_columns', {\n\t\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t\t$this.unique_columns = result.getResult();\n\t\t\t\t\t\t$this.api['getOptions']( 'linked_columns', {\n\t\t\t\t\t\t\tonResult: function( result1 ) {\n\t\t\t\t\t\t\t\t$this.linked_columns = result1.getResult();\n\t\t\t\t\t\t\t\tif ( $this.linked_columns === true ) {\n\t\t\t\t\t\t\t\t\t//there are no columns, you should be an empty array.\n\t\t\t\t\t\t\t\t\t$this.linked_columns = [];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( $this.sub_view_mode && $this.parent_key ) {\n\t\t\t\t\t\t\t\t\tresult_data[$this.parent_key] = $this.parent_value;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t$this.current_edit_record = result_data;\n\t\t\t\t\t\t\t\t$this.initEditView();\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\t/*\n\t * View Click handlers - Start\n\t */\n\tgetViewSelectedRecordId( record ) {\n\t\tvar retval = false;\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( record ) ) {\n\t\t\t//Handle cases where record object is passed in, so we can extract the string ID.\n\t\t\t// As well where the string ID is passed in directly as a UUID and accept that too.\n\t\t\t// This is required to handle MyAccount -> Request Authorization, view any record, then refresh the browser.\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( record ) && record.id ) {\n\t\t\t\tretval = record.id;\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isString */ .x.isString( record ) && TTUUID.isUUID( record ) ) {\n\t\t\t\tretval = record;\n\t\t\t}\n\t\t} else {\n\t\t\tif ( grid_selected_length > 0 ) {\n\t\t\t\tretval = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tdoViewAPICall( filter, api_args ) {\n\t\tvar callback = { onResult: this.handleViewAPICallbackResult.bind( this ) };\n\t\tif ( api_args ) {\n\t\t\t// If api_args specified, use api_args.filter, and ignore function filter parameter.\n\t\t\tapi_args.push( callback );\n\t\t\treturn this.api['get' + this.api.key_name].apply( this.api, api_args );\n\t\t} else {\n\t\t\treturn this.api['get' + this.api.key_name]( filter, callback );\n\t\t}\n\t}\n\n\thandleViewAPICallbackResult( result ) {\n\t\tvar result_data;\n\t\tif ( result && result.getResult ) {\n\t\t\tresult_data = result.getResult();\n\n\t\t\t//Do any result manipulation processes here, such as combining IDs together into a composite.\n\t\t\tresult_data = this.processAPICallbackResult( result_data );\n\n\t\t\tif ( !result_data ) {\n\t\t\t\tresult_data = [];\n\t\t\t}\n\n\t\t\tresult_data = result_data[0];\n\t\t} else {\n\t\t\t//Do not call processAPICallbackResult() here as we assume all processing has been completed earlier.\n\t\t\tresult_data = result;\n\t\t}\n\n\t\tif ( !result_data ) {\n\t\t\tTAlertManager.showAlert( $.i18n._( 'Record does not exist.' ) );\n\t\t\treturn this.onCancelClick();\n\t\t} else {\n\t\t\treturn this.doViewClickResult( result_data );\n\t\t}\n\t}\n\n\tdoViewClickResult( result_data ) {\n\t\tthis.current_edit_record = result_data;\n\t\tthis.initEditView();\n\t\treturn this.clearCurrentSelectedRecord();\n\t}\n\n\tonViewClick( record, noRefreshUI ) {\n\t\tthis.setCurrentEditViewState( 'view' );\n\t\tthis.openEditView();\n\n\t\tvar record_id = this.getViewSelectedRecordId( record );\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isFalseOrNull */ .x.isFalseOrNull( record_id ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.setCurrentSelectedRecord( record_id );\n\n\t\tvar filter = this.getAPIFilters();\n\n\t\treturn this.doViewAPICall( filter );\n\t}\n\n\tsetCurrentSelectedRecord( record ) {\n\t\tif ( record ) {\n\t\t\tthis.current_selected_record = record;\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetCurrentSelectedRecord() {\n\t\treturn this.current_selected_record;\n\t}\n\n\tclearCurrentSelectedRecord() {\n\t\tdelete this.current_selected_record;\n\t\treturn true;\n\t}\n\n\t// do we need this, Mike created it but check with him, as it may have just been a potential idea, not used.\n\tgetRecordIdFromRecord( object ) {\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( object ) ) {\n\t\t\treturn object_id;\n\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isString */ .x.isString( object ) ) {\n\t\t\treturn object;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/*\n\t * View Click handlers - End\n\t */\n\n\t/*\n\t * Common between View and Edit\n\t */\n\tprocessAPICallbackResult( result_data ) {\n\t\treturn result_data;\n\t}\n\n\tgetAPIFilters() {\n\t\t// override this function if view requires more filters\n\t\tvar record_id = this.getCurrentSelectedRecord();\n\t\tvar filter = {};\n\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_data.id = [record_id];\n\n\t\treturn filter;\n\t}\n\n\t/*\n\t * Edit Click handlers - Start\n\t */\n\tgetEditSelectedRecordId( record ) {\n\t\tvar retval = false;\n\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( record ) ) {\n\t\t\t//Handle cases where record object is passed in, so we can extract the string ID.\n\t\t\t// As well where the string ID is passed in directly as a UUID and accept that too.\n\t\t\t// This is required to handle editing any record, then refresh the browser.\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( record ) && record.id ) {\n\t\t\t\tretval = record.id;\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isString */ .x.isString( record ) && TTUUID.isUUID( record ) ) {\n\t\t\t\tretval = record;\n\t\t\t}\n\t\t} else {\n\t\t\t//Check for is_viewing and is_edit as the state may have changed from viewing to editing immediately before it got here.\n\t\t\t// Test this with: Attendance -> TimeSheet, Edit Punch, click Station field to view the station, then click \"Edit\" icon.\n\t\t\tif ( ( this.is_viewing || this.is_edit ) && this.current_edit_record && this.current_edit_record.id ) {\n\t\t\t\tretval = this.current_edit_record.id;\n\t\t\t} else if ( grid_selected_length > 0 ) {\n\t\t\t\tretval = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tretval = null;\n\t\t\t}\n\t\t}\n\t\treturn retval;\n\t}\n\n\tdoEditAPICall( filter, api_args, callback ) {\n\t\tif ( !callback ) {\n\t\t\tcallback = { onResult: this.handleEditAPICallbackResult.bind( this ) };\n\t\t}\n\t\tif ( api_args ) {\n\t\t\t// If api_args specified, use api_args.filter, and ignore function filter parameter.\n\t\t\tapi_args.push( callback );\n\t\t\treturn this.api['get' + this.api.key_name].apply( this.api, api_args );\n\t\t} else {\n\t\t\treturn this.api['get' + this.api.key_name]( filter, callback );\n\t\t}\n\t}\n\n\thandleEditAPICallbackResult( result ) {\n\t\tvar result_data;\n\t\tif ( result.getResult ) {\n\t\t\tresult_data = result.getResult();\n\n\t\t\t//Do any result manipulation processes here, such as combining IDs together into a composite.\n\t\t\tresult_data = this.processAPICallbackResult( result_data );\n\n\t\t\tif ( !result_data ) {\n\t\t\t\tresult_data = [];\n\t\t\t}\n\n\t\t\tresult_data = result_data[0];\n\t\t} else {\n\t\t\t//Do not call processAPICallbackResult() here as we assume all processing has been completed earlier.\n\t\t\tresult_data = result;\n\t\t}\n\t\tif ( !result_data ) {\n\t\t\tTAlertManager.showAlert( $.i18n._( 'Record does not exist.' ) );\n\t\t\treturn this.onCancelClick();\n\t\t}\n\n\t\tif ( this.sub_view_mode && this.parent_key ) {\n\t\t\tresult_data[this.parent_key] = this.parent_value;\n\t\t}\n\t\treturn this.doEditClickResult( result_data );\n\t}\n\n\tdoEditClickResult( result_data ) {\n\t\tthis.current_edit_record = result_data;\n\t\tthis.initEditView();\n\t}\n\n\tonEditClick( record_id, noRefreshUI ) {\n\t\tthis.setCurrentEditViewState( 'edit' );\n\t\tthis.openEditView();\n\n\t\trecord_id = this.getEditSelectedRecordId( record_id );\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isFalseOrNull */ .x.isFalseOrNull( record_id ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.setCurrentSelectedRecord( record_id );\n\n\t\tvar filter = this.getAPIFilters();\n\n\t\treturn this.doEditAPICall( filter );\n\t}\n\n\t/*\n\t * Edit Click handlers - End\n\t */\n\n\tonCopyClick() {\n\t\tif ( this.getGridSelectIdArray().length > 1 ) {\n\t\t\t//Warn user if they are trying to copy multiple records.\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.copy_multiple_confirm_message */ .x.copy_multiple_confirm_message, null, ( answer ) => {\n\t\t\t\tif ( answer === true ) {\n\t\t\t\t\tthis.doCopyClick();\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.doCopyClick();\n\t\t}\n\t}\n\n\tdoCopyClick() {\n\t\tvar $this = this;\n\t\tvar copyIds = [];\n\t\t$this.is_add = false;\n\t\tif ( $this.edit_view ) {\n\t\t\tcopyIds.push( $this.current_edit_record.id );\n\t\t\tif ( this.is_changed ) {\n\t\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t\t$this.is_changed = false;\n\t\t\t\t\t\t$this._continueDoCopy( copyIds );\n\t\t\t\t\t}\n\t\t\t\t\tProgressBar.closeOverlay();\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this._continueDoCopy( copyIds );\n\t\t\t}\n\t\t} else {\n\t\t\tcopyIds = $this.getGridSelectIdArray().slice();\n\t\t\t$this._continueDoCopy( copyIds );\n\t\t}\n\t}\n\n\t_continueDoCopy( copyIds ) {\n\t\tvar $this = this;\n\t\tProgressBar.showOverlay();\n\n\t\t//$this.api.setIsIdempotent( true ); //Force to idempotent API call to avoid duplicate network requests from causing errors displayed to the user.\n\t\t$this.api['copy' + $this.api.key_name]( copyIds, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onCopyResult( result );\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonCopyResult( result ) {\n\t\tvar $this = this;\n\n\t\tif ( result.isValid() ) {\n\t\t\t$this.search();\n\t\t\tif ( $this.edit_view ) {\n\t\t\t\t$this.removeEditView();\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tTAlertManager.showErrorAlert( result );\n\n\t\t\tif ( result.getRecordDetails().total > 1 ) {\n\t\t\t\t$this.search();\n\t\t\t}\n\t\t}\n\t}\n\n\tonCopyAsNewClick() {\n\t\tvar $this = this;\n\t\tif ( this.is_changed ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t$this._continueDoCopyAsNew();\n\t\t\t\t\tif ( $this.sub_view_mode ) {\n\t\t\t\t\t\t$this.clearSubViewControllers( false );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//Issue #3009 - Copy as new could cause blank tabs or old data to be shown instead of Save and Continue button.\n\t\t\t\t\t\t$this.clearSubViewControllers( true );\n\t\t\t\t\t\t$this.showSaveAndContinueButton();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} );\n\t\t} else {\n\t\t\tthis._continueDoCopyAsNew();\n\t\t\tif ( this.sub_view_mode ) {\n\t\t\t\tthis.clearSubViewControllers( false );\n\t\t\t} else {\n\t\t\t\t//Issue #3009 - Copy as new could cause blank tabs or old data to be shown instead of Save and Continue button.\n\t\t\t\tthis.clearSubViewControllers( true );\n\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t}\n\t\t}\n\t}\n\n\tcopyAsNewResetIds( data ) {\n\t\t//override where needed.\n\t\tdata.id = '';\n\t\treturn data;\n\t}\n\n\tshowSaveAndContinueButton() {\n\t\tif ( this.edit_view ) {\n\t\t\tlet save_and_continue_buttons = this.edit_view.find( '.save-and-continue-div' );\n\t\t\tif ( save_and_continue_buttons ) {\n\t\t\t\tsave_and_continue_buttons.css( 'display', 'block' );\n\t\t\t}\n\t\t}\n }\n\n\tclearSubViewControllers( force ) {\n\t\t//Issue #2915 - Sub view controllers should not be cleared while the user is on a sub view. For example when the user\n\t\t//clicks \"Copy as New\" on a record in the sub view and finishes using that sub view they are returned to\n\t\t//the primary controller and if data is wiped in that scenario the tab would be blank.\n\t\tif ( LocalCacheData.current_open_sub_controller == null || force ) {\n\t\t\t//Issue #2913 - Sub view data would remain on a view if a user viewed a sub view tab before clicking \"Copy as New\", \"Save & New\" and similar saving actions.\n\t\t\t//Clearing out the sub view controllers aims to prevent any old data from remaining.\n\t\t\t//If this does not happen the sub view HTML would remain and overlap with the \"Save & Continue\" message and in general show no longer relevant data.\n\t\t\tfor ( var property in LocalCacheData.current_open_primary_controller ) {\n\t\t\t\tif ( property.match( 'sub_([a-z_]*)view_controller' ) && LocalCacheData.current_open_primary_controller[property] && LocalCacheData.current_open_primary_controller[property].$el ) {\n\t\t\t\t\tDebug.Text( property, 'BaseViewController.js', 'BaseViewController', 'onSaveAndNextClick', 9 );\n\t\t\t\t\tLocalCacheData.current_open_primary_controller[property].$el.remove();\n\t\t\t\t\tLocalCacheData.current_open_primary_controller[property] = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetCopyAsNewFilter( filter ) {\n\t\t// override where needed.\n\t\treturn filter;\n\t}\n\n\t_continueDoCopyAsNew() {\n\t\tvar $this = this;\n\t\tthis.setCurrentEditViewState( 'new' );\n\t\tLocalCacheData.current_doing_context_action = 'copy_as_new';\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view ) ) {\n\t\t\tthis.current_edit_record = this.copyAsNewResetIds( this.current_edit_record );\n\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t\tthis.setEditMenu();\n\t\t\tthis.setTabStatus(); // Show tabs based on permission. setCurrentEditRecordData has functions to set by record type. See #2687 - setTabStatus() must go before setCurrentEditRecordData(), otherwise Premium Policy Tabs incorrectly shown.\n\t\t\t//Issue #2913 - When using copy and save actions (\"Copy As New\", \"Save & Copy\", etc) on views with sub views such as \"Pay Periods\" on Pay Period Schedules\n\t\t\t//the sub view tab might appear blank. This is because these copy functions do not go through the same order of events as a regular add click.\n\t\t\t//Because of that we need to call onTabShow() to make sure the code that creates the \"Save and continue\" message and button triggers.\n\t\t\tthis.onTabShow();\n\t\t\tif ( !this.editor ) {\n\t\t\t\t// #2687 if an editor exists in the view/tabs, we do not want to call setCurrentEditRecordData() as it wipes out the editor data in one of its child functions initInsideEditorData().\n\t\t\t\tthis.setCurrentEditRecordData();\n\t\t\t}\n\t\t\tthis.is_changed = false;\n\t\t\tProgressBar.closeOverlay();\n\t\t} else {\n\t\t\tvar filter = {};\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tvar grid_selected_length = grid_selected_id_array.length;\n\t\t\tif ( grid_selected_length > 0 ) {\n\t\t\t\tvar selectedId = grid_selected_id_array[0];\n\t\t\t} else {\n\t\t\t\tTAlertManager.showAlert( $.i18n._( 'No selected record' ) );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfilter.filter_data = {};\n\t\t\tfilter.filter_data.id = [selectedId];\n\n\t\t\tfilter = this.getCopyAsNewFilter( filter );\n\n\t\t\tthis.api['get' + this.api.key_name]( filter, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.onCopyAsNewResult( result );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tonCopyAsNewResult( result ) {\n\t\tvar result_data = result.getResult();\n\n\t\tif ( typeof result_data != 'object' ) {\n\t\t\tthis.onAddClick();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.openEditView(); // Put it here is to avoid if the selected one is not existed in data or have deleted by other pragram. in this case, the edit view should not be opend.\n\n\t\tresult_data = result_data[0];\n\n\t\tresult_data = this.copyAsNewResetIds( result_data );\n\n\t\tif ( this.sub_view_mode && this.parent_key ) {\n\t\t\tresult_data[this.parent_key] = this.parent_value;\n\t\t}\n\n\t\tthis.current_edit_record = result_data;\n\t\tvar $this = this;\n\n\t\t$( '.PunchesEditView .edit-view-tab-bar' ).css( 'opacity', 1 );\n\t\t$( '.PunchesEditView .edit-view-tab' ).css( 'opacity', 1 );\n\t\t$this.initEditView();\n\t}\n\n\t/*\n\t 1. Job is switched.\n\t 2. If a Task is already selected (and its not Task=0), keep it selected *if its available* in the newly populated Task list.\n\t 3. If the task selected is *not* available in the Task list, or the selected Task=0, then check the default_item_id field from the Job and if its *not* 0 also, select that Task by default.\n\n\t 'job' argument must be an object, or false/null\n\t */\n\tsetJobItemValueWhenJobChanged( job, job_item_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\tif ( job_item_id_col_name == undefined ) {\n\t\t\tjob_item_id_col_name = 'job_item_id';\n\t\t}\n\n\t\t//Error: Uncaught TypeError: Cannot set property 'job_item_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[job_item_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tTTPromise.add( 'BaseViewController', 'setJobItemValueWhenJobChanged' );\n\n\t\tif ( filter_data == undefined ) {\n\t\t\tfilter_data = { status_id: 10 };\n\t\t}\n\n\t\tif ( job != undefined && job != false ) {\n\t\t\tfilter_data['job_id'] = job.id; //Always filter by job\n\t\t}\n\n\t\tvar job_item_widget = $this.edit_view_ui_dic[job_item_id_col_name];\n\t\tvar current_job_item_id = job_item_widget.getValue();\n\t\tjob_item_widget.setSourceData( null );\n\t\tjob_item_widget.setCheckBox( true );\n\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[job_item_id_col_name].setDefaultArgs( args );\n\n\t\t//Make sure if current task is selected, that its still available on the new job.\n\t\tif ( current_job_item_id && current_job_item_id != TTUUID.zero_id ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\t//We are checking if the current selected record validates against the job costing criteria.\n\t\t\t//To avoid issues with pagination we are only checking against the current selected record.\n\t\t\tnew_arg.filter_data.id = current_job_item_id;\n\t\t\tnew_arg.filter_data.job_id = job.id;\n\t\t\tnew_arg.filter_columns = $this.edit_view_ui_dic[job_item_id_col_name].getColumnFilter();\n\t\t\t$this.job_item_api.getJobItem( new_arg, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot set property 'job_item_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed id. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a normal record.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_item_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_item_id === -2 ) {\n\t\t\t\t\t\tdata.push( { id: -2 } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.length == 0 ) {\n\t\t\t\t\t\tsetDefaultData( job_item_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( job_item_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( job_item_id_col_name ) {\n\t\t\tif ( job_item_id_col_name == undefined ) {\n\t\t\t\tjob_item_id_col_name = 'job_item_id';\n\t\t\t}\n\t\t\tif ( $this.current_edit_record.hasOwnProperty( job_item_id_col_name ) ) {\n\t\t\t\tjob_item_widget.setValue( job.default_item_id );\n\t\t\t\t$this.current_edit_record[job_item_id_col_name] = job.default_item_id;\n\n\t\t\t\tif ( job.default_item_id === false || job.default_item_id === 0 || job.default_item_id === TTUUID.zero_id || job.default_item_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tjob_item_widget.setValue( '' );\n\t\t\t\t$this.current_edit_record[job_item_id_col_name] = false;\n\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t}\n\n\t\t\tTTPromise.resolve( 'BaseViewController', 'setJobItemValueWhenJobChanged' );\n\t\t}\n\t}\n\n\tsetJobValueWhenCriteriaChanged( job_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\t//Error: Uncaught TypeError: Cannot set property 'job_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[job_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar job_widget = $this.edit_view_ui_dic[job_id_col_name];\n\t\tvar current_job_id = job_widget.getValue();\n\t\tjob_widget.setSourceData( null );\n\t\tjob_widget.setCheckBox( true );\n\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[job_id_col_name].setDefaultArgs( args );\n\n\t\t//Make sure if current job is selected, and that its still available after new criteria.\n\t\tif ( current_job_id && current_job_id != TTUUID.zero_id ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\t//We are checking if the current selected record validates against the job costing criteria.\n\t\t\t//To avoid issues with pagination we are only checking against the current selected record.\n\t\t\tnew_arg.filter_data.id = current_job_id;\n\t\t\tnew_arg.filter_columns = $this.edit_view_ui_dic[job_id_col_name].getColumnFilter();\n\t\t\t$this.job_api.getJob( new_arg, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot set property 'job_id' of null in /interface/html5/#!m=TimeSheet&date=20150126&user_id=54286 line 6785\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed id. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a normal record.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_job_id === -2 ) {\n\t\t\t\t\t\tdata.push( { id: -2 } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.length == 0 ) {\n\t\t\t\t\t\tsetDefaultData( job_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( job_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( job_id_col_name ) {\n\t\t\tif ( job_id_col_name == undefined ) {\n\t\t\t\tjob_id_col_name = 'job_id';\n\t\t\t}\n\t\t\tjob_widget.setValue( '' );\n\t\t\t$this.current_edit_record[job_id_col_name] = false;\n\t\t\t$this.edit_view_ui_dic.job_quick_search.setValue( '' );\n\t\t}\n\t}\n\n\tonJobQuickSearch( key, value, job_id_field, job_item_id_field, filter_data ) {\n\t\tvar $this = this;\n\n\t\tvar args = {};\n\n\t\tTTPromise.add( 'BaseViewController', 'onJobQuickSearch' );\n\n\t\tif ( job_id_field == undefined ) {\n\t\t\tjob_id_field = 'job_id';\n\t\t}\n\t\tif ( job_item_id_field == undefined ) {\n\t\t\tjob_item_id_field = 'job_item_id';\n\t\t}\n\n\t\t//Error: Uncaught TypeErro: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20141222&user_id=13566 line 6686\n\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[job_id_field] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === 'job_quick_search' ) {\n\t\t\targs.filter_data = { manual_id: value, user_id: this.current_edit_record.user_id, status_id: '10' };\n\n\t\t\tif ( this.current_edit_record.branch_id ) {\n\t\t\t\targs.filter_data.punch_branch_id = this.current_edit_record.branch_id;\n\t\t\t}\n\n\t\t\tif ( this.current_edit_record.department_id ) {\n\t\t\t\targs.filter_data.punch_department_id = this.current_edit_record.department_id;\n\t\t\t}\n\n\t\t\tthis.job_api.getJob( args, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20141222&user_id=13566 line 6686\n\t\t\t\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[job_id_field] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_id_field].setValue( result_data[0].id );\n\t\t\t\t\t\t$this.current_edit_record[job_id_field] = result_data[0].id;\n\t\t\t\t\t\t$this.setJobItemValueWhenJobChanged( result_data[0], job_item_id_field, filter_data );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_id_field].setValue( '' );\n\t\t\t\t\t\t$this.current_edit_record[job_id_field] = false;\n\t\t\t\t\t\t$this.setJobItemValueWhenJobChanged( false, job_item_id_field, filter_data );\n\t\t\t\t\t}\n\n\t\t\t\t\tTTPromise.resolve( 'BaseViewController', 'onJobQuickSearch' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t$this.edit_view_ui_dic['job_quick_search'].setCheckBox( true );\n\t\t\t$this.edit_view_ui_dic[job_id_field].setCheckBox( true );\n\t\t} else if ( key === 'job_item_quick_search' ) {\n\t\t\targs.filter_data = { manual_id: value, job_id: this.current_edit_record[job_id_field], status_id: '10' };\n\n\t\t\tthis.job_item_api.getJobItem( args, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'setValue' of undefined in /interface/html5/#!m=TimeSheet&date=20141222&user_id=13566 line 6686\n\t\t\t\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[job_item_id_field] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar result_data = result.getResult();\n\t\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_item_id_field].setValue( result_data[0].id );\n\t\t\t\t\t\t$this.current_edit_record[job_item_id_field] = result_data[0].id;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.edit_view_ui_dic[job_item_id_field].setValue( '' );\n\t\t\t\t\t\t$this.current_edit_record[job_item_id_field] = false;\n\t\t\t\t\t}\n\n\t\t\t\t\tTTPromise.resolve( 'BaseViewController', 'onJobQuickSearch' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true );\n\t\t\tthis.edit_view_ui_dic[job_item_id_field].setCheckBox( true );\n\t\t}\n\t}\n\n\tsetDepartmentValueWhenBranchChanged( department, department_id_col_name, filter_data ) {\n\t\tvar $this = this;\n\n\t\tif ( department_id_col_name == undefined ) {\n\t\t\tdepartment_id_col_name = 'department_id';\n\t\t}\n\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[department_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar department_widget = $this.edit_view_ui_dic[department_id_col_name];\n\t\tvar current_department_id = department_widget.getValue();\n\t\tdepartment_widget.setSourceData( null );\n\t\tdepartment_widget.setCheckBox( true );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\t$this.edit_view_ui_dic[department_id_col_name].setDefaultArgs( args );\n\n\t\t//Make sure if current department is selected, that its still available on the new job.\n\t\tif ( current_department_id && current_department_id != TTUUID.zero_id ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\t//We are checking if the current selected record validates against the job costing criteria.\n\t\t\t//To avoid issues with pagination we are only checking against the current selected record.\n\t\t\tnew_arg.filter_data.id = current_department_id;\n\t\t\tnew_arg.filter_columns = $this.edit_view_ui_dic[department_id_col_name].getColumnFilter();\n\t\t\t$this.department_api.getDepartment( new_arg, {\n\t\t\t\tonResult: function( result ) {\n\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed id. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a normal record.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_department_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( current_department_id === -2 ) {\n\t\t\t\t\t\tdata.push( { id: -2 } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( data.length === 0 ) {\n\t\t\t\t\t\tsetDefaultData( department_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( department_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( department_id_col_name ) {\n\t\t\tif ( department_id_col_name == undefined ) {\n\t\t\t\tdepartment_id_col_name = 'department_id';\n\t\t\t}\n\t\t\tif ( $this.current_edit_record.hasOwnProperty( department_id_col_name ) ) {\n\t\t\t\tdepartment_widget.setValue( department.default_item_id );\n\t\t\t\t$this.current_edit_record[department_id_col_name] = department.default_item_id;\n\n\t\t\t\tif ( department.default_item_id === false || department.default_item_id === 0 || department.default_item_id === TTUUID.zero_id || department.default_item_id === TTUUID.not_exist_id ) {\n\t\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tdepartment_widget.setValue( '' );\n\t\t\t\t$this.current_edit_record[department_id_col_name] = false;\n\t\t\t\t$this.edit_view_ui_dic.job_item_quick_search.setValue( '' );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetPunchTagValuesWhenCriteriaChanged( filter_data, punch_tag_id_col_name ) {\n\t\tvar $this = this;\n\n\t\tif ( !$this.current_edit_record || !$this.edit_view_ui_dic[punch_tag_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar punch_tag_widget = $this.edit_view_ui_dic[punch_tag_id_col_name];\n\t\tvar current_punch_tag_ids = punch_tag_widget.getValue();\n\t\tpunch_tag_widget.setSourceData( null );\n\n\t\tvar args = {};\n\t\targs.filter_data = filter_data;\n\t\tpunch_tag_widget.setDefaultArgs( args );\n\n\t\t//Make sure if current punch tags are selected, that they are still available on the new punch tag list.\n\t\tif ( current_punch_tag_ids && current_punch_tag_ids.length > 0 ) {\n\t\t\tvar new_arg = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( args );\n\t\t\tnew_arg.filter_data.id = current_punch_tag_ids;\n\t\t\t//Disabling paging to the API ($disable_paging = true) so that the user can have more punch tags selected than their preference for items per page.\n\t\t\t//Otherwise if they have 7 punch tags selected and their preference is 5, the api would only return 5 and 2 would be lost and unselected.\n\t\t\t$this.punch_tag_api.getPunchTag( new_arg, true,{\n\t\t\t\tonResult: function( punch_tag_result ) {\n\t\t\t\t\tif ( !$this.current_edit_record ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar data = punch_tag_result.getResult();\n\n\t\t\t\t\t//Data must be an array of allowed punch tags. If no results, data might be true or false from the API.\n\t\t\t\t\t//Convert this to an array so that data can contain TTUUID.not_exist_id.\n\t\t\t\t\t//This allows users to still select \"default\" or a different option that is not a punch tag.\n\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( Array.isArray( data ) && Array.isArray( current_punch_tag_ids ) && current_punch_tag_ids.includes( TTUUID.not_exist_id ) ) {\n\t\t\t\t\t\tdata.push( { id: TTUUID.not_exist_id } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( Array.isArray( data ) && data.length > 0 ) {\n\t\t\t\t\t\tif ( current_punch_tag_ids !== TTUUID.zero_id && current_punch_tag_ids.length > 0 && $this.shouldUpdatePunchTags( current_punch_tag_ids, data ) ) {\n\t\t\t\t\t\t\t//Merge in users last selected punch tags in case they switched back to that selection.\n\t\t\t\t\t\t\t//Example: They have selected a New York branch punch tag but switch their selection to a different branch\n\t\t\t\t\t\t\t//and then back to New York. In that case we should reselect the New York punch tag.\n\t\t\t\t\t\t\tcurrent_punch_tag_ids = _.union( current_punch_tag_ids, $this.previous_punch_tag_selection );\n\t\t\t\t\t\t\t//Compare current selected punch tags and the list of punch tags from the API and remove invalid punch tags.\n\t\t\t\t\t\t\tvar intersected_values = current_punch_tag_ids.filter( punch_tag_id => data.some( punch_tag => punch_tag_id === punch_tag.id ) );\n\t\t\t\t\t\t\tpunch_tag_widget.setValue( intersected_values );\n\t\t\t\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = intersected_values;\n\t\t\t\t\t\t\t//Update manual IDs in punch_tag_quick_search.\n\t\t\t\t\t\t\tvar punch_tag_manual_ids = data.filter( punch_tag => intersected_values.includes( punch_tag.id ) ).map( ( { manual_id } ) => manual_id );\n\t\t\t\t\t\t\t$this.edit_view_ui_dic['punch_tag_quick_search'].setValue( punch_tag_manual_ids.join() );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetDefaultData( punch_tag_id_col_name );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else {\n\t\t\tsetDefaultData( punch_tag_id_col_name );\n\t\t}\n\n\t\tfunction setDefaultData( punch_tag_id_col_name ) {\n\t\t\tif ( $this.current_edit_record.hasOwnProperty( punch_tag_id_col_name ) ) {\n\t\t\t\tpunch_tag_widget.setValue( $this.default_punch_tag );\n\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = $this.default_punch_tag;\n\n\t\t\t\tif ( $this.default_punch_tag.length === 0 ) {\n\t\t\t\t\t$this.edit_view_ui_dic.punch_tag_quick_search.setValue( '' );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tpunch_tag_widget.setValue( '' );\n\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = false;\n\t\t\t\t$this.edit_view_ui_dic.punch_tag_quick_search.setValue( '' );\n\t\t\t}\n\t\t}\n\t}\n\n\tshouldUpdatePunchTags( current_punch_tag_ids, data ) {\n\t\t//If the current selected punch tags and previously user selected punch tags do not match we should check and update.\n\t\tif ( Array.isArray( this.previous_punch_tag_selection ) && this.previous_punch_tag_selection.every( punch_tag => current_punch_tag_ids.includes( punch_tag ) ) === false ) {\n\t\t\treturn true;\n\t\t}\n\t\t//If the data returned from the API does not contain every currently selected punch tag then we need to remove invalid tags.\n\t\tif ( current_punch_tag_ids.every( punch_tag_id => data.some( punch_tag => punch_tag.id === punch_tag_id ) ) === false ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tsetPunchTagQuickSearchManualIds( punch_tags, get_real_data ) {\n\t\tif ( punch_tags == false || !this.edit_view_ui_dic['punch_tag_quick_search'] || ( Array.isArray( punch_tags ) && punch_tags.length === 0 ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( punch_tags === TTUUID.not_exist_id || ( Array.isArray( punch_tags ) && punch_tags.includes( TTUUID.not_exist_id ) ) ) {\n\t\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setValue( '' );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( get_real_data ) {\n\t\t\tvar $this = this;\n\t\t\tvar args = {};\n\t\t\targs.filter_data = { id: punch_tags };\n\t\t\tthis.punch_tag_api.getPunchTag( args, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\tvar data = result.getResult();\n\t\t\t\t\tvar manual_ids = [];\n\n\t\t\t\t\tfor ( var i = 0; i < data.length; i++ ) {\n\t\t\t\t\t\tmanual_ids.push( data[i].manual_id );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( $this.edit_view_ui_dic && $this.edit_view_ui_dic['punch_tag_quick_search'] ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic['punch_tag_quick_search'].setValue( manual_ids.join() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tvar manual_ids = [];\n\t\t\tfor ( var i = 0; i < punch_tags.length; i++ ) {\n\t\t\t\tmanual_ids.push( punch_tags[i].manual_id );\n\t\t\t}\n\n\t\t\tif ( this.edit_view_ui_dic && this.edit_view_ui_dic['punch_tag_quick_search'] ) {\n\t\t\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setValue( manual_ids.join() );\n\t\t\t}\n\t\t}\n\t}\n\n\tonPunchTagQuickSearch( value, filter_data, punch_tag_id_col_name ) {\n\t\tvar $this = this;\n\n\t\tvar args = {};\n\n\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[punch_tag_id_col_name] ) {\n\t\t\treturn;\n\t\t}\n\n\t\targs.filter_data = filter_data;\n\t\targs.filter_data.manual_id = value.split( ',' );\n\n\t\tthis.punch_tag_api.GetPunchTag( args, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic[punch_tag_id_col_name] ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar result_data = result.getResult();\n\n\t\t\t\t$this.edit_view_ui_dic[punch_tag_id_col_name].setSourceData( null );\n\n\t\t\t\tif ( result_data.length > 0 ) {\n\t\t\t\t\tvar punch_tags = result_data.map( punch_tag => punch_tag.id );\n\t\t\t\t\t$this.edit_view_ui_dic[punch_tag_id_col_name].setValue( punch_tags );\n\t\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = punch_tags;\n\t\t\t\t\t$this.previous_punch_tag_selection = punch_tags;\n\t\t\t\t} else {\n\t\t\t\t\t$this.edit_view_ui_dic[punch_tag_id_col_name].setValue( '' );\n\t\t\t\t\t$this.current_edit_record[punch_tag_id_col_name] = false;\n\t\t\t\t\t$this.previous_punch_tag_selection = [];\n\t\t\t\t}\n\n\t\t\t\tdelete args['manual_id'];\n\n\t\t\t}\n\t\t} );\n\n\t\tthis.edit_view_ui_dic['punch_tag_quick_search'].setCheckBox( true );\n\t\tthis.edit_view_ui_dic[punch_tag_id_col_name].setCheckBox( true );\n\t}\n\n\tgetPunchTagFilterData() {\n\t\tif ( !this.current_edit_record || !this.current_edit_record.user_id ) {\n\t\t\treturn {};\n\t\t}\n\n\t\tvar filter_data = {\n\t\t\tstatus_id: 10,\n\t\t\tuser_id: this.current_edit_record.user_id,\n\t\t\tbranch_id: this.current_edit_record.branch_id,\n\t\t\tdepartment_id: this.current_edit_record.department_id,\n\t\t\tjob_id: this.current_edit_record.job_id,\n\t\t\tjob_item_id: this.current_edit_record.job_item_id\n\t\t};\n\n\t\treturn filter_data;\n\t}\n\n\tonCancelClick( force_no_confirm, cancel_all, callback ) {\n\t\tTTPromise.add( 'base', 'onCancelClick' );\n\t\tvar $this = this;\n\t\t//#2342 This logic is also in onSubMenuClick click in RibbonViewController\n\t\tif ( !force_no_confirm\n\t\t\t&&\n\t\t\t(\n\t\t\t\t$this.is_changed == true\n\t\t\t\t|| ( LocalCacheData.current_open_primary_controller && LocalCacheData.current_open_primary_controller.edit_view && LocalCacheData.current_open_primary_controller.is_changed == true )\n\t\t\t\t|| ( LocalCacheData.current_open_report_controller && LocalCacheData.current_open_report_controller.is_changed == true )\n\t\t\t\t|| ( LocalCacheData.current_open_edit_only_controller && LocalCacheData.current_open_edit_only_controller.is_changed == true )\n\t\t\t\t|| ( LocalCacheData.current_open_sub_controller && LocalCacheData.current_open_sub_controller.edit_view && LocalCacheData.current_open_sub_controller.is_changed == true )\n\n\t\t\t) ) {\n\t\t\tthis.confirm_on_exit = true;\n\t\t}\n\n\t\tLocalCacheData.current_doing_context_action = 'cancel';\n\t\tif ( this.confirm_on_exit == true ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( clicked_yes ) {\n\t\t\t\tif ( clicked_yes === true ) {\n\t\t\t\t\tdoNext( force_no_confirm, cancel_all, callback );\n\t\t\t\t} else {\n\t\t\t\t\tTTPromise.reject( 'base', 'onCancelClick' );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tdoNext( force_no_confirm, cancel_all, callback );\n\t\t}\n\n\t\tfunction doNext( force_no_confirm, cancel_all, callback ) {\n\t\t\tif ( !$this.edit_view && $this.parent_view_controller && $this.sub_view_mode ) {\n\t\t\t\t$this.parent_view_controller.is_changed = false;\n\t\t\t\t$this.parent_view_controller.confirm_on_exit = false;\n\t\t\t\t$this.parent_view_controller.buildContextMenu( true );\n\t\t\t\t$this.parent_view_controller.onCancelClick( true ); //Force no confirm so we don't get two messages when cancelling from Edit Employee -> Wage (tab) -> Edit Wage.\n\t\t\t} else {\n\t\t\t\t$this.removeEditView( true );\n\t\t\t}\n\n\t\t\tif ( cancel_all ) {\n\t\t\t\tif ( LocalCacheData.current_open_edit_only_controller ) {\n\t\t\t\t\tLocalCacheData.current_open_edit_only_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t} else if ( LocalCacheData.current_open_sub_controller && LocalCacheData.current_open_sub_controller.edit_view ) {\n\t\t\t\t\tLocalCacheData.current_open_sub_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t} else if ( LocalCacheData.current_open_primary_controller && LocalCacheData.current_open_primary_controller.edit_view ) {\n\t\t\t\t\tLocalCacheData.current_open_primary_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t} else if ( LocalCacheData.current_open_report_controller ) {\n\t\t\t\t\tLocalCacheData.current_open_report_controller.onCancelClick( force_no_confirm, cancel_all );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( callback ) {\n\t\t\t\tcallback();\n\t\t\t}\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setUIInitComplete */ .x.setUIInitComplete();\n\t\t\tTTPromise.resolve( 'base', 'onCancelClick' );\n\t\t}\n\t}\n\n\t//Don't call super if override this function.\n\tonFormItemChange( target, doNotValidate ) {\n\t\t// Error: TypeError: this.current_edit_record is undefined in interface/html5/views/BaseViewController.js?v=9.0.7-20160202-113244 line 1691\n\t\tif ( !this.current_edit_record ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setIsChanged( target );\n\t\tthis.setMassEditingFieldsWhenFormChange( target );\n\t\tvar key = target.getField();\n\t\tthis.current_edit_record[key] = target.getValue();\n\n\t\tif ( !doNotValidate ) {\n\t\t\tthis.validate();\n\t\t}\n\t}\n\n\tsetIsChanged( target ) {\n\t\tvar key = target.getField();\n\t\tif ( this.current_edit_record && this.current_edit_record[key] != target.getValue() ) {\n\t\t\tthis.is_changed = true;\n\t\t}\n\t}\n\n\tonFormItemKeyUp( target ) {\n\t}\n\n\tonFormItemKeyDown( target ) {\n\t}\n\n\tsetMassEditingFieldsWhenFormChange( target ) {\n\t\tvar $this = this;\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tvar field = target.getField();\n\t\t\tvar linked_fields = [];\n\t\t\tvar is_linked_field = false;\n\t\t\t$.each( this.linked_columns, function( index, value ) {\n\t\t\t\tif ( value !== field ) {\n\t\t\t\t\tlinked_fields.push( value );\n\t\t\t\t} else {\n\t\t\t\t\tis_linked_field = true;\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif ( is_linked_field ) {\n\t\t\t\t$.each( linked_fields, function( index, value ) {\n\t\t\t\t\tvar is_checked = $this.edit_view_ui_dic[field].isChecked();\n\t\t\t\t\t$this.edit_view_ui_dic[value].setCheckBox( is_checked );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tinitEditViewTabs( tab_options ) {\n\t\tvar $this = this;\n\t\tif( tab_options === undefined ) {\n\t\t\ttab_options = {\n\t\t\t\tactivate: function( e, ui ) {\n\t\t\t\t\tif ( !$this.edit_view_tab || !$this.edit_view_tab.is( ':visible' ) ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t$this.onTabShow( e, ui );\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsTabs */ .x.triggerAnalyticsTabs( e, ui );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.setTabOVisibility( false );\n\n\t\tthis.edit_view_tab = this.edit_view_tab.tabs( tab_options );\n\n\t\tthis.edit_view_tab.off( 'click' ).on( 'click', function( e ) {\n\t\t\t$this.onTabIndexChange( e );\n\t\t} );\n\t}\n\n\tsetTabHtml( tab_model ) {\n\n\t\t// TODO: Go off tab_model not labels. Will need to do this anyway, as we trigger earlier.\n\t\t// HTML2JS TODO: For now this will just generate the tab labels, and once that works, we move on to the tab content div's.\n\t\t// TODO: This needs to be triggered sooner in BaseView.initEditViewUI as currently it happens after the .tabs() initialization and causing the class styles for tabs not to be added to the right tab elems, as they did not exist at the time to be added.\n\t\t// Maybe directly into initEditViewUI, as theres only 11 overrides for that.\n\n\t\tvar tab_bar_labels = this.edit_view.find( '.edit-view-tab-bar-label' );\n\t\tvar tab_bar_content; // insert after the label element.\n\t\t// find the html first, and check if its not already set.\n\t\tif( tab_bar_labels.children().length === 0 ) { // TODO: Perhaps in future also count number of children and compare against labels. If not matching, clear and start again.\n\t\t\t// No label elements found, likely using the new templating logic. Continue to generate the tab html.\n\n\t\t\t// Notes\n\t\t\t/* Fri Dec 17\n\t\t\tTODO:\n\t\t\t- 1. [Done]. First add the save and continue divs into templates as if subview.\n\t\t\t\t1b. Fix subview state issues on Employee->Employees tabs.\n\t\t\t- 2. then hardcode the hierarchy behaviour into its tab_model\n\t\t\t- 3. also hardcode potentially audit, but it might be covered by 1.\n\t\t\t- 4. qualifactions tab hardcoded with the subview things.\n\t\t\t- 5. sort out the first-column second column.\n\t\t\t--- either hardcode into the tab_model for number of columns or\n\t\t\t--- count the number of child elements in second column, and if zero, remove,\n\t\t\t\tand then add full width into the first column element.\n\t\t\t- 6. what was the subviewcontroller errors on some tabs. might be solved by 1. check employee view tabs.\n\t\t\t */\n\n\t\t\t// search for 'first-column full' - 73+ files\n\t\t\t// search for 'second-column' - 27 files\n\t\t\t// therefore first-column full width will be default, and second column will be specified in view controller, to avoid lots of avoidable editing of view files.\n\t\t\tfor ( let tab_id in tab_model ) {\n\t\t\t\t// Create and insert the label elements.\n\t\t\t\tvar new_tab_label_li = document.createElement( 'li' );\n\t\t\t\tvar new_tab_label_li_a = document.createElement( 'a' );\n\t\t\t\tnew_tab_label_li_a.setAttribute('ref', tab_id );\n\t\t\t\tnew_tab_label_li_a.setAttribute('href', '#' + tab_id );\n\t\t\t\tnew_tab_label_li.appendChild( new_tab_label_li_a );\n\n\t\t\t\ttab_bar_labels.append( new_tab_label_li ); // jQuery append()\n\t\t\t\t// TODO: Could also directly set the label value part here too in future.\n\t\t\t}\n\n\t\t} else {\n\t\t\t// Do nothing, labels already exist, likely from legacy html template loading.\n\t\t}\n\n\t\tvar tab_bar_parent = tab_bar_labels.parent();\n\t\tvar tab_bar_content_divs = tab_bar_parent.find( '.edit-view-tab-outside' );\n\n\t\tif( tab_bar_content_divs.children().length === 0 ) {\n\t\t\t// Create and insert the tab content divs\n\n\n\t\t\tfor ( let tab_id in tab_model ) {\n\t\t\t\t// Create and insert the label elements.\n\t\t\t\tlet tab_content_html = '';\n\t\t\t\tlet tab = tab_model[ tab_id ];\n\t\t\t\tlet is_sub_view = inferSubViewFromTab( tab ); // TODO: HTML2JS: Improve this to avoid inferring, by adding is_sub_view to relevant tab models.\n\n\t\t\t\tif( tab.html_template ) {\n\t\t\t\t\t// html template provided as override, do not use HtmlTemplatesGlobal. Only used for complex one-off tab html's.\n\t\t\t\t\ttab_content_html = tab.html_template;\n\t\t\t\t} else {\n\t\t\t\t\ttab_content_html = $( _services_HtmlTemplates__WEBPACK_IMPORTED_MODULE_5__/* .HtmlTemplatesGlobal.genericTab */ .H.genericTab({\n\t\t\t\t\t\ttab_id: tab_id,\n\t\t\t\t\t\tis_multi_column: tab.is_multi_column ? true : false,\n\t\t\t\t\t\tshow_permission_div: tab.show_permission_div ? true : false,\n\t\t\t\t\t\tis_sub_view: is_sub_view // to convert undefined's to false\n\t\t\t\t\t}));\n\t\t\t\t}\n\n\t\t\t\ttab_bar_parent.append( tab_content_html ); // Insert each new tab content at the end of tab_bar div (and after the ul.edit-view-tab-bar-label element, and other tab contents.)\n\t\t\t}\n\n\t\t\t// tab_bar.append( $( HtmlTemplatesGlobal.auditTab()) ); // after all the tab contents, add the audit tab. (TODO: handle situations where audit not needed). Auctually, audit should be in the list of tabs already. comment out for now.\n\n\t\t\t// switch ( tab_ref_key ) {\n\t\t\t// \tcase x:\n\t\t\t// \t\t// code block\n\t\t\t// \t\tbreak;\n\t\t\t// \tcase y:\n\t\t\t// \t\t// code block\n\t\t\t// \t\tbreak;\n\t\t\t// \tdefault:\n\t\t\t// \t// code block\n\t\t\t// }\n\n\t\t} else {\n\t\t\t// tab_bar_content_divs.length must be greater than 0\n\t\t\t// Do nothing, and no html will be affected.\n\t\t}\n\n\t\tfunction inferSubViewFromTab( tab ) {\n\t\t\tif ( tab.is_sub_view == true ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif( tab.init_callback === undefined ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar init_callback_string = tab.init_callback || '';\n\t\t\tvar infer_subview_tab_state = init_callback_string.toLowerCase().indexOf( 'sub' ) !== -1;\n\t\t\tif ( infer_subview_tab_state === true ) {\n\t\t\t\t// This one is a little more experimental (assumes all sub views have init callback functions named with 'sub'), but might work as temporary during refactor.\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Nothing matched, return false by default.\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tsetTabLabels( source ) {\n\t\tfor ( var key in source ) {\n\t\t\tthis.edit_view.find( 'a[ref=' + key + ']' ).text( source[key] );\n\t\t}\n\t}\n\n\tgetTabModel() {\n\t\treturn this.tab_model;\n\t}\n\n\tsetTabModel( model ) {\n\t\tvar tab_labels = {};\n\n\t\tfor ( var i in model ) {\n\t\t\t//If the model is \"true\", then use default models for audit/attachment tabs.\n\t\t\tif ( i == 'tab_audit' && model[i] === true ) {\n\t\t\t\tmodel['tab_audit'] = {\n\t\t\t\t\t'label': $.i18n._( 'Audit' ),\n\t\t\t\t\t'init_callback': 'initSubLogView',\n\t\t\t\t\t'display_on_mass_edit': false,\n\t\t\t\t\t'display_on_add': false\n\t\t\t\t};\n\t\t\t} else if ( i == 'tab_attachment' && model[i] === true ) {\n\t\t\t\tmodel['tab_attachment'] = {\n\t\t\t\t\t'label': $.i18n._( 'Attachment' ),\n\t\t\t\t\t'init_callback': 'initSubDocumentView',\n\t\t\t\t\t'display_on_mass_edit': false\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( model[i].hasOwnProperty( 'label' ) && model[i].label != '' ) {\n\t\t\t\ttab_labels[i] = model[i].label;\n\t\t\t}\n\t\t}\n\n\t\tthis.tab_model = model;\n\t\tthis.setTabHtml( model );\n\t\tthis.initEditViewTabs();\n\t\tthis.setTabLabels( tab_labels );\n\n\t\treturn true;\n\t}\n\n\tonTabShow( e, ui ) {\n\t\tif ( !this.current_edit_record ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar key = this.getEditViewTabIndex();\n\t\tthis.editFieldResize( key );\n\n\t\tvar tab_model = this.getTabModel();\n\n\t\tif ( tab_model != null ) {\n\t\t\tif ( ui && ui.oldTab ) {\n\t\t\t\tvar prev_tab_name = ui.oldTab.find( 'a' )[0].getAttribute( 'href' ).substring( 1 );\n\t\t\t\tif ( tab_model[prev_tab_name] && tab_model[prev_tab_name].hasOwnProperty( 'on_exit_callback' ) && tab_model[prev_tab_name].on_exit_callback != '' ) {\n\t\t\t\t\tthis[tab_model[prev_tab_name].on_exit_callback]( prev_tab_name ); //Call mapped function to initialize the tab.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//ReFactored path to handle tabs based on a tab model mapping defined in each view class.\n\t\t\t//This abstracts the entry point for all tabs initializations to help with hiding/showing them and to reduce code duplication.\n\t\t\tvar tab_name = null;\n\t\t\tvar sub_view_div = null;\n\n\t\t\tvar tab_bar = this.edit_view.find( '.edit-view-tab-bar li.ui-tabs-active' ).find( 'a' );\n\t\t\tif ( tab_bar.length > 0 ) {\n\t\t\t\ttab_name = tab_bar[0].getAttribute( 'href' ).substring( 1 ); //Remove the '#';\n\t\t\t\tsub_view_div = this.edit_view_tab.find( '#' + tab_name ).find( '.first-column-sub-view' );\n\t\t\t}\n\n\t\t\tif ( sub_view_div && sub_view_div.length > 0 && this.tab_model[tab_name] && !this.tab_model[tab_name].initialized ) { //Only hide grid on first initialization as it has to load all the data. Otherwise the 2nd time the user goes to the tab they will see some minor \"flashing\"\n\t\t\t\tTTPromise.add( 'BaseViewController', 'onTabShow' );\n\t\t\t\tTTPromise.wait( 'BaseViewController', 'onTabShow', function() {\n\t\t\t\t\tsub_view_div.css( 'opacity', '1' );\n\t\t\t\t} );\n\n\t\t\t\tsub_view_div.css( 'opacity', '0' ); //Hide the grid while its loading/sizing.\n\t\t\t\tthis.tab_model[tab_name].initialized = true;\n\t\t\t}\n\n\t\t\tif ( tab_model[tab_name] ) {\n\t\t\t\t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t//Call the init_callback even if we are editing an existing record or creating a new one.\n\t\t\t\t// As some views (ie: OverTime Policy) need to control whats shown on each tab regardless of if we are editing or adding.\n\t\t\t\tif ( tab_model[tab_name].hasOwnProperty( 'init_callback' ) && tab_model[tab_name].init_callback != '' ) {\n\t\t\t\t\tthis[tab_model[tab_name].init_callback]( tab_name ); //Call mapped function to initialize the tab.\n\t\t\t\t} else {\n\t\t\t\t\t//Assume primary tab and build context menu.\n\t\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\t\tthis.setEditMenu();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'none' ); //This would prevent the grid from showing in Attendance -> TimeSheet, Accumulated Time view.\n\t\t\t\t\t\t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if ( this.current_edit_record.id ) {\n\t\t\t\t// \t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t// \tif ( tab_model[tab_name].hasOwnProperty('init_callback') && tab_model[tab_name].init_callback != '' ) {\n\t\t\t\t// \t\tthis[tab_model[tab_name].init_callback]( tab_name ); //Call mapped function to initialize the tab.\n\t\t\t\t// \t} else {\n\t\t\t\t// \t\t//Assume primary tab and build context menu.\n\t\t\t\t// \t\tthis.buildContextMenu( true );\n\t\t\t\t// \t\tthis.setEditMenu();\n\t\t\t\t// \t}\n\t\t\t\t// } else {\n\t\t\t\t// \t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'none' ); //This would prevent the grid from showing in Attendance -> TimeSheet, Accumulated Time view.\n\t\t\t\t// \t//this.edit_view_tab.find( '#'+ tab_name ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t// \tthis.edit_view.find( '.save-and-continue-div' ).css( 'display', 'block' );\n\t\t\t\t// }\n\t\t\t} else {\n\t\t\t\t//Assume primary tab and build context menu.\n\t\t\t\tthis.buildContextMenu( true );\n\t\t\t\tthis.setEditMenu();\n\t\t\t}\n\t\t} else {\n\t\t\t//Handle most cases that one tab and on audit tab\n\t\t\tif ( key === 1 ) {\n\n\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t\tthis.initSubLogView( 'tab_audit' );\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'none' );\n\t\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tthis.buildContextMenu( true );\n\t\t\t\tthis.setEditMenu();\n\t\t\t}\n\t\t}\n\t}\n\n\t//When overriding this function, always call super() so it can handle tab_audit/tab_attachment on its own.\n\tcheckTabPermissions( tab ) {\n\t\tvar retval = true; //Most tabs are shown, so default to true.\n\n\t\tswitch ( tab ) {\n\t\t\tcase 'tab_audit':\n\t\t\t\tretval = this.subAuditValidate();\n\t\t\t\tbreak;\n\t\t\tcase 'tab_attachment':\n\t\t\t\tretval = this.subDocumentValidate();\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn retval;\n\t}\n\n\tsetTabStatus() {\n\t\t// exception that edit_view_tab is null\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tab_model = this.getTabModel();\n\n\t\tif ( tab_model != null ) {\n\t\t\tvar visible_tab_indexes = Array();\n\n\t\t\t//ReFactored path to handle tabs based on a tab model mapping defined in each view class.\n\t\t\t//This abstracts the entry point for all tabs initializations to help with hiding/showing them and to reduce code duplication.\n\t\t\tfor ( var i in tab_model ) {\n\t\t\t\tvar tab_index = $( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().index();\n\n\t\t\t\tif ( ( this.is_mass_editing && tab_model[i].hasOwnProperty( 'display_on_mass_edit' ) && tab_model[i].display_on_mass_edit == false )\n\t\t\t\t\t|| ( ( this.is_add || this.is_mass_adding ) && tab_model[i].hasOwnProperty( 'display_on_add' ) && tab_model[i].display_on_add == false ) ) {\n\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().hide();\n\t\t\t\t} else {\n\t\t\t\t\tif ( this.checkTabPermissions( i ) == true ) {\n\t\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().show();\n\t\t\t\t\t\tvisible_tab_indexes.push( tab_index );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"' + i + '\"]' ) ).parent().hide();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Always start with the first tab that actually has permissions to be shown. This is important for sub-views like Edit Employee, Tax, New icon, where it shows only a single tab where there are really 5+ tabs just hidden.\n\t\t\tvisible_tab_indexes = visible_tab_indexes.sort( function( a, b ) {\n\t\t\t\treturn a - b;\n\t\t\t} ); //numeric sort.\n\n\t\t\tif ( visible_tab_indexes[0] ) {\n\t\t\t\tthis.edit_view_tab.tabs( 'option', 'active', visible_tab_indexes[0] );\n\t\t\t}\n\t\t} else {\n\t\t\t//Handle most cases that one tab and on audit tab\n\t\t\tif ( this.is_mass_editing ) {\n\n\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"tab_audit\"]' ) ).parent().hide();\n\t\t\t\tthis.edit_view_tab.tabs( 'option', 'active', 0 );\n\n\t\t\t} else {\n\n\t\t\t\tif ( this.subAuditValidate() ) {\n\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"tab_audit\"]' ) ).parent().show();\n\t\t\t\t} else {\n\t\t\t\t\t$( this.edit_view_tab.find( 'ul li a[ref=\"tab_audit\"]' ) ).parent().hide();\n\t\t\t\t\tthis.edit_view_tab.tabs( 'option', 'active', 0 );\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tthis.editFieldResize( 0 );\n\t}\n\n\tonTabIndexChange( e ) {\n\t\tTTPromise.add( 'BaseViewController', 'onTabIndexChange' );\n\t\tTTPromise.wait();\n\n\t\tif ( ( !this.sub_view_mode && !this.edit_only_mode ) || typeof this.initReport == 'function' ) {\n\t\t\tvar current_url = window.location.href;\n\n\t\t\tif ( current_url.indexOf( '&tab' ) > 0 ) {\n\t\t\t\tcurrent_url = current_url.substring( 0, current_url.indexOf( '&tab' ) );\n\t\t\t}\n\t\t\tvar tab_name = this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().eq( this.getEditViewTabIndex() ).text();\n\t\t\ttab_name = tab_name.replace( /\\/|\\s+/g, '' );\n\t\t\tcurrent_url = current_url + '&tab=' + tab_name;\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( current_url );\n\n\t\t}\n\n\t\tthis.hideErrorTips();\n\t\tTTPromise.resolve( 'BaseViewController', 'onTabIndexChange' );\n\t}\n\n\thideErrorTips() {\n\t\tfor ( var key in this.edit_view_error_ui_dic ) {\n\t\t\t//#2581 - Uncaught TypeError: this.edit_view_error_ui_dic[key].hideErrorTip is not a function\n\t\t\tif ( this.edit_view_error_ui_dic[key] && typeof this.edit_view_error_ui_dic[key].hideErrorTip == 'function' ) {\n\t\t\t\tthis.edit_view_error_ui_dic[key].hideErrorTip();\n\t\t\t}\n\t\t}\n\t\tthis.removeEditViewErrorTip();\n\t}\n\n\t//removed workarounds and comments for qtip1 when upgrading to qtip2.\n\tremoveEditViewErrorTip() {\n\t\tif ( $( '.qtip2-error-tip:visible' ) ) {\n\t\t\t$( '.qtip2-error-tip' ).remove();\n\t\t}\n\n\t}\n\n\tremoveEditViewWarningTip() {\n\t\tif ( $( '.qtip2-warning-tip:visible' ) ) {\n\t\t\t$( '.qtip2-warning-tip' ).remove();\n\t\t}\n\t}\n\n\tonCountryChange() {\n\t\tvar selectVal = this.edit_view_ui_dic['country'].getValue();\n\t\tthis.eSetProvince( selectVal, true );\n\t\tthis.clearErrorTips();\n\t\tthis.setEditMenu();\n\t}\n\n\t//Make sure this.current_edit_record is updated before validate\n\tvalidate( api ) {\n\t\tif ( this.enable_validation ) {\n\t\t\t//Allow alternate api to be validated.\n\t\t\tif ( api == undefined ) {\n\t\t\t\tvar api = this.api;\n\t\t\t}\n\n\t\t\tvar $this = this;\n\t\t\tvar record = {};\n\t\t\tif ( this.is_mass_editing ) {\n\t\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.isChecked ) ) {\n\t\t\t\t\t\tif ( widget.isChecked() && widget.getEnabled() ) {\n\t\t\t\t\t\t\trecord[key] = this.current_edit_record[key]; // Note: Some view controllers use widget.getValue() instead of current_edit_record[key]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trecord = this.current_edit_record;\n\t\t\t}\n\t\t\trecord = this.uniformVariable( record );\n\t\t\tapi['validate' + api.key_name]( record, {\n\t\t\t\tonResult: function( result ) {\n\t\t\t\t\t$this.validateResult( result );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tDebug.Text( 'Validation disabled', 'BaseViewController.js', 'BaseViewController', 'validate', 10 );\n\t\t}\n\t}\n\n\tvalidateResult( result ) {\n\t\tvar $this = this;\n\t\t$this.clearErrorTips(); //Always clear error\n\t\tif ( !$this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !result ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( result.isValid() ) {\n\t\t\t$this.edit_view.attr( 'validate_complete', true );\n\t\t\t$this.setEditMenu();\n\t\t} else {\n\t\t\t$this.setErrorMenu();\n\t\t\t$this.setErrorTips( result, this.show_warning_when_validation );\n\n\t\t}\n\t}\n\n\tclearErrorTips() {\n\n\t\tfor ( var key in this.edit_view_error_ui_dic ) {\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'clearErrorStyle' of undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-111140 line 1779\n\t\t\tif ( !this.edit_view_error_ui_dic.hasOwnProperty( key ) || !this.edit_view_error_ui_dic[key] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.edit_view_error_ui_dic[key].clearErrorStyle();\n\t\t}\n\n\t\t// Error: Uncaught TypeError: Cannot read property 'interfaces' of undefined in interface/html5/framework/jquery.qtip.min.js?v=9.0.0-20150918-221906 line 15\n\t\tthis.removeEditViewErrorTip();\n\t\tthis.removeEditViewWarningTip();\n\t\t$( '.error-tab' ).removeClass( 'error-tab' );\n\t\t$( '.error-tab-hide' ).removeClass( 'error-tab-hide' );\n\t\t$( '.warning-tab' ).removeClass( 'warning-tab' );\n\t\t$( '.warning-tab-hide' ).removeClass( 'warning-tab-hide' );\n\t\t// Clear pulse on tabs\n\t\tif ( this.pulse_time_dic ) {\n\t\t\tfor ( var key1 in this.pulse_time_dic ) {\n\t\t\t\tclearInterval( this.pulse_time_dic[key1] );\n\t\t\t}\n\t\t\tthis.pulse_time_dic = {};\n\t\t}\n\t\tthis.edit_view_error_ui_dic = {};\n\n\t\t$( '.qtip .qtip2-error-tip' ).remove();\n\t}\n\n\t//Override this if more than one tab\n\tsetErrorTips( result, show_warning ) {\n\t\tthis.clearErrorTips();\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( show_warning ) ) {\n\t\t\tshow_warning = true;\n\t\t}\n\n\t\t//Error: Unable to get property 'find' of undefined or null reference in http://timeclock:8085/interface/html5/views/BaseViewController.js?v=7.4.3-20140926-105827 line 1769\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar details = result.getDetails();\n\t\t// Only check first item\n\t\t// Error: Uncaught TypeError: Cannot call method 'hasOwnProperty' of undefined in /interface/html5/views/BaseViewController.js?v=9.0.0-20150822-134259 line 1879\n\t\t// Zero is not always the first element;\n\t\tvar first_el = 0;\n\t\tfor ( var first_el in details ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif ( details && details[first_el] && details[first_el].hasOwnProperty( 'error' ) ) {\n\t\t\tthis.setErrorTipsError( result );\n\t\t} else if ( details && details[first_el] && details[first_el].hasOwnProperty( 'warning' ) ) { //Error: TypeError: details[0] is undefined in https://greenacres.timetrex.com/interface/html5/views/BaseViewController.js?v=9.0.0-20150822-105118 line 1883\n\t\t\tif ( show_warning ) {\n\t\t\t\tthis.setErrorTipsWarning( result );\n\t\t\t}\n\t\t\tthis.setEditMenu();\n\t\t} else if ( result.getCode() == 'PERMISSION' || result.getCode() == 'VALIDATION' ) {\n\t\t\tTAlertManager.showErrorAlert( result );\n\t\t} else {\n\t\t\t// Make sure current codes work.\n\t\t\tthis.setErrorTipsError( result );\n\t\t}\n\t}\n\n\tsetErrorTipsWarning( result ) {\n\t\tvar $this = this;\n\t\tvar widget;\n\t\t// when do validation, only show warning no alert\n\t\tvar $current_doing_context_action = LocalCacheData.current_doing_context_action; //#2474 - LocalCacheData.current_doing_context_action can change to \"validate\" while waiting for user to respond to warning box.\n\t\tif ( $current_doing_context_action != 'validate' ) {\n\t\t\tTAlertManager.showWarningAlert( result, function( flag ) {\n\t\t\t\tif ( flag ) {\n\t\t\t\t\tswitch ( $current_doing_context_action ) {\n\t\t\t\t\t\tcase 'save':\n\t\t\t\t\t\t\t$this.onSaveClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'save_and_continue':\n\t\t\t\t\t\t\t$this.onSaveAndContinue( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'save_and_next':\n\t\t\t\t\t\t\t$this.onSaveAndNextClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\t\t\t$this.onSaveAndCopy( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'new':\n\t\t\t\t\t\t\t$this.onSaveAndNewClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'authorize': //Allow validation warnings to work when authorizing Request/TimeSheet/Expense.\n\t\t\t\t\t\t\t$this.onAuthorizationClick( true );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.show_warning_when_validation = true;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t//Error: Unable to get property 'warning' of undefined or null reference\n\t\tvar error_list = [];\n\t\tif ( result.getDetails().length == 1 ) {\n\t\t\terror_list = result.getDetails()[0].warning;\n\t\t}\n\t\tvar found_in_current_tab = false;\n\t\tfor ( var key in error_list ) {\n\t\t\tif ( !error_list.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key] ) && this.edit_view_ui_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key];\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\t\tvar len = this.edit_view_ui_validation_field_dic[key].length;\n\t\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\t\tvar item = this.edit_view_ui_validation_field_dic[key][i];\n\t\t\t\t\t\tif ( item.closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\t\t\twidget = item;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( this.edit_view_ui_validation_field_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\twidget = this.edit_view_ui_validation_field_dic[key];\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if ( key.indexOf( '_id' ) < 0 && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key + '_id'] ) && this.edit_view_ui_dic[key + '_id'].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key + '_id'];\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( error_list[key] ) {\n\t\t\t\tvar show_error = false;\n\t\t\t\tif ( widget.is( ':visible' ) ) {\n\t\t\t\t\tshow_error = true;\n\t\t\t\t\tfound_in_current_tab = true;\n\t\t\t\t}\n\n\t\t\t\tif ( typeof widget.setErrorStyle === 'function' ) { //Fix JS exception: Uncaught TypeError: widget.setErrorStyle is not a function\n\t\t\t\t\twidget.setErrorStyle( error_list[key], show_error, true );\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tthis.showErrorStatusOnTab( widget, false );\n\t\t\tthis.edit_view_error_ui_dic[key] = widget;\n\t\t}\n\t\tif ( !found_in_current_tab ) {\n\t\t\tthis.showEditViewError( result );\n\t\t}\n\t}\n\n\tshowErrorStatusOnTab( widget, isError ) {\n\t\tvar parentContainer = widget.parent();\n\t\tvar i = 0;\n\t\twhile ( !parentContainer.hasClass( 'edit-view-tab-outside' ) && i < 5 ) {\n\t\t\ti = i + 1;\n\t\t\tparentContainer = parentContainer.parent();\n\t\t}\n\t\tif ( parentContainer.hasClass( 'edit-view-tab-outside' ) ) {\n\t\t\tvar id = parentContainer.attr( 'id' );\n\t\t\tvar tab = this.edit_view.find( 'a[ref=\"' + id + '\"]' );\n\t\t\tif ( isError ) {\n\t\t\t\ttab.parent().addClass( 'error-tab' );\n\t\t\t\tthis.startPulse( id, tab.parent() );\n\t\t\t} else {\n\t\t\t\ttab.parent().addClass( 'warning-tab' );\n\t\t\t\tthis.startPulse( id, tab.parent(), true );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tstartPulse( tab_id, target, is_warning ) {\n\t\tvar $this = this;\n\t\tif ( !this.pulse_time_dic ) {\n\t\t\tthis.pulse_time_dic = {};\n\t\t}\n\t\tif ( this.pulse_time_dic[tab_id] ) {\n\t\t\tcleanTimer( tab_id );\n\t\t}\n\t\tthis.pulse_time_dic[tab_id] = setInterval( function() {\n\t\t\tif ( is_warning ) {\n\t\t\t\tif ( target.hasClass( 'warning-tab-hide' ) ) {\n\t\t\t\t\ttarget.removeClass( 'warning-tab-hide' );\n\t\t\t\t} else if ( target.hasClass( 'warning-tab' ) ) {\n\t\t\t\t\ttarget.addClass( 'warning-tab-hide' );\n\t\t\t\t} else {\n\t\t\t\t\tcleanTimer( tab_id );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( target.hasClass( 'error-tab-hide' ) ) {\n\t\t\t\t\ttarget.removeClass( 'error-tab-hide' );\n\t\t\t\t} else if ( target.hasClass( 'error-tab' ) ) {\n\t\t\t\t\ttarget.addClass( 'error-tab-hide' );\n\t\t\t\t\tcleanTimer( tab_id );\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tif ( target.hasClass( 'error-tab-hide' ) ) {\n\t\t\t\t\t\t\ttarget.removeClass( 'error-tab-hide' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$this.startPulse( tab_id, target, is_warning );\n\t\t\t\t\t}, 1700 );\n\t\t\t\t} else {\n\t\t\t\t\tcleanTimer( tab_id );\n\t\t\t\t}\n\t\t\t}\n\t\t}, 2000 );\n\n\t\tfunction cleanTimer( tab_id ) {\n\t\t\tclearInterval( $this.pulse_time_dic[tab_id] );\n\t\t\t$this.pulse_time_dic[tab_id] = null;\n\t\t}\n\t}\n\n\tsetErrorTipsError( result ) {\n\n\t\t//Error: TypeError: details[0] is undefined in interface/html5/views/BaseViewController.js?v=9.0.0-20150822-105118 line 1883\n\t\t// Zero is not always the firwst index.\n\t\tvar result_array = result.getDetails() ? result.getDetails() : {};\n\t\tvar first_el = 0;\n\t\tfor ( var first_el in result_array ) {\n\t\t\tbreak;\n\t\t}\n\t\tvar error_list = result_array ? result_array[first_el] : {};\n\t\tvar widget;\n\t\tif ( error_list && error_list.hasOwnProperty( 'error' ) ) {\n\t\t\terror_list = error_list.error;\n\t\t}\n\t\tvar found_in_current_tab = false;\n\t\tfor ( var key in error_list ) {\n\t\t\tif ( !error_list.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key] ) && this.edit_view_ui_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key];\n\t\t\t} else if ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( this.edit_view_ui_validation_field_dic[key] ) ) {\n\t\t\t\t\tvar len = this.edit_view_ui_validation_field_dic[key].length;\n\t\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\t\tvar item = this.edit_view_ui_validation_field_dic[key][i];\n\t\t\t\t\t\tif ( item.closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\t\t\twidget = item;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( this.edit_view_ui_validation_field_dic[key].closest( document.documentElement ).length > 0 ) {\n\t\t\t\t\twidget = this.edit_view_ui_validation_field_dic[key];\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if ( key.indexOf( '_id' ) < 0 && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_ui_dic[key + '_id'] ) && this.edit_view_ui_dic[key + '_id'].closest( document.documentElement ).length > 0 ) {\n\t\t\t\twidget = this.edit_view_ui_dic[key + '_id'];\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( widget.is( ':visible' ) ) {\n\t\t\t\t// Error: Uncaught TypeError: widget.setErrorStyle is not a function\n\t\t\t\tif ( widget.setErrorStyle && typeof widget.setErrorStyle == 'function' ) {\n\t\t\t\t\twidget.setErrorStyle( error_list[key], true );\n\t\t\t\t\tfound_in_current_tab = true;\n\t\t\t\t} else {\n\t\t\t\t\tDebug.Text( 'ERROR: widget.setErrorStyle is not a function.', 'BaseViewController.js', 'BaseViewController', null, 10 );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Error: Uncaught TypeError: widget.setErrorStyle is not a function\n\t\t\t\tif ( widget.setErrorStyle && typeof widget.setErrorStyle == 'function' ) {\n\t\t\t\t\twidget.setErrorStyle( error_list[key] );\n\t\t\t\t} else {\n\t\t\t\t\tDebug.Text( 'ERROR: widget.setErrorStyle is not a function.', 'BaseViewController.js', 'BaseViewController', null, 10 );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.showErrorStatusOnTab( widget, true );\n\t\t\tthis.edit_view_error_ui_dic[key] = widget;\n\t\t}\n\t\tif ( !found_in_current_tab ) {\n\t\t\tthis.showEditViewError( result );\n\t\t}\n\t}\n\n\tshowEditViewError( result ) {\n\t\tvar details = result.getDetails()[0];\n\t\tvar isError = true;\n\t\t//Error: TypeError: details is undefined in interface/html5/views/BaseViewController.js?v=9.0.0-20150908-081451 line 2078\n\t\tif ( !details ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( details.hasOwnProperty( 'error' ) ) {\n\t\t\tdetails = details.error;\n\t\t\tisError = true;\n\t\t} else if ( details.hasOwnProperty( 'warning' ) ) {\n\t\t\tisError = false;\n\t\t\tdetails = details.warning;\n\t\t}\n\t\tvar error_string = '';\n\t\tvar background_color = isError ? '#cb2e2e' : '#ffff00';\n\t\tvar color = isError ? '#fff' : '#000';\n\t\tvar border_color = isError ? '#CB2E2E' : '#e7be00';\n\n\t\terror_string = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertValidationErrorToString */ .x.convertValidationErrorToString( details );\n\n\t\tthis.removeEditViewErrorTip();\n\t\tthis.edit_view.find('.ui-helper-reset').qtip( {\n\t\t\tshow: {\n\t\t\t\twhen: false,\n\t\t\t\tready: true\n\t\t\t},\n\t\t\tevents: {\n\t\t\t\thide: function( event, api ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\t\t\tcontent: error_string,\n\t\t\tstyle: {\n\t\t\t\tclasses: isError ? 'qtip2-error-tip' : 'qtip2-warning-tip', //used for styling and removal.\n\t\t\t\ttip: {\n\t\t\t\t\tcorner: 'bottom center'\n\t\t\t\t}\n\t\t\t},\n\t\t\tposition: {\n\t\t\t\tmy: 'bottom left',\n\t\t\t\tat: 'top center'\n\t\t\t}\n\t\t} );\n\t}\n\n\topenEditView() {\n\t\tif ( !this.edit_view ) {\n\t\t\tthis.initEditViewUI( this.viewId, this.edit_view_tpl );\n\t\t}\n\t}\n\n\tsetTabOVisibility( flag ) {\n\t\tvar tab0 = $( this.edit_view_tab.find( '.edit-view-tab' )[0] );\n\t\tif ( flag ) {\n\t\t\ttab0.css( 'opacity', 1 );\n\t\t\tthis.setEditViewTabSize();\n\t\t\tif ( this.edit_view_close_icon ) {\n\t\t\t\tthis.edit_view_close_icon.show();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.edit_view_tab.find( 'ul li' ).hide();\n\t\t\ttab0.css( 'opacity', 0 );\n\t\t}\n\t}\n\n\t//set widget disablebility if view mode or edit mode\n\tsetEditViewWidgetsMode() {\n\t\tvar did_clean_dic = {};\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\twidget.css( 'opacity', 1 );\n\t\t\tvar column = widget.parent().parent().parent();\n\t\t\tvar tab_id = column.parent().attr( 'id' );\n\t\t\tif ( !column.hasClass( 'v-box' ) ) {\n\t\t\t\tif ( !did_clean_dic[tab_id] ) {\n\t\t\t\t\tdid_clean_dic[tab_id] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.is_viewing ) {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( false );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.setEnabled ) ) {\n\t\t\t\t\twidget.setEnabled( true );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//Call this when edit view open\n\tinitEditViewUI( view_id, edit_view_file_name ) {\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setUINotready */ .x.setUINotready();\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.wait();\n\n\t\tvar $this = this;\n\t\tif ( this.edit_view ) {\n\t\t\tthis.edit_view.remove();\n\t\t}\n\n\t\tthis.edit_view = $( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadViewSource */ .x.loadViewSource( view_id, edit_view_file_name, null, true ) );\n\n\t\tthis.edit_view_tab = $( this.edit_view.find( '.edit-view-tab-bar' ) );\n\t\tthis.edit_view_tab.css( 'opacity', 0 );\n\n\t\t//Give edt view tab a id, so we can load it when put right click menu on it\n\t\tthis.edit_view_tab.attr( 'id', this.ui_id + '_edit_view_tab' );\n\n\t\t// Moved into generic BaseView.initEditViewTabs\n\t\t// this.setTabOVisibility( false );\n\n\t\t// this.edit_view_tab = this.edit_view_tab.tabs( {\n\t\t// \tactivate: function( e, ui ) {\n\t\t// \t\tif ( !$this.edit_view_tab || !$this.edit_view_tab.is( ':visible' ) ) {\n\t\t// \t\t\treturn;\n\t\t// \t\t}\n\t\t//\n\t\t// \t\t$this.onTabShow( e, ui );\n\t\t// \t\tGlobal.triggerAnalyticsTabs( e, ui );\n\t\t// \t}\n\t\t// } );\n\n\t\t// this.edit_view_tab.off( 'click' ).on( 'click', function( e ) {\n\t\t// \t$this.onTabIndexChange( e );\n\t\t// } );\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.contentContainer */ .x.contentContainer().append( this.edit_view );\n\n\t\t// Moved to buildEditViewUI, as the init might only be called once, and the context menu needs to be rebuilt on every view build.\n\t\t// // After we add the edit_view to the page, add the context menu (Vue needs a valid id in dom)\n\t\t// if( ContextMenuManager.getMenu( this.determineContextMenuMountAttributes().id ) === undefined ) {\n\t\t// \tthis.buildContextMenu();\n\t\t// }\n\t\t// #VueContextMenu#Dynamic-EditView Once edit view html has loaded and mounted to DOM, then insert container for context_menu and initialise menu.\n\n\t\t// Testing to see if just having the code in buildContextMenu is enough.\n\t\t// if( !this.edit_view_context_menu ) {\n\t\t// \tvar context_menu_id = 'contextmenu-' + this.edit_view_tab.attr( 'id' );\n\t\t// \tthis.edit_view_context_menu = new ContextMenuManager( context_menu_id ); // #VueContextMenu# Initialize Vue ContextMenuManager here so that each view has their own unique one. Currently we are sharing one contextmenu, but most views use their own context menu manager instance. (Not required, just simplifies the refactor for now, and it might be used in future).\n\t\t//\n\t\t// \t// Create dynamic container for the vue context menu\n\t\t// \t// this.edit_view_context_menu.setContextMenuId( 'contextmenu-' + this.edit_view_tab.attr( 'id' ) ); // TODO: Potentially move this into param for constructor.\n\t\t// \tthis.edit_view_tab.prepend('<div id=\"'+ this.edit_view_context_menu.menu_id +'\"></div>');\n\t\t//\n\t\t// \t// Create and mount unique context menu for this view.\n\t\t// \tthis.edit_view_context_menu.mountContextMenu( '#' + this.edit_view_context_menu.menu_id );\n\t\t//\n\t\t// } else {\n\t\t// \t// If each view has a unique context menu, then this should never happen, as context menu should only be initiated once.\n\t\t// \t// However, there are many cases where tabs repeatedly call this.buildContextMenu, whilst keeping the same view controller, so this is now a warning rather than an error.\n\t\t// \tDebug.Text( 'Context Menu Manager already exists for: '+ this.viewId, 'BaseViewController.js', 'BaseViewController', 'buildContextMenu', 10 );\n\t\t// }\n\n\t\tthis.buildEditViewUI();\n\n\t\t$this.setEditViewTabHeight();\n\t\tTTPromise.wait( 'init', 'init', function() {\n\t\t\t$( '.edit-view-tab-bar' ).css( 'opacity', 1 );\n\t\t} );\n\t}\n\n\tsetEditViewTabHeight() {\n\t\tvar $this = this;\n\t}\n\n\t//Call this after initEditViewUI, usually after current_edit_record is set\n\tinitEditView() {\n\t\tthis.show_warning_when_validation = false;\n\t\t//Uncaught TypeError: Cannot read property 'find' of null in Timehseet Authorization view when quickly click Cancel from replay\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\t\tthis.setURL();\n\n\t\t// Overrides form with data from push notification and http get variables.\n\t\tthis.fillCurrentRecord();\n\n\t\tthis.setEditMenu(); //This is done in onTabeShow() later on, so it can probably be removed from here?\n\t\t//Remove cover once edit menu is set\n\t\tProgressBar.closeOverlay();\n\n\t\t//Error: Unable to get property 'find' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=7.4.6-20141027-074127 line 2055\n\t\tif ( this.edit_view_tab ) {\n\t\t\tthis.edit_view_tab.find( 'ul li' ).show(); // All tabs are hidden when initEditView UI, show all of them before set status\n\t\t}\n\t\tthis.setTabStatus();\n\t\tthis.clearEditViewData();\n\t\tthis.setEditViewWidgetsMode();\n\t\tthis.setEditViewData();\n\t\tthis.setCustomFields();\n\t\tthis.setFocusToFirstInput();\n\t}\n\n\tsetCustomFields() {\n\t\tvar parent_table = this.getCustomFieldParentTable();\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getFeatureFlag */ .x.getFeatureFlag( 'custom_field' ) == false || LocalCacheData.getCustomFieldData().parent_tables.includes( parent_table ) == false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\tif ( Array.isArray( this.custom_fields ) ) {\n\t\t\t\tthis.custom_fields.forEach( ( custom_field ) => {\n\t\t\t\t\tthis.buildCustomFieldUI( this.getPrefixedCustomFieldID( custom_field.id ), custom_field.name, custom_field.type_id, custom_field.meta_data );\n\t\t\t\t} );\n\n\t\t\t\tthis.editFieldResize( 0 );\n\t\t\t}\n\n\t\t\tthis.resetLastWidgetStyle();\n\t\t}.bind( this ) );\n\t}\n\n\tgetPrefixedCustomFieldID( id ) {\n\t\treturn 'custom_field-' + id;\n\t}\n\n\tgetCustomFieldsForView() {\n\t\tvar $this = this;\n\t\tvar parent_table = this.getCustomFieldParentTable();\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getFeatureFlag */ .x.getFeatureFlag( 'custom_field' ) == false || LocalCacheData.getCustomFieldData().parent_tables.includes( parent_table ) == false ) {\n\t\t\tTTPromise.resolve( 'BaseViewController', 'getCustomFields' );\n\t\t\treturn;\n\t\t}\n\n\t\tvar filter = { filter_data: { parent_table: parent_table, status_id: 10 }, filter_sort: { display_order: 'asc', created_date: 'asc', id: 'asc' } };\n\n\t\tthis.custom_field_api.getCustomField( filter, true, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar res_data = result.getResult();\n\t\t\t\tif ( Array.isArray( res_data ) ) {\n\t\t\t\t\t$this.custom_fields = res_data;\n\t\t\t\t}\n\n\t\t\t\tTTPromise.resolve( 'BaseViewController', 'getCustomFields' );\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetCustomFieldReferenceField() {\n\t\treturn false;\n\t}\n\n\tbuildCustomFieldUI( field, label, type_id, meta_data ) {\n\n\t\tif ( !type_id ) {\n\t\t\treturn; //User does not have permissions to use custom fields\n\t\t}\n\n\t\tfield = this.convertCustomFieldFieldId( type_id, field );\n\n\t\tif ( this.getCustomFieldParentTable() === 'punch_control' ) {\n\t\t\t//Permissions can be dynamic for punch control custom fields and we need to check for them.\n\t\t\t//Permissions are for the non-'_id' custom fields.\n\t\t\tlet custom_field_id = field.replace( '_id', '' );\n\t\t\tif ( PermissionManager.validate( this.permission_id, 'edit_' + custom_field_id ) == false ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif ( !this.edit_view_tab ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar form_item_input;\n\t\tvar $this = this;\n\t\tvar tab0 = $( this.edit_view_tab.find( '.edit-view-tab-outside' )[0] );\n\t\tvar tab0_column1 = tab0.find( '.first-column' );\n\n\t\tif ( $this.edit_view_ui_dic[field] ) {\n\t\t\tform_item_input = $this.edit_view_ui_dic[field];\n\t\t\tform_item_input.setValue( $this.current_edit_record[field] );\n\t\t} else {\n\t\t\tlet form_array = $this.getCustomFieldFormInputByType( type_id, field, meta_data );\n\t\t\tform_item_input = form_array[0];\n\t\t\tlet widget_container = form_array[1];\n\n\t\t\tvar input_div = $this.addEditFieldToColumn( label, form_item_input, tab0_column1, '', widget_container );\n\t\t\tif ( this.getCustomFieldReferenceField() !== false && $this.edit_view_ui_dic[this.getCustomFieldReferenceField()] != undefined ) {\n\t\t\t\tinput_div.insertBefore( $this.edit_view_ui_dic[this.getCustomFieldReferenceField()].parent().parent() );\n\t\t\t}\n\n\t\t\tif ( this.current_edit_record ) {\n\t\t\t\tform_item_input.setValue( this.current_edit_record[field] );\n\t\t\t}\n\t\t}\n\t\tform_item_input.css( 'opacity', 1 );\n\n\t\tif ( $this.is_viewing ) {\n\t\t\tform_item_input.setEnabled( false );\n\t\t} else {\n\t\t\tform_item_input.setEnabled( true );\n\t\t}\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tform_item_input.setMassEditMode( true );\n\t\t}\n\t}\n\n\tconvertCustomFieldFieldId( type_id, field ) {\n\t\tif ( LocalCacheData.getCustomFieldData().conversion_field_types[type_id] ) {\n\t\t\treturn field + '_id';\n\t\t}\n\t\treturn field;\n\t}\n\n\tgetCustomFieldFormInputByType( type_id, field, meta_data ) {\n\t\tlet form_item_input;\n\t\tlet widget_container = null;\n\n\t\ttype_id = parseInt( type_id ); //Switch is strict on type, so we need to parseInt()\n\n\t\tswitch ( type_id ) {\n\t\t\tcase 100: //Text\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\t\tform_item_input.css( 'minWidth', 300 );\n\t\t\t\tbreak;\n\t\t\tcase 110: //Textarea\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_AREA );\n\t\t\t\tform_item_input.TTextArea( { field: field, width: '100%' } );\n\t\t\t\tbreak;\n\t\t\tcase 400: //Integer\n\t\t\tcase 410: //Decimal\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\t\tform_item_input.css( 'minWidth', 300 );\n\t\t\t\tbreak;\n\t\t\tcase 420: //Currency\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field } );\n\t\t\t\tform_item_input.css( 'minWidth', 300 );\n\n\t\t\t\tvar widgetContainer = $( '<div class=\\'widget-h-box\\'></div>' );\n\t\t\t\tlet currency = $( '<span class=\\'widget-left-label\\'></span>' );\n\t\t\t\tlet code = $( '<span class=\\'widget-right-label\\'></span>' );\n\n\t\t\t\twidgetContainer.append( currency );\n\t\t\t\twidgetContainer.append( form_item_input );\n\t\t\t\twidgetContainer.append( code );\n\t\t\t\tbreak;\n\t\t\tcase 500: //Checkbox\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.CHECKBOX );\n\t\t\t\tform_item_input.TCheckbox( { field: field } );\n\t\t\t\tbreak;\n\t\t\tcase 1000: //Date\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER );\n\t\t\t\tform_item_input.TDatePicker( { field: field } );\n\t\t\t\tbreak;\n\t\t\tcase 1010: //Date Range\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER );\n\t\t\t\tform_item_input.TRangePicker( { field: field, validation_field: 'date_stamp' } );\n\t\t\t\tbreak;\n\t\t\tcase 1100: //Time\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER );\n\t\t\t\tform_item_input.TTimePicker( { field: field } );\n\t\t\t\tbreak;\n\t\t\tcase 1110: //Time Range\n\t\t\t\t//TODO: Jeremy Time Range\n\t\t\t\tbreak;\n\t\t\tcase 1200: //Datetime\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER );\n\t\t\t\tform_item_input.TDatePicker( { field: field, mode: 'date_time' } );\n\t\t\t\tbreak;\n\t\t\tcase 1300: //Time Unit\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tform_item_input.TTextInput( { field: field, width: 120, mode: 'time_unit', need_parser_sec: true } );\n\t\t\t\tbreak;\n\t\t\tcase 2100: //Single-select Dropdown\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tallow_multiple_selection: false,\n\t\t\t\t\tlayout_name: 'global_option_column', //Need dynamic layout name? global_option_column\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\tfield: field\n\t\t\t\t} );\n\t\t\t\tform_item_input.setSourceData( meta_data.validation.multi_select_items );\n\t\t\t\tbreak;\n\t\t\tcase 2110: //Multi-select Dropdown\n\t\t\t\tform_item_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\t\tform_item_input.AComboBox( {\n\t\t\t\t\tallow_multiple_selection: true,\n\t\t\t\t\tlayout_name: 'global_option_column', //Need dynamic layout name? global_option_column\n\t\t\t\t\tshow_search_inputs: true,\n\t\t\t\t\tset_empty: true,\n\t\t\t\t\tfield: field\n\t\t\t\t} );\n\t\t\t\tform_item_input.setSourceData( meta_data.validation.multi_select_items );\n\t\t}\n\n\t\treturn [form_item_input, widget_container];\n\t}\n\n\tresetLastWidgetStyle() {\n\n\t\tif ( !this.edit_view_tab || !this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tgetCustomFieldParentTable() {\n\t\t//Punch views get their custom fields from the punch_control table.\n\t\tif ( this.table_name_key === 'punch' ) {\n\t\t\treturn 'punch_control';\n\t\t} else if ( this.viewId === 'TimeSheet' ) { //Timesheet view does not declare a table_name_key\n\t\t\treturn 'punch_control';\n\t\t}\n\n\t\treturn this.table_name_key;\n\t}\n\n\tsetURL() {\n\t\tvar a = '';\n\t\tswitch ( LocalCacheData.current_doing_context_action ) {\n\t\t\tcase 'new':\n\t\t\tcase 'edit':\n\t\t\tcase 'view':\n\t\t\t\ta = LocalCacheData.current_doing_context_action;\n\t\t\t\tbreak;\n\t\t\tcase 'copy_as_new':\n\t\t\t\ta = 'new';\n\t\t\t\tbreak;\n\t\t}\n\t\tif ( this.canSetURL() ) {\n\n\t\t\tvar tab_name = this.edit_view_tab ? this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().eq( this.getEditViewTabIndex() ).text() : '';\n\t\t\ttab_name = tab_name.replace( /\\/|\\s+/g, '' );\n\n\t\t\t//Error: Unable to get property 'id' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-132941 line 2234\n\t\t\tif ( this.current_edit_record && this.current_edit_record.id ) {\n\t\t\t\tif ( a ) {\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&a=' + a + '&id=' + this.current_edit_record.id + '&tab=' + tab_name );\n\t\t\t\t} else {\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&id=' + this.current_edit_record.id );\n\t\t\t\t}\n\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.trackView */ .x.trackView( this.viewId, LocalCacheData.current_doing_context_action );\n\t\t\t} else {\n\t\t\t\tif ( a ) {\n\n\t\t\t\t\t//Edit a record which don't have id, schedule view Recurring Scedule\n\t\t\t\t\tif ( a === 'edit' ) {\n\t\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&a=' + 'new' +\n\t\t\t\t\t\t\t'&tab=' + tab_name );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId + '&a=' + a +\n\t\t\t\t\t\t\t'&tab=' + tab_name );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + '#!m=' + this.viewId );\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tcanSetURL() {\n\t\tif ( this.sub_view_mode || this.edit_only_mode ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tsetFocusToFirstInput() {\n\t\t//Do not set focus to first input in unit test mode as it causes a blink that is inconsistent in screenshots. Also disable on mobile mode so its not a jarring experience with the zoom changes on each page\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.UNIT_TEST_MODE */ .x.UNIT_TEST_MODE || $( 'body' ).hasClass( 'mobile-device-mode' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.is_viewing ) {\n\t\t\tif ( this.script_name === 'ScheduleView' ) {\n\t\t\t\tif ( this.edit_view_ui_dic.start_time ) {\n\t\t\t\t\tthis.edit_view_ui_dic.start_time.children().eq( 0 ).focus();\n\t\t\t\t\tthis.edit_view_ui_dic.start_time.children().eq( 0 )[0].select();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\t\t\tif ( widget.is( ':visible' ) === true ) {\n\t\t\t\t\t\tif ( widget.hasClass( 't-text-input' ) && !widget.attr( 'readonly' ) ) {\n\t\t\t\t\t\t\twidget.focus();\n\t\t\t\t\t\t\twidget[0].select();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if ( widget.hasClass( 't-time-picker-div' ) && !widget.children().eq( 0 ).attr( 'readonly' ) ) {\n\t\t\t\t\t\t\twidget.children().eq( 0 ).focus();\n\t\t\t\t\t\t\twidget.children().eq( 0 )[0].select();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else if ( widget.hasClass( 't-date-picker-div' ) && !widget.children().eq( 0 ).attr( 'readonly' ) ) {\n\t\t\t\t\t\t\twidget.children().eq( 0 ).focus();\n\t\t\t\t\t\t\twidget.children().eq( 0 )[0].select();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tinitNavigationWidget( navigation_widget_div ) {\n\t\tif ( !this.navigation ) {\n\t\t\tthis.navigation = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\tnavigation_widget_div.append( this.navigation );\n\t\t} else {\n\t\t\tnavigation_widget_div.append( this.navigation );\n\t\t}\n\t\tthis.setNavigationArrowsStatus();\n\t}\n\n\tbuildEditViewUI() {\n\t\tvar $this = this;\n\n\t\t//No navigation when edit only mode\n\n\t\t// #VueContextMenu# After we add the edit_view to the page in initEditViewUI(), add the context menu (Vue needs a valid id in dom)\n\t\tif( ContextMenuManager.getMenu( this.determineContextMenuMountAttributes().id ) === undefined ) {\n\t\t\tthis.buildContextMenu();\n\t\t} else {\n\t\t\tDebug.Warn( 'Context Menu ('+ this.determineContextMenuMountAttributes().id +') already exists for: '+ this.viewId, 'BaseViewController.js', 'BaseViewController', 'buildEditViewUI', 10 );\n\t\t}\n\n\t\tif ( this.edit_view ) {\n\t\t\tif ( !this.edit_only_mode ) {\n\t\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\t\t\t\tvar label = navigation_div.find( '.navigation-label' );\n\t\t\t\tvar left_click = navigation_div.find( '.left-click' );\n\t\t\t\tvar right_click = navigation_div.find( '.right-click' );\n\t\t\t\tvar navigation_widget_div = navigation_div.find( '.navigation-widget-div' );\n\t\t\t\tthis.initNavigationWidget( navigation_widget_div );\n\t\t\t\tleft_click.attr( 'src', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRealImagePath */ .x.getRealImagePath( 'images/left_arrow.svg' ) );\n\t\t\t\tright_click.attr( 'src', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getRealImagePath */ .x.getRealImagePath( 'images/right_arrow.svg' ) );\n\t\t\t\tlabel.text( this.navigation_label );\n\n\t\t\t}\n\n\t\t\tthis.edit_view_close_icon = this.edit_view.find( '.close-icon' );\n\t\t\tthis.edit_view_close_icon.hide();\n\n\t\t\tthis.edit_view_close_icon.click( function() {\n\t\t\t\t$this.onCloseIconClick();\n\t\t\t} );\n\t\t}\n\n\t\tif( this.edit_only_mode ) {\n\n\t\t}\n\n\t\tthis.edit_view_ui_dic = {};\n\t\tthis.edit_view_ui_validation_field_dic = {};\n\t\tthis.edit_view_form_item_dic = {};\n\t\tthis.edit_view_error_ui_dic = {};\n\t}\n\n\tonCloseIconClick() {\n\t\tthis.onCancelClick();\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsNavigationOther */ .x.triggerAnalyticsNavigationOther( 'close-X', 'click', this.viewId );\n\t}\n\n\tsetWidgetVisible( widgets ) {\n\t\tvar widget = widgets;\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\t\t\tfor ( var i = 0; i < widgets.length; i++ ) {\n\t\t\t\twidget = widgets[i];\n\t\t\t\twidget.css( 'opacity', 1 );\n\t\t\t}\n\t\t} else {\n\t\t\twidget.css( 'opacity', 1 );\n\t\t}\n\t}\n\n\t//widgetContainer: add widget to custom container\n\t//saveFormItemDiv: if cache current formItemDiv and use it later\n\taddEditFieldToColumn( label, widgets, column, firstOrLastRecord, widgetContainer, saveFormItemDiv, setResizeEvent, saveFormItemDivKey, hasKeyEvent, customLabelWidget ) {\n\n\t\tvar $this = this;\n\t\tvar form_item = $( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.EDIT_VIEW_FORM_ITEM ) );\n\t\tvar form_item_label_div = form_item.find( '.edit-view-form-item-label-div' );\n\t\tvar form_item_label = form_item.find( '.edit-view-form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.edit-view-form-item-input-div' );\n\t\tvar widget = widgets;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\t\t\tfor ( var i = 0; i < widgets.length; i++ ) {\n\t\t\t\twidget = widgets[i];\n\t\t\t\twidget.css( 'opacity', 0 );\n\t\t\t}\n\t\t} else {\n\t\t\twidget.css( 'opacity', 0 );\n\t\t}\n\n\t\tif ( customLabelWidget ) {\n\t\t\tform_item_label.parent().append( customLabelWidget );\n\t\t\tform_item_label.remove();\n\t\t} else {\n\t\t\tform_item_label.text( label ); // Remove ':' to match Figma design.\n\t\t\tif ( label && label.indexOf( '\\n' ) !== -1 ) {\n\t\t\t\tform_item_label.html( form_item_label.html().replace( /\\n/g, '<br>' ) ); //Allow newlines (\\n) to be accepted in labels. Used by T4 Report. Use this instead of .html() directly as its introduces XSS\n\t\t\t}\n\t\t}\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widgetContainer ) ) {\n\n\t\t\tform_item_input_div.append( widgetContainer );\n\n\t\t} else {\n\t\t\tform_item_input_div.append( widget );\n\t\t}\n\n\t\tcolumn.append( form_item );\n\n\t\t//set height to text area\n\t\tif ( form_item.height() > 35 ) {\n\t\t\tform_item_label_div.css( 'height', form_item.height() );\n\t\t} else if ( widget.hasClass( 'a-dropdown' ) ) {\n\t\t\tform_item_label_div.css( 'height', 240 );\n\t\t}\n\n\t\t//these aren't hit uniformly for every field so the vertical resize events will be disabled in unit test mode.\n\t\tif ( setResizeEvent && !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.UNIT_TEST_MODE */ .x.UNIT_TEST_MODE ) {\n\t\t\tform_item.unbind( 'resize' ).bind( 'resize', function() {\n\t\t\t\t//When switching tabs, the heights are all -1, which causes \"flashing\" when the user returns back to the original tab and all the heights need to be set again.\n\t\t\t\t// To prevent this, only change heights if they are > 0.\n\t\t\t\tif ( form_item_label_div.height() !== form_item.height() && form_item.height() > 0 ) {\n\t\t\t\t\tform_item_label_div.css( 'height', form_item.height() );\n\t\t\t\t}\n\t\t\t} );\n\t\t\twidget.unbind( 'setSize' ).bind( 'setSize', function() {\n\t\t\t\tform_item_label_div.css( 'height', widget.height() + 10 );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !label ) {\n\t\t\tform_item_input_div.remove();\n\t\t\tform_item_label_div.remove();\n\n\t\t\tform_item.append( widget );\n\t\t\twidget.css( 'opacity', 1 );\n\n\t\t\tif ( saveFormItemDiv && saveFormItemDivKey ) {\n\t\t\t\tthis.edit_view_form_item_dic[saveFormItemDivKey] = form_item;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif ( saveFormItemDiv ) {\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\t\t\t\tthis.edit_view_form_item_dic[widgets[0].getField()] = form_item;\n\t\t\t} else {\n\t\t\t\tthis.edit_view_form_item_dic[widget.getField()] = form_item;\n\t\t\t}\n\n\t\t}\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( widgets ) ) {\n\n\t\t\tfor ( var i = 0; i < widgets.length; i++ ) {\n\t\t\t\twidget = widgets[i];\n\t\t\t\tthis.edit_view_ui_dic[widget.getField()] = widget;\n\t\t\t\tsetValidationDic();\n\n\t\t\t\twidget.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target, doNotValidate ) {\n\t\t\t\t\t$this.onFormItemChange( target, doNotValidate );\n\t\t\t\t} );\n\n\t\t\t\tif ( hasKeyEvent ) {\n\t\t\t\t\twidget.unbind( 'formItemKeyUp' ).bind( 'formItemKeyUp', function( e, target ) {\n\t\t\t\t\t\t$this.onFormItemKeyUp( target );\n\t\t\t\t\t} );\n\n\t\t\t\t\twidget.unbind( 'formItemKeyDown' ).bind( 'formItemKeyDown', function( e, target ) {\n\t\t\t\t\t\t$this.onFormItemKeyDown( target );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.edit_view_ui_dic[widget.getField()] = widget;\n\t\t\tsetValidationDic();\n\n\t\t\twidget.bind( 'formItemChange', function( e, target, doNotValidate ) {\n\t\t\t\t$this.onFormItemChange( target, doNotValidate );\n\t\t\t} );\n\n\t\t\tif ( hasKeyEvent ) {\n\t\t\t\twidget.bind( 'formItemKeyUp', function( e, target ) {\n\t\t\t\t\t$this.onFormItemKeyUp( target );\n\t\t\t\t} );\n\n\t\t\t\twidget.bind( 'formItemKeyDown', function( e, target ) {\n\t\t\t\t\t$this.onFormItemKeyDown( target );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tfunction setValidationDic() {\n\t\t\tif ( widget.hasOwnProperty( 'getValidationField' ) && widget.getValidationField() ) {\n\t\t\t\tif ( $this.edit_view_ui_validation_field_dic[widget.getValidationField()] ) {\n\t\t\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( $this.edit_view_ui_validation_field_dic[widget.getValidationField()] ) ) {\n\t\t\t\t\t\t$this.edit_view_ui_validation_field_dic[widget.getValidationField()] = [$this.edit_view_ui_validation_field_dic[widget.getValidationField()], widget];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.edit_view_ui_validation_field_dic[widget.getValidationField()].push( widget );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.edit_view_ui_validation_field_dic[widget.getValidationField()] = widget;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\treturn form_item;\n\t}\n\n\t//Set fields label to same size\n\teditFieldResize( index ) {\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( index ) ) {\n\n\t\t} else {\n\t\t\tindex = this.getEditViewTabIndex();\n\t\t}\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.edit_view_tabs[index] ) && !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isFalseOrNull */ .x.isFalseOrNull( this.edit_view_tabs[index] ) && this.edit_view_tabs[index].length > 0 ) {\n\t\t\tvar tab_div = this.edit_view_tabs[index];\n\t\t\tfor ( var i = 0; i < tab_div.length; i++ ) {\n\t\t\t\tvar tab_column_div = tab_div[i].find( '.edit-view-form-item-label-div' );\n\t\t\t\tvar tab_column_sub_div = tab_div[i].find( '.edit-view-form-item-sub-label-div > span' );\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( tab_column_sub_div ) && tab_column_sub_div.length > 0 ) {\n\t\t\t\t\tthis.setEditFieldSize( tab_column_sub_div );\n\t\t\t\t}\n\t\t\t\tthis.setEditFieldSize( tab_column_div );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetEditFieldSize( tab_column_div, width ) {\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( width ) ) {\n\n\t\t\ttab_column_div.each( function() {\n\t\t\t\t$( this ).width( width );\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\tvar item_label_div_width = [];\n\t\t\ttab_column_div.each( function() {\n\n\t\t\t\tif ( $( this ).width() === 0 ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t$( this ).css( 'width', 'auto' );\n\n\t\t\t\titem_label_div_width.push( $( this ).width() );\n\t\t\t} );\n\n\t\t\titem_label_div_width.sort( function( a, b ) {\n\t\t\t\treturn ( b - a );\n\t\t\t} );\n\n\t\t\ttab_column_div.each( function() {\n\t\t\t\tif ( item_label_div_width[0] >= 0 ) { // #2701 - Do not set width if value is negative. Happens when trying to calculate width of something on another tab not currently visible.\n\t\t\t\t\t$( this ).width( item_label_div_width[0] + 1 );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tsetNavigation() {\n\n\t\tvar $this = this;\n\n\t\t//Error: Unable to get value of the property 'getGridParam': object is null or undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-103725 line 2575\n\t\tif ( !this.grid ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.navigation.setPossibleDisplayColumns( this.buildDisplayColumnsByColumnModel( this.grid.getColumnModel() ), this.buildDisplayColumns( this.default_display_columns ) );\n\t\tthis.navigation.unbind( 'onClose' ).bind( 'onClose', () => {\n\t\t\tthis.setNavigationArrowsEnabled();\n\t\t} );\n\t\tthis.navigation.unbind( 'formItemChange' ).bind( 'formItemChange', function( e, target ) {\n\n\t\t\tvar key = target.getField();\n\t\t\tvar next_select_item_id = target.getValue();\n\n\t\t\tif ( !next_select_item_id ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( next_select_item_id !== $this.current_edit_record.id ) {\n\t\t\t\tProgressBar.showOverlay();\n\n\t\t\t\tif ( $this.is_viewing ) {\n\t\t\t\t\t$this.onViewClick( next_select_item_id ); //Dont refresh UI\n\t\t\t\t} else {\n\t\t\t\t\t$this.onEditClick( next_select_item_id ); //Dont refresh UI\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsEditViewNavigation */ .x.triggerAnalyticsEditViewNavigation( 'navigation', $this.viewId );\n\n\t\t} );\n\t}\n\n\tclearEditViewData() {\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( _.isFunction( this.edit_view_ui_dic[key].setEmptyValueAndShowLoading ) ) {\n\t\t\t\tthis.edit_view_ui_dic[key].setEmptyValueAndShowLoading();\n\t\t\t} else {\n\t\t\t\tthis.edit_view_ui_dic[key].setValue( null );\n\t\t\t}\n\t\t\tthis.edit_view_ui_dic[key].clearErrorStyle();\n\t\t}\n\t}\n\n\t//Called after set current_edit_record\n\tsetEditViewData() {\n\t\tthis.is_changed = false;\n\t\tthis.initEditViewData();\n\t\tthis.initTabData();\n\t\tthis.switchToProperTab();\n\t}\n\n\tswitchToProperTab() {\n\t\tif ( LocalCacheData.getAllURLArgs() &&\n\t\t\tLocalCacheData.getAllURLArgs().hasOwnProperty( 'tab' ) &&\n\t\t\tLocalCacheData.getAllURLArgs().tab.length > 0 &&\n\t\t\tLocalCacheData.current_open_primary_controller.viewId === this.viewId ) {\n\n\t\t\tvar target_node = this.edit_view_tab.find( '.edit-view-tab-bar-label' ).children().filter( function() {\n\t\t\t\tvar value = $( this ).text().replace( /\\/|\\s+/g, '' );\n\t\t\t\treturn value === LocalCacheData.getAllURLArgs().tab;\n\t\t\t} );\n\n\t\t\tvar target_index = 0;\n\t\t\tif ( target_node.length > 0 ) {\n\t\t\t\ttarget_node = $( target_node[0] );\n\t\t\t\ttarget_index = target_node.index();\n\t\t\t}\n\t\t\tthis.edit_view_tab.tabs( 'option', 'active', target_index );\n\t\t}\n\t}\n\n\t//Call this from setEditViewData\n\t// This is called to initialize data for the first/primary tab, and is called from many views. So it needs to stay even after fully refactored to use tab_model.\n\tinitTabData() {\n\t\tvar tab_model = this.getTabModel();\n\t\tif ( tab_model != null ) {\n\t\t\tthis.onTabShow();\n\t\t} else {\n\t\t\tvar current_tab_index = this.getEditViewTabIndex();\n\t\t\t//Handle most case that one tab and one audit tab\n\t\t\tif ( current_tab_index === 1 ) {\n\t\t\t\tif ( this.current_edit_record.id && this.current_edit_record.id != TTUUID.zero_id ) {\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'block' );\n\t\t\t\t\tthis.initSubLogView( 'tab_audit' );\n\t\t\t\t} else {\n\t\t\t\t\tthis.edit_view_tab.find( '#tab_audit' ).find( '.first-column-sub-view' ).css( 'display', 'none' );\n\t\t\t\t\tthis.showSaveAndContinueButton();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetEditViewTabIndex() {\n\t\treturn this.edit_view.find( '.edit-view-tab-bar li.ui-tabs-active' ).index();\n\t}\n\n\tgetEditViewActiveTabName() {\n\t\tif( !this.edit_view ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.edit_view.find( '.edit-view-tab-bar li.ui-tabs-active' ).attr( 'aria-controls' );\n\t}\n\n\tneedShowNavigation() {\n\t\tif ( this.current_edit_record && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.current_edit_record.id ) && this.current_edit_record.id ) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t//Call this from setEditViewData\n\tinitEditViewData() {\n\t\tvar $this = this;\n\n\t\t//add this.grid to fix exception\n\t\t//Error: Unable to get property 'getGridParam' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=7.4.3-20140924-090129 line 2523\n\t\tif ( !this.edit_only_mode && this.navigation && this.grid ) {\n\n\t\t\tvar grid_current_page_items = this.grid.getData();\n\n\t\t\tvar navigation_div = this.edit_view.find( '.navigation-div' );\n\n\t\t\t//Error: TypeError: this.current_edit_record is undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-103725 line 2673\n\t\t\tif ( this.needShowNavigation() ) {\n\t\t\t\tnavigation_div.css( 'display', 'block' );\n\t\t\t\t//Set Navigation Awesomebox\n\n\t\t\t\t//#3175 - Get current navigation data if it exists so that we do not overwrite it when switching records.\n\t\t\t\t//For example when clicking the right arrow on the last record of page 1 brings you to page 2. Page 2 data was being reset.\n\t\t\t\t//In that scenario we want to keep navigation data from page 2 and not overwrite it with the grid data from the list view.\n\t\t\t\tlet current_navigation_data = this.navigation.getSourceData();\n\t\t\t\tlet current_pager_data = this.navigation.getPagerData();\n\n\t\t\t\t//#2349 - update source data every time so that it doesn't go unrefreshed in the case of saving a new record or deleting exiting\n\t\t\t\tthis.navigation.setSourceData( current_navigation_data ? current_navigation_data : grid_current_page_items );\n\t\t\t\tthis.navigation.setPagerData( current_pager_data ? current_pager_data: this.pager_data );\n\t\t\t\t//init navigation only when open edit view\n\t\t\t\tif ( !this.navigation.getSourceData() ) {\n\t\t\t\t\tif ( LocalCacheData.getLoginUserPreference() ) {\n\t\t\t\t\t\tthis.navigation.setRowPerPage( LocalCacheData.getLoginUserPreference().items_per_page );\n\t\t\t\t\t}\n\t\t\t\t\tthis.navigation.setPagerData( this.pager_data );\n\n\t\t\t\t\tvar default_args = {};\n\t\t\t\t\tdefault_args.filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertLayoutFilterToAPIFilter */ .x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\t\t\t\tdefault_args.filter_sort = this.select_layout.data.filter_sort;\n\t\t\t\t\tthis.navigation.setDefaultArgs( default_args );\n\t\t\t\t}\n\n\t\t\t\tthis.navigation.setValue( this.current_edit_record );\n\n\t\t\t} else {\n\t\t\t\tnavigation_div.css( 'display', 'none' );\n\t\t\t}\n\t\t}\n\n\t\tthis.setUIWidgetFieldsToCurrentEditRecord();\n\n\t\tif ( this.is_mass_editing ) {\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\n\t\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t//JS Exception: \"this.unique_columns.indexOf is not a function\"\n\t\t\t\tif ( this.unique_columns && this.unique_columns.length > 0 && this.unique_columns.indexOf( key ) != -1 ) {\n\t\t\t\t\t$this.edit_view_ui_dic[key].css( 'opacity', '0' );\n\t\t\t\t\tif ( $this.edit_view_ui_dic[key].setEnabled ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[key].setEnabled( false );\n\t\t\t\t\t}\n\t\t\t\t\tif ( $this.edit_view_ui_dic[key].setMassEditMode ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[key].setMassEditMode( false );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget.setMassEditMode ) ) {\n\t\t\t\t\t\twidget.setMassEditMode( true );\n\t\t\t\t\t}\n\t\t\t\t\t$this.edit_view_ui_dic[key].css( 'opacity', '1' );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\t\t$this.edit_view_ui_dic[key].css( 'opacity', '1' );\n\t\t\t}\n\t\t}\n\n\t\tthis.setNavigationArrowsEnabled( true );\n\n\t\t// Create this function alone because of the column value of view is different from each other, some columns need to be handle specially. and easily to rewrite this function in sub-class.\n\n\t\tthis.setCurrentEditRecordData();\n\n\t\t//Init *Please save this record before modifying any related data* box\n\t\tthis.edit_view.find( '.save-and-continue-div' ).SaveAndContinueBox( { related_view_controller: this } );\n\t\tthis.edit_view.find( '.save-and-continue-div' ).css( 'display', 'none' );\n\t}\n\n\tsetUIWidgetFieldsToCurrentEditRecord() {\n\t\tvar $this = this;\n\n\t\t$this.old_current_edit_record = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( $this.current_edit_record ); //Save the current edit record before any changes are made so we can later check what fields may have changed.\n\n\t\tif ( $this.current_edit_record === true ) {\n\t\t\t$this.current_edit_record = {};\n\t\t};\n\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n//\t\t\t//Set all UI field to current edit record, we need validate all UI field when save and validate\n\t\t\t//use != to ingore string or number, value from html is string.\n\t\t\t//Error: TypeError: $this.current_edit_record is undefined in /interface/html5/views/BaseViewController.js?v=8.0.0-20141117-122453 line 2702\n\t\t\tif ( $this.current_edit_record && !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.current_edit_record[key] ) ) {\n\t\t\t\t$this.current_edit_record[key] = false;\n\t\t\t}\n\n\t\t}\n\t}\n\n\t/**\n\t * Set default data into current_edit_record\n\t *\n\t * @param columnsArr\n\t * @param force\n\t *\n\t * if force is true set the current_edit_record and populate edit_view_ui_dic\n\t * this is used in view controllers (RequestViewController::setRequestFormDefaultData) where the api call for default values is late\n\t *\n\t */\n\tsetDefaultData( columnsArr, force ) {\n\t\tvar $this = this;\n\t\t$.each( columnsArr, function( field, value ) {\n\t\t\tif ( force != true && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.current_edit_record[field] ) ) {\n\t\t\t\t//do nothing\n\t\t\t} else {\n\t\t\t\tif ( force == true ) {\n\t\t\t\t\tif ( $this.edit_view_ui_dic[field] ) {\n\t\t\t\t\t\t$this.edit_view_ui_dic[field].setValue( value );\n\t\t\t\t\t\t$this.current_edit_record[field] = value;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.current_edit_record[field] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tcollectUIDataToCurrentEditRecord() {\n\t\tif ( this.is_mass_editing ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $this = this;\n\t\tfor ( var key in this.edit_view_ui_dic ) {\n\t\t\tif ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\n\t\t\t//only check dropdownlist\n\t\t\tif ( !widget.hasClass( 't-select' ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar value = widget.getValue();\n\n//\t\t\t//Set all UI field to current edit record, we need validate all UI field when save and validate\n\t\t\t//use != to ingore string or number, value from html is string.\n\t\t\t//is visible make sure the widget is shown on screen of current select type\n\n\t\t\t//Error: TypeError: undefined is not an object (evaluating '$this.current_edit_record[key]') in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-124906 line 2792\n\t\t\tif ( value && $this.current_edit_record && $this.current_edit_record[key] != value ) {\n\n\t\t\t\tif ( !value || value === '0' || ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( value ) && value.length === 0 ) ) {\n\t\t\t\t\t$this.current_edit_record[key] = false;\n\t\t\t\t} else {\n\t\t\t\t\t$this.current_edit_record[key] = value;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsetCurrentEditRecordData() {\n\t\t//Set current edit record data to all widgets\n\t\tfor ( var key in this.current_edit_record ) {\n\n\t\t\tif ( !this.current_edit_record.hasOwnProperty( key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar widget = this.edit_view_ui_dic[key];\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( widget ) ) {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'country': //popular case\n\t\t\t\t\t\tthis.setCountryValue( widget, key );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\twidget.setValue( this.current_edit_record[key] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tthis.collectUIDataToCurrentEditRecord();\n\t\tthis.setEditViewDataDone();\n\t}\n\n\tsetCountryValue( widget, key ) {\n\t\tif ( !this.current_edit_record['province'] ) {\n\t\t\tthis.eSetProvince( this.current_edit_record[key], true );\n\t\t} else {\n\t\t\tthis.eSetProvince( this.current_edit_record[key] );\n\t\t}\n\t\twidget.setValue( this.current_edit_record[key] );\n\t}\n\n\tputInputToInsideFormItem( form_item_input, label ) {\n\t\tvar form_item = $( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.EDIT_VIEW_SUB_FORM_ITEM ) );\n//\t\tvar form_item_label_div = form_item.find( '.edit-view-form-item-label-div' );\n//\n//\t\tform_item_label_div.attr( 'class', 'edit-view-form-item-sub-label-div' );\n\n\t\tvar form_item_label = form_item.find( '.edit-view-form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.edit-view-form-item-input-div' );\n\t\tform_item.addClass( 'remove-margin' );\n\n\t\tform_item_label.text( $.i18n._( label ) );\n\n\t\tform_item_input_div.append( form_item_input );\n\n\t\treturn form_item;\n\t}\n\n\t//set tab 0 visible after all data set done. This be hide when init edit view data\n\tsetEditViewDataDone() {\n\t\t// Remove this on 14.9.14 because adding tab url support, ned set url when tab index change and\n\t\t// need know waht's current doing action. See if this cause any problem\n\t\t//LocalCacheData.current_doing_context_action = '';\n\t\tthis.setTabOVisibility( true );\n\t\tTTPromise.resolve( 'init', 'init' );\n\n\t\t$( '.edit-view-tab-bar' ).css( 'opacity', 1 );\n\t}\n\n\tsetNavigationArrowsStatus() {\n\t\tif ( !this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar left_arrow = this.edit_view.find( '.left-click' );\n\t\tvar right_arrow = this.edit_view.find( '.right-click' );\n\t\tvar $this = this;\n\n\t\tleft_arrow.off( 'click' ).on( 'click', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.debounce */ .x.debounce( function NavigationLeftArrowClick( e ) {\n\t\t\tif ( !left_arrow.hasClass( 'disabled' ) ) {\n\t\t\t\t$this.onLeftArrowClick();\n\t\t\t}\n\n\t\t}, _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.calcDebounceWaitTimeBasedOnNetwork */ .x.calcDebounceWaitTimeBasedOnNetwork(), true ) );\n\n\t\tright_arrow.off( 'click' ).on( 'click', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.debounce */ .x.debounce( function NavigationRightArrowClick( e ) {\n\t\t\tif ( !right_arrow.hasClass( 'disabled' ) ) {\n\t\t\t\t$this.onRightArrowClick();\n\t\t\t}\n\n\t\t}, _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.calcDebounceWaitTimeBasedOnNetwork */ .x.calcDebounceWaitTimeBasedOnNetwork(), true ) );\n\t}\n\n\tsetNavigationArrowsEnabled( check_search ) {\n\t\tif ( !this.edit_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If search data exists, search when making a record change to ensure arrow status will reflect the search result\n\t\tif ( check_search && this.navigation && typeof this.navigation.buildUnSelectGridFilter == 'function' ) {\n\t\t\t//Run this condition first to avoid flashing arrows enabling/disabling.\n\t\t\tvar data = this.navigation.buildUnSelectGridFilter();\n\t\t\tif ( data && data.filter_data && Object.keys( data.filter_data ).length !== 0 ) {\n\t\t\t\tthis.navigation.onADropDownSearch( 'unselect_grid', undefined, undefined, () => {\n\t\t\t\t\tthis.setNavigationArrowsEnabled( false );\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tvar left_arrow = this.edit_view.find( '.left-click' );\n\t\tvar right_arrow = this.edit_view.find( '.right-click' );\n\n\t\tleft_arrow.removeClass( 'disabled' );\n\t\tright_arrow.removeClass( 'disabled' );\n\n\t\t//TypeError: this.navigation.getSelectIndex is not a function\n\t\t//navigation could not be initial in cases, for example in Request new view\n\t\tif ( !this.navigation || !( this.navigation.hasOwnProperty( 'getSelectIndex' ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar selected_index = this.navigation.getSelectIndex();\n\t\tvar source_data = this.navigation.getSourceData();\n\n\t\tif ( !source_data || ( Array.isArray( source_data ) && source_data.length === 0 ) ) {\n\t\t\t//No records in navigation box, so make sure arrows are disbled.\n\t\t\tleft_arrow.addClass( 'disabled' );\n\t\t\tright_arrow.addClass( 'disabled' );\n\t\t\treturn;\n\t\t}\n\n\t\tvar current_pager_data = this.navigation.getPagerData();\n\n\t\t// It's possible the navigation don't have a pager data, like Timesheet edit view, so it's become a no page navigation.\n\t\tif ( !current_pager_data ) {\n\t\t\tif ( selected_index === 0 ) {\n\t\t\t\tleft_arrow.addClass( 'disabled' );\n\t\t\t}\n\n\t\t\tif ( selected_index === source_data.length - 1 ) {\n\t\t\t\tright_arrow.addClass( 'disabled' );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( selected_index === 0 && current_pager_data.current_page === 1 ) {\n\t\t\t\tleft_arrow.addClass( 'disabled' );\n\t\t\t}\n\n\t\t\tif ( selected_index === source_data.length - 1 && current_pager_data.current_page === current_pager_data.last_page_number ) {\n\t\t\t\tright_arrow.addClass( 'disabled' );\n\t\t\t}\n\t\t}\n\t}\n\n\tonLeftArrowClick( cancel_callback ) {\n\t\tvar $this = this;\n\n\t\tif ( this.is_changed ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t$this.is_changed = false;\n\t\t\t\t\tdoLeftArrowClick();\n\t\t\t\t}\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} );\n\t\t} else {\n\t\t\tdoLeftArrowClick();\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsEditViewNavigation */ .x.triggerAnalyticsEditViewNavigation( 'left-arrow', this.viewId );\n\n\t\tfunction doLeftArrowClick() {\n\t\t\tvar selected_index = $this.navigation.getSelectIndex();\n\t\t\tvar source_data = $this.navigation.getSourceData();\n\t\t\tvar current_pager_data = $this.navigation.getPagerData();\n\t\t\tvar next_select_item;\n\t\t\tif ( selected_index > 0 ) {\n\t\t\t\tnext_select_item = $this.navigation.getItemByIndex( selected_index - 1 );\n\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\t\t\t} else if ( selected_index === 0 && current_pager_data && current_pager_data.current_page > 1 ) {\n\t\t\t\t$this.navigation.onADropDownSearch( 'unselect_grid', current_pager_data.current_page - 1, 'last', function( result ) {\n\t\t\t\t\tnext_select_item = result;\n\t\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.onCancelClick( null, null, cancel_callback );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\trefreshCurrentRecord() {\n\t\tvar next_select_item = this.navigation.getItemByIndex( this.navigation.getSelectIndex() );\n\t\tProgressBar.showOverlay();\n\t\tif ( this.is_viewing ) {\n\t\t\tthis.onViewClick( next_select_item.id ); //Dont refresh UI\n\t\t} else {\n\t\t\tthis.onEditClick( next_select_item.id ); //Dont refresh UI\n\t\t}\n\n\t\tthis.setNavigationArrowsEnabled();\n\t}\n\n\t//exists for RecurringScheduleControlView due to the unique way we handle the ids there. (Change: That view no longer uses composite IDs)\n\tgetRightArrowClickSelectedIndex( selected_index ) {\n\t\treturn selected_index;\n\t}\n\n\tonRightArrowClick( cancel_callback ) {\n\t\tvar $this = this;\n\t\tif ( this.is_changed ) {\n\t\t\tTAlertManager.showConfirmAlert( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.modify_alert_message */ .x.modify_alert_message, null, function( flag ) {\n\t\t\t\tif ( flag === true ) {\n\t\t\t\t\t$this.is_changed = false;\n\t\t\t\t\tdoRightArrowClick();\n\t\t\t\t}\n\t\t\t\tProgressBar.closeOverlay();\n\t\t\t} );\n\t\t} else {\n\t\t\tdoRightArrowClick();\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.triggerAnalyticsEditViewNavigation */ .x.triggerAnalyticsEditViewNavigation( 'right-arrow', this.viewId );\n\n\t\tfunction doRightArrowClick() {\n\t\t\tvar selected_index = $this.getRightArrowClickSelectedIndex( $this.navigation.getSelectIndex() );\n\t\t\tvar source_data = $this.navigation.getSourceData();\n\t\t\tvar current_pager_data = $this.navigation.getPagerData();\n\t\t\tvar next_select_item;\n\t\t\t//Error: Uncaught TypeError: Cannot read property 'length' of null in /interface/html5/views/BaseViewController.js?v=8.0.0-20141230-125919 line 2956\n\t\t\tif ( !source_data ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( selected_index < ( source_data.length - 1 ) ) {\n\t\t\t\t// next_select_item = $this.navigation.getItemByIndex( (selected_index + 1) );\n\t\t\t\tnext_select_item = $this.navigation.getItemByIndex( $this.navigation.getSelectIndex() + 1 );\n\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\n\t\t\t\t//Error: Unable to get property 'current_page' of undefined or null reference in interface/html5/views/BaseViewController.js?v=9.0.0-20151016-102254 line 3204\n\t\t\t} else if ( selected_index === ( source_data.length - 1 ) && current_pager_data && current_pager_data.current_page < current_pager_data.last_page_number ) {\n\t\t\t\t$this.navigation.onADropDownSearch( 'unselect_grid', current_pager_data.current_page + 1, 'first', function( result ) {\n\t\t\t\t\tnext_select_item = result;\n\t\t\t\t\t$this.onRightOrLeftArrowClickCallBack( next_select_item );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.onCancelClick( null, null, cancel_callback );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tonRightOrLeftArrowClickCallBack( next_select_item ) {\n\t\tProgressBar.showOverlay();\n\t\tif ( this.is_viewing ) {\n\t\t\tthis.onViewClick( next_select_item ); //Dont refresh UI\n\t\t} else {\n\t\t\tthis.onEditClick( next_select_item.id ); //Dont refresh UI\n\t\t}\n\t\tthis.setNavigationArrowsEnabled();\n\t\tif ( this.sub_log_view_controller ) {\n\t\t\tthis.sub_log_view_controller.search();\n\t\t}\n\t}\n\n\tsetParentContextMenuAfterSubViewClose() {\n\t\t//Error: Uncaught TypeError: Cannot read property 'buildContextMenu' of null in /interface/html5/views/BaseViewController.js?v=7.4.6-20141027-085016 line 2887\n\t\tif ( !this.parent_view_controller ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.parent_view_controller.buildContextMenu();\n\n\t\tif ( this.parent_view_controller.edit_view ) {\n\t\t\tthis.parent_view_controller.setEditMenu();\n\t\t} else {\n\t\t\tthis.parent_view_controller.setDefaultMenu();\n\t\t}\n\t}\n\n\t//This should only be used on its own if removeEditView is causing flashing.\n\t//This function should only really be called from onViewClick (see RequestViewCommonController.js)\n\tclearEditView() {\n\t\tif ( this.edit_view ) {\n\t\t\tthis.clearErrorTips();\n\t\t\tthis.edit_view.remove();\n\t\t}\n\t\tthis.edit_view = null;\n\t\tthis.edit_view_tab = null;\n\t}\n\n\tremoveEditView() {\n\t\tthis.unmountContextMenu();\n\t\tthis.clearEditView();\n\t\tthis.setCurrentEditViewState( '' );\n\t\tthis.is_changed = false;\n\t\tthis.confirm_on_exit = false;\n\t\tthis.mass_edit_record_ids = [];\n\n\t\tif ( this.edit_only_mode ) {\n\t\t\tvar current_url = window.location.href;\n\t\t\tif ( current_url.indexOf( '&sm' ) > 0 ) {\n\t\t\t\tcurrent_url = current_url.substring( 0, current_url.indexOf( '&sm' ) );\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( current_url );\n\t\t\t}\n\n\t\t\tLocalCacheData.current_open_edit_only_controller = null;\n\t\t}\n\n\t\t// reset parent context menu if edit only mode\n\n\t\tif ( !this.edit_only_mode ) {\n\t\t\t//#2777 - If the user goes to Employee -> Employees, click on Wage tab, then goes to Employee -> Employees again, the Context Menu will be incorrect and still be for the \"Wage\" record and not the proper \"Employee\" record.\n\t\t\t//This tries to detect when the context menu doesn't match the view and forces it to be rebuilt completely.\n\n\t\t\tthis.buildContextMenu( true );\n\t\t\tthis.setDefaultMenu();\n\t\t} else {\n\t\t\tthis.setParentContextMenuAfterSubViewClose();\n\t\t}\n\t\tthis.reSetURL();\n\t\t//If there is a action in url, add it back. So we have correct url when set tabs urls\n\t\t//This caused a bug where whenever saving a punch on Attendance ->TimeSheet, it would re-open the edit view, same with navigating between weeks, or even deleting punches in some cases.\n\t\t//This need to put under reSetUrl and need clean url_agrs until it set from onViewChange in router again\n\t\tif ( LocalCacheData.getAllURLArgs() && LocalCacheData.getAllURLArgs().a ) {\n\t\t\tLocalCacheData.current_doing_context_action = LocalCacheData.getAllURLArgs().a;\n\t\t}\n\n\t\tthis.sub_log_view_controller = null;\n\t\tthis.edit_view_ui_dic = {};\n\t\tthis.edit_view_ui_validation_field_dic = {};\n\t\tthis.edit_view_form_item_dic = {};\n\t\tthis.edit_view_error_ui_dic = {};\n\t\tthis.current_edit_record = null;\n\n\t\tif ( this.sub_document_view_controller ) {\n\t\t\tthis.sub_document_view_controller = null;\n\t\t}\n\t}\n\n\treSetURL() {\n\t\tif ( this.canSetURL() ) {\n\t\t\tvar args = '#!m=' + this.viewId;\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.setURLToBrowser */ .x.setURLToBrowser( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getBaseURL */ .x.getBaseURL() + args );\n\t\t\tLocalCacheData.setAllURLArgs( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildArgDic */ .x.buildArgDic( args.split( '&' ) ) );\n\t\t}\n\t}\n\n\tgetGridSelectIdArray() {\n\t\tif ( !this.grid ) {\n\t\t\treturn []; //Return empty array so .length on the result doesn't fail with Cannot read property 'length' of undefined\n\t\t}\n\n\t\treturn this.grid.getSelectedRows();\n\t}\n\n\tsetDefaultMenuAddIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.addPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuEditIcon( context_btn, grid_selected_length, p_id ) {\n\t\tif ( !this.editPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\t// Updated to toggle with mass edit icon in new menu - Note: This logic is duplicated in TimeSheetViewController.\n\t\tif ( grid_selected_length === 1 && this.editOwnerOrChildPermissionValidate( p_id ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tif ( grid_selected_length !== 0 ) {\n\t\t\t\t// This ensures the edit icon is still visible when nothing is selected, but should still be disabled. (to keep consistency with old design)\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetDefaultMenuViewIcon( context_btn, grid_selected_length, p_id ) {\n\t\tif ( !this.viewPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 && this.viewOwnerOrChildPermissionValidate() ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuMassEditIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\t// updated to toggle with mass edit icon in new menu\n\t\tif ( grid_selected_length > 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuCopyIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.copyPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuDeleteIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length >= 1 && this.deleteOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuDeleteAndNextIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndNextIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndCopyIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndContinueIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuSaveAndAddIcon( context_btn, grid_selected_length, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetDefaultMenuCopyAsNewIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( ( !this.copyAsNewPermissionValidate( pId ) ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( grid_selected_length === 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuLoginIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !PermissionManager.validate( 'company', 'login_other_user' ) ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.getGridSelectIdArray().length !== 1 ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuCancelIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.sub_view_mode ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuExportIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( this.edit_only_mode || this.is_viewing || this.is_edit || this.is_add ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t} else if ( grid_selected_length == 0 || this.grid == undefined ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetDefaultMenuImportIcon( context_btn, grid_selected_length, pId ) {\n\t\tif ( !this.addPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetDefaultMenuPermissionWizardIcon( context_btn, pId ) {\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetEditMenuPermissionWizardIcon( context_btn, pId ) {\n\t}\n\n\tsetEditMenuImportIcon( context_btn ) {\n\t\tif ( this.edit_only_mode || this.is_viewing || this.is_edit || this.is_add ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuAddIcon( context_btn, pId ) {\n\t\tif ( !this.addPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( this.is_add == true ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuEditIcon( context_btn, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode || this.is_mass_editing ) {\n\t\t\t//Not shown in edit only mode or mass edit. Mass edit should only show mass edit (need to set that part in mass edit icon).\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\n\t\tif ( !this.is_viewing || !this.editOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuNavEditIcon( context_btn, p_id ) {\n\t\tif ( !this.editPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetEditMenuNavViewIcon( context_btn, p_id ) {\n\t\tif ( !this.viewPermissionValidate( p_id ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetEditMenuViewIcon( context_btn, pId ) {\n\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetEditMenuMassEditIcon( context_btn, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode || !this.is_mass_editing ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetEditMenuDeleteIcon( context_btn, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || !this.deleteOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuDeleteAndNextIcon( context_btn, pId ) {\n\t\tif ( !this.deletePermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || !this.deleteOwnerOrChildPermissionValidate( pId ) ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCopyIcon( context_btn, pId ) {\n\t\tif ( !this.copyPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( !this.current_edit_record || !this.current_edit_record.id ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCopyAndAddIcon( context_btn, pId ) {\n\t\tif ( !this.copyAsNewPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveIcon( context_btn, pId ) {\n\n\t\tthis.saveValidate( context_btn, pId );\n\n\t\tif ( this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndContinueIcon( context_btn, pId ) {\n\t\tthis.saveAndContinueValidate( context_btn, pId );\n\n\t\tif ( this.is_mass_adding || this.is_mass_editing || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndCopyIcon( context_btn, pId ) {\n\t\tthis.saveAndCopyValidate( context_btn, pId );\n\n\t\tif ( this.is_mass_editing || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndNextIcon( context_btn, pId ) {\n\t\tif ( !this.editPermissionValidate( pId ) || this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) || this.is_viewing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuSaveAndAddIcon( context_btn, pId ) {\n\t\tthis.saveAndNewValidate( context_btn, pId );\n\n\t\tif ( this.is_viewing || this.is_mass_editing ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuCancelIcon( context_btn, pId ) {\n\t}\n\n\tifContextButtonExist( value ) {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tif ( id === value && context_btn.visible ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tonSubViewModeDisableParentContextMenuButtons() {\n\t\t//When on a sub view mode tab we want to disable certain context menu buttons of the parent view.\n\t\t//This is to help prevent users from using context menu buttons for the wrong view and deleting/copying records they did not intend to use.\n\t\tif ( this.sub_view_mode && this.parent_view_controller ) {\n\t\t\tvar parent_context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.parent_view_controller.determineContextMenuMountAttributes().id );\n\t\t\tvar len = parent_context_menu_array.length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tlet context_btn = parent_context_menu_array[i];\n\t\t\t\tlet id = parent_context_menu_array[i].id;\n\n\t\t\t\t//Switch instead of if/else incase we want differences between buttons in future, easier to read than long conditional.\n\t\t\t\tswitch ( id ) {\n\t\t\t\t\tcase 'add':\n\t\t\t\t\tcase 'delete_icon':\n\t\t\t\t\tcase 'delete_and_next':\n\t\t\t\t\tcase 'copy':\n\t\t\t\t\tcase 'copy_as_new':\n\t\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\tcase 'save_and_new':\n\t\t\t\t\t\tContextMenuManager.disableMenuItem( this.parent_view_controller.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\thideJumpToMenu() {\n\t\t//Jump to should be hidden on all \"new\" record views and only available when editing a record.\n\t\t//This is to prevent users from using the jump to button to navigating to broken or blank pages.\n\t\tif ( this.is_add || this.is_mass_adding ) {\n\t\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\n\t\t\tfor ( var i = 0; i < context_menu_array.length; i++ ) {\n\t\t\t\tif ( context_menu_array[i].action_group === 'jump_to' ) {\n\t\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_menu_array[i].id, false );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t//Call this when select grid row\n\t//Call this when setLayout\n\tsetDefaultMenu( doNotSetFocus, grid_selected_length ) {\n\t\t//Check if there is a current_company object at all.\n\t\tif ( LocalCacheData.isLocalCacheExists( 'current_company' ) == false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.setTotalDisplaySpan();\n\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tif ( grid_selected_length === undefined ) {\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tgrid_selected_length = grid_selected_id_array.length;\n\t\t}\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'add':\n\t\t\t\t\tthis.setDefaultMenuAddIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'edit':\n\t\t\t\t\tthis.setDefaultMenuEditIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'view':\n\t\t\t\t\tthis.setDefaultMenuViewIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'mass_edit':\n\t\t\t\t\tthis.setDefaultMenuMassEditIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy':\n\t\t\t\t\tthis.setDefaultMenuCopyIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_icon':\n\t\t\t\t\tthis.setDefaultMenuDeleteIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_and_next':\n\t\t\t\t\tthis.setDefaultMenuDeleteAndNextIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save':\n\t\t\t\t\tthis.setDefaultMenuSaveIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_next':\n\t\t\t\t\tthis.setDefaultMenuSaveAndNextIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_continue':\n\t\t\t\t\tthis.setDefaultMenuSaveAndContinueIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_new':\n\t\t\t\t\tthis.setDefaultMenuSaveAndAddIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\tthis.setDefaultMenuSaveAndCopyIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy_as_new':\n\t\t\t\t\tthis.setDefaultMenuCopyAsNewIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'login':\n\t\t\t\t\tthis.setDefaultMenuLoginIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'cancel':\n\t\t\t\t\tthis.setDefaultMenuCancelIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'import_icon':\n\t\t\t\t\tthis.setDefaultMenuImportIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'permission_wizard':\n\t\t\t\t\tthis.setDefaultMenuPermissionWizardIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'map':\n\t\t\t\t\tthis.setDefaultMenuMapIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'export_excel':\n\t\t\t\t\tthis.setDefaultMenuExportIcon( context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.setCustomDefaultMenuIcon( id, context_btn, grid_selected_length );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t}\n\n\t\tthis.initRightClickMenu();\n\t}\n\n\tsetCustomDefaultMenuIcon( id, context_btn, grid_selected_length ) {\n\t\treturn false; //FALSE tells setCustomDefaultMenuIcon() to keep processing.\n\t}\n\n\tsetEditMenu() {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\n\t\tvar len = context_menu_array.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\n\t\t\tif ( this.is_mass_editing ) {\n\t\t\t\tswitch ( id ) {\n\t\t\t\t\tcase 'save':\n\t\t\t\t\t\tthis.setEditMenuSaveIcon( context_btn );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'edit':\n\t\t\t\t\t\tthis.setEditMenuEditIcon( context_btn );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'cancel':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'add':\n\t\t\t\t\tthis.setEditMenuAddIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'edit':\n\t\t\t\t\tthis.setEditMenuEditIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'view':\n\t\t\t\t\tthis.setEditMenuViewIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'mass_edit':\n\t\t\t\t\tthis.setEditMenuMassEditIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy':\n\t\t\t\t\tthis.setEditMenuCopyIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_icon':\n\t\t\t\t\tthis.setEditMenuDeleteIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'delete_and_next':\n\t\t\t\t\tthis.setEditMenuDeleteAndNextIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save':\n\t\t\t\t\tthis.setEditMenuSaveIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_continue':\n\t\t\t\t\tthis.setEditMenuSaveAndContinueIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_new':\n\t\t\t\t\tthis.setEditMenuSaveAndAddIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_next':\n\t\t\t\t\tthis.setEditMenuSaveAndNextIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'save_and_copy':\n\t\t\t\t\tthis.setEditMenuSaveAndCopyIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'copy_as_new':\n\t\t\t\t\tthis.setEditMenuCopyAndAddIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'cancel':\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'import_icon':\n\t\t\t\t\tthis.setEditMenuImportIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'permission_wizard':\n\t\t\t\t\tthis.setEditMenuPermissionWizardIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'login':\n\t\t\t\t\tthis.setEditMenuLoginIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'map':\n\t\t\t\t\tthis.setEditMenuMapIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'export_excel':\n\t\t\t\t\tthis.setDefaultMenuExportIcon( context_btn );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.setCustomEditMenuIcon( id, context_btn );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis.hideJumpToMenu();\n\t\tthis.initRightClickMenu( RightClickMenuType.EDITVIEW );\n\t}\n\n\tsetCustomEditMenuIcon( id, context_btn ) {\n\t\treturn false; //FALSE tells setCustomEditMenuIcon() to keep processing.\n\t}\n\n\tsetDefaultMenuMapIcon( context_btn ) {\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getProductEdition */ .x.getProductEdition() <= 10 ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\n\t\tvar show = false;\n\t\tif ( this.grid ) {\n\t\t\tvar selected_items = this.getSelectedItems();\n\t\t\tDebug.Arr( selected_items, 'selected items', 'BaseViewController.js', 'BaseViewController', 'setDefaultMenuMapIcon', 10 );\n\t\t\tif ( selected_items.length > 0 ) {\n\t\t\t\tfor ( var x = 0; x < selected_items.length; x++ ) {\n\t\t\t\t\tif ( selected_items[x] && selected_items[x].latitude && selected_items[x].longitude ) {\n\t\t\t\t\t\tshow = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( show ) {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\t\t} else {\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t}\n\t}\n\n\tsetEditMenuMapIcon( context_btn ) {\n\t\tthis.setDefaultMenuMapIcon( context_btn );\n\t}\n\n\tsetEditMenuLoginIcon( context_btn ) {\n\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t}\n\n\tsetErrorMenu() {\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tlet context_btn = context_menu_array[i];\n\t\t\tlet id = context_menu_array[i].id;\n\n\t\t\tif ( context_menu_array[i].split_button_active_item ) {\n\t\t\t\t//Temporarily sets split button to ignore resetting of the active item. This stops active split button item from resetting.\n\t\t\t\t//Example if doing \"Save & Continue\" we do not want the button to switch back to \"Save\" just because validation failed.\n\t\t\t\tContextMenuManager.freezeSplitButtonActiveItem( this.determineContextMenuMountAttributes().id, context_btn.id );\n\t\t\t}\n\n\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, true );\n\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'cancel':\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tContextMenuManager.disableMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t}\n\t}\n\n\trender() {\n\t\tvar $this = this;\n\n\t\t$( window ).off( 'resize.edit_tabs' ).on( 'resize.edit_tabs', _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.debounce */ .x.debounce( function() {\n\t\t\tif ( $this.edit_view ) {\n\t\t\t\t$this.setEditViewTabSize();\n\t\t\t}\n\t\t}, 200 ) );\n\n\t\tTTPromise.add( 'BaseViewController', 'getCustomFields' );\n\n\t\tthis.getCustomFieldsForView();\n\n\t\t//Create search panel only when show as a main view\n\n\t\tif ( !this.sub_view_mode && !this.edit_only_mode && !this.tree_mode ) {\n\t\t\tvar search_panel_w = $( $.fn.SearchPanel.html.search_panel );\n\n\t\t\t$( this.el ).prepend( search_panel_w );\n\n\t\t\tif ( !this.show_search_tab ) {\n\t\t\t\tsearch_panel_w.hide();\n\t\t\t}\n\n\t\t\tthis.search_panel = search_panel_w.SearchPanel( { viewController: this } );\n\n\t\t\tthis.search_panel.on( 'searchTabSelect', function() {\n\t\t\t\t$this.onSearchTabSelect;\n\t\t\t} );\n\n\t\t\tTTPromise.wait( 'BaseViewController', 'getCustomFields', function() {\n\t\t\t\tthis.buildSearchFields();\n\t\t\t\tthis.buildCustomFieldSearchFields()\n\t\t\t\tthis.buildBasicSearchUI();\n\t\t\t\tthis.buildAdvancedSearchUI();\n\t\t\t\tthis.buildSearchAndLayoutUI();\n\n\t\t\t\t//Work around that the li offset is empty in chrome\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$this.setCurrentViewPosition();\n\t\t\t\t}, 500 );\n\t\t\t}.bind( this ) );\n\n\t\t}\n\t}\n\n\tsetCurrentViewPosition() {\n\t\tvar current_view_div = this.search_panel.find( '.layout-selector-div' );\n\t\tvar saved_layout_li = this.search_panel.find( 'a[ref=\\'saved_layout\\']' ).parent();\n\t\t// Error: Unable to get property 'left' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=8.0.6-20150417-083849 line 3691\n\t\tif ( !current_view_div || !saved_layout_li || !saved_layout_li.offset() ) {\n\t\t\treturn;\n\t\t}\n\t\t// Now controlled from CSS in SearchPanel.css Dont understand why there is a complex left: x JS calc, right position seems better and more consistent.\n\t\t// current_view_div.css( 'left', saved_layout_li.offset().left + saved_layout_li.width() - 60 ); // Change to 60 is trial and error trying to prevent current view dropdown from overlapping in new layout design\n\t}\n\n\t//Build fields when search tab change\n\tonSearchTabSelect( e, e1, ui ) {\n\t\tvar tab_id = $( ui ).prop( 'id' );\n\n\t\tswitch ( tab_id ) {\n\t\t\tcase 'basic_search':\n\n\t\t\t\tif ( this.search_panel.getLastSelectTabId() !== 'saved_layout' ) {\n\t\t\t\t\tthis.getSearchPanelFilter( 1, true );\n\t\t\t\t\tthis.buildBasicSearchUI();\n\t\t\t\t\tthis.setSearchPanelFilter( false, 0 );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'adv_search':\n\t\t\t\tif ( this.search_panel.getLastSelectTabId() !== 'saved_layout' ) {\n\t\t\t\t\tthis.getSearchPanelFilter( 0, true );\n\t\t\t\t\tthis.buildAdvancedSearchUI();\n\t\t\t\t\tthis.setSearchPanelFilter( false, 1 );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'saved_layout':\n\t\t\t\tthis.getSearchPanelFilter( this.search_panel.getLastSelectTabIndex() );\n\t\t}\n\t}\n\n\tinitDropDownOptions( options, callBack ) {\n\t\tlet $this = this;\n\t\tlet api_groups = {};\n\n\t\t//Fill any values that are not set and group option calls by their API endpoint.\n\t\tfor ( let i = 0; i < options.length; i++ ) {\n\t\t\tlet option = options[i];\n\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( option.api ) ) {\n\t\t\t\toption.api = this.api;\n\t\t\t}\n\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( option.field_name ) || !option.field_name ) {\n\t\t\t\toption.field_name = option.option_name + '_id';\n\t\t\t}\n\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( option.parent ) || !option.parent ) {\n\t\t\t\toption.parent = null;\n\t\t\t}\n\n\t\t\t//Group getOption calls by their API endpoint.\n\t\t\tif ( !api_groups[option.api.className] ) {\n\t\t\t\tapi_groups[option.api.className] = [];\n\t\t\t}\n\t\t\tapi_groups[option.api.className].push( option );\n\t\t}\n\n\t\t//Call getOptionsBatch on each requested API\n\t\tlet completed_api_calls = 0;\n\t\tfor ( let api_class in api_groups ) {\n\t\t\tif ( Array.isArray( api_groups[api_class] ) === false ) {\n\t\t\t\t//Issue #3223 - Error: Uncaught TypeError: api_groups[api_class].reduce is not a function\n\t\t\t\t//The cause for this exception is unknown as the above code is syncronous and should always produce\n\t\t\t\t//the same results given the same input. However, for some reason api_groups[api_class] is not an always an array.\n\t\t\t\t//This change is simply meant to prevent the error from being thrown.\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\t\t\tcallBack();\n\t\t\t\t}\n\t\t\t\tDebug.Text( 'Unexpected error api_groups[api_class] is not an array.', 'BaseViewController.js', 'BaseViewController', 'initDropDownOptions', 9 );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//Reduce data sent to API with only data required for the API.\n\t\t\tlet data = api_groups[api_class].reduce( ( new_obj, option ) => ( new_obj[option.option_name] = option.parent, new_obj ), {} );\n\t\t\t_services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI */ .y[api_class].getOptionsBatch( data, {\n\t\t\t\tonResult: function( response ) {\n\t\t\t\t\tlet results = response.getResult();\n\t\t\t\t\tif ( results && Object.keys( results ).length > 0 ) {\n\t\t\t\t\t\tfor ( let option in results ) {\n\t\t\t\t\t\t\tlet option_data = results[option];\n\t\t\t\t\t\t\tlet option_field_info = api_groups[api_class].find( icon => icon.option_name === option );\n\t\t\t\t\t\t\t//Set view controller variables and field data\n\t\t\t\t\t\t\t$this[option + '_array'] = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( option_data );\n\t\t\t\t\t\t\tif ( !$this.sub_view_mode ) {\n\t\t\t\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.basic_search_field_ui_dic[option_field_info.field_name] ) ) {\n\t\t\t\t\t\t\t\t\t$this.basic_search_field_ui_dic[option_field_info.field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( option_data ) );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.adv_search_field_ui_dic[option_field_info.field_name] ) ) {\n\t\t\t\t\t\t\t\t\t$this.adv_search_field_ui_dic[option_field_info.field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( option_data ) );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcompleted_api_calls++;\n\n\t\t\t\t\tif ( Object.keys( api_groups ).length === completed_api_calls && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\t\t\t\t//Only call the callback when all API calls have completed.\n\t\t\t\t\t\tcallBack( response );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tbuildWidgetContainerWithTextTip( widget, tip ) {\n\t\tvar h_box = $( '<div class=\\'h-box\\'></div>' );\n\n\t\tvar text_box = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT );\n\t\ttext_box.css( 'margin-left', '10px' );\n\t\ttext_box.TText();\n\t\ttext_box.setValue( tip );\n\n\t\th_box.append( widget );\n\t\th_box.append( text_box );\n\n\t\treturn h_box;\n\t}\n\n\t//Set option list for search panel and edit view\n\tinitDropDownOption( option_name, field_name, api, callBack, array_name ) {\n\t\tvar $this = this;\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( api ) ) {\n\t\t\tapi = this.api;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( field_name ) || !field_name ) {\n\t\t\tfield_name = option_name + '_id';\n\t\t}\n\t\tapi.getOptions( option_name, {\n\t\t\tonResult: function( res ) {\n\t\t\t\tvar result = res.getResult();\n\n\t\t\t\tif ( array_name ) {\n\t\t\t\t\t$this[array_name] = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result );\n\t\t\t\t} else {\n\n\t\t\t\t\t$this[option_name + '_array'] = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result );\n\t\t\t\t}\n\n\t\t\t\tif ( !$this.sub_view_mode ) {\n\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.basic_search_field_ui_dic[field_name] ) ) {\n\t\t\t\t\t\t$this.basic_search_field_ui_dic[field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.adv_search_field_ui_dic[field_name] ) ) {\n\t\t\t\t\t\t$this.adv_search_field_ui_dic[field_name].setSourceData( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildRecordArray */ .x.buildRecordArray( result ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\t\t\tcallBack( res );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tclearSearchPanel() {\n\n\t\tfor ( var key in this.basic_search_field_ui_dic ) {\n\t\t\tvar search_input = this.basic_search_field_ui_dic[key];\n\t\t\tsearch_input.setValue( null );\n\t\t}\n\n\t\tfor ( var key in this.adv_search_field_ui_dic ) {\n\t\t\tsearch_input = this.adv_search_field_ui_dic[key];\n\t\t\tsearch_input.setValue( null );\n\t\t}\n\t}\n\n\tonSearch() {\n\t\tTTPromise.add( 'init', 'init' );\n\t\tTTPromise.wait();\n\n\t\tvar do_update = false;\n\n\t\t//don't keep temp filter any more, set them when change tab\n\t\tthis.temp_adv_filter_data = null;\n\t\tthis.temp_basic_filter_data = null;\n\t\tthis.getSearchPanelFilter();\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tvar default_layout_id = $( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\n\n\t\t\tif ( !default_layout_id ) {\n\t\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar layout_name = BaseViewController.default_layout_name;\n\n\t\t} else if ( this.show_search_tab ) {\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\t\t} else if ( !this.show_search_tab ) {\n\t\t\tthis.search();\n\t\t\tthis.setGridHeaderStyle();\n\t\t\treturn;\n\t\t}\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.id = default_layout_id;\n\t\targs.data = {};\n\t\targs.data.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.filter_sort = sort_filter;\n\n\t\tProgressBar.showOverlay();\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tonClearSearch() {\n\t\tvar do_update = false;\n\t\tif ( this.search_panel.getLayoutsArray() && this.search_panel.getLayoutsArray().length > 0 ) {\n\t\t\tvar default_layout_id = $( this.previous_saved_layout_selector ).children( 'option:contains(\\'' + BaseViewController.default_layout_name + '\\')' ).attr( 'value' );\n\n\t\t\tif ( !default_layout_id ) {\n\t\t\t\tthis.clearSearchPanel();\n\t\t\t\tthis.filter_data = null;\n\t\t\t\tthis.temp_adv_filter_data = null;\n\t\t\t\tthis.temp_basic_filter_data = null;\n\t\t\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\t\t\t\tthis.sort_by_selector.setValue( null );\n\n\t\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar layout_name = BaseViewController.default_layout_name;\n\t\t\tthis.clearSearchPanel();\n\t\t\tthis.filter_data = null;\n\t\t\tthis.temp_adv_filter_data = null;\n\t\t\tthis.temp_basic_filter_data = null;\n\t\t\tdo_update = true;\n\n\t\t} else {\n\n\t\t\tthis.clearSearchPanel();\n\t\t\tthis.filter_data = null;\n\t\t\tthis.temp_adv_filter_data = null;\n\t\t\tthis.temp_basic_filter_data = null;\n\t\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\t\t\tthis.sort_by_selector.setValue( null );\n\n\t\t\tthis.onSaveNewLayout( BaseViewController.default_layout_name );\n\t\t\treturn;\n\n\t\t}\n\n//\t\tthis.column_selector.setSelectGridData( this.default_display_columns );\n\n\t\tthis.sort_by_selector.setValue( null );\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tif ( do_update ) {\n\t\t\tvar args = {};\n\t\t\targs.id = default_layout_id;\n\t\t\targs.data = {};\n\t\t\targs.data.display_columns = selected_display_columns;\n\t\t\targs.data.filter_data = filter_data;\n\t\t\targs.data.filter_sort = sort_filter;\n\n\t\t}\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonSaveNewLayout( default_layout_name ) {\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( default_layout_name ) ) {\n\t\t\tvar layout_name = default_layout_name;\n\t\t} else {\n\t\t\tlayout_name = this.save_search_as_input.getValue();\n\t\t}\n\n\t\tif ( !layout_name || layout_name.length < 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.script = this.script_name;\n\t\targs.name = layout_name;\n\t\targs.is_default = false;\n\t\targs.data = {};\n\t\targs.data.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.filter_sort = sort_filter;\n\n\t\tvar $this = this;\n\n\t\tvar a_layout_name = ALayoutCache.layout_dic[this.script_name];\n\t\tif ( a_layout_name && ALayoutCache.layout_dic[a_layout_name] ) {\n\t\t\tALayoutCache.layout_dic[a_layout_name] = null;\n\t\t}\n\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\n\t\t\t\t} else {\n\t\t\t\t\tTAlertManager.showErrorAlert( res );\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tonUpdateLayout() {\n\n\t\tvar selectId = $( this.previous_saved_layout_selector ).children( 'option:selected' ).attr( 'value' );\n\t\tvar layout_name = $( this.previous_saved_layout_selector ).children( 'option:selected' ).text();\n\n\t\tvar sort_filter = this.getSearchPanelSortFilter();\n\t\tvar selected_display_columns = this.getSearchPanelDisplayColumns();\n\t\tvar filter_data = this.getValidSearchFilter();\n\n\t\tvar args = {};\n\t\targs.id = selectId;\n\t\targs.data = {};\n\t\targs.data.display_columns = selected_display_columns;\n\t\targs.data.filter_data = filter_data;\n\t\targs.data.filter_sort = sort_filter;\n\n\t\tvar $this = this;\n\n\t\tvar a_layout_name = ALayoutCache.layout_dic[this.script_name];\n\t\tif ( a_layout_name && ALayoutCache.layout_dic[a_layout_name] ) {\n\t\t\tALayoutCache.layout_dic[a_layout_name] = null;\n\t\t}\n\n\t\tthis.user_generic_data_api.setUserGenericData( args, {\n\t\t\tonResult: function( res ) {\n\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = layout_name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tclearViewLayoutCache() {\n\t\tif ( LocalCacheData.view_layout_cache && LocalCacheData.view_layout_cache[this.script_name] ) {\n\t\t\tLocalCacheData.view_layout_cache[this.script_name] = null;\n\t\t}\n\t}\n\n\tclearAwesomeboxLayoutCache() {\n\t\t// Removed saved view layout for awesomebox if it existed.\n\t\tif ( ALayoutCache.layout_dic && ALayoutCache.layout_dic[this.script_name] ) {\n\t\t\tALayoutCache.layout_dic[ALayoutCache.layout_dic[this.script_name]] = null;\n\t\t}\n\t}\n\n\tonDeleteLayout() {\n\t\tvar selectId = $( this.previous_saved_layout_selector ).children( 'option:selected' ).attr( 'value' );\n\n\t\tvar $this = this;\n\t\tthis.user_generic_data_api.deleteUserGenericData( selectId, {\n\t\t\tonResult: function( res ) {\n\t\t\t\tif ( res.isValid() ) {\n\t\t\t\t\t$this.clearAwesomeboxLayoutCache();\n\t\t\t\t\t$this.clearViewLayoutCache();\n\t\t\t\t\t$this.need_select_layout_name = $this.select_layout.name;\n\t\t\t\t\t$this.initLayout();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tbuildSearchFields() {\n\t\t//Override in all subview\n\t}\n\n\tbuildCustomFieldSearchFields() {\n\t\tif ( !this.search_fields ) {\n\t\t\tthis.search_fields = [];\n\t\t}\n\n\t\tthis.custom_fields.forEach( ( field ) => {\n\t\t\tif ( field.enable_search ) {\n\n\t\t\t\tlet field_settings = {\n\t\t\t\t\tlabel: field.name,\n\t\t\t\t\tin_column: 1,\n\t\t\t\t\tfield: this.getPrefixedCustomFieldID( field.id ),\n\t\t\t\t\tbasic_search: false,\n\t\t\t\t\tadv_search: true,\n\t\t\t\t};\n\n\t\t\t\tlet type_id = parseInt( field.type_id );\n\n\t\t\t\tswitch ( type_id ) {\n\t\t\t\t\tcase 500: //Checkbox\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX;\n\t\t\t\t\t\tfield_settings.multiple = false;\n\t\t\t\t\t\tfield_settings.layout_name = 'global_option_column';\n\t\t\t\t\t\tfield_settings.addition_source_function = ( target, source_data ) => {\n\t\t\t\t\t\t\tsource_data = [\n\t\t\t\t\t\t\t\t{ value: TTUUID.zero_id, label: '-- ' + $.i18n._( 'ANY' ) + ' --' },\n\t\t\t\t\t\t\t\t{ value: true, label: $.i18n._( 'Yes' ) },\n\t\t\t\t\t\t\t\t{ value: false, label: $.i18n._( 'No' ) }\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\treturn source_data;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1000: //Date\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// case 1010: //Date Range Search Disabled\n\t\t\t\t\t// \tfield_settings.form_item_type = FormItemType.DATE_PICKER;\n\t\t\t\t\t// \tbreak;\n\t\t\t\t\tcase 1100: //Time\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1200: //Datetime\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER;\n\t\t\t\t\t\tfield_settings.mode = 'date_time';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1300: //Time Unit\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT;\n\t\t\t\t\t\tfield_settings.mode = 'time_unit';\n\t\t\t\t\t\tfield_settings.need_parser_sec = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2100: //Single-select dropdown\n\t\t\t\t\tcase 2110: //Multi-select dropdown\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX;\n\t\t\t\t\t\tfield_settings.multiple = false;\n\t\t\t\t\t\tfield_settings.layout_name = 'global_option_column';\n\t\t\t\t\t\tfield_settings.addition_source_function = ( target, source_data ) => {\n\t\t\t\t\t\t\tsource_data = []; //Overwriting source data to empty array.\n\t\t\t\t\t\t\tif ( field.meta_data.validation.multi_select_items ) {\n\t\t\t\t\t\t\t\tfield.meta_data.validation.multi_select_items.forEach( ( item ) => {\n\t\t\t\t\t\t\t\t\tsource_data.push( {\n\t\t\t\t\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\t\t\t\t\tvalue: item.id,\n\t\t\t\t\t\t\t\t\t\tlabel: item.label\n\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn source_data;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tfield_settings.form_item_type = _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tthis.search_fields.push( new SearchField( field_settings ) );\n\t\t\t}\n\t\t} );\n\t}\n\n\tbuildBasicSearchUI() {\n\t\tif ( !this.search_fields ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar basic_search_div = this.search_panel.find( 'div #basic_search_content_div' );\n\n\t\tvar len = this.search_fields.length;\n\t\tvar $this = this;\n\n\t\tvar column1 = basic_search_div.find( '.first-column' );\n\t\tvar column2 = basic_search_div.find( '.second-column' );\n\t\tvar column3 = basic_search_div.find( '.third-column' );\n\n\t\tvar already_created_ui = false;\n\t\t$.each( this.search_fields, function( index, search_field ) {\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.basic_search_field_ui_dic[search_field.get( 'field' )] ) ) {\n\t\t\t\talready_created_ui = true;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( !search_field.get( 'basic_search' ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// var form_item = $( Global.loadWidget( 'global/widgets/search_panel/FormItem.html' ) ); // TODO: #3023: Delete this line once widget html converted and no longer need this quick reference for the old format.\n\t\t\tvar form_item = $( $.fn.SearchPanel.html.form_item );\n\t\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\t\t\tvar form_item_input = $this.getFormItemInput( search_field );\n\t\t\tform_item_label.text( search_field.get( 'label' ) );\n\t\t\tform_item_input_div.append( form_item_input );\n\n\t\t\tswitch ( search_field.get( 'in_column' ) ) {\n\t\t\t\tcase 1:\n\t\t\t\t\tcolumn1.append( form_item );\n\t\t\t\t\tcolumn1.append( '<div class=\\'clear-both-div\\'></div>' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tcolumn2.append( form_item );\n\t\t\t\t\tcolumn2.append( '<div class=\\'clear-both-div\\'></div>' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tcolumn3.append( form_item );\n\t\t\t\t\tcolumn3.append( '<div class=\\'clear-both-div\\'></div>' );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$this.basic_search_field_ui_dic[search_field.get( 'field' )] = form_item_input;\n\t\t} );\n\n\t\tif ( !already_created_ui ) {\n\t\t\tthis.onBuildBasicUIFinished();\n\t\t}\n\t}\n\n\tbuildAdvancedSearchUI() {\n\t\tif ( !this.search_fields ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar advSearchDiv = this.search_panel.find( 'div #adv_search_content_div' );\n\n\t\tvar $this = this;\n\n\t\tvar column1 = advSearchDiv.find( '.first-column' );\n\t\tvar column2 = advSearchDiv.find( '.second-column' );\n\t\tvar column3 = advSearchDiv.find( '.third-column' );\n\n\t\tvar already_created_ui = false;\n\t\tvar no_adv_ui = true;\n\n\t\t$.each( this.search_fields, function( index, search_field ) {\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.adv_search_field_ui_dic[search_field.get( 'field' )] ) ) {\n\t\t\t\talready_created_ui = true;\n\t\t\t\tno_adv_ui = false;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( !search_field.get( 'adv_search' ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tvar form_item = $( $.fn.SearchPanel.html.form_item );\n\t\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\t\t\tvar form_item_input = $this.getFormItemInput( search_field );\n\t\t\tform_item_label.text( search_field.get( 'label' ) );\n\t\t\tform_item_input_div.append( form_item_input );\n\n\t\t\tswitch ( search_field.get( 'in_column' ) ) {\n\t\t\t\tcase 1:\n\t\t\t\t\tcolumn1.append( form_item );\n\t\t\t\t\tcolumn1.append( '<div class=\\'clear-both-div\\'></div>' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tcolumn2.append( form_item );\n\t\t\t\t\tcolumn2.append( '<div class=\\'clear-both-div\\'></div>' );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tcolumn3.append( form_item );\n\t\t\t\t\tcolumn3.append( '<div class=\\'clear-both-div\\'></div>' );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$this.adv_search_field_ui_dic[search_field.get( 'field' )] = form_item_input;\n\t\t\tno_adv_ui = false;\n\t\t} );\n\n\t\tif ( no_adv_ui ) {\n\n\t\t\tthis.search_panel.hideAdvSearchPanel();\n\t\t}\n\n\t\tif ( !already_created_ui ) {\n\t\t\tthis.onBuildAdvUIFinished();\n\t\t}\n\t}\n\n\tonSetSearchFilterFinished() {\n\t}\n\n\tonBuildAdvUIFinished() {\n\t\t//Always override in sub class\n\t}\n\n\tonBuildBasicUIFinished() {\n\t\t//Always override in sub class\n\t}\n\n\tgetFormItemInput( search_field ) {\n\t\tvar input;\n\t\tvar form_type = search_field.get( 'form_item_type' );\n\n\t\tswitch ( form_type ) {\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\t\t\tvar show_search = false;\n\t\t\t\tvar key;\n\n\t\t\t\tif ( search_field.get( 'layout_name' ) !== 'global_option_column' && search_field.get( 'layout_name' ) !== 'global_tree_column' ) {\n\t\t\t\t\tshow_search = true;\n\t\t\t\t\tkey = 'id';\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( search_field.get( 'layout_name' ) === 'global_tree_column' ) {\n\t\t\t\t\t\tkey = 'id';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tkey = 'value';\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tinput.AComboBox( {\n\t\t\t\t\tapi_class: search_field.get( 'api_class' ),\n\t\t\t\t\tallow_multiple_selection: search_field.get( 'multiple' ),\n\t\t\t\t\tlayout_name: search_field.get( 'layout_name' ),\n\t\t\t\t\ttree_mode: search_field.get( 'tree_mode' ),\n\t\t\t\t\tdefault_args: search_field.get( 'default_args' ),\n\t\t\t\t\tshow_search_inputs: show_search,\n\t\t\t\t\tset_any: search_field.get( 'set_any' ),\n\t\t\t\t\taddition_source_function: search_field.get( 'addition_source_function' ),\n\t\t\t\t\tscript_name: search_field.get( 'script_name' ),\n\t\t\t\t\tcustom_first_label: search_field.get( 'custom_first_label' ),\n\t\t\t\t\tkey: key,\n\t\t\t\t\tsearch_panel_model: true,\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\n\t\t\t\tif ( search_field.get( 'customSearchFilter' ) ) {\n\t\t\t\t\tinput.customSearchFilter = search_field.get( 'customSearchFilter' );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\t\t\tinput.TTextInput( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tneed_parser_sec: search_field.get( 'need_parser_sec' ),\n\t\t\t\t\tmode: search_field.get( 'mode' ),\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TIME_PICKER );\n\t\t\t\tinput.TTimePicker( {\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.PASSWORD_INPUT:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.PASSWORD_INPUT );\n\t\t\t\tinput.TTextInput( {\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.COMBO_BOX:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.COMBO_BOX );\n\t\t\t\tinput.TComboBox( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tset_any: true\n\t\t\t\t} );\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TAG_INPUT:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TAG_INPUT );\n\t\t\t\tinput.TTagInput( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tobject_type_id: search_field.get( 'object_type_id' )\n\t\t\t\t} );\n\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.DATE_PICKER:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( form_type );\n\t\t\t\tinput = $( input );\n\t\t\t\tinput.TDatePicker( {\n\t\t\t\t\tfield: search_field.get( 'field' ),\n\t\t\t\t\tmode: search_field.get( 'mode' ),\n\t\t\t\t} );\n\n\t\t\t\tbreak;\n\t\t\tcase _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.CHECKBOX:\n\t\t\t\tinput = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.CHECKBOX );\n\t\t\t\tinput.TCheckbox( {\n\t\t\t\t\tfield: search_field.get( 'field' )\n\t\t\t\t} );\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tDebug.Error( 'ERROR: Form type does not exist: '+ form_type, 'BaseViewController.js', 'BaseViewController', 'getFormItemInput', 2 );\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn input;\n\t}\n\n\tbuildSearchAndLayoutUI() {\n\t\tvar layout_div = this.search_panel.find( 'div #saved_layout_content_div' );\n\n\t\t//Display Columns\n\n\t\tvar form_item = $( $.fn.SearchPanel.html.form_item );\n\t\tvar form_item_label = form_item.find( '.form-item-label' );\n\t\tvar form_item_input_div = form_item.find( '.form-item-input-div' );\n\n\t\tthis.column_selector = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_DROPDOWN );\n\n\t\tthis.column_selector = this.column_selector.ADropDown( {\n\t\t\tdisplay_show_all: false,\n\t\t\tid: this.ui_id + '_column_selector',\n\t\t\tkey: 'value',\n\t\t\tallow_drag_to_order: true,\n\t\t\tdisplay_close_btn: false,\n\t\t\tdisplay_column_settings: false,\n\t\t\tmax_height: 150\n\t\t} );\n\t\tthis.column_selector.on( 'formItemChange', function() {\n\t\t\t$this.layout_changed = true;\n\t\t} );\n\n\t\tform_item_label.text( $.i18n._( 'Display Columns' ) );\n\t\tform_item_label.addClass( 'SearchPanel-displayColumns-label' );\n\t\tform_item_input_div.append( this.column_selector );\n\n\t\tlayout_div.append( form_item );\n\n\t\tlayout_div.append( '<div class=\\'clear-both-div\\'></div>' );\n\n\t\tthis.column_selector.setColumns( [\n\t\t\t{ name: 'label', index: 'label', label: $.i18n._( 'Column Name' ), width: 100, sortable: false }\n\t\t] );\n\n\t\t//Sort By\n\t\tform_item = $( $.fn.SearchPanel.html.form_item );\n\t\tform_item_label = form_item.find( '.form-item-label' );\n\t\tform_item_input_div = form_item.find( '.form-item-input-div' );\n\t\tthis.sort_by_selector = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.AWESOME_BOX );\n\t\tthis.sort_by_selector = this.sort_by_selector.AComboBox( {\n\t\t\tallow_drag_to_order: true,\n\t\t\tallow_multiple_selection: true,\n\t\t\tset_empty: true,\n\t\t\tlayout_name: 'global_sort_columns'\n\t\t} );\n\n\t\tform_item_label.text( $.i18n._( 'Sort By' ) );\n\t\tform_item_input_div.append( this.sort_by_selector );\n\n\t\tlayout_div.append( form_item );\n\n\t\tlayout_div.append( '<div class=\\'clear-both-div\\'></div>' );\n\n\t\t//Save and update layout\n\n\t\tform_item = $( $.fn.SearchPanel.html.form_item );\n\t\tform_item_label = form_item.find( '.form-item-label' );\n\t\tform_item_input_div = form_item.find( '.form-item-input-div' );\n\n\t\tform_item_label.text( $.i18n._( 'Save Search As' ) );\n\n\t\tthis.save_search_as_input = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.FormItemType.TEXT_INPUT );\n\t\tthis.save_search_as_input.TTextInput();\n\n\t\tvar save_btn = $( '<button class=\"tt-button p-button p-component small-search-panel-button\" type=\"button\">\\n' +\n\t\t\t'<span class=\"tticon tticon-save_black_24dp\"></span>\\n' +\n\t\t\t'<span class=\"p-button-label\">' + $.i18n._( 'Save' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tform_item_input_div.append( this.save_search_as_input );\n\t\tform_item_input_div.append( save_btn );\n\n\t\tvar $this = this;\n\t\tsave_btn.click( function() {\n\t\t\t$this.saving_layout_in_layout_tab = true;\n\t\t\t$this.onSaveNewLayout();\n\t\t\t$this.search();\n\t\t} );\n\n\t\t//Previous Saved Layout\n\n\t\tthis.previous_saved_layout_div = $( '<div class=\\'previous-saved-layout-div\\'></div>' );\n\n\t\tform_item_input_div.append( this.previous_saved_layout_div );\n\n\t\tform_item_label = $( '<span style=\\'margin-left: 5px\\' >' + $.i18n._( 'Previous Saved Searches' ) + ':</span>' );\n\t\tthis.previous_saved_layout_div.append( form_item_label );\n\n\t\tthis.previous_saved_layout_selector = $( '<select style=\\'margin-left: 5px\\' class=\\'t-select\\'>' );\n\t\tvar update_btn = $( '<button class=\"tt-button p-button p-component small-search-panel-button\" type=\"button\">\\n' +\n\t\t\t'<span class=\"tticon tticon-save_black_24dp\"></span>\\n' +\n\t\t\t'<span class=\"p-button-label\">' + $.i18n._( 'Update' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tvar del_btn = $( '<button class=\"tt-button p-button p-component small-search-panel-button\" type=\"button\">\\n' +\n\t\t\t'<span class=\"tticon tticon-delete_black_24dp\"></span>\\n' +\n\t\t\t'<span class=\"p-button-label\">' + $.i18n._( 'Delete' ) + '</span>\\n' +\n\t\t\t'</button>' );\n\n\t\tupdate_btn.click( function() {\n\t\t\t$this.onUpdateLayout();\n\t\t} );\n\n\t\tdel_btn.click( function() {\n\t\t\t$this.onDeleteLayout();\n\t\t} );\n\n\t\tthis.previous_saved_layout_div.append( this.previous_saved_layout_selector );\n\t\tthis.previous_saved_layout_div.append( update_btn );\n\t\tthis.previous_saved_layout_div.append( del_btn );\n\n\t\tlayout_div.append( form_item );\n\n\t\tthis.previous_saved_layout_div.css( 'display', 'none' );\n\t}\n\n\tonGridSelectRow() {\n\t\t$( '#ribbon_view_container .context-menu:visible a' ).click();\n\t\tthis.setDefaultMenu();\n\t}\n\n\tsetPreviousSavedSearchSourcesAndValue( layouts_array ) {\n\t\tvar $this = this;\n\n\t\tif ( this.previous_saved_layout_selector ) {\n\t\t\tthis.previous_saved_layout_selector.empty();\n\n\t\t\tif ( layouts_array && layouts_array.length > 0 ) {\n\t\t\t\tthis.previous_saved_layout_div.css( 'display', 'inline' );\n\n\t\t\t\tvar len = layouts_array.length;\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tvar item = layouts_array[i];\n\t\t\t\t\tthis.previous_saved_layout_selector.append( $( '<option value=\"' + item.id + '\"></option>' ).text( item.name ) );\n\t\t\t\t}\n\n\t\t\t\t$( this.previous_saved_layout_selector.find( 'option' ) ).filter( function() {\n\t\t\t\t\treturn $( this ).attr( 'value' ) == $this.select_layout.id;\n\t\t\t\t} ).prop( 'selected', true ).attr( 'selected', true );\n\n\t\t\t} else {\n\t\t\t\tthis.previous_saved_layout_div.css( 'display', 'none' );\n\t\t\t}\n\t\t}\n\t}\n\n\tsetSelectLayout( exclude_column ) {\n\t\tvar $this = this;\n\t\tvar grid;\n\n\t\tvar grid_id = 'grid';\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.grid ) ) {\n\t\t\tgrid = $( this.el ).find( '#grid' );\n\n\t\t\tgrid.attr( 'id', this.ui_id + '_grid' ); //Grid's id is ScriptName + _grid\n\n\t\t\tgrid_id = this.ui_id + '_grid';\n\t\t}\n\n\t\tvar column_info_array = [];\n\n\t\tif ( !this.select_layout ) { //Set to default layout if no layout at all\n\t\t\tthis.select_layout = { id: '' };\n\t\t\tthis.select_layout.data = { filter_data: {}, filter_sort: {} };\n\t\t\tthis.select_layout.data.display_columns = this.default_display_columns;\n\t\t}\n\n\t\tvar layout_data = this.select_layout.data;\n\n\t\tif ( !layout_data.display_columns || layout_data.display_columns.length == 0 ) {\n\t\t\tlayout_data.display_columns = this.default_display_columns;\n\t\t}\n\n\t\tvar display_columns = this.buildDisplayColumns( layout_data.display_columns );\n\n\t\tif ( !this.sub_view_mode && this.search_panel ) {\n\n\t\t\t//Set Display Column in layout panel\n\t\t\t//Error: TypeError: null is not an object (evaluating 'this.column_selector.setSelectGridData')\n\t\t\tif ( this.column_selector ) {\n\t\t\t\tthis.column_selector.setSelectGridData( display_columns );\n\t\t\t\t//this.column_selector.setGridColumnsWidths(); //This is called in SearchPanel.setGridSize() on expand instead, as browsers seem to optimize out scrollbar calculations until the DOM element is visible.\n\t\t\t}\n\n\t\t\t//Set Sort by awesomebox in layout panel\n\t\t\t//Error: TypeError: null is not an object (evaluating 'this.sort_by_selector.setSourceData')\n\t\t\tif ( this.sort_by_selector ) {\n\t\t\t\tthis.sort_by_selector.setSourceData( this.buildSortSelectorUnSelectColumns( display_columns ) );\n\t\t\t\tthis.sort_by_selector.setValue( this.buildSortBySelectColumns() );\n\t\t\t}\n\n\t\t\t//Set Previoous Saved layout combobox in layout panel\n\t\t\tvar layouts_array = this.search_panel.getLayoutsArray();\n\n\t\t\tthis.setPreviousSavedSearchSourcesAndValue( layouts_array );\n\n\t\t}\n\n\t\t//Set Data Grid on List view\n\t\tvar len = display_columns.length;\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar view_column_data = display_columns[i];\n\n\t\t\tif ( $.inArray( view_column_data.value, exclude_column ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar column_info = {\n\t\t\t\tname: view_column_data.value,\n\t\t\t\tindex: view_column_data.value,\n\t\t\t\tlabel: view_column_data.label,\n\t\t\t\twidth: 100,\n\t\t\t\tsortable: false,\n\t\t\t\ttitle: false\n\t\t\t};\n\t\t\tcolumn_info_array.push( column_info );\n\t\t}\n\n\t\tvar grid_needs_reload = false;\n\t\tif ( this.grid ) {\n\t\t\tgrid_id = this.ui_id + '_grid';\n\n\t\t\tif ( this.layout_changed == true ) {\n\t\t\t\t$this.layout_changed = false;\n\t\t\t\tthis.grid.grid.jqGrid( 'GridUnload' );\n\t\t\t\tthis.grid = null;\n\t\t\t} else {\n\t\t\t\t//This is done in BaseViewControler->search() right before the data is set, which prevents \"flashing\".\n\t\t\t\t// However some views override this function and need to be fixed manually.\n\t\t\t\t//this.grid.clearGridData();\n\t\t\t}\n\t\t}\n\n\t\tthis.showGridBorders();\n\n\t\tif ( !this.grid ) {\n\t\t\tvar grid_setup = this.getGridSetup();\n\t\t\tif ( this.sub_view_mode ) {\n\t\t\t\tgrid_setup.height = 1;\n\t\t\t}\n\t\t\tthis.grid = new TTGrid( grid_id, grid_setup, column_info_array );\n\n\t\t\tif ( this.sub_view_mode ) {\n\t\t\t\tthis.grid.grid.hide();\n\t\t\t}\n\n\t\t\tthis.setGridColumnsWidth(); //Helps makes changing layouts \"flash\" less, especially when going from only a few columns to many.\n\t\t\tthis.setGridSize( this.ui_id, this.sub_view_mode, this.sub_view_grid_autosize, this.pager_data );\n\t\t}\n\n\t\tif ( this.grid && grid_needs_reload ) {\n\t\t\tthis.grid.reloadGrid();\n\t\t}\n\n\t\t//Add widget on UI and bind events. Next set data in it in search result\n\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\tif ( this.paging_widget.parent().length > 0 ) {\n\t\t\t\tthis.paging_widget.remove();\n\t\t\t}\n\n\t\t\tthis.paging_widget.css( 'width', this.grid.grid.width() );\n\t\t\tthis.grid.grid.append( this.paging_widget );\n\n\t\t\tthis.paging_widget.click( $this.onPaging() );\n\n\t\t} else {\n\t\t\t$( this.el ).find( '.total-number-div' ).append( this.paging_widget );\n\t\t\t$( this.el ).find( '.bottom-div' ).append( this.paging_widget_2 );\n\n\t\t\tthis.paging_widget.on( 'paging', function( e, action, page_number ) {\n\t\t\t\t$this.onPaging2( e, action, page_number );\n\t\t\t} );\n\t\t\tthis.paging_widget_2.bind( 'paging', function( e, action, page_number ) {\n\t\t\t\t$this.onPaging2( e, action, page_number );\n\t\t\t} );\n\t\t}\n\n\t\tthis.bindGridColumnEvents();\n\n\t\tthis.setGridHeaderStyle(); //Set Sort Style\n\t\t//replace select layout filter_data to filter set in onNavigation function when goto view from navigation context group\n\t\tif ( LocalCacheData.default_filter_for_next_open_view ) {\n\t\t\tthis.select_layout.data.filter_data = LocalCacheData.default_filter_for_next_open_view.filter_data;\n\t\t\tLocalCacheData.default_filter_for_next_open_view = null;\n\t\t}\n\n\t\tthis.filter_data = this.select_layout.data.filter_data;\n\n\t\tif ( !this.sub_view_mode ) {\n\t\t\tthis.setSearchPanelFilter( true ); //Auto change to property tab when set value to search fields.\n\t\t}\n\t}\n\n\tgetGridSetup() {\n\t\tvar $this = this;\n\n\t\tvar container = this.grid_parent ? this.grid_parent : '.grid-div';\n\t\tif ( !this.grid_parent && this.sub_view_mode ) {\n\t\t\tif ( $( '#' + this.ui_id + '_grid' ).parents( '.sub-view' ).length > 0 ) {\n\t\t\t\tcontainer = '.sub-grid-view-div';\n\t\t\t} else {\n\t\t\t\tcontainer = '.edit-view-tab-bar';\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tcontainer_selector: container,\n\t\t\tsub_grid_mode: this.sub_view_mode,\n\t\t\tonResizeGrid: true,\n\t\t\tonSelectRow: function() {\n\t\t\t\t$this.onGridSelectRow();\n\t\t\t},\n\t\t\tonCellSelect: function() {\n\t\t\t\t$this.onGridSelectRow();\n\t\t\t},\n\t\t\tonSelectAll: function() {\n\t\t\t\t$this.onGridSelectAll();\n\t\t\t},\n\t\t\tondblClickRow: function( e ) {\n\t\t\t\t$this.onGridDblClickRow( e );\n\t\t\t},\n\t\t\tonRightClickRow: function( rowId ) {\n\t\t\t\tvar id_array = $this.getGridSelectIdArray();\n\t\t\t\tif ( id_array.indexOf( rowId ) < 0 ) {\n\t\t\t\t\t$this.grid.grid.resetSelection();\n\t\t\t\t\t$this.grid.grid.setSelection( rowId );\n\t\t\t\t\t$this.onGridSelectRow();\n\t\t\t\t}\n\t\t\t},\n\t\t\theight: 1, //Start really small to reduce flashing, as height is changed with setGridSize() shortly after anyways.\n\t\t};\n\t}\n\n\tonGridSelectAll() {\n\t\tthis.setDefaultMenu();\n\t}\n\n\tunSelectAll() {\n\t\tthis.grid.grid.resetSelection();\n\t}\n\n\tonGridDblClickRow( e ) {\n\t\tthis.grid.grid.resetSelection();\n\t\tthis.grid.setSelection( e, false );\n\t\tthis.setDefaultMenu( true );\n\t\tvar context_menu_array = ContextMenuManager.getMenuModelByMenuId( this.determineContextMenuMountAttributes().id );\n\t\tvar len = context_menu_array.length;\n\t\tvar need_break = false;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tif ( need_break ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvar id = context_menu_array[i].id;\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'edit':\n\t\t\t\t\tif ( !context_menu_array[i].disabled && context_menu_array[i].visible ) {\n\t\t\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t\t\tthis.onEditClick();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tif ( need_break ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvar id = context_menu_array[i].id;\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'view':\n\t\t\t\t\tneed_break = true;\n\t\t\t\t\tif ( !context_menu_array[i].disabled && context_menu_array[i].visible ) {\n\t\t\t\t\t\tProgressBar.showOverlay();\n\t\t\t\t\t\tthis.onViewClick();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar id = context_menu_array[i].id;\n\t\t\tswitch ( id ) {\n\t\t\t\tcase 'add':\n\t\t\t\t\tif ( !context_menu_array[i].disabled && context_menu_array[i].visible ) {\n\t\t\t\t\t\tthis.onAddClick();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tonPaging() {\n\t\tthis.search( true, 'next' );\n\t}\n\n\tonPaging2( e, action, page_number ) {\n\t\tthis.search( true, action, page_number );\n\t}\n\n\t//Bind column click event to change sort type and save columns to t_grid_header_array to use to set column style (asc or desc)\n\tbindGridColumnEvents() {\n\t\tvar display_columns = this.grid.getColumnModel();\n\n\t\tif ( !display_columns ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar len = display_columns.length;\n\n\t\tthis.t_grid_header_array = [];\n\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar column_info = display_columns[i];\n\t\t\tvar column_header = $( $( this.el ).find( '#gbox_' + this.ui_id + '_grid' ).find( 'div #jqgh_' + this.ui_id + '_grid_' + column_info.name ) );\n\n\t\t\tthis.t_grid_header_array.push( column_header.TGridHeader() );\n\t\t\tif ( this.search_panel ) {\n\t\t\t\tcolumn_header.on( 'click', onColumnHeaderClick );\n\t\t\t}\n\t\t}\n\n\t\tvar $this = this;\n\n\t\tfunction onColumnHeaderClick( e ) {\n\t\t\tvar field = $( this ).attr( 'id' );\n\t\t\tfield = field.substring( 10 + $this.ui_id.length + 1, field.length );\n\n\t\t\tif ( field === 'cb' ) { //first column, check box column.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\te.preventDefault(); //can't be cancelled before cb is detected as we need the default event in that case.\n\n\t\t\tif ( !$this.sorting_rows ) {\n\t\t\t\t$this.sorting_rows = true;\n\t\t\t\tTTPromise.add( 'init', 'init' );\n\t\t\t\tTTPromise.wait( null, null, function() {\n\t\t\t\t\t$this.sorting_rows = false; //prevent doubling up events ( which loops forever )\n\t\t\t\t} );\n\n\t\t\t\tif ( e.metaKey || e.ctrlKey ) {\n\t\t\t\t\t$this.buildSortCondition( false, field );\n\t\t\t\t} else {\n\t\t\t\t\t$this.buildSortCondition( true, field );\n\n\t\t\t\t}\n\n\t\t\t\tif ( $this.sub_view_mode ) {\n\t\t\t\t\t$this.search();\n\t\t\t\t\t$this.setGridHeaderStyle();\n\t\t\t\t} else {\n\t\t\t\t\tif ( $this.sort_by_selector ) {\n\t\t\t\t\t\t$this.sort_by_selector.setValue( $this.buildSortBySelectColumns() );\n\t\t\t\t\t}\n\t\t\t\t\t$this.onSearch();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDebug.Text( 'Skipping column sort call ', '', 'BaseViewController', 'onColumnHeaderClick', 10 );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tgetValidSearchFilter() {\n\t\tvar validFilterData = {};\n\t\tfor ( var key in this.filter_data ) {\n\t\t\t// Error: Unable to get property 'value' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=8.0.6-20150417-143734 line 4727\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.filter_data[key] ) && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.filter_data[key].value ) && this.filter_data[key].value !== '' ) {\n\t\t\t\tvalidFilterData[key] = this.filter_data[key];\n\t\t\t}\n\t\t}\n\n\t\treturn validFilterData;\n\t}\n\n\tgetSearchPanelDisplayColumns() {\n\t\tvar display_columns = [];\n\n\t\tvar select_items = this.column_selector.getSelectItems();\n\n\t\tif ( select_items && select_items.length > 0 ) {\n\t\t\t$.each( select_items, function( index, content ) {\n\t\t\t\tdisplay_columns.push( content.value );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !display_columns || display_columns.length == 0 ) {\n\t\t\tdisplay_columns = this.default_display_columns;\n\t\t}\n\n\t\treturn display_columns;\n\t}\n\n\tgetSearchPanelSortFilter() {\n\t\tvar sort_filter = [];\n\t\tif ( this.sort_by_selector ) {\n\t\t\tvar select_items = this.sort_by_selector.getValue( true );\n\n\t\t\tif ( select_items && select_items.length > 0 ) {\n\t\t\t\t$.each( select_items, function( index, content ) {\n\t\t\t\t\tvar sort = {};\n\t\t\t\t\tsort[content.value] = content.sort;\n\t\t\t\t\tsort_filter.push( sort );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\treturn sort_filter;\n\t}\n\n\tgetSearchPanelFilter( getFromTabIndex, save_temp_filter ) {\n\t\tif ( !this.search_panel ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( getFromTabIndex ) ) {\n\t\t\tvar search_tab_select_index = getFromTabIndex;\n\t\t} else {\n\t\t\tsearch_tab_select_index = this.search_panel.getSelectTabIndex();\n\t\t}\n\n//\t\tvar basic_fields_len = this.search_fields.length;\n\t\tvar target_ui_dic = null;\n\n\t\tif ( search_tab_select_index === 0 ) {\n\t\t\tthis.filter_data = [];\n\t\t\ttarget_ui_dic = this.basic_search_field_ui_dic;\n\t\t} else if ( search_tab_select_index === 1 && this.search_panel.isAdvTabVisible() ) {\n\t\t\tthis.filter_data = [];\n\t\t\ttarget_ui_dic = this.adv_search_field_ui_dic;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $this = this;\n\t\t$.each( target_ui_dic, function( key, content ) {\n\t\t\t$this.filter_data[key] = { field: key, id: '', value: target_ui_dic[key].getValue( true ) };\n\n\t\t\tif ( $this.temp_basic_filter_data ) {\n\t\t\t\t$this.temp_basic_filter_data[key] = $this.filter_data[key];\n\t\t\t}\n\n\t\t\tif ( $this.temp_adv_filter_data ) {\n\t\t\t\t$this.temp_adv_filter_data[key] = $this.filter_data[key];\n\t\t\t}\n\t\t} );\n\n\t\tif ( save_temp_filter ) {\n\t\t\tif ( search_tab_select_index === 0 ) {\n\t\t\t\t$this.temp_basic_filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( $this.filter_data );\n\t\t\t} else if ( search_tab_select_index === 1 ) {\n\t\t\t\t$this.temp_adv_filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( $this.filter_data );\n\t\t\t}\n\n\t\t}\n\t}\n\n\t//Set value to field UI in search tab\n\tsetSearchPanelFilter( autoChangeTab, tab_index ) {\n\n\t\tthis.clearSearchPanel();\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( autoChangeTab ) ) {\n\t\t\tautoChangeTab = false;\n\t\t}\n\n\t\tvar filter = this.filter_data;\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( tab_index ) ) {\n\t\t\tif ( tab_index === 0 && this.temp_basic_filter_data ) {\n\t\t\t\tfilter = this.temp_basic_filter_data;\n\t\t\t} else if ( tab_index === 1 && this.temp_adv_filter_data ) {\n\t\t\t\tfilter = this.temp_adv_filter_data;\n\t\t\t}\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( filter ) || !this.search_fields ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar basic_fields_len = this.search_fields.length;\n\n\t\tfor ( var i = 0; i < basic_fields_len; i++ ) {\n\t\t\tvar field = this.search_fields[i];\n\t\t\tvar field_name = field.get( 'field' );\n\n\t\t\tvar search_input = this.basic_search_field_ui_dic[field_name];\n\t\t\tvar search_input_1 = this.adv_search_field_ui_dic[field_name];\n\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( filter[field_name] ) ) {\n\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( search_input ) ) {\n\n\t\t\t\t\tif ( $.type( filter[field_name] ) === 'string' || $.type( filter[field_name] ) === 'number' ) {\n\t\t\t\t\t\tsearch_input.setValue( filter[field_name] );\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( filter[field_name].hasOwnProperty( 'value' ) ) { // when set default filter don't have 'value' in it, For example Invoice edit view\n\t\t\t\t\t\t\tsearch_input.setValue( filter[field_name].value );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsearch_input.setValue( filter[field_name] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( autoChangeTab && !this.saving_layout_in_layout_tab ) {\n\t\t\t\t\tif ( this.search_panel.getSelectTabIndex() !== 1 ) {\n\t\t\t\t\t\tthis.search_panel.setSelectTabIndex( 1, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( search_input_1 ) ) {\n\n\t\t\t\t\tif ( $.type( filter[field_name] ) === 'string' || $.type( filter[field_name] ) === 'number' ) {\n\t\t\t\t\t\tsearch_input_1.setValue( filter[field_name] );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( filter[field_name].hasOwnProperty( 'value' ) ) { // when set default filter don't have 'value' in it, For example Invoice edit view\n\t\t\t\t\t\t\tsearch_input_1.setValue( filter[field_name].value );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsearch_input_1.setValue( filter[field_name] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n//\t\t\t\t\tsearch_input_1.setValue( filter[field_name].value );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.getSearchPanelFilter(); //Make sure filter only has fields on current display ab\n\n\t\tthis.search_panel.setSearchFlag( this.getValidSearchFilter() ); // Add ! to tab which has search condition in it\n\n\t\tthis.onSetSearchFilterFinished();\n\t}\n\n\t//Set Grid header style for asc or desc\n\tsetGridHeaderStyle() {\n\t\tfor ( var i = 0; i < this.t_grid_header_array.length; i++ ) {\n\t\t\tvar t_grid_header = this.t_grid_header_array[i];\n\n\t\t\tvar field = t_grid_header.attr( 'id' );\n\t\t\tif ( typeof field === 'string' || field instanceof String ) {\n\t\t\t\tfield = field.substring( 10 + this.ui_id.length + 1, field.length );\n\n\t\t\t\tt_grid_header.cleanSortStyle();\n\n\t\t\t\tif ( this.select_layout.data.filter_sort ) {\n\t\t\t\t\tvar sort_array_len = this.select_layout.data.filter_sort.length;\n\n\t\t\t\t\tfor ( var j = 0; j < sort_array_len; j++ ) {\n\t\t\t\t\t\tvar sort_item = this.select_layout.data.filter_sort[j];\n\t\t\t\t\t\tvar sortField = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getFirstKeyFromObject */ .x.getFirstKeyFromObject( sort_item );\n\t\t\t\t\t\tif ( sortField === field ) {\n\t\t\t\t\t\t\tif ( sort_array_len > 1 ) {\n\t\t\t\t\t\t\t\tt_grid_header.setSortStyle( sort_item[sortField], j + 1 );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tt_grid_header.setSortStyle( sort_item[sortField], 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildSortCondition( reset, field ) {\n\t\tvar next_sort = 'desc';\n\n\t\tif ( reset ) {\n\n\t\t\tif ( this.select_layout.data.filter_sort && this.select_layout.data.filter_sort.length > 0 ) {\n\t\t\t\tvar len = this.select_layout.data.filter_sort.length;\n\t\t\t\tvar found = false;\n\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tvar sort_item = this.select_layout.data.filter_sort[i];\n\t\t\t\t\tfor ( var key in sort_item ) {\n\n\t\t\t\t\t\tif ( !sort_item.hasOwnProperty( key ) ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( key === field ) {\n\t\t\t\t\t\t\tif ( sort_item[key] === 'asc' ) {\n\t\t\t\t\t\t\t\tnext_sort = 'desc';\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnext_sort = 'asc';\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( found ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.select_layout.data.filter_sort = [\n\t\t\t\t{}\n\t\t\t];\n\t\t\tthis.select_layout.data.filter_sort[0][field] = next_sort;\n\n\t\t} else {\n\t\t\tif ( !this.select_layout.data.filter_sort ) {\n\t\t\t\tthis.select_layout.data.filter_sort = [\n\t\t\t\t\t{}\n\t\t\t\t];\n\t\t\t\tthis.select_layout.data.filter_sort[0][field] = 'asc';\n\t\t\t} else {\n\t\t\t\tlen = this.select_layout.data.filter_sort.length;\n\t\t\t\tfound = false;\n\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\tsort_item = this.select_layout.data.filter_sort[i];\n\t\t\t\t\tfor ( var key in sort_item ) {\n\n\t\t\t\t\t\tif ( !sort_item.hasOwnProperty( key ) ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( key === field ) {\n\t\t\t\t\t\t\tif ( sort_item[key] === 'asc' ) {\n\t\t\t\t\t\t\t\tsort_item[key] = 'desc';\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsort_item[key] = 'asc';\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( found ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( !found ) {\n\t\t\t\t\tthis.select_layout.data.filter_sort.push( {} );\n\t\t\t\t\tthis.select_layout.data.filter_sort[len][field] = 'asc';\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsearch( set_default_menu, page_action, page_number, callBack ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( set_default_menu ) ) {\n\t\t\tset_default_menu = true;\n\t\t}\n\n\t\tvar filter = {};\n\t\tfilter.filter_data = {};\n\t\tfilter.filter_sort = {};\n\t\tfilter.filter_columns = this.getFilterColumnsFromDisplayColumns();\n\t\tfilter.filter_items_per_page = 0; // Default to 0 to load user preference defined\n\t\tif ( this.pager_data ) {\n\n\t\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\t\tif ( page_action === 'next' ) {\n\t\t\t\t\tfilter.filter_page = this.pager_data.next_page;\n\t\t\t\t} else {\n\t\t\t\t\tfilter.filter_page = 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( page_action ) {\n\t\t\t\t\tcase 'next':\n\t\t\t\t\t\tfilter.filter_page = this.pager_data.next_page;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'last':\n\t\t\t\t\t\tfilter.filter_page = this.pager_data.previous_page;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'start':\n\t\t\t\t\t\tfilter.filter_page = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'end':\n\t\t\t\t\t\tfilter.filter_page = this.pager_data.last_page_number;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'go_to':\n\t\t\t\t\t\tfilter.filter_page = page_number;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tfilter.filter_page = this.pager_data.current_page;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfilter.filter_page = 1;\n\t\t}\n\t\t//Error: Uncaught TypeError: Cannot read property 'data' of null\n\t\tif ( typeof this.select_layout != 'undefined' && this.sub_view_mode && this.parent_key ) {\n\t\t\tthis.select_layout.data.filter_data[this.parent_key] = this.parent_value;\n\t\t}\n\t\t//Error: Uncaught TypeError: Cannot read property 'data' of null\n\t\t//If sub view controller set custom filters, get it\n\t\tif ( typeof this.select_layout != 'undefined' && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.getSubViewFilter ) ) {\n\t\t\tthis.select_layout.data.filter_data = this.getSubViewFilter( this.select_layout.data.filter_data );\n\t\t}\n\n\t\t//select_layout will not be null, it's set in setSelectLayout function\n\t\tfilter.filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertLayoutFilterToAPIFilter */ .x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\t//Error: Uncaught TypeError: Cannot read property 'data' of null\n\t\tif ( this.select_layout && this.select_layout.data ) {\n\t\t\tfilter.filter_sort = this.select_layout.data.filter_sort;\n\t\t}\n\n\t\tif ( TTUUID.isUUID( this.refresh_id ) ) {\n\t\t\tfilter.filter_data = {};\n\t\t\tfilter.filter_data.id = [this.refresh_id];\n\n\t\t\tthis.last_select_ids = filter.filter_data.id;\n\n\t\t} else {\n\t\t\tthis.last_select_ids = [];\n\t\t\tvar ids = this.getGridSelectIdArray();\n\t\t\t//ensure detached reference to value source or lose this.last_select_ids when grid is cleared.\n\t\t\tfor ( var i = 0; i < ids.length; i++ ) {\n\t\t\t\tthis.last_select_ids.push( ids[i] );\n\t\t\t}\n\t\t}\n\n\t\tvar $this = this;\n\t\tthis.api['get' + this.api.key_name]( filter, {\n\t\t\tonResult: function( result ) {\n\t\t\t\tvar result_data = result.getResult();\n\t\t\t\tvar len;\n\t\t\t\tif ( set_default_menu ) {\n\t\t\t\t\t$this.setDefaultMenu( true );\n\t\t\t\t}\n\t\t\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isArray */ .x.isArray( result_data ) && ( !TTUUID.isUUID( $this.refresh_id ) || $this.refresh_id == TTUUID.zero_id || $this.refresh_id == TTUUID.not_exist_id ) ) {\n\t\t\t\t\t$this.refresh_id = null;\n\t\t\t\t\t$this.showNoResultCover();\n\t\t\t\t} else {\n\t\t\t\t\t$this.removeNoResultCover();\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.__createRowId ) ) {\n\t\t\t\t\t\tresult_data = $this.__createRowId( result_data );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( $this.showGridOptionFields ) ) {\n\t\t\t\t\t\tresult_data = $this.showGridOptionFields( result_data );\n\t\t\t\t\t}\n\n\t\t\t\t\tresult_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.formatGridData */ .x.formatGridData( result_data, $this.api.key_name );\n\t\t\t\t\tlen = result_data.length;\n\t\t\t\t}\n\n\t\t\t\tif ( TTUUID.isUUID( $this.refresh_id ) ) {\n\t\t\t\t\t$this.refresh_id = null;\n\t\t\t\t\tvar grid_source_data = $this.grid.getData();\n\t\t\t\t\tlen = grid_source_data.length;\n\t\t\t\t\tif ( $.type( grid_source_data ) !== 'array' ) {\n\t\t\t\t\t\tgrid_source_data = [];\n\t\t\t\t\t}\n\t\t\t\t\tvar found = false;\n\t\t\t\t\tvar new_record = result_data[0];\n\t\t\t\t\t//Error: Uncaught TypeError: Cannot read property 'id' of undefined in /interface/html5/views/BaseViewController.js?v=7.4.3-20140924-084605 line 4851\n\t\t\t\t\tif ( new_record ) {\n\t\t\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\t\t\tvar record = grid_source_data[i];\n\t\t\t\t\t\t\t//Fixed === issue. The id set by jQGrid is string type.\n\t\t\t\t\t\t\t//Commented out as we now expect the variable type of the ids to be UUID (string in javascript)\n\t\t\t\t\t\t\t//if ( !isNaN( parseInt( record.id ) ) ) {\n\t\t\t\t\t\t\t//\trecord.id = parseInt( record.id );\n\t\t\t\t\t\t\t//}\n\t\t\t\t\t\t\tif ( record.id == new_record.id ) {\n\t\t\t\t\t\t\t\t$this.grid.setRowData( new_record.id, new_record );\n\t\t\t\t\t\t\t\tgrid_source_data[i] = new_record;\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !found ) {\n\t\t\t\t\t\t\t$this.grid.setData( grid_source_data.concat( new_record ) );\n\t\t\t\t\t\t\t// $this.setGridColumnsWidth();\n\t\t\t\t\t\t\t// if ( $this.sub_view_mode && Global.isSet( $this.resizeSubGrid ) ) {\n\t\t\t\t\t\t\t// \tlen = Global.isSet( len ) ? len : 0;\n\t\t\t\t\t\t\t// \t$this.resizeSubGrid( len + 1 );\n\t\t\t\t\t\t\t// }\n\t\t\t\t\t\t\t$this.highLightGridRowById( new_record.id );\n\t\t\t\t\t\t\t$this.reSelectLastSelectItems();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t//Set Page data to widget, next show display info when setDefault Menu\n\t\t\t\t\t$this.pager_data = result.getPagerData();\n\t\t\t\t\t//CLick to show more mode no need this step\n\t\t\t\t\tif ( LocalCacheData.paging_type !== 0 && $this.paging_widget && $this.paging_widget_2 ) {\n\t\t\t\t\t\t$this.paging_widget.setPagerData( $this.pager_data );\n\t\t\t\t\t\t$this.paging_widget_2.setPagerData( $this.pager_data );\n\t\t\t\t\t}\n\t\t\t\t\tif ( LocalCacheData.paging_type === 0 && page_action === 'next' ) {\n\t\t\t\t\t\tvar current_data = $this.grid.getData();\n\t\t\t\t\t\tresult_data = current_data.concat( result_data );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Process result_data if necessary, this always needs override.\n\t\t\t\t\tresult_data = $this.processResultData( result_data );\n\n\t\t\t\t\tif ( $this.grid ) {\n\t\t\t\t\t\t$this.grid.setData( result_data ); //This calls clearGridData and reloadGrid.\n\n\t\t\t\t\t\t//$this.setGridColumnsWidth(); //Handle in searchDone() instead.\n\t\t\t\t\t\t// if ( $this.sub_view_mode && Global.isSet( $this.resizeSubGrid ) ) {\n\t\t\t\t\t\t// \t$this.resizeSubGrid( len );\n\t\t\t\t\t\t// }\n\t\t\t\t\t\t$this.reSelectLastSelectItems();\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\t$this.setGridCellBackGround(); //Set cell background for some views\n\t\t\t\tProgressBar.closeOverlay(); //Add this in initData\n\t\t\t\tif ( LocalCacheData.paging_type === 0 ) {\n\t\t\t\t\tif ( !$this.pager_data || $this.pager_data.is_last_page ) {\n\t\t\t\t\t\t$this.paging_widget.css( 'display', 'none' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this.paging_widget.css( 'display', 'block' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( callBack ) {\n\t\t\t\t\tcallBack( result );\n\t\t\t\t}\n\t\t\t\t// when call this from save and new result, we don't call auto open, because this will call onAddClick twice\n\t\t\t\tif ( set_default_menu ) {\n\t\t\t\t\t$this.autoOpenEditViewIfNecessary();\n\t\t\t\t}\n\t\t\t\t$this.searchDone();\n\t\t\t}\n\t\t} );\n\t}\n\n\t//This shouldn't be called anymore, in favor of: baseViewSubTabGridResize()\n\tresizeSubGrid( length ) {\n\t\tvar height = ( length * 26 >= 200 ) ? 200 : length * 26;\n\t\tif ( $( '.edit-view-tab:visible .grid-div' ).length > 1 ) {\n\t\t\tif ( height < 100 ) {\n\t\t\t\theight = 100;\n\t\t\t}\n\t\t} else {\n\t\t\theight = ( $( '.edit-view-tab:visible' ).parent().height() - 85 );\n\t\t}\n\t\tthis.setGridColumnsWidth();\n\t\tthis.setGridHeight( height );\n\t}\n\n\tsetGridColumnsWidth() {\n\t\tif ( this.grid ) {\n\t\t\tthis.grid.setGridColumnsWidth();\n\t\t}\n\t}\n\n\tsetGridHeight( height ) {\n\t\tif ( this.grid ) {\n\t\t\tthis.grid.setGridHeight( height );\n\t\t}\n\t}\n\n\tsetGridWidth( width ) {\n\t\tif ( this.grid ) {\n\t\t\tthis.grid.setGridWidth( width );\n\t\t}\n\t}\n\n\tprocessResultData( result_data ) {\n\t\t//Always needs override\n\t\treturn result_data;\n\t}\n\n\tsearchDone() {\n\t\t//the rotate icon from search panel\n\t\tvar $this = this;\n\t\t$( '.button-rotate' ).removeClass( 'button-rotate' );\n\n\t\tthis.setTotalDisplaySpan();\n\n\t\tthis.setGridColumnsWidth();\n\t\tthis.setGridSize( this.ui_id, this.sub_view_mode, this.sub_view_grid_autosize, this.pager_data );\n\n\t\tif ( this.sub_view_mode && this.grid ) {\n\t\t\tthis.grid.grid.show();\n\t\t}\n\n\t\tTTPromise.resolve( 'BaseViewController', 'onTabShow' );\n\t\tTTPromise.resolve( 'init', 'init' );\n\t}\n\n\treSelectLastSelectItems() {\n\t\tvar $this = this;\n\t\tif ( this.last_select_ids && this.last_select_ids.length > 0 ) {\n\t\t\t$.each( this.last_select_ids, function( index, content ) {\n\t\t\t\t$this.grid.grid.setSelection( content, false );\n\n\t\t\t\tif ( $this.grid_select_id_array ) {\n\t\t\t\t\t$this.grid_select_id_array.push( content );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\tthis.last_select_ids = [];\n\t\t\tif ( !this.edit_view ) {\n\t\t\t\tthis.setDefaultMenu();\n\t\t\t}\n\t\t}\n\t}\n\n\tautoOpenEditViewIfNecessary() {\n\t\t//Auto open edit view. Should set in IndexController\n\n\t\t//There are various bugs that happen when auto opening edit views during sub_view_mode from a \"Jump To\" action. (Master branch also and not onlu Vue)\n\t\t//This is due to the fact that the view inherits the \"LocalCacheData.current_doing_context_action\" of the last view. Examples:\n\t\t// - TimeSheet -> Add Punch -> Jump To -> Edit Employee and switching tabs would auto open a new entry instead of list view.\n\t\t// - TimeSheet -> Add Punch -> Jump To -> Add Request would cause the user stuck to be stuck in the view.\n\t\tif ( this.sub_view_mode && !LocalCacheData.edit_id_for_next_open_view ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( LocalCacheData.current_doing_context_action ) {\n\t\t\tcase 'edit':\n\t\t\t\tif ( LocalCacheData.edit_id_for_next_open_view ) {\n\t\t\t\t\tthis.onEditClick( LocalCacheData.edit_id_for_next_open_view );\n\t\t\t\t\tLocalCacheData.edit_id_for_next_open_view = null;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'view':\n\t\t\t\tif ( LocalCacheData.edit_id_for_next_open_view ) {\n\t\t\t\t\tthis.onViewClick( LocalCacheData.edit_id_for_next_open_view );\n\t\t\t\t\tLocalCacheData.edit_id_for_next_open_view = null;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'new':\n\t\t\t\tif ( !this.edit_view ) {\n\t\t\t\t\tthis.onAddClick();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tthis.autoOpenEditOnlyViewIfNecessary();\n\t}\n\n\tautoOpenEditOnlyViewIfNecessary() {\n\n\t\t//Don't try to open anything if current loading a sub view\n\t\tif ( this.sub_view_mode ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( LocalCacheData.getAllURLArgs() && LocalCacheData.getAllURLArgs().sm && !LocalCacheData.current_open_edit_only_controller ) {\n\n\t\t\tif ( LocalCacheData.getAllURLArgs().sm.indexOf( 'Report' ) < 0 ) {\n\t\t\t\tIndexViewController.openEditView( this, LocalCacheData.getAllURLArgs().sm, LocalCacheData.getAllURLArgs().sid );\n\t\t\t} else {\n\t\t\t\tIndexViewController.openReport( this, LocalCacheData.getAllURLArgs().sm );\n\n\t\t\t\tif ( LocalCacheData.getAllURLArgs().sid ) {\n\t\t\t\t\tLocalCacheData.default_edit_id_for_next_open_edit_view = LocalCacheData.getAllURLArgs().sid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tsetGridCellBackGround() {\n\t\t//Set background color for in_use=false rows for all policy view and RecurringScheduleTemplateControlView\n\t\tif ( this.grid\n\t\t\t&&\n\t\t\t(\n\t\t\t\tthis.script_name.indexOf( 'Policy' ) >= 0 ||\n\t\t\t\tthis.script_name === 'RecurringScheduleTemplateControlView' ||\n\t\t\t\tthis.script_name === 'PayCodeView' ||\n\t\t\t\tthis.script_name === 'RecurringHolidayView' ||\n\t\t\t\tthis.script_name === 'LegalEntityView' ||\n\t\t\t\tthis.script_name === 'RemittanceSourceAccountView' ||\n\t\t\t\tthis.script_name === 'PayrollRemittanceAgencyView' ||\n\t\t\t\tthis.script_name === 'RemittanceDestinationAccountView'\n\t\t\t)\n\t\t) {\n\t\t\tvar data = this.grid.getData();\n\n\t\t\t//Error: TypeError: data is undefined in /interface/html5/framework/jquery.min.js?v=7.4.6-20141027-074127 line 2 > eval line 70\n\t\t\tif ( !data ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar len = data.length;\n\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tvar item = data[i];\n\n\t\t\t\tif ( item.is_in_use === false ) {\n\t\t\t\t\t$( 'tr[id=\\'' + item.id + '\\']' ).addClass( 'policy-not-in-use' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tshowGridBorders() {\n\t\tvar top_border = $( this.el ).find( '.grid-top-border' );\n\t\tvar bottom_border = $( this.el ).find( '.grid-bottom-border' );\n\n\t\ttop_border.css( 'display', 'block' );\n\t\tbottom_border.css( 'display', 'block' );\n\t}\n\n\t_setGridSizeGroupheight( header_size ) {\n\t\tthis.grid.grid.setGridHeight( ( $( this.el ).height() - ( this.search_panel && this.search_panel.is( ':visible' ) ? this.search_panel.height() : 0 ) - 43 - header_size ) );\n\t}\n\n\tsetEditViewTabSize() {\n\t\tvar $this = this;\n\t\tvar tab_bar_label = this.edit_view_tab.find( '.edit-view-tab-bar-label' );\n\t\tvar tab_width = this.edit_view_tab.width() - 80; // -80 is to hopefully account for the 20px padding and margin for the context-border\n\t\tvar nav_width = this.edit_view_tab.find( '.navigation-div' ).width();\n\t\tvar wrap_div = this.edit_view.find( '.tab-label-wrap' );\n\n\t\tvar total_tab_width = 0;\n\t\ttab_bar_label.children().each( function() {\n\t\t\ttotal_tab_width += $( this ).width();\n\t\t} );\n\n\t\tif ( total_tab_width > ( tab_width - nav_width - 25 ) ) {\n\n\t\t\ttab_bar_label.width( total_tab_width + 20 );\n\n\t\t\tif ( wrap_div.length === 0 ) {\n\t\t\t\tvar right_arrow = $( '<img class=\"tab-arrow tab-right-arrow\" style=\"display: none\" src=\"theme/default/images/right_big_arrow.png\" >' );\n\t\t\t\tvar left_arrow = $( '<img class=\"tab-arrow tab-left-arrow\" style=\"display: none\" src=\"theme/default/images/left_big_arrow.png\" >' );\n\t\t\t\twrap_div = $( '<div class=\"tab-label-wrap\"><div class=\"label-wrap\"></div><div class=\"btn-wrap\"></div></div>' );\n\t\t\t\twrap_div.insertBefore( tab_bar_label );\n\t\t\t\twrap_div.width( tab_width - nav_width - 25 );\n\t\t\t\twrap_div.children().eq( 0 ).width( tab_width - nav_width - 100 );\n\t\t\t\twrap_div.children().eq( 0 ).append( tab_bar_label );\n\t\t\t\twrap_div.children().eq( 1 ).append( left_arrow );\n\t\t\t\twrap_div.children().eq( 1 ).append( right_arrow );\n\n\t\t\t\tright_arrow.bind( 'click', function() {\n\t\t\t\t\twrap_div.children().eq( 0 ).scrollLeft( wrap_div.children().eq( 0 ).scrollLeft() + 500 );\n\t\t\t\t\tsetArrowStatus();\n\t\t\t\t} );\n\t\t\t\tleft_arrow.bind( 'click', function() {\n\t\t\t\t\twrap_div.children().eq( 0 ).scrollLeft( wrap_div.children().eq( 0 ).scrollLeft() - 500 );\n\t\t\t\t\tsetArrowStatus();\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\twrap_div.width( tab_width - nav_width - 25 );\n\t\t\t\twrap_div.children().eq( 0 ).width( tab_width - nav_width - 100 );\n\t\t\t}\n\n\t\t\tif ( tab_bar_label.children().eq( 0 ).is( ':visible' ) && !this.is_mass_editing ) {\n\t\t\t\tthis.edit_view_tab.find( '.tab-arrow' ).show();\n\t\t\t} else {\n\t\t\t\tthis.edit_view_tab.find( '.tab-arrow' ).hide();\n\t\t\t}\n\n\t\t\tsetArrowStatus();\n\n\t\t} else {\n\t\t\ttab_bar_label.width( 'auto' );\n\t\t\tif ( wrap_div.length > 0 ) {\n\t\t\t\ttab_bar_label.insertBefore( wrap_div );\n\t\t\t\twrap_div.remove();\n\n\t\t\t}\n\t\t}\n\n\t\tfunction setArrowStatus() {\n\t\t\tvar left_arrow = $this.edit_view_tab.find( '.tab-left-arrow' );\n\t\t\tvar right_arrow = $this.edit_view_tab.find( '.tab-right-arrow' );\n\t\t\tvar label_wrap = wrap_div.children().eq( 0 );\n\n\t\t\tleft_arrow.removeClass( 'disable-image' );\n\t\t\tright_arrow.removeClass( 'disable-image' );\n\n\t\t\tif ( label_wrap.scrollLeft() === 0 ) {\n\t\t\t\tleft_arrow.addClass( 'disable-image' );\n\t\t\t}\n\n\t\t\t//Ceil and abs required as value can be off by a tiny pixel amount such as 1.2.\n\t\t\tif ( Math.abs( label_wrap.scrollLeft() - Math.ceil( label_wrap[0].scrollWidth - label_wrap.width() ) ) < 2 ) {\n\t\t\t\tright_arrow.addClass( 'disable-image' );\n\t\t\t}\n\n\t\t}\n\t}\n\n\tgetFilterColumnsFromDisplayColumns( column_filter, enable_system_columns ) {\n\t\treturn this._getFilterColumnsFromDisplayColumns( column_filter, enable_system_columns );\n\t}\n\n\t/**\n\t * super for getFilterColumnsFromDisplayColumns\n\t * used when function is overridden by child class.\n\t *\n\t * @param column_filter\n\t * @param enable_system_columns TRUE\n\t * @returns {*}\n\t * @private\n\t */\n\t_getFilterColumnsFromDisplayColumns( column_filter, enable_system_columns ) {\n\t\tif ( !column_filter ) {\n\t\t\tcolumn_filter = {};\n\t\t}\n\n\t\tif ( enable_system_columns == undefined || enable_system_columns == true ) {\n\t\t\tcolumn_filter.is_owner = true;\n\t\t\tcolumn_filter.id = true;\n\t\t\tcolumn_filter.is_child = true;\n\t\t\tcolumn_filter.in_use = true;\n\t\t\tcolumn_filter.first_name = true;\n\t\t\tcolumn_filter.last_name = true;\n\t\t}\n\n\t\tvar display_columns = {};\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( LocalCacheData.view_layout_cache[this.script_name] ) ) {\n\t\t\tvar result = LocalCacheData.view_layout_cache[this.script_name].getResult();\n\t\t\tif ( result != undefined && result.length > 0 ) {\n\t\t\t\tdisplay_columns = result[0].data.display_columns;\n\t\t\t}\n\t\t}\n\n\t\tif ( this.select_layout && this.select_layout.data && this.select_layout.data.display_columns ) {\n\t\t\tfor ( var n in this.select_layout.data.display_columns ) {\n\t\t\t\tdisplay_columns[n] = this.select_layout.data.display_columns[n];\n\t\t\t}\n\t\t}\n\n\t\t//get the default display columns if no columns have been defined.\n\t\tif ( display_columns.length == undefined || ( display_columns.length == 0 && _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.default_display_columns ) ) ) {\n\t\t\tdisplay_columns = this.default_display_columns;\n\t\t}\n\n\t\t//Fixed possible exception -- Error: Unable to get property 'length' of undefined or null reference in /interface/html5/views/BaseViewController.js?v=7.4.3-20140924-090129 line 5031\n\t\tif ( display_columns.length != undefined && display_columns.length > 0 ) {\n\t\t\tvar len = display_columns.length;\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tcolumn_filter[display_columns[i]] = true;\n\t\t\t}\n\t\t}\n\n\t\treturn column_filter;\n\t}\n\n\tgetAllLayouts( callBack ) {\n\n\t\tvar $this = this;\n\n\t\tvar current_select_layout_name;\n\n\t\tif ( this.need_select_layout_name ) {\n\t\t\tcurrent_select_layout_name = this.need_select_layout_name;\n\t\t\tthis.need_select_layout_name = '';\n\t\t} else {\n\t\t\tcurrent_select_layout_name = BaseViewController.default_layout_name;\n\t\t}\n\n\t\t//Issue #3286 - Users without permission to display \"Current View\" dropdown on TimeSheet still need to load select layout from user generic data\n\t\t//This is to ensure the API attempts to update the current layout and not create a new one causing a validation error.\n\t\t//force_get_select_layout still gets the layout data, but does not display it.\n\t\tif ( !this.force_get_select_layout && ( this.sub_view_mode || !this.show_search_tab ) ) {\n\t\t\t$this.select_layout = null;\n\t\t\tif ( callBack ) {\n\t\t\t\tcallBack();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Check view layout cache.\n\t\tif ( LocalCacheData.view_layout_cache[this.script_name] ) {\n\t\t\t//Make this async way\n\t\t\tsetTimeout( function() {\n\t\t\t\tonGetUserGenericDataResult( LocalCacheData.view_layout_cache[$this.script_name] );\n\t\t\t}, 0 );\n\t\t} else {\n\t\t\tif ( !this.user_generic_data_api ) {\n\t\t\t\tthis.user_generic_data_api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APIUserGenericData */ .y.APIUserGenericData;\n\t\t\t}\n\t\t\tthis.user_generic_data_api.getUserGenericData( {\n\t\t\t\tfilter_data: {\n\t\t\t\t\tscript: this.script_name,\n\t\t\t\t\tdeleted: false\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\tonResult: function( results ) {\n\t\t\t\t\tonGetUserGenericDataResult( results );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tfunction onGetUserGenericDataResult( results ) {\n\t\t\tif ( results ) {\n\t\t\t\tvar result_data = results.getResult();\n\t\t\t\t$this.select_layout = null; //Reset select layout;\n\t\t\t\tLocalCacheData.view_layout_cache[$this.script_name] = results;\n\t\t\t\tif ( result_data && result_data.length > 0 ) {\n\t\t\t\t\tresult_data.sort( function( a, b ) {\n\t\t\t\t\t\t\treturn _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.compare */ .x.compare( a, b, 'name' );\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t\tvar len = result_data.length;\n\t\t\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\t\t\tvar layout = result_data[i];\n\t\t\t\t\t\tif ( layout.name === current_select_layout_name ) {\n\t\t\t\t\t\t\t$this.select_layout = layout;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( !$this.select_layout ) {\n\t\t\t\t\t\t$this.select_layout = result_data[0];\n\t\t\t\t\t}\n\t\t\t\t\t$this.search_panel.setLayoutsArray( result_data );\n\t\t\t\t} else {\n\t\t\t\t\t$this.select_layout = null;\n\t\t\t\t\tif ( $this.search_panel ) {\n\t\t\t\t\t\t$this.search_panel.setLayoutsArray( null );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( callBack ) {\n\t\t\t\t\tcallBack();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetAllColumns( callBack ) {\n\t\tvar $this = this;\n\t\tthis.api.getOptions( 'columns', {\n\t\t\tonResult: function( columns_result ) {\n\t\t\t\tvar columns_result_data = columns_result.getResult();\n\n\t\t\t\t$this.all_columns = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.buildColumnArray */ .x.buildColumnArray( columns_result_data );\n\t\t\t\tif ( !$this.sub_view_mode && $this.column_selector ) {\n\t\t\t\t\t$this.column_selector.setUnselectedGridData( $this.all_columns );\n\t\t\t\t\t$this.column_selector.setHeight( $this.all_columns.length * 32 );\n\t\t\t\t}\n\n\t\t\t\tif ( callBack ) {\n\t\t\t\t\tcallBack();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tgetDefaultDisplayColumns( callBack ) {\n\n\t\tvar $this = this;\n\t\tthis.api.getOptions( 'default_display_columns', {\n\t\t\tonResult: function( columns_result ) {\n\n\t\t\t\tvar columns_result_data = columns_result.getResult();\n\n\t\t\t\t$this.default_display_columns = columns_result_data;\n\n\t\t\t\tif ( callBack ) {\n\t\t\t\t\tcallBack();\n\t\t\t\t}\n\n\t\t\t}\n\t\t} );\n\t}\n\n\tbuildSortBySelectColumns() {\n\t\tvar sort_by_array = this.select_layout.data.filter_sort;\n\t\tvar sort_by_select_columns = [];\n\t\tvar sort_by_unselect_columns = this.sort_by_selector.getSourceData();\n\n\t\tif ( sort_by_array ) {\n\t\t\t$.each( sort_by_array, function( index, content ) {\n\n\t\t\t\tfor ( var key in content ) {\n\n\t\t\t\t\t$.each( sort_by_unselect_columns, function( index1, content1 ) {\n\t\t\t\t\t\tif ( content1.value === key ) {\n\t\t\t\t\t\t\tcontent1.sort = content[key];\n\t\t\t\t\t\t\tsort_by_select_columns.push( content1 );\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t} );\n\t\t}\n\n\t\treturn sort_by_select_columns;\n\t}\n\n\tbuildSortSelectorUnSelectColumns( display_columns ) {\n\t\tvar fina_array = [];\n\t\tvar i = 100;\n\t\t$.each( display_columns, function( index, content ) {\n\t\t\tvar new_content = $.extend( {}, content );\n\t\t\tnew_content.id = i; //Need\n\t\t\tnew_content.sort = 'asc';\n\t\t\tfina_array.push( new_content );\n\t\t\ti = i + 1;\n\t\t} );\n\n\t\treturn fina_array;\n\t}\n\n\tbuildDisplayColumns( apiDisplayColumnsArray ) {\n\n\t\tvar len = this.all_columns.length;\n\t\tvar len1 = apiDisplayColumnsArray.length;\n\t\tvar display_columns = [];\n\n\t\tfor ( var j = 0; j < len1; j++ ) {\n\t\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\t\tif ( apiDisplayColumnsArray[j] === this.all_columns[i].value ) {\n\t\t\t\t\tdisplay_columns.push( this.all_columns[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn display_columns;\n\t}\n\n\tbuildDisplayColumnsByColumnModel( colModel ) {\n\n\t\tif ( !colModel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar len = colModel.length;\n\t\tvar display_columns = [];\n\t\tvar id = 2000; // Makse sure the id not duplicate with all_columns, this wiil be used in acombox, set possible columns in navigation mode\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar column = colModel[i];\n\t\t\tif ( column.name === 'cb' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tdisplay_columns.push( { label: column.label, value: column.name, id: id } );\n\t\t\tid = id + 1;\n\t\t}\n\n\t\treturn display_columns;\n\t}\n\n\tremoveContentMenuByName( name ) {\n\t\t// VUE NOTE: This function is for the legacy context menu, this is not for the Vue context menu, as legacy only has to delete a contextmenu from a view, Vue has menus in multiple places instead. See BaseViewController.unmountContextMenu and related functions.\n\n\t\tif ( !LocalCacheData.current_open_primary_controller ) {\n\t\t\treturn;\n\t\t}\n\t\tvar primary_view_id = LocalCacheData.current_open_primary_controller.viewId;\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( name ) ) {\n\t\t\tname = this.context_menu_name;\n\t\t}\n\n\t\tvar tab = $( '#ribbon ul a' ).filter( function() {\n\t\t\treturn $( this ).attr( 'ref' ) === name;\n\t\t} ).parent();\n\n\t\tvar index = $( 'li', $( '#ribbon' ) ).index( tab );\n\t\tif ( index >= 0 ) {\n\t\t\t// $( '#ribbon_view_container' ).tabs( {'remove': index} );\n\t\t\t$( '#ribbon_view_container' ).tabs( 'refresh' );\n\t\t}\n\t}\n\n\tmovePermissionValidate( p_id ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( this.addPermissionValidate( p_id ) && this.deletePermissionValidate( p_id ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tsubAuditValidate() {\n\t\tif ( this.editPermissionValidate() ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tsubDocumentValidate() {\n\t\tif ( ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getProductEdition */ .x.getProductEdition() >= 20 ) && PermissionManager.checkTopLevelPermission( 'Document' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\taddPermissionValidate( p_id ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'add' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetRecordFromGridById( id ) {\n\n\t\tvar data = this.grid.getData();\n\t\tvar result = null;\n\t\t/* jshint ignore:start */\n\t\t//id could be string or number.\n\t\t$.each( data, function( index, value ) {\n\n\t\t\tif ( value.id == id ) {\n\t\t\t\tresult = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( value );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t} );\n\t\t/* jshint ignore:end */\n\t\treturn result;\n\t}\n\n\tgetSelectedItems() {\n\t\tvar $this = this;\n\t\tvar selected_items = [];\n\t\tif ( this.edit_view ) {\n\t\t\tselected_items = [this.current_edit_record];\n\t\t} else {\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tvar grid_selected_length = grid_selected_id_array.length;\n\t\t\tselected_items = _.map( grid_selected_id_array, function( id ) {\n\t\t\t\treturn $this.getRecordFromGridById( id );\n\t\t\t} );\n\t\t}\n\t\treturn selected_items;\n\t}\n\n\tgetSelectedItem() {\n\n\t\tvar selected_item = null;\n\t\tif ( this.edit_view ) {\n\t\t\tselected_item = this.current_edit_record;\n\t\t} else {\n\t\t\tvar grid_selected_id_array = this.getGridSelectIdArray();\n\t\t\tvar grid_selected_length = grid_selected_id_array.length;\n\n\t\t\tif ( grid_selected_length > 0 ) {\n\t\t\t\tselected_item = this.getRecordFromGridById( grid_selected_id_array[0] );\n\t\t\t}\n\n\t\t}\n\n\t\tif ( selected_item ) {\n\t\t\treturn _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.clone */ .x.clone( selected_item );\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tdeleteOwnerOrChildPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !selected_item ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\n\t\t\tPermissionManager.validate( p_id, 'delete' ) ||\n\t\t\t( selected_item && selected_item.is_owner && PermissionManager.validate( p_id, 'delete_own' ) ) ||\n\t\t\t( selected_item && selected_item.is_child && PermissionManager.validate( p_id, 'delete_child' ) ) ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tviewOwnerOrChildPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !selected_item ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif (\n\t\t\tPermissionManager.validate( p_id, 'view' ) ||\n\t\t\t( selected_item && selected_item.is_owner && PermissionManager.validate( p_id, 'view_own' ) ) ||\n\t\t\t( selected_item && selected_item.is_child && PermissionManager.validate( p_id, 'view_child' ) ) ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\t}\n\n\teditOwnerOrChildPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !p_id ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !selected_item ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\n\t\t\tPermissionManager.validate( p_id, 'edit' ) ||\n\t\t\t( selected_item && selected_item.is_owner && PermissionManager.validate( p_id, 'edit_own' ) ) ||\n\t\t\t( selected_item && selected_item.is_child && PermissionManager.validate( p_id, 'edit_child' ) ) ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\t}\n\n\townerOrChildPermissionValidate( p_id, permission_name, selected_item ) {\n\n\t\tvar field;\n\t\tif ( permission_name.indexOf( 'child' ) > -1 ) {\n\t\t\tfield = 'is_child';\n\t\t} else {\n\t\t\tfield = 'is_owner';\n\t\t}\n//\n//\t\tif ( PermissionManager.validate( p_id, permission_name ) &&\n//\t\t\t(!selected_item ||\n//\t\t\t\t( selected_item && (selected_item[field] || (!selected_item.id && !selected_item.hasOwnProperty( field )) ) ) ) ) {\n//\t\t\treturn true;\n//\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, permission_name ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\teditChildPermissionValidate( p_id, selected_item ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !PermissionManager.validate( p_id, 'enabled' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit' ) ||\n\t\t\tthis.ownerOrChildPermissionValidate( p_id, 'edit_child', selected_item ) ) {\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\teditPermissionValidate( p_id, selected_item ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'edit' ) || this.ownerOrChildPermissionValidate( p_id, 'edit_child', selected_item ) || this.ownerOrChildPermissionValidate( p_id, 'edit_own', selected_item ) ) {\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tcopyPermissionValidate( p_id, selected_item ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( this.viewPermissionValidate( p_id, selected_item ) && this.addPermissionValidate( p_id, selected_item ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tcopyAsNewPermissionValidate( p_id, selected_item ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( this.viewPermissionValidate( p_id, selected_item ) && this.addPermissionValidate( p_id, selected_item ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tviewPermissionValidate( p_id, selected_item ) {\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'view' ) || this.ownerOrChildPermissionValidate( p_id, 'view_child', selected_item ) || this.ownerOrChildPermissionValidate( p_id, 'view_own', selected_item ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tdeletePermissionValidate( p_id, selected_item ) {\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( p_id ) ) {\n\t\t\tp_id = this.permission_id;\n\t\t}\n\n\t\tif ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( selected_item ) ) {\n\t\t\tselected_item = this.getSelectedItem();\n\t\t}\n\n\t\tif ( p_id === 'report' ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( PermissionManager.validate( p_id, 'delete' ) || this.ownerOrChildPermissionValidate( p_id, 'delete_child', selected_item ) || this.ownerOrChildPermissionValidate( p_id, 'delete_own', selected_item ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tsaveValidate( context_btn, p_id ) {\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) && !this.is_mass_editing ) {\n\t\t\tif ( !this.addPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t} else if ( ( ( !this.current_edit_record || !this.current_edit_record.id ) && this.is_mass_editing ) || this.current_edit_record.id ) {\n\n\t\t\tif ( !this.editPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t}\n\t}\n\n\tsaveAndCopyValidate( context_btn, p_id ) {\n\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) && !this.is_mass_editing ) {\n\t\t\tif ( !this.addPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t} else if ( ( ( !this.current_edit_record || !this.current_edit_record.id ) && this.is_mass_editing ) || this.current_edit_record.id ) {\n\n\t\t\tif ( !this.editPermissionValidate( p_id ) || !this.addPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t}\n\n\t\tif ( this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsaveAndContinueValidate( context_btn, p_id ) {\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) && !this.is_mass_editing ) {\n\t\t\tif ( !this.addPermissionValidate( p_id ) || !this.editPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t} else if ( ( ( !this.current_edit_record || !this.current_edit_record.id ) && this.is_mass_editing ) || this.current_edit_record.id ) {\n\n\t\t\tif ( !this.editPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t}\n\n\t\tif ( this.showSaveAndContinueOnEditOnly() == false ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tshowSaveAndContinueOnEditOnly() {\n\t\t//By default, views marked as edit_only_mode do not show save and continue.\n\t\t//However, in certain cases we do want to show it, such as when clicking \"Hire Applicant\" on JobApplication view\n\t\tif ( this.edit_only_mode == true && ( this.parent_view_controller && this.viewId === 'Employee' && this.parent_view_controller.viewId === 'JobApplication' ) == false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tsaveAndNewValidate( context_btn, p_id ) {\n\t\tif ( ( !this.current_edit_record || !this.current_edit_record.id ) && !this.is_mass_editing ) {\n\t\t\tif ( !this.addPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t} else if ( ( !_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.current_edit_record.id ) && this.is_mass_editing ) || _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.current_edit_record.id ) ) {\n\n\t\t\tif ( !this.editPermissionValidate( p_id ) || !this.addPermissionValidate( p_id ) ) {\n\t\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t\t}\n\t\t}\n\n\t\tif ( this.edit_only_mode ) {\n\t\t\tContextMenuManager.hideMenuItem( this.determineContextMenuMountAttributes().id, context_btn.id, false )\n\t\t}\n\t}\n\n\tsetSubLogViewFilter() {\n\t\t// #2761 Refactor of setSubLogViewController and setSubViewFilterFunction into setSubLogViewFilter\n\t\t// This refactor is because the key value attributes are linked with the filter.\n\t\t// In general, it was found that either the key value are set, or the filters, but not both. So makes sense to be in the same function. Not confirmed that this is the case in all views, so its not been made into an 'either or' function.\n\n\t\tif ( !this.sub_log_view_controller ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Option #1: filter on single criteria (default)\n\t\tthis.sub_log_view_controller.parent_key = 'object_id';\n\t\tthis.sub_log_view_controller.parent_value = this.uniformVariable( this.current_edit_record ).id;\n\t\tthis.sub_log_view_controller.table_name_key = this.table_name_key;\n\n\t\t// Option #2: filter on multiple criteria.\n\n\t\t// #2761: Filter function appears to only work if parent_key, value and table are null or not set.\n\t\t// Filter structure works similar to pseudo code: WHERE ( table_name = 'punch' AND object_id = '$punch_id') OR ( table_name = 'punch_control' AND object_id = '$punch_control_id' )\n\t\t// key, value, table lines can just be ommitted, as default state is null. Included here for emphasis in example.\n\t\t// this.sub_log_view_controller.parent_key = null;\n\t\t// this.sub_log_view_controller.parent_value = null;\n\t\t// this.sub_log_view_controller.table_name_key = null;\n\t\t// this.sub_log_view_controller.getSubViewFilter = function ( filter ) {\n\t\t// \tfilter['table_name_object_id'] = {\n\t\t// \t\t'punch': [this.parent_edit_record.id],\n\t\t// \t\t'punch_control': [this.parent_edit_record.punch_control_id]\n\t\t// \t};\n\t\t//\n\t\t// \treturn filter;\n\t\t// };\n\n\t\treturn true;\n\t}\n\n\tinitSubLogView( tab_id ) {\n\t\tvar $this = this;\n\n\t\tif ( !this.current_edit_record.id || this.current_edit_record.id == TTUUID.zero_id ) {\n\t\t\tTTPromise.resolve( 'BaseViewController', 'onTabShow' ); //Since search() isn't called in this case, and we just display the \"Please Save This Record ...\" message, resolve the promise.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.sub_log_view_controller ) {\n\t\t\t// If the Audit tab has already been opened before in this edit view.\n\t\t\tthis.sub_log_view_controller.buildContextMenu( true );\n\t\t\tthis.sub_log_view_controller.setDefaultMenu();\n\t\t\tthis.sub_log_view_controller.parent_edit_record = this.current_edit_record;\n\t\t\tthis.setSubLogViewFilter(); // triggers the setting of the filter function for views that need it.\n\t\t\t// $this.sub_log_view_controller.parent_key = 'object_id';\n\t\t\t// $this.sub_log_view_controller.parent_value = $this.current_edit_record.id;\n\t\t\t// $this.sub_log_view_controller.table_name_key = $this.table_name_key;\n\n\t\t\tthis.sub_log_view_controller.search();\n\t\t} else {\n\t\t\t// If the Audit tab has NOT yet been opened before in this edit view.\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadScript */ .x.loadScript( 'views/core/log/LogViewController.js', function() {\n\t\t\t\tif ( !$this.edit_view_tab ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvar tab = $this.edit_view_tab.find( '#' + tab_id );\n\t\t\t\tvar firstColumn = tab.find( '.first-column-sub-view' );\n\n\t\t\t\tTTPromise.add( 'initSubAudit', 'init' );\n\t\t\t\tTTPromise.wait( 'initSubAudit', 'init', function() {\n\t\t\t\t\tfirstColumn.css( 'opacity', '1' );\n\t\t\t\t} );\n\n\t\t\t\tfirstColumn.css( 'opacity', '0' ); //Hide the grid while its loading/sizing.\n\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.trackView */ .x.trackView( 'Sub' + 'Log' + 'View', LocalCacheData.current_doing_context_action );\n\t\t\t\tLogViewController.loadSubView( firstColumn, beforeLoadView, afterLoadView );\n\t\t\t} );\n\t\t}\n\n\t\tfunction beforeLoadView() {\n\n\t\t}\n\n\t\tfunction afterLoadView( subViewController ) {\n\t\t\t$this.sub_log_view_controller = subViewController;\n\t\t\t$this.sub_log_view_controller.parent_view_controller = $this;\n\t\t\t$this.sub_log_view_controller.parent_edit_record = $this.current_edit_record;\n\t\t\t$this.setSubLogViewFilter(); // triggers the setting of the filter function for views that need it.\n\t\t\t// $this.sub_log_view_controller.parent_key = 'object_id';\n\t\t\t// $this.sub_log_view_controller.parent_value = $this.current_edit_record.id;\n\t\t\t// $this.sub_log_view_controller.table_name_key = $this.table_name_key;\n\n\t\t\t$this.sub_log_view_controller.postInit = function() {\n\t\t\t\tthis.initData();\n\t\t\t};\n\n\t\t}\n\t}\n\n\tshowNoResultCover( show_new_btn ) {\n\t\tif ( !show_new_btn ) {\n\t\t\tshow_new_btn = this.ifContextButtonExist( 'add' );\n\t\t}\n\n\t\tthis.removeNoResultCover();\n\t\tthis.no_result_box = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadWidgetByName */ .x.loadWidgetByName( _global_widgets_search_panel_FormItemType__WEBPACK_IMPORTED_MODULE_2__.WidgetNamesDic.NO_RESULT_BOX );\n\t\tthis.no_result_box.NoResultBox( { related_view_controller: this, is_new: show_new_btn } );\n\t\tthis.no_result_box.attr( 'id', this.ui_id + '_no_result_box' );\n\n\t\tvar grid_div = $( this.el ).find( '.grid-div' );\n\n\t\tgrid_div.append( this.no_result_box );\n\n\t\tthis.initRightClickMenu( RightClickMenuType.NORESULTBOX );\n\t}\n\n\tremoveNoResultCover() {\n\n\t\tif ( this.no_result_box && this.no_result_box.length > 0 ) {\n\t\t\tthis.no_result_box.remove();\n\t\t}\n\t\tthis.no_result_box = null;\n\t}\n\n\tcleanWhenUnloadView( callBack ) {\n\t\tthis.unmountContextMenu(); // This is just in case, contextmenu should already be unmounted in IndexController.removeCurrentView\n\t\tthis.removeContentMenuByName();\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( callBack ) ) {\n\t\t\tcallBack();\n\t\t}\n\t}\n\n\tgridScrollTop() {\n\n\t\tif ( this.viewId === 'TimeSheet' || this.viewId === 'Schedule' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.grid ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.grid.grid.parent().parent().scrollTop( 0 );\n\t}\n\n\tgridScrollDown() {\n\n\t\tif ( this.viewId === 'TimeSheet' || this.viewId === 'Schedule' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.grid ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.grid.grid.parent().parent().scrollTop( 10000 );\n\t}\n\n\tselectAll() {\n\t\tif ( this.viewId === 'TimeSheet' || this.viewId === 'Schedule' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.grid ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.grid.grid.resetSelection();\n\t\tvar source_data = this.grid.getData();\n\t\tvar len = source_data.length;\n\t\tfor ( var i = 0; i < len; i++ ) {\n\t\t\tvar item = source_data[i];\n\t\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( item.id ) ) {\n\t\t\t\tthis.grid.grid.setSelection( item.id, false );\n\t\t\t} else {\n\t\t\t\tthis.grid.grid.setSelection( i + 1, false );\n\t\t\t}\n\n\t\t}\n\n\t\tthis.grid.grid.parent().parent().parent().find( '.cbox-header' ).prop( 'checked', true );\n\t\tthis.setDefaultMenu();\n\t}\n\n\tdetachElement( key ) {\n\t\t//Error: Uncaught TypeError: Cannot read property 'detach' of undefined in interface/html5/views/BaseViewController.js?v=9.0.0-20150824-110300 line 6441\n\t\tif ( !this.edit_view_form_item_dic || !this.edit_view_form_item_dic[key] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar place_holder = $( '<p style=\"display: none\">' );\n\t\tplace_holder.addClass( '.edit-view:visible place_holder_' + key );\n\t\tplace_holder.insertBefore( this.edit_view_form_item_dic[key] );\n\t\tthis.edit_view_form_item_dic[key].detach();\n\t}\n\n\tattachElement( key ) {\n\t\t//Error: Uncaught TypeError: Cannot read property 'insertBefore' of undefined in interface/html5/views/BaseViewController.js?v=9.0.0-20150822-210544 line 6439\n\t\tif ( !this.edit_view_form_item_dic || !this.edit_view_form_item_dic[key] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//var place_holder = $( '.edit-view:visible .edit-view-tab:visible .place_holder_' + key);\n\t\tvar place_holder = $( '.edit-view:visible .place_holder_' + key );\n\t\tthis.edit_view_form_item_dic[key].insertBefore( place_holder );\n\t\tplace_holder.remove();\n\t}\n\n\tgetBalanceHandler( result, last_date_stamp ) {\n\t\tvar $this = this;\n\t\tvar available_balance_value, current_time_value, remaining_balance_value, summary_available_value;\n\n\t\t//Error: TypeError: this.edit_view_ui_dic.available_balance is undefined in /interface/html5/framework/jquery.min.js?v=8.0.0-20141117-091433 line 2 > eval line 6570\n\t\tif ( !$this.edit_view_ui_dic || !$this.edit_view_ui_dic['available_balance'] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isObject */ .x.isObject( result ) ) {\n\t\t\tvar result_data = result.getResult();\n\t\t\tif ( !result_data ) {\n\t\t\t\t$this.detachElement( 'available_balance' );\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t$this.detachElement( 'available_balance' );\n\t\t\treturn;\n\t\t}\n\t\t$this.attachElement( 'available_balance' );\n\n\t\tavailable_balance_value = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getTimeUnit */ .x.getTimeUnit( result_data.available_balance );\n\t\tcurrent_time_value = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getTimeUnit */ .x.getTimeUnit( result_data.current_time );\n\t\tremaining_balance_value = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getTimeUnit */ .x.getTimeUnit( result_data.remaining_balance );\n\t\tsummary_available_value = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getTimeUnit */ .x.getTimeUnit( result_data.projected_remaining_balance );\n\t\tif ( result_data.hasOwnProperty( 'remaining_dollar_balance' ) ) {\n\t\t\tavailable_balance_value = available_balance_value + ' / ' + LocalCacheData.getCurrentCurrencySymbol() + result_data.available_dollar_balance;\n\t\t\tcurrent_time_value = current_time_value + ' / ' + LocalCacheData.getCurrentCurrencySymbol() + result_data.current_dollar_amount;\n\t\t\tremaining_balance_value = remaining_balance_value + ' / ' + LocalCacheData.getCurrentCurrencySymbol() + result_data.remaining_dollar_balance;\n\t\t\tsummary_available_value = summary_available_value + ' / ' + LocalCacheData.getCurrentCurrencySymbol() + result_data.remaining_dollar_balance;\n\t\t}\n\t\t$this.edit_view_ui_dic['available_balance'].setValue( summary_available_value );\n\n\t\t//If available balance is negative, change font color to red so its more noticable.\n\t\tif ( result_data.projected_remaining_balance < 0 ) {\n\t\t\t$this.edit_view_ui_dic['available_balance'].css( 'color', 'red' ); //Font color to red.\n\t\t} else {\n\t\t\t$this.edit_view_ui_dic['available_balance'].css( 'color', 'black' );\n\t\t}\n\n\t\tif ( $this.available_balance_info ) {\n\t\t\t$this.available_balance_info.qtip(\n\t\t\t\t{\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tevent: 'click',\n\t\t\t\t\t\tdelay: 10,\n\t\t\t\t\t\teffect: true\n\t\t\t\t\t},\n\n\t\t\t\t\thide: {\n\t\t\t\t\t\tevent: ['unfocus click'],\n\t\t\t\t\t},\n\t\t\t\t\tstyle: {\n\t\t\t\t\t\t//classes: 'cream',\n\t\t\t\t\t\twidth: 340 //Dynamically changing the width causes display bugs when switching between Absence Policies and thereby widths.\n\t\t\t\t\t},\n\t\t\t\t\tcontent: '<div style=\"width:100%;\">' +\n\t\t\t\t\t\t'<div style=\"width:100%; clear: both;\"><span style=\"float:left;\">' + $.i18n._( 'Available Balance' ) + ': </span><span style=\"float:right;\">' + available_balance_value + '</span></div>' +\n\t\t\t\t\t\t'<div style=\"width:100%; clear: both;\"><span style=\"float:left;\">' + $.i18n._( 'Current Time' ) + ': </span><span style=\"float:right;\">' + current_time_value + '</span></div>' +\n\t\t\t\t\t\t'<div style=\"width:100%; clear: both;\"><span style=\"float:left;\">' + $.i18n._( 'Remaining Balance' ) + ': </span><span style=\"float:right;\">' + remaining_balance_value + '</span></div>' +\n\t\t\t\t\t\t'<div style=\"width:100%; height: 20px; clear: both;\"></div>' +\n\t\t\t\t\t\t'<div style=\"width:100%; clear: both;\"><span style=\"float:left;\">' + $.i18n._( 'Projected Balance by' ) + ' ' + last_date_stamp + ': </span><span style=\"float:right;\">' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getTimeUnit */ .x.getTimeUnit( result_data.projected_balance ) + '</span></div>' +\n\t\t\t\t\t\t'<div style=\"width:100%; clear: both;\"><span style=\"float:left;\">' + $.i18n._( 'Projected Remaining Balance' ) + ':</span><span style=\"float:right;\">' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getTimeUnit */ .x.getTimeUnit( result_data.projected_remaining_balance ) + '</span></div>' +\n\t\t\t\t\t\t'</div>'\n\t\t\t\t} );\n\t\t}\n\t}\n\n\tonExportClick( method ) {\n\t\tProgressBar.showOverlay();\n\t\tif ( method == undefined ) {\n\t\t\tmethod = this.api['export' + this.api.key_name];\n\t\t}\n\n\t\t//Debug.Text('Exporting Grid To CSV: '+method, 'BaseViewController.js', 'BaseViewController', 'onExportClick', 10);\n\n\t\tvar args = {};\n\t\targs.filter_columns = this._getFilterColumnsFromDisplayColumns( null, false );\n\t\targs.filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertLayoutFilterToAPIFilter */ .x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isSet */ .x.isSet( this.sort_by_selector ) ) {\n\t\t\targs.filter_sort = this.getSearchPanelSortFilter();\n\t\t}\n\t\tvar post_data = { 0: 'csv', 1: args, 2: true };\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.APIFileDownload */ .x.APIFileDownload( this.api.className, method, post_data );\n\t}\n\n\thighLightGridRowById( id ) {\n\t\tif ( this.grid && this.grid.grid ) {\n\t\t\tthis.grid.grid.find( 'tr#' + id ).addClass( 'flashBackground' );\n\t\t\tthis.gridScrollDown();\n\t\t}\n\t}\n\n\tsetConversionRateExampleText( conversion_rate, iso_code, currency_id ) {\n\t\tvar data = {};\n\t\tdata.filter_data = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.convertLayoutFilterToAPIFilter */ .x.convertLayoutFilterToAPIFilter( this.select_layout );\n\t\tvar api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APICurrency */ .y.APICurrency;\n\t\tvar my_currencies = api.getCurrency( data, { async: false } ).getResult();\n\t\tvar base_currency_iso_code = '';\n\t\tif ( this.edit_view_ui_dic.round_decimal_places ) {\n\t\t\tvar decimal_places = this.edit_view_ui_dic.round_decimal_places.getValue();\n\t\t}\n\t\tfor ( var i = 0; i < my_currencies.length; i++ ) {\n\t\t\tif ( my_currencies[i].is_base ) {\n\t\t\t\tbase_currency_iso_code = my_currencies[i].iso_code;\n\n\t\t\t}\n\t\t\tif ( currency_id && !iso_code && my_currencies[i].id == currency_id ) {\n\t\t\t\tiso_code = my_currencies[i].iso_code;\n\t\t\t\tif ( !decimal_places ) {\n\t\t\t\t\tdecimal_places = my_currencies[i].round_decimal_places;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//need different id on the subview for rate.\n\t\tif ( iso_code != base_currency_iso_code ) {\n\t\t\tif ( this.sub_view_mode ) {\n\t\t\t\t$( '#rate_conversion_rate_clarification_box' ).html( '&nbsp;&nbsp;1.00 ' + base_currency_iso_code + ' = ' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.removeTrailingZeros */ .x.removeTrailingZeros( conversion_rate, decimal_places ) + ' ' + iso_code );\n\t\t\t} else {\n\t\t\t\t$( '#conversion_rate_clarification_box' ).html( '&nbsp;&nbsp;1.00 ' + base_currency_iso_code + ' = ' + _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.removeTrailingZeros */ .x.removeTrailingZeros( conversion_rate, decimal_places ) + ' ' + iso_code );\n\t\t\t}\n\t\t} else {\n\t\t\t$( '#conversion_rate_clarification_box' ).hide();\n\t\t}\n\t}\n\n\t/**\n\t * gets default coordinates object for maps.\n\t */\n\tstartMapCoordinates() {\n\t\tvar lat = 39.50;\n\t\tvar lng = -98.35;\n\n\t\tif ( LocalCacheData.getCurrentCompany().latitude != 0 && LocalCacheData.getCurrentCompany().longitude != 0 ) {\n\t\t\tlat = LocalCacheData.getCurrentCompany().latitude;\n\t\t\tlng = LocalCacheData.getCurrentCompany().longitude;\n\t\t\tDebug.Text( 'Using company coordinates.', 'BaseViewController.js', 'BaseViewController', 'startMapCoordinates', 10 );\n\t\t} else if ( LocalCacheData.getLoginUser().latitude != 0 && LocalCacheData.getLoginUser().longitude != 0 ) {\n\t\t\tlat = LocalCacheData.getLoginUser().latitude;\n\t\t\tlng = LocalCacheData.getLoginUser().longitude;\n\t\t\tDebug.Text( 'Using user coordinates.', 'BaseViewController.js', 'BaseViewController', 'startMapCoordinates', 10 );\n\t\t} else {\n\t\t\tvar company_api = _services_TimeTrexClientAPI__WEBPACK_IMPORTED_MODULE_1__/* .TTAPI.APICompany */ .y.APICompany;\n\t\t\tvar country_arr = company_api.getOptions( 'country', { async: false } ).getResult();\n\t\t\tvar province_arr = company_api.getOptions( 'province', LocalCacheData.getCurrentCompany().country, { async: false } ).getResult();\n\n\t\t\tif ( APIGlobal.pre_login_data.map_geocode_url && province_arr && country_arr && province_arr[LocalCacheData.getCurrentCompany().province] && country_arr[LocalCacheData.getCurrentCompany().country] ) {\n\t\t\t\tvar query = LocalCacheData.getCurrentCompany().city + ' ' + province_arr[LocalCacheData.getCurrentCompany().province] + ', ' + country_arr[LocalCacheData.getCurrentCompany().country];\n\t\t\t\tvar url = APIGlobal.pre_login_data.map_geocode_url + '?q=' + query + '&format=json&tt_key=' + APIGlobal.pre_login_data.registration_key;\n\t\t\t\tvar result = jQuery.ajax( { url: url, async: false } );\n\t\t\t\tDebug.Arr( 'Geocoding address: ' + query, result, 'BaseViewController.js', 'BaseViewController', 'startMapCoordinates', 10 );\n\t\t\t}\n\n\t\t\tif ( result && result.responseJSON && result.responseJSON[0] && result.responseJSON[0].lat && result.responseJSON[0].lon ) {\n\t\t\t\tlat = result.responseJSON[0].lat;\n\t\t\t\tlng = result.responseJSON[0].lon;\n\t\t\t\tDebug.Text( 'Using company address coordinates.', 'BaseViewController.js', 'BaseViewController', 'startMapCoordinates', 10 );\n\t\t\t} else {\n\t\t\t\tDebug.Text( 'Using default coordinates.', 'BaseViewController.js', 'BaseViewController', 'startMapCoordinates', 10 );\n\t\t\t}\n\t\t}\n\n\t\tDebug.Text( 'Coordinates (lat,long): ' + lat + ',' + lng, 'BaseViewController.js', 'BaseViewController', 'startMapCoordinates', 10 );\n\t\treturn new L.LatLng( lat, lng );\n\t}\n\n\tinitSubDocumentView() {\n\t\tvar $this = this;\n\n\t\tif ( !this.current_edit_record.id ) {\n\t\t\tTTPromise.resolve( 'BaseViewController', 'onTabShow' ); //Since search() isn't called in this case, and we just display the \"Please Save This Record ...\" message, resolve the promise.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.sub_document_view_controller ) {\n\t\t\tthis.sub_document_view_controller.buildContextMenu( true );\n\t\t\tthis.sub_document_view_controller.setDefaultMenu();\n\t\t\t$this.sub_document_view_controller.parent_value = $this.current_edit_record.id;\n\t\t\t$this.sub_document_view_controller.parent_edit_record = $this.current_edit_record;\n\t\t\t$this.sub_document_view_controller.initData();\n\t\t\treturn;\n\t\t}\n\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadScript */ .x.loadScript( 'views/document/DocumentViewController.js', function() {\n\t\t\tif ( !$this.edit_view_tab ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar tab_contact_info = $this.edit_view_tab.find( '#tab_attachment' );\n\t\t\tvar firstColumn = tab_contact_info.find( '.first-column-sub-view' );\n\n\t\t\tTTPromise.add( 'initSubDocumentView', 'init' );\n\t\t\tTTPromise.wait( 'initSubDocumentView', 'init', function() {\n\t\t\t\tfirstColumn.css( 'opacity', '1' );\n\t\t\t} );\n\n\t\t\tfirstColumn.css( 'opacity', '0' ); //Hide the grid while its loading/sizing.\n\n\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.trackView */ .x.trackView( 'SubDocumentView' );\n\t\t\tDocumentViewController.loadSubView( firstColumn, beforeLoadView, afterLoadView );\n\n\t\t} );\n\n\t\tfunction beforeLoadView() {\n\n\t\t}\n\n\t\tfunction afterLoadView( subViewController ) {\n\t\t\t$this.sub_document_view_controller = subViewController;\n\t\t\t$this.sub_document_view_controller.parent_key = 'object_id';\n\t\t\t$this.sub_document_view_controller.parent_value = $this.current_edit_record.id;\n\t\t\t$this.sub_document_view_controller.document_object_type_id = $this.document_object_type_id;\n\t\t\t$this.sub_document_view_controller.parent_edit_record = $this.current_edit_record;\n\t\t\t$this.sub_document_view_controller.parent_view_controller = $this;\n\t\t\t$this.sub_document_view_controller.initData();\n\t\t}\n\t}\n\n\tonDeleteImage( callback ) {\n\t\tvar $this = this;\n\t\tthis.api.deleteImage( this.current_edit_record.id, {\n\t\t\tonResult: function( result ) {\n\t\t\t\t$this.onEditClick( $this.current_edit_record.id, true );\n\t\t\t}\n\t\t} );\n\t}\n\n\tonTreeGridNavigationRowSelect( id ) {\n\t\tif ( !id ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//don't close on collapse of tree mode element\n\t\tif ( LocalCacheData.currently_collapsing_navigation_tree_element != true ) {\n\t\t\tthis.onEditClick( id );\n\t\t\t$( '.a-dropdown-div' ).remove();\n\t\t\tLocalCacheData.openAwesomeBox = null;\n\t\t} else {\n\t\t\tLocalCacheData.currently_collapsing_navigation_tree_element = false;\n\t\t\tthis.onEditClick( id, true );\n\t\t\tthis.setNavigation();\n\t\t}\n\t}\n\n\tparserDatesRange( date ) {\n\t\tvar dates = date.split( \" - \" );\n\t\tvar resultArray = [];\n\t\tvar beginDate = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.strToDate */ .x.strToDate( dates[0] );\n\t\tvar endDate = _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.strToDate */ .x.strToDate( dates[1] );\n\n\t\tvar nextDate = beginDate;\n\n\t\twhile ( nextDate.getTime() < endDate.getTime() ) {\n\t\t\tresultArray.push( nextDate.format() );\n\t\t\tnextDate = new Date( new Date( nextDate.getTime() ).setDate( nextDate.getDate() + 1 ) );\n\t\t}\n\n\t\tresultArray.push( dates[1] );\n\n\t\treturn resultArray;\n\t}\n\n\tbaseViewSubTabGridResize( id ) {\n\t\tvar $this = this;;\n\n\t\tif ( !id ) {\n\t\t\tid = '.edit-view-tab-outside-sub-view';\n\t\t} else if ( id.indexOf( '#' ) === -1 && id.indexOf( '.' ) != 0 ) {\n\t\t\tid = '#' + id;\n\t\t}\n\n\t\tif ( this.grid.grid.parents( id ).length > 0 ) {\n\n\t\t\tvar height = Math.floor( this.getAvailableHeightForGrid( id ) );\n\n\t\t\tthis.grid.setup.container_selector = id;\n\n\t\t\tDebug.Text( 'Special SubView ID: ' + id + ' Height: ' + height + ' Offset: ' + offset, 'TTGrid.js', 'TTGrid', 'baseViewSubTabGridResize', 10 );\n\t\t} else {\n\t\t\tvar offset = this.getDefaultHeightOffset();\n\t\t\tvar height = ( this.grid.grid.parents( '.edit-view-tab' ).innerHeight() - offset );\n\n\t\t\tDebug.Text( 'Normal SubView ID: ' + id + ' Height: ' + height + ' Offset: ' + offset, 'TTGrid.js', 'TTGrid', 'baseViewSubTabGridResize', 10 );\n\t\t}\n\n\t\tif ( height < 250 ) {\n\t\t\theight = 250;\n\t\t}\n\n\t\tthis.setGridHeight( height );\n\t\tthis.setGridWidth();\n\t}\n\n\t/**\n\t * Sets the grid's height.\n\t * @param ui_id\n\t * @param sub_view_mode\n\t * @param sub_view_grid_autosize\n\t * @param pager_data\n\t */\n\tsetGridSize( ui_id, sub_view_mode, sub_view_grid_autosize, pager_data ) {\n\t\tvar $this = this;\n\t\tif ( this.grid && this.grid.setup && this.grid.setup.setGridSize && typeof this.grid.setup.setGridSize == 'function' ) {\n\t\t\tthis.grid.setup.setGridSize();\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ( !ui_id && !this.ui_id ) || !this.grid ) {\n\t\t\tDebug.Text( 'ERROR: You must provide at least a ui_id for setGridSize()', 'TTGrid.js', 'TTGrid', 'setGridSize', 10 );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !ui_id && this.ui_id ) {\n\t\t\tui_id = this.ui_id;\n\t\t}\n\n\t\tif ( !sub_view_mode && this.sub_view_mode ) {\n\t\t\tsub_view_mode = this.sub_view_mode;\n\t\t}\n\n\t\tif ( !sub_view_grid_autosize && this.sub_view_grid_autosize ) {\n\t\t\tsub_view_grid_autosize = this.sub_view_grid_autosize;\n\t\t}\n\n\t\t//this.setGridWidth ( this.setGridColumnsWidth() );\n\n\t\tvar height = 100;\n\n\t\tif ( sub_view_mode &&\n\t\t\tthis.grid.grid.parents( '.grid-div' ).find( '.no-result-div:visible' ).length > 0 &&\n\t\t\tthis.grid.grid.parents( '#tab_history, #tab_qualifications' ).length > 0\n\t\t) {\n\t\t\theight = 100;\n\t\t} else if ( this.grid.setup.static_height ) {\n\t\t\theight = this.grid.setup.static_height;\n\t\t} else if ( this.grid.setup.verticalResize && this.grid.setup.verticalResize === true ) {\n\t\t\tif ( sub_view_mode ) {\n\t\t\t\tif ( this.grid.grid.parents( '.edit-view-tab-outside-sub-view' ).find( '.context-border' ).length > 1 || this.grid.grid.parents( '.edit-view-tab-outside-sub-view' ).find( '.ui-jqgrid-htable' ).length > 1 ) {\n\t\t\t\t\t//This tab has multiple grids or sub views.\n\t\t\t\t\t//Tabs like this are \"Employee -> Edit Employee -> Qualifications\" or Recruitment -> Job Applicant History and Qualification tab with multiple grids.\n\n\t\t\t\t\tlet length = this.grid.getRecordCount();\n\t\t\t\t\tlet cell_height = this.grid.grid.find( 'tr:last td:first' ).height();\n\n\t\t\t\t\tif ( cell_height < 18 ) { //If cannot determine cell height, use default of 22.\n\t\t\t\t\t\tcell_height = 22;\n\t\t\t\t\t}\n\n\t\t\t\t\t//Grid height is between 3 and 6 rows. Nothing too small or tall so that all grids can be viewed easily\n\t\t\t\t\tlet rows_to_show = 3;\n\t\t\t\t\tif ( length > 6 ) {\n\t\t\t\t\t\trows_to_show = 6;\n } else if ( length > 3 ) {\n\t\t\t\t\t\trows_to_show = length;\n }\n\n\t\t\t\t\theight = ( rows_to_show * cell_height );\n\t\t\t\t} else {\n\t\t\t\t\t//Normal single grid sub view.\n\t\t\t\t\tif ( this.grid.grid.parents( '.edit-view-tab-outside-sub-view' ) && this.grid.grid.parents( '.edit-view-tab-outside-sub-view' ).length > 0 && this.grid.grid.parents( '.edit-view-tab-outside-sub-view' )[0] ) {\n\t\t\t\t\t\theight = this.getAvailableHeightForGrid( this.grid.grid.parents( '.edit-view-tab-outside-sub-view' )[0].id );\n\n\t\t\t\t\t\tlet child_context_border = this.grid.grid.parents( '.edit-view-tab-outside-sub-view' ).find( '.context-border' );\n\t\t\t\t\t\tif ( child_context_border.length !== 0 ) {\n\t\t\t\t\t\t\t//Adjust height by margins of the context border.\n\t\t\t\t\t\t\theight -= ( child_context_border.outerHeight( true ) - child_context_border.innerHeight() );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\theight = this.getAvailableHeightForGrid( ui_id );\n\t\t\t}\n\t\t}\n\n\t\t//Ensure grid has a minimum height.\n\t\tif ( height < 100 ) {\n\t\t\theight = 100;\n\t\t}\n\n\t\tthis.grid.grid.setGridHeight( height );\n\n\t\t//this looks odd, but css does not have a has selector.\n\t\t$( '.sub-view .bottom-div:has(.paging-2-div:visible)' ).css( 'height', '20px' );\n\t\t$( '.sub-view .bottom-div:has(.paging-2-div:hidden)' ).css( 'height', 'auto' );\n\t\t//this.reloadGrid(); //slows down awesomeboxes\n\t}\n\n\tgetAvailableHeightForGrid( element_id, offset ) {\n\t\t//The available height for the table is the view height minus the difference between top of view and bottom of table header.\n\t\tif ( element_id.indexOf( '#' ) === -1 && element_id.indexOf( '.' ) != 0 ) {\n\t\t\telement_id = '#' + element_id;\n\t\t}\n\t\tlet table_header = $( element_id ).find( '#gbox_' + this.grid.getGridId() + ' .ui-jqgrid-labels' );\n\t\tif ( table_header.length === 0 ) {\n\t\t\t//Issue #3120 - Certain sub views have grid in a different part of the DOM.\n\t\t\t//Need to make sure to check for that else the grid will be given an incorrect or 0 height;\n\t\t\ttable_header = $( '#gbox_' + this.grid.getGridId() + ' .ui-jqgrid-labels' );\n\t\t\tif ( table_header.length === 0 ) {\n\t\t\t\treturn 100; //Default height.\n\t\t\t}\n\t\t}\n\n\t\tlet container_height = $( element_id ).children('.context-border').length !== 0 ? $( element_id ).children('.context-border').innerHeight() : $( element_id ).height();\n\t\tlet height = container_height - ( ( table_header.offset().top + table_header.height() ) - $( element_id ).offset().top );\n\n\t\t//Check if view has a paging / bottom div and adjust grid height accordingly.\n\t\tlet bottom_div = $( element_id ).find( '.bottom-div' );\n\t\tif ( bottom_div.length > 0 && bottom_div.is(\":visible\") ) {\n height -= 50;\n }\n\n\t\tif ( _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.isHorizontalScrollBarRequired */ .x.isHorizontalScrollBarRequired( $( '#gbox_' + this.grid.getGridId() )[0] ) ) { //pass dom element not jquery object\n\t\t\theight -= _global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.getScrollbarHeight */ .x.getScrollbarHeight();\n\t\t}\n\n\t\treturn height;\n\t}\n\n\tgetDefaultHeightOffset() {\n\t\t//protect against NaNs\n\n\t\tvar offset = this.grid.grid.parents( '.ui-jqgrid-jquery-ui' ).find( '.ui-jqgrid-hbox' ).height() - 22; // 22 is default cell height. we just want the overage here.\n\t\tDebug.Text( 'Initial offset: ' + offset, 'BaseViewController.js', 'BaseViewController', 'getDefaultHeightOffset', 10 );\n\n\t\t//getting these selectors right for every grid was a lot of trial and error.\n\t\tif ( this.grid.grid.parents( '.ui-jqgrid-bdiv' ).width() > this.grid.grid.parents( '.ui-jqgrid-jquery-ui' ).width() ) {\n\t\t\toffset += 15; //scrollbar offset\n\t\t\tDebug.Text( 'Scrollbar offset detected: 15', 'BaseViewController.js', 'BaseViewController', 'getDefaultHeightOffset', 10 );\n\t\t}\n\n\t\tif ( this.search_panel && this.search_panel.is( ':visible' ) == true ) {\n\t\t\toffset += this.search_panel.height();\n\t\t\tDebug.Text( 'Search panel detected: ' + this.search_panel.height(), 'BaseViewController.js', 'BaseViewController', 'getDefaultHeightOffset', 10 );\n\t\t}\n\n\t\tvar total_number_div_height = ( $( '.total-number-div:visible' ).length > 0 ) ? $( '.total-number-div:visible' ).height() : 0;\n\t\tif ( total_number_div_height || total_number_div_height === 0 ) {\n\t\t\toffset += total_number_div_height;\n\t\t\tDebug.Text( 'Total number DIV height offset detected: ' + $( '.total-number-div:visible' ).height(), 'BaseViewController.js', 'BaseViewController', 'getDefaultHeightOffset', 10 );\n\t\t}\n\n\t\tvar footer_height = $( '.bottom-div' ).height() + 5;\n\t\tif ( footer_height || footer_height === 0 ) {\n\t\t\toffset += footer_height;\n\t\t\tDebug.Text( 'Footer height offset detected: ' + footer_height, 'BaseViewController.js', 'BaseViewController', 'getDefaultHeightOffset', 10 );\n\t\t}\n\n\t\tvar red_border_height = $( '.grid-top-border' ).height() * 2;\n\t\tif ( red_border_height || red_border_height === 0 ) {\n\t\t\toffset += red_border_height;\n\t\t\tDebug.Text( 'Red border height offset detected: ' + red_border_height, 'BaseViewController.js', 'BaseViewController', 'getDefaultHeightOffset', 10 );\n\t\t}\n\n\t\treturn offset;\n\t}\n\n\tfillCurrentRecord() {\n\t\t// Overrides form with data from push notification and http get variables.\n\t\tif ( LocalCacheData.getAutoFillData() ) {\n\t\t\tthis.current_edit_record = Object.assign( this.current_edit_record, this.filterAutoFillData( LocalCacheData.auto_fill_data ) );\n\t\t\tLocalCacheData.setAutoFillData( null );\n\t\t}\n\n\t\t// Filter http get variables.\n\t\tvar filtered_auto_fill_data = this.filterAutoFillData( LocalCacheData.all_url_args );\n\n\t\t// Remove common variables from url to prevent unintended overrides.\n\t\tfor ( var key in filtered_auto_fill_data ) {\n\t\t\tif ( key === 'sid' || key === 'm' || key === 'sm' || key === 'tab' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.current_edit_record[key] = filtered_auto_fill_data[key];\n\t\t}\n\t}\n\n\tfilterAutoFillData( auto_fill_data ) {\n\t\t// Auto fill variables only override data if the field exists on UI.\n\t\t// Helps prevent invisible changes in current_edit_record from users sharing links with purpose to trick/exploit.\n\n\t\tvar filtered_auto_fill_data = {};\n\t\tfor ( var key in auto_fill_data ) {\n\n\t\t\t// Ignore password fields\n\t\t\tif ( key.includes( 'password' ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( this.edit_view_ui_dic.hasOwnProperty( key ) ) {\n\t\t\t\tfiltered_auto_fill_data[key] = auto_fill_data[key];\n\t\t\t}\n\t\t}\n\t\treturn filtered_auto_fill_data;\n\t}\n\n\t//Compare two arrays of records and return an array of records that changed.\n\tgetChangedRecords( new_data, old_data, ignored_keys ) {\n\t\tlet changed_data = new_data.filter( ( record ) => {\n\n\t\t\tlet old_record = old_data.find( ( old_item ) => old_item.id == record.id );\n\t\t\t//If record id does not exist in old_data, it is a new record and should be marked as changed.\n\t\t\tif ( !old_record ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t//Compare each key for changed data. Loop over the keys in the current record and not old incase a new key was added that is not in the old record.\n\t\t\tfor ( let keys in record ) {\n\t\t\t\t//Some views add extra data to the record which is only used locally and should not be used for comparison.\n\t\t\t\tif ( ignored_keys.length > 0 && ignored_keys.includes( keys ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t//If the value is an array check each value exists in the old record array.\n\t\t\t\tif ( Array.isArray( record[keys] ) && Array.isArray( old_record[keys] ) ) {\n\t\t\t\t\t//If the arrays are different lengths, we know they are different, and do not need to check the values.\n\t\t\t\t\tif ( record[keys].length !== old_record[keys].length || !record[keys].every( value => old_record[keys].includes( value ) ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//Compare values of each key in the record.\n\t\t\t\telse if ( record[keys] != old_record[keys] ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} );\n\n\t\treturn changed_data;\n\t}\n\n}\n\n//Don't check the file for now. Too many issues\n/* jshint ignore:end */\n\nBaseViewController.loadView = function( view_id ) {\n\n\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadViewSource */ .x.loadViewSource( view_id, view_id + 'View.html', function( result ) {\n\n\t\t// #VueContextMenu# Vue route change, this triggers the context menu.\n\t\t// TODO: BaseViewController.loadView is overriden in many places. Also need to handle those.\n\t\t// Which is better, here or in IndexController.onViewChange? here will catch all changes from hash to login to final viewcontroller. will onViewChange catch that too?\n\t\t// console.log('aaaa BaseV.loadView', view_id); // comparing triggers against IndexController.\n\n\t\t// TODO: Can we simplify this and remove the needs for props:true in router?\n\t\t// Note: This behaviour/router call is also in IndexController.openReport()\n\t\t// VueRouter.push('/view/'+$this.viewId);\n\t\t// window.context_menus[ view_id ] = new ContextMenuManager(); // Initialize Vue ContextMenuManager here so that each view has their own unique one.\n\t\t// VueRouter.push({\n\t\t// \tname: 'view',\n\t\t// \tparams: {\n\t\t// \t\tviewId: view_id\n\t\t// \t}\n\t\t// }).then(function() {\n\t\t// \tdoNext( result );\n\t\t// });\n\t\tdoNext( result ); // Now using one global context menu, so no need for router calls. Just using the one single LegacyView for now.\n\t} );\n\n\n\tfunction doNext( result ) {\n\t\tvar args = {};\n\t\tswitch ( view_id ) {\n\t\t\tcase 'TimeSheet':\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadViewSource */ .x.loadViewSource( view_id, view_id + 'View.css' );\n\t\t\t\targs = {\n\t\t\t\t\taccumulated_time: $.i18n._( 'Accumulated Time' ),\n\t\t\t\t\tverify: $.i18n._( 'Verify' ),\n\t\t\t\t\ttimesheet_verification: $.i18n._( 'TimeSheet Verification' )\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase 'Login':\n\t\t\t\t$( 'body' ).addClass( 'login-bg' );\n\t\t\t\t$( 'body' ).removeClass( 'application-bg' );\n\t\t\t\t// Global.loadViewSource( view_id, view_id + 'View.css' ); // #2833 Login CSS was being loaded twice. Now only loaded in the index.php file for speed.\n\t\t\t\tbreak;\n\t\t\tcase 'PortalJobVacancyDetail':\n\t\t\t\targs = {\n\t\t\t\t\tsearch_label: $.i18n._( 'Search' )\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase 'PortalJobVacancy':\n\t\t\t\targs = {\n\t\t\t\t\tsearch_label: $.i18n._( 'Search' ),\n\t\t\t\t\tload_more: $.i18n._( 'Loading' ) + '...'\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase 'MyJobApplication':\n\t\t\tcase 'MyProfile':\n\t\t\t\tbreak;\n\t\t\tcase 'Schedule':\n\t\t\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.loadViewSource */ .x.loadViewSource( view_id, view_id + 'View.css' );\n\t\t\t\tbreak;\n\t\t}\n\t\tIndexViewController.instance.router.removeCurrentView();\n\t\tvar template = _.template( result );\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.contentContainer */ .x.contentContainer().html( template( args ) );\n\t\tLocalCacheData.current_open_view_id = view_id;\n\t\t_global_Global__WEBPACK_IMPORTED_MODULE_4__/* .Global.trackView */ .x.trackView( view_id, LocalCacheData.current_doing_context_action );\n\t}\n\n};\n\nBaseViewController.default_layout_name = $.i18n._( '-- Default --' );\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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LENBQUM7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWSxDQUFDO0FBQ2I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLFlBQVksQ0FBQztBQUNiO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxZQUFZLENBQUM7QUFDYjtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVSxDQUFDO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsQ0FBQztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0EsZ0RBQWdELGtGQUFrRjtBQUNsSTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxvQ0FBb0MsV0FBVzs7QUFFL0M7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxxREFBcUQ7QUFDckQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpRkFBaUY7QUFDakY7QUFDQTs7QUFFQSxpQ0FBaUM7QUFDakM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyREFBMkQ7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyx5R0FBNkI7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxVQUFVLENBQUM7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFLENBQUM7QUFDSDtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtB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QUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQkFBaUIsdUVBQVk7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLDBCQUEwQjtBQUM3Qzs7QUFFQTtBQUNBLG1CQUFtQixTQUFTO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTCxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3QkFBd0I7O0FBRXhCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxJQUFJO0FBQ0osd0JBQXdCOztBQUV4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQkFBaUIsdUVBQVk7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsMEJBQTBCO0FBQzdDOztBQUVBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQix1RUFBWTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQiwwQkFBMEI7QUFDN0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixDQUFDO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtSEFBbUgsWUFBWTtBQUMvSDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUwsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixpQkFBaUI7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJO0FBQ0o7QUFDQSxvQkFBb0IsdUJBQXVCO0FBQzNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQ0FBbUMscUdBQTJCO0FBQzlEO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hELEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRywrRkFBd0I7QUFDM0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHLENBQUM7QUFDSjtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0EsSUFBSSxDQUFDO0FBQ0w7QUFDQTtBQUNBLE1BQU07QUFDTjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLLHFHQUEyQjtBQUNoQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBLGlEQUFpRDtBQUNqRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtDQUErQztBQUMvQztBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0Q7O0FBRWxEO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTix3QkFBd0IsQ0FBQyxFQUFFLHVHQUE4QjtBQUN6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjs7QUFFQSwrQ0FBK0M7QUFDL0M7O0FBRUEsNERBQTREOztBQUU1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxDQUFDO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxjQUFjLENBQUM7QUFDZjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1RUFBdUU7QUFDdkU7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0E7O0FBRUEseUhBQXlIO0FBQ3pIO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU4sd0NBQXdDO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRDtBQUMxRCxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLDRHQUE0RztBQUM1RztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULDhHQUE4RztBQUM5RztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCOztBQUVyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixDQUFDOztBQUVyQjtBQUNBO0FBQ0EsS0FBSyxDQUFDO0FBQ04sTUFBTTtBQUNOO0FBQ0EsTUFBTSxDQUFDO0FBQ1A7QUFDQSxPQUFPO0FBQ1AsTUFBTSxDQUFDO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUssR0FBRzs7QUFFUjtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQSxJQUFJLENBQUM7QUFDTDs7QUFFQSxLQUFLOztBQUVMO0FBQ0EsS0FBSyxDQUFDO0FBQ04sTUFBTTtBQUNOLEtBQUssQ0FBQztBQUNOO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHLDJGQUFzQjs7QUFFekI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTyxDQUFDO0FBQ1IsR0FBRyxDQUFDO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQSxPQUFPLENBQUM7QUFDUixHQUFHLENBQUM7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsdUVBQVk7QUFDdEI7QUFDQSxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRSxDQUFDO0FBQ0gsRUFBRSxDQUFDO0FBQ0gsRUFBRSxDQUFDO0FBQ0gsRUFBRSxDQUFDO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFLENBQUM7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSSw0RkFBNEY7QUFDaEc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtRkFBbUY7QUFDbkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSx1RUFBWTtBQUNwQjtBQUNBLEtBQUssVUFBVSx1RUFBWTtBQUMzQixTQUFTLDJFQUFjO0FBQ3ZCO0FBQ0Esc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxLQUFLLHNDQUFzQyx1RUFBWTtBQUN2RDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHdEQUF3RDtBQUN4RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0EsS0FBSyxVQUFVLHVFQUFZO0FBQzNCLFNBQVMsMkVBQWM7QUFDdkI7QUFDQSxzQkFBc0IsU0FBUztBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLEtBQUssc0NBQXNDLHVFQUFZO0FBQ3ZEO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQix5SEFBcUM7O0FBRXREO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxhQUFhLENBQUM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsdUVBQVk7QUFDckI7QUFDQTtBQUNBLEtBQUs7QUFDTCxTQUFTLHVFQUFZO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUUsdUZBQW9CO0FBQ3RCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CLENBQUMsRUFBRSx5RkFBcUI7O0FBRTNDLHVCQUF1QixDQUFDO0FBQ3hCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQLEVBQUUsNkZBQXVCOztBQUV6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsK0VBQStFO0FBQy9FO0FBQ0E7QUFDQSwyR0FBMkc7QUFDM0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRyxDQUFDO0FBQ0osSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsT0FBTyx5RkFBcUI7QUFDNUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLE9BQU8seUZBQXFCO0FBQzVCO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIsZUFBZSwyQ0FBMkMsaUJBQWlCOztBQUU1RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsQ0FBQztBQUNkOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxpQ0FBaUM7O0FBRWpDO0FBQ0E7QUFDQSxzQkFBc0IsNkZBQXVCLEVBQUUsOEZBQXVCO0FBQ3RFLGtDQUFrQyxlQUFlO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQiw2RkFBdUIsRUFBRSw2RkFBc0I7QUFDckUsaUNBQWlDLDhCQUE4QjtBQUMvRDtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsNkZBQXVCLEVBQUUsOEZBQXVCO0FBQ3RFLGtDQUFrQyxlQUFlO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQiw2RkFBdUIsRUFBRSw4RkFBdUI7QUFDdEUsa0NBQWtDLGVBQWU7QUFDakQ7O0FBRUEsMEJBQTBCLENBQUM7QUFDM0IsbUJBQW1CLENBQUM7QUFDcEIsZUFBZSxDQUFDOztBQUVoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLDZGQUF1QixFQUFFLDRGQUFxQjtBQUNwRSxpQ0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0Esc0JBQXNCLDZGQUF1QixFQUFFLCtGQUF3QjtBQUN2RSxtQ0FBbUMsZUFBZTtBQUNsRDtBQUNBO0FBQ0Esc0JBQXNCLDZGQUF1QixFQUFFLCtGQUF3QjtBQUN2RSxvQ0FBb0MsK0NBQStDO0FBQ25GO0FBQ0E7QUFDQSxzQkFBc0IsNkZBQXVCLEVBQUUsK0ZBQXdCO0FBQ3ZFLG1DQUFtQyxlQUFlO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsNkZBQXVCLEVBQUUsK0ZBQXdCO0FBQ3ZFLG1DQUFtQyxrQ0FBa0M7QUFDckU7QUFDQTtBQUNBLHNCQUFzQiw2RkFBdUIsRUFBRSw4RkFBdUI7QUFDdEUsa0NBQWtDLHFFQUFxRTtBQUN2RztBQUNBO0FBQ0Esc0JBQXNCLDZGQUF1QixFQUFFLCtGQUF3QjtBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLDZGQUF1QixFQUFFLCtGQUF3QjtBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSSwwQ0FBMEM7QUFDOUM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSywyRkFBc0IsRUFBRSxpRkFBaUI7QUFDOUMsTUFBTTtBQUNOLEtBQUssMkZBQXNCLEVBQUUsaUZBQWlCO0FBQzlDOztBQUVBLElBQUksK0VBQWdCO0FBQ3BCLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsTUFBTSwyRkFBc0IsRUFBRSxpRkFBaUI7QUFDL0M7QUFDQSxPQUFPO0FBQ1AsTUFBTSwyRkFBc0IsRUFBRSxpRkFBaUI7QUFDL0M7QUFDQTs7QUFFQSxNQUFNO0FBQ04sS0FBSywyRkFBc0IsRUFBRSxpRkFBaUI7QUFDOUM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU8seUZBQXFCLElBQUksQ0FBQztBQUNqQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFCQUFxQiw2RkFBdUIsRUFBRSwrRkFBd0I7QUFDdEU7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLDZGQUF1QjtBQUNuRCw2QkFBNkIsNkZBQXVCO0FBQ3BEOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFLDJIQUFzQztBQUN4Qzs7QUFFQTtBQUNBO0FBQ0EsT0FBTywyRUFBYztBQUNyQixvQkFBb0Isb0JBQW9CO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLENBQUMsRUFBRSw2RkFBdUIsRUFBRSx5R0FBa0M7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTywyRUFBYztBQUNyQixvQkFBb0Isb0JBQW9CO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixrQ0FBa0M7QUFDbEM7QUFDQSw2RUFBNkU7QUFDN0U7QUFDQTs7QUFFQSxPQUFPLHVFQUFZOztBQUVuQjs7QUFFQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQix5RkFBcUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsUUFBUSwyRUFBYztBQUN0QjtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsT0FBTywyRUFBYzs7QUFFckIsb0JBQW9CLG9CQUFvQjtBQUN4QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLDJFQUFjO0FBQ3pCO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxPQUFPLHVFQUFZOztBQUVuQixJQUFJO0FBQ0o7QUFDQTs7QUFFQSxPQUFPLHVFQUFZLG1DQUFtQyx1RkFBb0I7QUFDMUU7QUFDQSxvQkFBb0Isb0JBQW9CO0FBQ3hDO0FBQ0E7QUFDQSxTQUFTLHVFQUFZO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxPQUFPLHVFQUFZOztBQUVuQjtBQUNBLElBQUksQ0FBQztBQUNMLEtBQUs7O0FBRUwsSUFBSTs7QUFFSjtBQUNBOztBQUVBLFNBQVMsQ0FBQztBQUNWO0FBQ0E7O0FBRUEsSUFBSSxDQUFDOztBQUVMLCtCQUErQixDQUFDO0FBQ2hDLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSwwQ0FBMEM7QUFDMUMsS0FBSyxDQUFDO0FBQ047QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLCtDQUErQztBQUMvQyxNQUFNO0FBQ04sK0NBQStDO0FBQy9DOztBQUVBOztBQUVBLEdBQUcsaUlBQXlDOztBQUU1QyxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsQ0FBQztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixDQUFDO0FBQ2pCO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0Esa0JBQWtCLENBQUM7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUNBQW1DLHVFQUFZO0FBQy9DO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0NBQWdDLHlIQUFxQztBQUNyRTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLFVBQVUsdUVBQVk7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLHdFQUF3RSxnQ0FBZ0M7QUFDeEc7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGtDQUFrQyx1RUFBWSwrQkFBK0I7O0FBRTdFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyx1RUFBWTtBQUNsRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRSxDQUFDO0FBQ0gseUJBQXlCLHVFQUFZO0FBQ3JDO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0NBQXNDLDJFQUFjO0FBQ3BEO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSx1RUFBWTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQixDQUFDLEVBQUUsNkZBQXVCLEVBQUUsNkdBQXNDO0FBQ3BGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsd0JBQXdCLENBQUM7O0FBRXpCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRSxDQUFDO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHlDQUF5Qyw2RUFBZTtBQUN4RDtBQUNBO0FBQ0E7O0FBRUEsR0FBRyxFQUFFLGlJQUF5Qzs7QUFFOUMsMENBQTBDLDZFQUFlO0FBQ3pEO0FBQ0E7QUFDQTs7QUFFQSxHQUFHLEVBQUUsaUlBQXlDO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbUNBQW1DLHFHQUEyQjtBQUM5RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBOztBQUVBLEVBQUUsaUlBQXlDOztBQUUzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QyxJQUFJO0FBQ0osNENBQTRDO0FBQzVDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHFHQUEyQjtBQUM5RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBOztBQUVBLEVBQUUsaUlBQXlDOztBQUUzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QztBQUN6QyxJQUFJO0FBQ0osNENBQTRDO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSSwyRkFBc0I7QUFDMUI7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUcsMkZBQXNCLEVBQUUsaUZBQWlCO0FBQzVDLGlDQUFpQyxtRkFBa0I7QUFDbkQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYztBQUNkOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CLFNBQVM7QUFDN0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CLCtCQUErQjtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixTQUFTO0FBQzVCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFFBQVEsdUVBQVk7QUFDcEI7QUFDQTs7QUFFQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFFBQVEsdUVBQVk7QUFDcEI7QUFDQTs7QUFFQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFFBQVEsdUVBQVk7QUFDcEI7QUFDQTs7QUFFQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSx1RUFBWTtBQUNwQjtBQUNBOztBQUVBLFFBQVEsdUVBQVk7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsUUFBUSx1RUFBWTtBQUNwQjtBQUNBOztBQUVBLFFBQVEsdUVBQVk7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRLHVFQUFZO0FBQ3BCO0FBQ0E7O0FBRUEsUUFBUSx1RUFBWTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FB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QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLHlGQUFxQjs7QUFFdEI7QUFDQTtBQUNBO0FBQ0Esa0RBQWtEOztBQUVsRDtBQUNBO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTixvQkFBb0I7QUFDcEIsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJLHlGQUFxQjtBQUN6QjtBQUNBLHVCQUF1QixDQUFDO0FBQ3hCLGFBQWEsQ0FBQztBQUNkLDZCQUE2QixDQUFDO0FBQzlCO0FBQ0E7QUFDQTtBQUNBLElBQUksQ0FBQztBQUNMLElBQUksQ0FBQztBQUNMLCtEQUErRDtBQUMvRDtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsQ0FBQztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixDQUFDO0FBQ3BCLGdCQUFnQixDQUFDO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUkseUZBQXFCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixDQUFDO0FBQ2xCLEVBQUUsNkZBQXVCO0FBQ3pCO0FBQ0EsRUFBRSwrRUFBZ0I7QUFDbEI7O0FBRUE7O0FBRUEseUNBQXlDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzPzI0ODgiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVFRCYWNrYm9uZVZpZXcgfSBmcm9tICdAL3ZpZXdzL1RUQmFja2JvbmVWaWV3JztcbmltcG9ydCB7IFRUQVBJIH0gZnJvbSAnQC9zZXJ2aWNlcy9UaW1lVHJleENsaWVudEFQSSc7XG5pbXBvcnQgeyBGb3JtSXRlbVR5cGUsIFdpZGdldE5hbWVzRGljIH0gZnJvbSAnQC9nbG9iYWwvd2lkZ2V0cy9zZWFyY2hfcGFuZWwvRm9ybUl0ZW1UeXBlJzsgLy8gVE9ETzogZHVwbGljYXRlZCBpbiBtZXJnZWQganMgZmlsZXMuXG5pbXBvcnQgJ0AvZ2xvYmFsL3dpZGdldHMvcGFnaW5nL1BhZ2luZzIuanMnO1xuaW1wb3J0IHsgR2xvYmFsIH0gZnJvbSAnQC9nbG9iYWwvR2xvYmFsJztcbmltcG9ydCB7IEh0bWxUZW1wbGF0ZXNHbG9iYWwgfSBmcm9tICdAL3NlcnZpY2VzL0h0bWxUZW1wbGF0ZXMnO1xuXG53aW5kb3cuRm9ybUl0ZW1UeXBlID0gRm9ybUl0ZW1UeXBlOyAvLyBUT0RPOiBFdmVudHVhbGx5IHJlZmFjdG9yIHRvIGltcG9ydCBvbmx5IHdoZXJlIHRoZXNlIGFyZSB1c2VkLlxud2luZG93LldpZGdldE5hbWVzRGljID0gV2lkZ2V0TmFtZXNEaWM7IC8vIFRPRE86IEV2ZW50dWFsbHkgcmVmYWN0b3IgdG8gaW1wb3J0IG9ubHkgd2hlcmUgdGhlc2UgYXJlIHVzZWQuXG5cbi8qIGpzaGludCBpZ25vcmU6c3RhcnQgKi9cblxuLy9Eb24ndCBjaGVjayB0aGlzIGZpbGUgZm9yIG5vdy4gVG9vIG1hbnkgaXNzdWVzLlxuZXhwb3J0IGNsYXNzIEJhc2VWaWV3Q29udHJvbGxlciBleHRlbmRzIFRUQmFja2JvbmVWaWV3IHtcblx0Y29uc3RydWN0b3IoIG9wdGlvbnMgPSB7fSApIHtcblx0XHRfLmRlZmF1bHRzKCBvcHRpb25zLCB7XG5cdFx0XHRyZWFsX3RoaXM6IG51bGwsIC8vRm9yIHN1cGVyIGNhbGwgaW4gc2Vjb25kIGxldmVsIHN1YiBjbGFzc1xuXG5cdFx0XHRzdWJfdmlld19tb2RlOiBmYWxzZSxcblxuXHRcdFx0ZWRpdF9vbmx5X21vZGU6IGZhbHNlLFxuXG5cdFx0XHRjYW5fY2FjaGVfY29udHJvbGxlcjogdHJ1ZSwgLy9pZiBhbGxvdyB0byBjYWNoZSBjdXJyZW50IGNvbnRyb2xsZXJcblxuXHRcdFx0cGVybWlzc2lvbl9pZDogJycsXG5cdFx0XHRhcGk6IG51bGwsXG5cdFx0XHR1c2VyX2dlbmVyaWNfZGF0YV9hcGk6IG51bGwsXG5cdFx0XHRhbGxfY29sdW1uczogW10sXG5cdFx0XHRkaXNwbGF5X2NvbHVtbnM6IFtdLFxuXHRcdFx0ZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnM6IFtdLFxuXHRcdFx0c2NyaXB0X25hbWU6ICcnLFxuXHRcdFx0ZmlsdGVyX2RhdGE6IG51bGwsIC8vY3VycmVudCBGaWx0ZXIgZGF0YSBnZXQgZnJvbSBTZWFyY2ggcGFuZWxcblx0XHRcdHRlbXBfYmFzaWNfZmlsdGVyX2RhdGE6IG51bGwsXG5cdFx0XHR0ZW1wX2Fkdl9maWx0ZXJfZGF0YTogbnVsbCxcblx0XHRcdHNvcnREYXRhOiBudWxsLCAvL0N1cnJlbnQgU29ydCBkYXRhIGdldCBmcm9tIHNlYXJjaCBwYW5lbFxuXHRcdFx0c2VsZWN0X2xheW91dDogbnVsbCxcblx0XHRcdGxheW91dF9jaGFuZ2VkOiBmYWxzZSxcblx0XHRcdHNlYXJjaF9wYW5lbDogbnVsbCxcblx0XHRcdGdyaWQ6IG51bGwsXG5cdFx0XHRjb250ZXh0X21lbnVfbmFtZTogJycsXG5cdFx0XHRuYXZpZ2F0aW9uX2xhYmVsOiAnJyxcblx0XHRcdGNvbnRleHRfbWVudV9hcnJheTogW10sXG5cdFx0XHR0X2dyaWRfaGVhZGVyX2FycmF5OiBbXSxcblxuXHRcdFx0Ly9Db2x1bW4gU2VsZWN0b3IgaW4gc2VhcmNoIHBhbmVsXG5cdFx0XHRjb2x1bW5fc2VsZWN0b3I6IG51bGwsXG5cblx0XHRcdHNvcnRfYnlfc2VsZWN0b3I6IG51bGwsXG5cblx0XHRcdHNhdmVfc2VhcmNoX2FzX2lucHV0OiBudWxsLFxuXG5cdFx0XHRwcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3I6IG51bGwsXG5cblx0XHRcdHByZXZpb3VzX3NhdmVkX2xheW91dF9kaXY6IG51bGwsXG5cblx0XHRcdG5lZWRfc2VsZWN0X2xheW91dF9uYW1lOiAnJywgLy9TZXQgdGhpcyB3aGVuIHNhdmUgbmV3IGxheW91dCB0byBjaG9vc2UgdGhlIG5ldyBsYXlvdXRcblxuXHRcdFx0c2VhcmNoX2ZpZWxkczogbnVsbCxcblxuXHRcdFx0YmFzaWNfc2VhcmNoX2ZpZWxkX3VpX2RpYzoge30sIC8vU2F2ZSBBd2Vzb21lQm94IHdoZW4gdGhleSBjcmVhdGVkXG5cblx0XHRcdGFkdl9zZWFyY2hfZmllbGRfdWlfZGljOiB7fSwgLy9TYXZlIEF3ZXNvbWVCb3ggd2hlbiB0aGV5IGNyZWF0ZWRcblxuXHRcdFx0ZWRpdF92aWV3X3VpX2RpYzoge30sXG5cblx0XHRcdGVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpYzoge30sXG5cblx0XHRcdGVkaXRfdmlld19mb3JtX2l0ZW1fZGljOiB7fSwgLy9XaG9sZSBGb3JtSXRlbVxuXG5cdFx0XHRlZGl0X3ZpZXdfZXJyb3JfdWlfZGljOiB7fSxcblxuXHRcdFx0ZWRpdF92aWV3OiBudWxsLFxuXG5cdFx0XHRlZGl0X3ZpZXdfdGFiOiBudWxsLFxuXG5cdFx0XHRjdXJyZW50X2VkaXRfcmVjb3JkOiBudWxsLCAvL0N1cnJlbnQgZWRpdCByZWNvcmRcblxuXHRcdFx0cmVmcmVzaF9pZDogbnVsbCwgLy9TZXQgdGhpcyB0byByZWZyZXNoIG9uZSByZWNvcmQgaW4gZ3JpZCB2aWV3LlxuXG5cdFx0XHRuYXZpZ2F0aW9uOiBudWxsLCAvLyBOYXZpZ2F0aW9uIHdpZGdldCBpbiBlZGl0IHZpZXdcblxuXHRcdFx0aXNfbWFzc19lZGl0aW5nOiBmYWxzZSwgLy9TZXQgd2hlbiBtYXNzIGVkaXRcblxuXHRcdFx0aXNfdmlld2luZzogZmFsc2UsXG5cdFx0XHRpc192aWV3aW5nX2RldGFpbDogZmFsc2UsXG5cdFx0XHRpc19lZGl0OiBmYWxzZSxcblx0XHRcdGlzX2FkZDogZmFsc2UsXG5cblx0XHRcdHVuaXF1ZV9jb2x1bW5zOiBbXSwgLy9TZXQgd2hlbiBNYXNzIGVkaXQsIG1hcmsgd2hpY2ggZmllbGRzIG5lZWQgdG8gYmUgZGlzYWJsZVxuXG5cdFx0XHRsaW5rZWRfZmllbGRzOiBbXSxcblxuXHRcdFx0bWFzc19lZGl0X3JlY29yZF9pZHM6IFtdLCAvLyBNYXNzIGVkaXQgcmVjb3Jkc1xuXG5cdFx0XHRlZGl0X3ZpZXdfdGFiczogW10sXG5cblx0XHRcdHJlZnJlc2hfc3ViX3ZpZXc6IGZhbHNlLFxuXG5cdFx0XHRwYXJlbnRfa2V5OiBudWxsLCAvL2RlZmF1bHQgZmlsdGVyIHdoZW4gc2VhcmNoXG5cblx0XHRcdHBhcmVudF92YWx1ZTogbnVsbCwgLy9kZWZhdWx0IGZpbHRlciB3aGVuIHNlYXJjaFxuXG5cdFx0XHRwYXJlbnRfZWRpdF9yZWNvcmQ6IG51bGwsXG5cblx0XHRcdHRvdGFsX2Rpc3BsYXlfc3BhbjogbnVsbCxcblxuXHRcdFx0cGFnaW5nX3dpZGdldDogbnVsbCxcblxuXHRcdFx0cGFnaW5nX3dpZGdldF8yOiBudWxsLCAvL1B1dCBpbiB0aGUgYm90dG9tIG9mIGRhdGEgZ3JpZFxuXG5cdFx0XHRwYWdlcl9kYXRhOiBudWxsLFxuXG5cdFx0XHR2aWV3SWQ6IG51bGwsXG5cblx0XHRcdGluaXRfb3B0aW9uc19jb21wbGV0ZTogZmFsc2UsXG5cblx0XHRcdG5vX3Jlc3VsdF9ib3g6IG51bGwsIC8vIE5vIFJlc3VsdCBGb3VuZCBCbGFjayBjb3ZlciB3aGVuIG5vIHJlc3VsdCBpbiBncmlkXG5cblx0XHRcdHRhYmxlX25hbWVfa2V5OiBudWxsLFxuXG5cdFx0XHRzdWJfbG9nX3ZpZXdfY29udHJvbGxlcjogbnVsbCxcblxuXHRcdFx0cGFyZW50X3ZpZXdfY29udHJvbGxlcjogbnVsbCwgLy9BZGQgdGhpcyB0byBjYWxsIHBhcmVudF92aWV3X2NvbnRyb2xsIGNhbmNlbCBhY3Rpb24gd2hlbiBjYW5jZWwgZnJvbSBzdWIgdmlld1xuXG5cdFx0XHR1aV9pZDogJycsXG5cblx0XHRcdGlzX2NoYW5nZWQ6IGZhbHNlLCAvLyBUcmFjayBpZiBtb2RpZmllZCBhbnkgZmllbGRzIGluIGVkaXQgdmlld1xuXG5cdFx0XHRjb25maXJtX29uX2V4aXQ6IGZhbHNlLCAvL2NvbmZpcm0gYmVmb3JlIGxlYXZpbmcgdGhlIGVkaXQgdmlldyBldmVuIGlmIG5vIGNoYW5nZXMgaGF2ZSBiZWVuIG1hZGVcblxuXHRcdFx0ZWRpdF92aWV3X3RwbDogJycsIC8vRWRpdCB2aWV3IGh0bWwgbmFtZVxuXG5cdFx0XHRzdWJNZW51TmF2TWFwOiBudWxsLFxuXG5cdFx0XHR0cnlTZXRHcmlkU2l6ZVdoZW5UYWJTaG93OiBmYWxzZSwgLy8gU2V0IHN1YiB2aWV3IGdyaWQgc2l6ZSB3aGVuIHRhYiBzaG93IGluc3RlYWQgd2hlbiB0YWIgc2VsZWN0XG5cblx0XHRcdGNvcGllZF9yZWNvcmRfaWQ6ICcnLCAvLyBXaGVuIGNvcHkgYXMgbmV3LCBzYXZlIGNvcGllZCByZW9yZCdzIGlkXG5cblx0XHRcdGN1c3RvbV9maWVsZF9hcGk6IG51bGwsXG5cblx0XHRcdGxhc3Rfc2VsZWN0X2lkczogbnVsbCxcblxuXHRcdFx0c2F2aW5nX2xheW91dF9pbl9sYXlvdXRfdGFiOiBmYWxzZSwgLy9NYXJrIGlmIHNhdmUgbGF5b3V0IGZyb20gU2F2ZWQgYW5kIGxheW91dCB0YWIuIGlmIHNvLCBkb24ndCBzd2l0Y2ggdGFicyB3aGVuIHNldCB2YWx1ZXMgdG8gc2VhcmNoIHBhbmVsXG5cblx0XHRcdG5lZWRfc3dpdGNoX3RvX2NvbnRleHRfbWVudTogZmFsc2UsXG5cblx0XHRcdHNob3dfc2VhcmNoX3RhYjogdHJ1ZSxcblxuXHRcdFx0Z3JpZF90b3RhbF93aWR0aDogbnVsbCxcblxuXHRcdFx0c2hvd193YXJuaW5nX3doZW5fdmFsaWRhdGlvbjogZmFsc2UsXG5cblx0XHRcdHB1bHNlX3RpbWVfZGljOiBmYWxzZSxcblxuXHRcdFx0ZWRpdF92aWV3X2Nsb3NlX2ljb246IG51bGwsXG5cblx0XHRcdGVuYWJsZV92YWxpZGF0aW9uOiB0cnVlLFxuXG5cdFx0XHQvLyBfcmVxdWlyZWRfZmlsZXM6IG51bGwsXG5cblx0XHRcdHRhYl9tb2RlbDogbnVsbCwgLy9UYWIgZGVmaW5pdGlvbnMgYW5kIGEgbWFwIHRvIHRoZWlyIGNhbGxiYWNrcy5cblxuXHRcdFx0Z3JpZF9wYXJlbnQ6IG51bGwsXG5cblx0XHRcdGN1c3RvbV9maWVsZHM6IFtdXG5cdFx0fSApO1xuXHRcdHN1cGVyKCBvcHRpb25zICk7XG5cdH1cblxuXHQvLyBnZXRSZXF1aXJlZEZpbGVzKCkge1xuXHQvLyBcdC8vb3ZlcnJpZGUgaW4gY2hpbGQgY2xhc3Ncblx0Ly8gXHRyZXR1cm4gW107XG5cdC8vIH1cblxuXHQvKipcblx0ICogV2hlbiBjaGFuZ2luZyB0aGlzIGZ1bmN0aW9uLCB5b3UgbmVlZCB0byBsb29rIGZvciBhbGwgb2NjdXJlbmNlcyBvZiB0aGlzIGZ1bmN0aW9uIGJlY2F1c2UgaXQgd2FzIG5lZWRlZCBpbiBzZXZlcmFsIGJhc2VzXG5cdCAqIEJhc2VWaWV3Q29udHJvbGxlciwgSG9tZVZpZXdDb250cm9sbGVyLCBCYXNlV2l6YXJkQ29udHJvbGxlciwgUXVpY2tQdW5jaEJhc2VWaWV3Q29udHJvbGVyXG5cdCAqXG5cdCAqIEByZXR1cm5zIHtBcnJheX1cblx0ICovXG5cdC8vIGZpbHRlclJlcXVpcmVkRmlsZXMoKSB7XG5cdC8vIFx0RGVidWcuV2FybiggJ0RlcHJlY2F0ZWQgcmVxdWlyZWpzIGZ1bmN0aW9uLiBSZXBsYWNlIHVzYWdlIGltbWVkaWF0ZWx5IHdpdGggd2VicGFjayBsb2FkZXJzLicsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2ZpbHRlclJlcXVpcmVkRmlsZXMnLCAyICk7XG5cdC8vXG5cdC8vIFx0dmFyIHJldHZhbCA9IFtdO1xuXHQvLyBcdHZhciByZXF1aXJlZF9maWxlcztcblx0Ly9cblx0Ly8gXHRpZiAoIHR5cGVvZiB0aGlzLl9yZXF1aXJlZF9maWxlcyA9PSAnb2JqZWN0JyApIHtcblx0Ly8gXHRcdHJlcXVpcmVkX2ZpbGVzID0gdGhpcy5fcmVxdWlyZWRfZmlsZXM7XG5cdC8vIFx0fSBlbHNlIHtcblx0Ly8gXHRcdHJlcXVpcmVkX2ZpbGVzID0gdGhpcy5nZXRSZXF1aXJlZEZpbGVzKCk7XG5cdC8vIFx0fVxuXHQvL1xuXHQvLyBcdGlmICggcmVxdWlyZWRfZmlsZXMgJiYgcmVxdWlyZWRfZmlsZXNbMF0gKSB7XG5cdC8vIFx0XHRyZXR2YWwgPSByZXF1aXJlZF9maWxlcztcblx0Ly8gXHR9IGVsc2Uge1xuXHQvLyBcdFx0Zm9yICggdmFyIGVkaXRpb25faWQgaW4gcmVxdWlyZWRfZmlsZXMgKSB7XG5cdC8vIFx0XHRcdGlmICggR2xvYmFsLmdldFByb2R1Y3RFZGl0aW9uKCkgPj0gZWRpdGlvbl9pZCApIHtcblx0Ly8gXHRcdFx0XHRyZXR2YWwgPSByZXR2YWwuY29uY2F0KCByZXF1aXJlZF9maWxlc1tlZGl0aW9uX2lkXSApO1xuXHQvLyBcdFx0XHR9XG5cdC8vIFx0XHR9XG5cdC8vIFx0fVxuXHQvL1xuXHQvLyBcdERlYnVnLkFyciggcmV0dmFsLCAnUkVUVkFMJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZmlsdGVyUmVxdWlyZWRGaWxlcycsIDEwICk7XG5cdC8vIFx0cmV0dXJuIHJldHZhbDtcblx0Ly8gfVxuXG5cdHByZUluaXQoKSB7XG5cdFx0Ly9vdmVycmlkZSBpbiBjaGlsZCBjbGFzc1xuXHR9XG5cblx0aW5pdGlhbGl6ZSggb3B0aW9ucyApIHtcblx0XHREZWJ1Zy5UZXh0KCAnSU5JVElBTElaRScsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2luaXRpYWxpemUnLCAxMCApO1xuXHRcdEdsb2JhbC5zZXRVSU5vdHJlYWR5KCk7XG5cblx0XHRzdXBlci5pbml0aWFsaXplKCBvcHRpb25zICk7XG5cblx0XHRUVFByb21pc2UuYWRkKCAnaW5pdCcsICdpbml0JyApO1xuXHRcdFRUUHJvbWlzZS5hZGQoICdCYXNlVmlld0NvbnRyb2xsZXInLCAnaW5pdGlhbGl6ZScgKTtcblx0XHQvL3RyaWdnZXIgcmVhZHlzdGF0ZSB1cGRhdGVcblx0XHRUVFByb21pc2Uud2FpdCgpO1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLmxheW91dF9jaGFuZ2VkID0gZmFsc2U7XG5cdFx0Ly8gdmFyIHJlcXVpcmVkX2ZpbGVzID0gdGhpcy5maWx0ZXJSZXF1aXJlZEZpbGVzKCk7XG5cblx0XHQvLyBfX25vbl93ZWJwYWNrX3JlcXVpcmVfXyggcmVxdWlyZWRfZmlsZXMsIGZ1bmN0aW9uKCkgeyAvLyBUaGlzIGlzIHRvIHByZXZlbnQgY29uZmxpY3Qgd2l0aCB0aGUgV2VicGFjayBOb2RlIHJlcXVpcmUgY2FsbHMuXG5cdFx0Ly8gRGVidWcuV2FybiggJ0RlcHJlY2F0ZWQgcmVxdWlyZWpzIGZ1bmN0aW9uLiBSZXBsYWNlIHVzYWdlIGltbWVkaWF0ZWx5IHdpdGggd2VicGFjayBsb2FkZXJzLicsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2luaXRpYWxpemUnLCAyICk7XG5cblx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyAvLyAjMjY2MiBUaGlzIHNldFRpbWVvdXQgaXMgZXNzZW50aWFsIGluIGtlZXBpbmcgdGhlIGNvZGUgZmxvdyB0aGUgc2FtZSBhcyB3aGVuIHRoaXMgY29kZSBibG9jayBoYXMgYSByZXF1aXJlanMgY2FsbGJhY2suIE90aGVyd2lzZSBpdCBjYXVzZXMgaXNzdWVzIGluIG1hbnkgYXJlYXMgbGlrZSBBdWRpdCBsb2dzIGdvaW5nIGJsYW5rLCBhcyB0aGUgc3VidmlldyBwb3N0SW5pdCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIGl0cyBzZXQgaW4gYWZ0ZXJMb2FkVmlldygpLlxuXG5cdFx0XHQkdGhpcy5wcmVJbml0KCBvcHRpb25zICk7XG5cblx0XHRcdCR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHRcdFx0aWYgKCAkdGhpcy5vcHRpb25zICYmIEdsb2JhbC5pc1NldCggJHRoaXMub3B0aW9ucy5jYW5fY2FjaGVfY29udHJvbGxlciApICkge1xuXHRcdFx0XHQkdGhpcy5jYW5fY2FjaGVfY29udHJvbGxlciA9ICR0aGlzLm9wdGlvbnMuY2FuX2NhY2hlX2NvbnRyb2xsZXI7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggJHRoaXMub3B0aW9ucyAmJiBHbG9iYWwuaXNTZXQoICR0aGlzLm9wdGlvbnMuZWRpdF9vbmx5X21vZGUgKSApIHtcblx0XHRcdFx0JHRoaXMuZWRpdF9vbmx5X21vZGUgPSAkdGhpcy5vcHRpb25zLmVkaXRfb25seV9tb2RlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICR0aGlzLm9wdGlvbnMgJiYgR2xvYmFsLmlzU2V0KCAkdGhpcy5vcHRpb25zLnN1Yl92aWV3X21vZGUgKSApIHtcblx0XHRcdFx0JHRoaXMuc3ViX3ZpZXdfbW9kZSA9ICR0aGlzLm9wdGlvbnMuc3ViX3ZpZXdfbW9kZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCR0aGlzLnN1Yl92aWV3X21vZGUgPSBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAkdGhpcy5vcHRpb25zICYmIEdsb2JhbC5pc1NldCggJHRoaXMub3B0aW9ucy5wYXJlbnRfdmlldyApICkge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnRfdmlldyA9ICR0aGlzLm9wdGlvbnMucGFyZW50X3ZpZXc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggJHRoaXMub3B0aW9ucyAmJiBHbG9iYWwuaXNTZXQoICR0aGlzLm9wdGlvbnMucGFyZW50X3ZpZXdfY29udHJvbGxlciApICkge1xuXHRcdFx0XHQkdGhpcy5wYXJlbnRfdmlld19jb250cm9sbGVyID0gJHRoaXMub3B0aW9ucy5wYXJlbnRfdmlld19jb250cm9sbGVyO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICEkdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblxuXHRcdFx0XHRpZiAoICR0aGlzLmNhbl9jYWNoZV9jb250cm9sbGVyICkge1xuXHRcdFx0XHRcdGlmICggISR0aGlzLnN1Yl92aWV3X21vZGUgKSB7XG5cdFx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fcHJpbWFyeV9jb250cm9sbGVyID0gJHRoaXM7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9zdWJfY29udHJvbGxlciA9ICR0aGlzO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vUmVzZXQgbWFpbiBjb250YWluZXIgaWQgc28gaXQgd29uJ3QgZHVwbGljYXRlIHdoZW4gaW4gc3ViIHZpZXcuIExpa2UgQXVkaXQgdmlldy5cblx0XHRcdFx0dmFyIHJvb3RfY29udGFpbmVyID0gJCggJHRoaXMuZWwgKTtcblx0XHRcdFx0dmFyIG5ld19pZCA9IHJvb3RfY29udGFpbmVyLmF0dHIoICdpZCcgKSArICdfJyArIEdsb2JhbC5nZXRSYW5kb21OdW0oKTtcblx0XHRcdFx0cm9vdF9jb250YWluZXIuYXR0ciggJ2lkJywgbmV3X2lkICk7XG5cdFx0XHRcdCR0aGlzLmVsID0gJyMnICsgbmV3X2lkO1xuXHRcdFx0XHQkdGhpcy51aV9pZCA9IG5ld19pZDtcblxuXHRcdFx0XHQkdGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkgPSBUVEFQSS5BUElVc2VyR2VuZXJpY0RhdGE7XG5cblx0XHRcdFx0JHRoaXMudG90YWxfZGlzcGxheV9zcGFuID0gJCggJCggJHRoaXMuZWwgKS5maW5kKCAnLnRvdGFsLW51bWJlci1zcGFuJyApWzBdICk7XG5cblx0XHRcdFx0Ly8kdGhpcyBzaG91bGRuJ3QgYmUgZGlzcGxheWVkIGFzIGl0IGNhdXNlZCBcImZsYXNoaW5nXCIgb2YgdGV4dCBhbmQgaXQgd2Fzbid0IHRyYW5zbGF0ZWQgZWl0aGVyLlxuXHRcdFx0XHQvL2lmICggJHRoaXMudG90YWxfZGlzcGxheV9zcGFuICkge1xuXHRcdFx0XHQvLyR0aGlzLnRvdGFsX2Rpc3BsYXlfc3Bhbi50ZXh0KCAnRGlzcGxheWluZyAwIC0gMCBvZiAwIHRvdGFsLiBTZWxlY3RlZDogMCcgKTtcblx0XHRcdFx0Ly99XG5cblx0XHRcdFx0Ly9KUyBsb2FkIE9wdGltaXplXG5cdFx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEubG9hZFZpZXdSZXF1aXJlZEpTUmVhZHkgKSB7XG5cdFx0XHRcdFx0Ly9Jbml0IHBhZ2luZyB3aWRnZXQsIG5leHQgc3RlcCwgYWRkIHdpZGdldCB0byBVSSBhbmQgYmluZCBldmVudHMgaW4gc2V0U2VsZWN0TGF5b3V0XG5cdFx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5wYWdpbmdfdHlwZSA9PT0gMCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnBhZ2luZ193aWRnZXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggV2lkZ2V0TmFtZXNEaWMuUEFHSU5HICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLnBhZ2luZ193aWRnZXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggV2lkZ2V0TmFtZXNEaWMuUEFHSU5HXzIgKTtcblx0XHRcdFx0XHRcdCR0aGlzLnBhZ2luZ193aWRnZXRfMiA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBXaWRnZXROYW1lc0RpYy5QQUdJTkdfMiApO1xuXHRcdFx0XHRcdFx0JHRoaXMucGFnaW5nX3dpZGdldCA9ICR0aGlzLnBhZ2luZ193aWRnZXQuUGFnaW5nMigpO1xuXHRcdFx0XHRcdFx0JHRoaXMucGFnaW5nX3dpZGdldF8yID0gJHRoaXMucGFnaW5nX3dpZGdldF8yLlBhZ2luZzIoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCR0aGlzLnVpX2lkID0gR2xvYmFsLmdldFJhbmRvbU51bSgpO1xuXHRcdFx0fVxuXG5cdFx0XHQvL2luaXQgYWxsIGRpYyBvciBhcnJheSwgb3IgaXQgd2lsbCBleHRlbmRzIGxhc3Qgdmlld2NvbnRyb2xsZXIncyB2YWx1ZS4gV2h5P1xuXHRcdFx0JHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIgPSBudWxsO1xuXHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpYyA9IHt9O1xuXHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljID0ge307XG5cdFx0XHQkdGhpcy5iYXNpY19zZWFyY2hfZmllbGRfdWlfZGljID0ge307XG5cdFx0XHQkdGhpcy5hZHZfc2VhcmNoX2ZpZWxkX3VpX2RpYyA9IHt9O1xuXHRcdFx0JHRoaXMuZWRpdF92aWV3X3RhYnMgPSBbXTtcblxuXHRcdFx0JHRoaXMuY3VzdG9tX2ZpZWxkX2FwaSA9IFRUQVBJLkFQSUN1c3RvbUZpZWxkO1xuXG5cdFx0XHQkdGhpcy5pbml0S2V5Ym9hcmRFdmVudCgpOyAvLyByZWdpc3RlciBrZXlib2FyZCBldmVudHMgaWYgaXQncyBhIG1haW4gdmlld1xuXG5cdFx0XHQkdGhpcy5pbml0KCBvcHRpb25zICk7XG5cdFx0XHQkdGhpcy5wb3N0SW5pdCggb3B0aW9ucyApO1xuXG5cdFx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdpbml0aWFsaXplJyApO1xuXHRcdFx0VFRQcm9taXNlLnJlc29sdmUoICdpbml0JywgJ2luaXQnICk7XG5cdFx0fSwgMSk7XG5cdH1cblxuXHRpbml0KCkge1xuXHRcdC8vb3ZlcnJpZGUgaW4gY2hpbGQgY2xhc3Ncblx0fVxuXG5cdHBvc3RJbml0KCkge1xuXHRcdC8vb3ZlcnJpZGUgaW4gY2hpbGQgY2xhc3Ncblx0fVxuXG5cdGluaXRLZXlib2FyZEV2ZW50KCkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHRoaXMuc3ViX3ZpZXdfbW9kZSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuLy9cdFx0JCggdGhpcy5lbCApLnVuYmluZCggJ2tleWRvd24nICkuYmluZCggJ2tleWRvd24nLCBmdW5jdGlvbiggZSApIHtcbi8vXG4vL1x0XHRcdGlmICggZS5rZXlDb2RlID09PSAxMyAmJiAhJHRoaXMuc2VhcmNoX3BhbmVsLmlzQ29sbGFwc2VkKCkgKSB7XG4vL1x0XHRcdFx0JHRoaXMub25TZWFyY2goKTtcbi8vXHRcdFx0fVxuLy9cbi8vXHRcdH0gKTtcblxuXHRcdCQoIHRoaXMuZWwgKS51bmJpbmQoICdrZXl1cCcgKS5iaW5kKCAna2V5ZG93bicsIGZ1bmN0aW9uKCBlICkge1xuXG5cdFx0XHRpZiAoIGUua2V5Q29kZSA9PT0gMTMgJiYgJHRoaXMuc2VhcmNoX3BhbmVsICYmICEkdGhpcy5zZWFyY2hfcGFuZWwuaXNDb2xsYXBzZWQoKSApIHtcblxuXHRcdFx0XHQkdGhpcy5vblNlYXJjaCgpO1xuXHRcdFx0XHQkKCAnOmZvY3VzJyApLmJsdXIoKTsgLy9NYWtlIGZvY3VzIG91dCBvZiBjdXJyZW50IHZpZXcuIHBldmVudCBzZWFyY2ggdG9vIG11Y2ggd2hlbiB1c2VyIGtlZXAgY2xpY2sgZW50ZXJcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHQvL1NwZWljYWwgcGVybWlzc2lvbiBjaGVjayBmb3Igdmlld3MsIG5lZWQgb3ZlcnJpZGVcblx0aW5pdFBlcm1pc3Npb24oKSB7XG5cdH1cblxuXHQvL1NldCB0aGlzIHdoZW4gc2V0RGVmYXVsdCBtZW51XG5cdHNldFRvdGFsRGlzcGxheVNwYW4oKSB7XG5cdFx0aWYgKCAhdGhpcy50b3RhbF9kaXNwbGF5X3NwYW4gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHZhciB0b3RhbFJvd3M7XG5cdFx0dmFyIHN0YXJ0O1xuXHRcdHZhciBlbmQ7XG5cdFx0dmFyIGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkgPSB0aGlzLmdldEdyaWRTZWxlY3RJZEFycmF5KCk7XG5cdFx0dmFyIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID0gMDtcblx0XHQvL1VuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2xlbmd0aCcgb2YgdW5kZWZpbmVkXG5cdFx0aWYgKCBncmlkX3NlbGVjdGVkX2lkX2FycmF5ICkge1xuXHRcdFx0Z3JpZF9zZWxlY3RlZF9sZW5ndGggPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5Lmxlbmd0aDtcblx0XHR9XG5cblx0XHR2YXIgaXRlbXNfcHJlX3BhZ2UgPSAxMDA7XG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5nZXRMb2dpblVzZXJQcmVmZXJlbmNlKCkgKSB7XG5cdFx0XHR2YXIgaXRlbXNfcGVyX3BhZ2UgPSBwYXJzZUludCggTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyUHJlZmVyZW5jZSgpLml0ZW1zX3Blcl9wYWdlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5wYWdpbmdfdHlwZSA9PT0gMCApIHtcblx0XHRcdGlmICggdGhpcy5wYWdlcl9kYXRhICkge1xuXHRcdFx0XHR0b3RhbFJvd3MgPSB0aGlzLnBhZ2VyX2RhdGEudG90YWxfcm93cztcblx0XHRcdFx0c3RhcnQgPSAxO1xuXHRcdFx0XHRlbmQgPSB0aGlzLmdyaWQuZ2V0RGF0YSgpLmxlbmd0aDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRvdGFsUm93cyA9IDA7XG5cdFx0XHRcdHN0YXJ0ID0gMDtcblx0XHRcdFx0ZW5kID0gMDtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCB0aGlzLnBhZ2VyX2RhdGEgKSB7XG5cdFx0XHRcdHRvdGFsUm93cyA9IHRoaXMucGFnZXJfZGF0YS50b3RhbF9yb3dzO1xuXHRcdFx0XHRzdGFydCA9IDA7XG5cdFx0XHRcdGVuZCA9IDA7XG5cblx0XHRcdFx0aWYgKCB0aGlzLnBhZ2VyX2RhdGEubGFzdF9wYWdlX251bWJlciA+IDEgKSB7XG5cdFx0XHRcdFx0aWYgKCAhdGhpcy5wYWdlcl9kYXRhLmlzX2xhc3RfcGFnZSApIHtcblxuXHRcdFx0XHRcdFx0c3RhcnQgPSAoIHRoaXMucGFnZXJfZGF0YS5jdXJyZW50X3BhZ2UgLSAxICkgKiBpdGVtc19wZXJfcGFnZSArIDE7XG5cdFx0XHRcdFx0XHRlbmQgPSBzdGFydCArIGl0ZW1zX3Blcl9wYWdlIC0gMTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0c3RhcnQgPSAoIHRoaXMucGFnZXJfZGF0YS5jdXJyZW50X3BhZ2UgLSAxICkgKiBpdGVtc19wZXJfcGFnZSArIDE7XG5cdFx0XHRcdFx0XHRlbmQgPSB0b3RhbFJvd3M7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0c3RhcnQgPSAxO1xuXHRcdFx0XHRcdGVuZCA9IHRvdGFsUm93cztcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdHRvdGFsUm93cyA9IDA7XG5cdFx0XHRcdHN0YXJ0ID0gMDtcblx0XHRcdFx0ZW5kID0gMDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvL0NvdW50aW5nIHBhZ2VzIGNhbiBiZSBkaXNhYmxlZCwgaW4gd2hpY2ggY2FzZSB0b3RhbFJvd3MgcmV0dXJucyBGQUxTRSB1bmxlc3MgdGhlIHVzZXIgaXMgb24gdGhlIGxhc3QgcGFnZS5cblx0XHR2YXIgdG90YWxJbmZvID0gc3RhcnQgKyAnIC0gJyArIGVuZDtcblx0XHRpZiAoIHRvdGFsUm93cyAhPT0gZmFsc2UgKSB7XG5cdFx0XHR0b3RhbEluZm8gPSB0b3RhbEluZm8gKyAnICcgKyAkLmkxOG4uXyggJ29mJyApICsgJyAnICsgdG90YWxSb3dzICsgJyAnICsgJC5pMThuLl8oICd0b3RhbCcgKSArICcuJztcblx0XHR9XG5cblx0XHR0aGlzLnRvdGFsX2Rpc3BsYXlfc3Bhbi50ZXh0KCAkLmkxOG4uXyggJ0Rpc3BsYXlpbmcnICkgKyAnICcgKyB0b3RhbEluZm8gKyAnIFsgJyArICQuaTE4bi5fKCAnU2VsZWN0ZWQnICkgKyAnOiAnICsgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKyAnIF0nICk7XG5cdH1cblxuXHRpc0NvbnRleHRJY29uRGlzYWJsZWQoIGlkICkge1xuXHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXHRcdHZhciBsZW4gPSBjb250ZXh0X21lbnVfYXJyYXkubGVuZ3RoO1xuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRsZXQgY29udGV4dF9idG4gPSBjb250ZXh0X21lbnVfYXJyYXlbaV07XG5cdFx0XHRpZiAoIGNvbnRleHRfbWVudV9hcnJheVtpXS5pZCA9PT0gaWQgKSB7XG5cdFx0XHRcdGlmICggY29udGV4dF9idG4uZGlzYWJsZWQgfHwgKCBjb250ZXh0X2J0bi5oYXNPd25Qcm9wZXJ0eSggJ3Zpc2libGUnICkgJiYgIWNvbnRleHRfYnRuLnZpc2libGUgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTsgLy9DYW5ub3QgZmluZCBjb250ZXh0IG1lbnUgYnV0dG9uLCByZXR1cm4gdHJ1ZSBhcyBpZiBidXR0b24gaXMgZGlzYWJsZWQgLyBjYW5ub3QgYmUgdXNlZC5cblx0fVxuXG5cdGdldFZpZXdNb2RlRXJyb3JNZXNzYWdlKCkge1xuXHRcdC8vQ2hhbmdlIGVycm9yIG1lc3NhZ2UgZGVwZW5kaW5nIG9uIGlmIGVkaXQgY29udGV4dCBtZW51IGljb24gaXMgYXZhaWxhYmxlIG9yIG5vdC5cblx0XHRpZiAoIHRoaXMuaXNDb250ZXh0SWNvbkRpc2FibGVkKCAnZWRpdCcgKSApIHtcblx0XHRcdHJldHVybiBHbG9iYWwudmlld19tb2RlX21lc3NhZ2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIEdsb2JhbC52aWV3X21vZGVfbWVzc2FnZSArICcsICcgKyBHbG9iYWwudmlld19tb2RlX2VkaXRfbWVzc2FnZTtcblx0fVxuXG5cdC8vU2V0IHJpZ2h0IGNsaWNrIG1lbnUgZm9yIGxpc3QgdmlldyBncmlkXG5cdGluaXRSaWdodENsaWNrTWVudSggdGFyZ2V0X3R5cGUgKSB7XG5cdFx0Ly9FcnJvcjogT2JqZWN0IGRvZXNuJ3Qgc3VwcG9ydCBwcm9wZXJ0eSBvciBtZXRob2QgJ2NvbnRleHRNZW51JyBpbiAvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTcuNC42LTIwMTQxMDI3LTEzMjczMyBsaW5lIDM5M1xuXHRcdGlmICggISQuaGFzT3duUHJvcGVydHkoICdjb250ZXh0TWVudScgKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBzZWxlY3RvciA9ICcnO1xuXG5cdFx0c3dpdGNoICggdGFyZ2V0X3R5cGUgKSB7XG5cdFx0XHRjYXNlIFJpZ2h0Q2xpY2tNZW51VHlwZS5MSVNUVklFVzpcblx0XHRcdFx0c2VsZWN0b3IgPSAnI2dib3hfJyArIHRoaXMudWlfaWQgKyAnX2dyaWQnO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgUmlnaHRDbGlja01lbnVUeXBlLkVESVRWSUVXOlxuXHRcdFx0XHRzZWxlY3RvciA9ICcjJyArIHRoaXMudWlfaWQgKyAnX2VkaXRfdmlld190YWInO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgUmlnaHRDbGlja01lbnVUeXBlLk5PUkVTVUxUQk9YOlxuXHRcdFx0XHRzZWxlY3RvciA9ICcjJyArIHRoaXMudWlfaWQgKyAnX25vX3Jlc3VsdF9ib3gnO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgUmlnaHRDbGlja01lbnVUeXBlLkFCU0VOQ0VfR1JJRDpcblx0XHRcdFx0c2VsZWN0b3IgPSAnIycgKyB0aGlzLnVpX2lkICsgJ19hYnNlbmNlX2dyaWQnO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgUmlnaHRDbGlja01lbnVUeXBlLlZJRVdfSUNPTjpcblx0XHRcdFx0c2VsZWN0b3IgPSAnIycgKyAndmlld19odG1sJztcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRzZWxlY3RvciA9ICcjZ2JveF8nICsgdGhpcy51aV9pZCArICdfZ3JpZCc7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0fVxuXG5cdFx0aWYgKCAkKCBzZWxlY3RvciApLmxlbmd0aCA9PSAwICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBpdGVtcyA9IHRoaXMuZ2V0UmlnaHRDbGlja01lbnVJdGVtcygpO1xuXG5cdFx0aWYgKCAhaXRlbXMgfHwgJC5pc0VtcHR5T2JqZWN0KCBpdGVtcyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQkLmNvbnRleHRNZW51KCAnZGVzdHJveScsIHNlbGVjdG9yICk7XG5cdFx0JC5jb250ZXh0TWVudSgge1xuXHRcdFx0c2VsZWN0b3I6IHNlbGVjdG9yLFxuXHRcdFx0Y2FsbGJhY2s6IGZ1bmN0aW9uKCBrZXksIG9wdGlvbnMgKSB7XG5cdFx0XHRcdCR0aGlzLm9uQ29udGV4dE1lbnVDbGljayggbnVsbCwga2V5ICk7XG5cdFx0XHR9LFxuXG5cdFx0XHRvbkNvbnRleHRNZW51OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fSxcblx0XHRcdGl0ZW1zOiBpdGVtc1xuXHRcdH0gKTtcblx0fVxuXG5cdGdldFJpZ2h0Q2xpY2tNZW51SXRlbXMoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBpdGVtcyA9IHt9O1xuXHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXHRcdHZhciBsZW4gPSBjb250ZXh0X21lbnVfYXJyYXkubGVuZ3RoO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGNvbnRleHRfYnRuID0gY29udGV4dF9tZW51X2FycmF5W2ldO1xuXG5cdFx0XHRpZiAoIGNvbnRleHRfYnRuLnZpc2libGUgPT09IGZhbHNlIHx8IGNvbnRleHRfYnRuLmFjdGlvbl9ncm91cF9oZWFkZXIgfHwgY29udGV4dF9idG4uc2VwYXJhdG9yIHx8ICFjb250ZXh0X2J0bi5zaG93X29uX3JpZ2h0X2NsaWNrICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGxhYmVsID0gR2xvYmFsLmh0bWxEZWNvZGUoIGNvbnRleHRfYnRuLmxhYmVsLnJlcGxhY2UoICc8YnI+JywgJyAnICkgKTtcblx0XHRcdHZhciBpZCA9IGNvbnRleHRfYnRuLmlkO1xuXG5cdFx0XHRpdGVtc1tpZF0gPSB7XG5cdFx0XHRcdG5hbWU6IGxhYmVsLFxuXHRcdFx0XHRkaXNhYmxlZDogZnVuY3Rpb24oIGtleSApIHtcblx0XHRcdFx0XHRyZXR1cm4gJHRoaXMuaXNDb250ZXh0SWNvbkRpc2FibGVkKCBrZXkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9XG5cblx0XHRyZXR1cm4gaXRlbXM7XG5cdH1cblxuXHQvL0Rvbid0IGluaXRPcHRpb25zIGlmIGVkaXRfb25seV9tb2RlLiBEbyBpdCBpbiBzdWIgdmlld3Ncblx0aW5pdERhdGEoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdC8vV29yayBhcm91bmQgdG8gaW5pdCBzdWIgdmlldyBhZnRlciB0YWIgaXMgc2hvd24uXG5cdFx0R2xvYmFsLnJlbW92ZVZpZXdUYWIoIHRoaXMudmlld0lkICk7XG5cdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHRpZiAoICEkdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblxuXHRcdFx0Ly9WYXJpb3VzIHZpZXdzIGV4cGVjdCBzZWFyY2ggZmllbGRzIHRvIGJlIGJ1aWx0IGFscmVhZHksIHN1Y2ggYXMgaW5pdE9wdGlvbnMoKSBpbiBQdW5jaGVzVmlld0NvbnRyb2xsZXIgb3IgZ2V0QWxsQ29sdW1ucygpIGluIFNjaGVkdWxlVmlld0NvbnRyb2xsZXIuXG5cdFx0XHQvL0JlY2F1c2Ugb2YgdGhhdCB3ZSBuZWVkIHRvIHdhaXQgZm9yIHJlc29sdXRpb24gb2YgZ2V0Q3VzdG9tRmllbGRzIHByb21pc2UgdG8gYXZvaWQgZXhjZXB0aW9ucyBhbmQgYnJlYWtpbmcgdmlld3MuXG5cdFx0XHRUVFByb21pc2Uud2FpdCggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXRDdXN0b21GaWVsZHMnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMuaW5pdE9wdGlvbnMoKTtcblx0XHRcdFx0JHRoaXMuZ2V0QWxsQ29sdW1ucyggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JHRoaXMuaW5pdExheW91dCgpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdC8vV2hlbiBvbiBhIHN1YiB2aWV3IG1vZGUgdGFiIHdlIHdhbnQgdG8gZGlzYWJsZSBjZXJ0YWluIGNvbnRleHQgbWVudSBidXR0b25zIG9mIHRoZSBwYXJlbnQgdmlldy5cblx0XHRcdC8vVGhpcyBpcyB0byBoZWxwIHByZXZlbnQgdXNlcnMgZnJvbSB1c2luZyBjb250ZXh0IG1lbnUgYnV0dG9ucyBmb3IgdGhlIHdyb25nIHZpZXcgYW5kIGRlbGV0aW5nL2NvcHlpbmcgcmVjb3JkcyB0aGV5IGRpZCBub3QgaW50ZW5kIHRvIHVzZS5cblx0XHRcdHRoaXMub25TdWJWaWV3TW9kZURpc2FibGVQYXJlbnRDb250ZXh0TWVudUJ1dHRvbnMoKTtcblx0XHR9XG5cdH1cblxuXHRpbml0TGF5b3V0KCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0JHRoaXMuZ2V0QWxsTGF5b3V0cyggZnVuY3Rpb24oKSB7XG5cdFx0XHQkdGhpcy5nZXREZWZhdWx0RGlzcGxheUNvbHVtbnMoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5zZXRTZWxlY3RMYXlvdXQoKTtcblx0XHRcdFx0Ly8kdGhpcy5zZXRHcmlkQ29sdW1uc1dpZHRoKCk7IC8vVGhpcyBpcyBkb25lIGluIHNldFNlbGVjdExheW91dCgpIGFuZCBzZWFyY2hEb25lKCksIHNvIG5vIHBvaW50IGluIGRvaW5nIGl0IG11bHRpcGxlIHRpbWVzLlxuXHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBlZGl0X29ubHlfbW9kZSBjYWxsIHRoaXMgd2hlbiBvcGVuIGVkaXQgdmlldy4gTm90IGluIGluaXREYXRhXG5cdGluaXRPcHRpb25zKCkge1xuXHR9XG5cblx0Ly8gVE9ETzogQ29uc29saWRhdGUgaWQgYW5kIG1lbnUgY29udGFpbmVyIGludG8gb25lIGZ1bmN0aW9uLlxuXHQvKipcblx0ICogRGV0ZXJtaW5lIHdoYXQgaWQsIG1vdW50IHBvaW50LCBhbmQgbWVudSB0eXBlIGFyZSBuZWVkZWQgdG8gY3JlYXRlIHRoZSBjb250ZXh0IG1lbnUgZm9yIGEgc3BlY2lmaWMgdmlldy9lZGl0IHZpZXcsIGJhc2VkIG9uIHRoZSBjdXJyZW50IHZpZXcgc3RhdGUuIE1haW4sIEVkaXQgVmlldywgU3ViIFZpZXcgZXRjLlxuXHQgKi9cblx0ZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKSB7XG5cdFx0dmFyIHJldHVybl9vYmplY3QgPSB7XG5cdFx0XHRpZDogbnVsbCxcblx0XHRcdHBhcmVudF9tb3VudF9wb2ludDogbnVsbCxcblx0XHRcdG1lbnVfdHlwZTogbnVsbCxcblx0XHRcdHBhcmVudF9pZDogbnVsbFxuXHRcdH07XG5cblx0XHQvLyBGaWd1cmUgb3V0IHBhcmVudCB0eXBlXG5cblx0XHQvKiBCZSBhd2FyZSB0aGF0IGlmIHNvbWV0aGluZyBpcyBpbmNvcnJlY3RseSBtYXRjaGVkIGhlcmUsIGl0IG1heSB0cnkgdG8gbWF0Y2ggd2l0aCBhIHdyb25nIG1lbnUsIG9yIGV4aXN0aW5nIG90aGVyIG1lbnUsXG5cdFx0ICogYW5kIHRodXMgbWF5IGhhdmUgdGhlIHNpZGUgZWZmZWN0IG9mIGNsb3NpbmcgdGhlIHdyb25nIG1lbnUgd2hlbiBhIHdpbmRvdyBpcyBjbG9zZWQuXG5cdFx0ICogSWYgdGhhdCBzeW1wdG9tIGhhcHBlbnMsIGNoZWNrIHRoZSBtYXRjaGluZyBoZXJlLlxuXHRcdCAqL1xuXG5cdFx0Ly8gWW91IGNhbiBzZWUgYW4gZXh0ZW5zaXZlIGxpc3QgaW4gc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoKS5cblx0XHRpZiggdGhpcy5pc19hZGRcblx0XHRcdHx8IHRoaXMuaXNfdmlld2luZ1xuXHRcdFx0fHwgdGhpcy5pc192aWV3aW5nX2RldGFpbCAvL0Nhbm5vdCB1c2UganVzdCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID09PSAndmlld19kZXRhaWwnIGFzIGl0IGdldHMgb3ZlcndyaXR0ZW4gdG8gY2FuY2VsLlxuXHRcdFx0fHwgdGhpcy5pc19lZGl0XG5cdFx0XHR8fCB0aGlzLmlzX21hc3NfZWRpdGluZ1xuXHRcdFx0fHwgdGhpcy5pc19tYXNzX2FkZGluZyAvLyBOb3QgdGVzdGVkLCBidXQgYXMgYWxsIHRoZSBvdGhlcnMgZnJvbSBzZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSBhcmUgbm93IGhlcmUsIG1pZ2h0IGFzIHdlbGwgYWRkIGl0LlxuXHRcdFx0fHwgdGhpcy5lZGl0X29ubHlfbW9kZVxuXHRcdFx0fHwgTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9PT0gJ3ZpZXdfZGV0YWlsJyAvL1dpdGggaXNfdmlld2luZ19kZXRhaWwgd2UgbWF5IG5vIGxvbmdlciBuZWVkIHRoaXMgY29uZGl0aW9uLlxuXHRcdFx0fHwgTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9PT0gJ2RlbGV0ZSdcblx0XHQpIHtcblx0XHRcdHJldHVybl9vYmplY3QgPSB0aGlzLnBhcnNlQ29udGV4dE1lbnVFZGl0Vmlld0F0dHJpYnV0ZXMoKTtcblx0XHR9IGVsc2UgaWYoICQoIHRoaXMuZWwgKS5wYXJlbnRzKCAnLmVkaXQtdmlldy10YWItb3V0c2lkZS1zdWItdmlldycgKS5sZW5ndGggPiAwICYmIHRoaXMudWlfaWQgKSB7XG5cdFx0XHQvLyBVc2luZyB0aGlzIGFwcHJvYWNoIHJhdGhlciB0aGFuIHRoaXMuc3ViX3ZpZXdfbW9kZSwgYXMgc29tZSB2aWV3cyBoYXZlIGVkaXQgdmlld3Mgc3RpbGwgc2hvd2luZyBhcyBzdWJ2aWV3cy5cblx0XHRcdC8vICNWdWVDb250ZXh0TWVudSNTdWJWaWV3cyMgT2xkIGFwcHJvYWNoIGNhbiBiZSBmb3VuZCBpbiBCYXNlVkMucGFyc2VDdXN0b21Db250ZXh0TW9kZWxGb3JTdWJWaWV3cyBidXQgaXRzIGJldHRlciB0byBjb250cm9sIGl0IGZyb20gaGVyZSBpbiBvbmUgcGxhY2UuXG5cdFx0XHQvLyBUaGVzZSBtYXRjaGVzIHdvdWxkIHByZXZpb3VzbHkgbWF0Y2ggdG8gbWFpbl92aWV3LCBidXQgc3Vidmlld3Mgc2hvdWxkIGJlIGRpZmZlcmVudCB0byBtYWluIHZpZXdzLlxuXHRcdFx0cmV0dXJuX29iamVjdCA9IHRoaXMucGFyc2VDb250ZXh0TWVudUVkaXRTdWJWaWV3VGFiQXR0cmlidXRlcygpO1xuXHRcdH1cblx0XHRlbHNlIGlmKCB0aGlzLnVpX2lkICkge1xuXHRcdFx0cmV0dXJuX29iamVjdCA9IHRoaXMucGFyc2VDb250ZXh0TWVudU1haW5WaWV3QXR0cmlidXRlcygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBJZiBlYWNoIHZpZXcgaGFzIGEgdW5pcXVlIGNvbnRleHQgbWVudSwgdGhlbiB0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIGFzIGNvbnRleHQgbWVudSBzaG91bGQgb25seSBiZSBpbml0aWF0ZWQgb25jZS5cblx0XHRcdC8vIEhvd2V2ZXIsIHRoZXJlIGFyZSBtYW55IGNhc2VzIHdoZXJlIHRhYnMgcmVwZWF0ZWRseSBjYWxsIHRoaXMuYnVpbGRDb250ZXh0TWVudSwgd2hpbHN0IGtlZXBpbmcgdGhlIHNhbWUgdmlldyBjb250cm9sbGVyLCBzbyB0aGlzIGlzIG5vdyBhIHdhcm5pbmcgcmF0aGVyIHRoYW4gYW4gZXJyb3IuXG5cdFx0XHREZWJ1Zy5FcnJvciggJ0Vycm9yOiBWaWV3IHN0YXRlIGZvciAnKyB0aGlzLnZpZXdJZCArJyAoJysgdGhpcy51aV9pZCArJykgZG9lcyBub3QgbWF0Y2ggb3B0aW9ucy4nLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdkZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcycsIDEgKTtcblx0XHR9XG5cblx0XHQvLyBSZWdhcmRsZXNzIG9mIGVkaXR2aWV3L21haW4gdHlwZSBhYm92ZSwgdGhlcmUgYXJlIHNvbWUgb2NjYXNpb25zIHdoZW4gaXQgZGV0ZWN0cyBhcyBtYWluIG1lbnUsIGJ1dCBpdHMgc3RpbGwgd2l0aGluIHRhYnMuXG5cdFx0Ly8gSGVyZSBpdCB3b3VsZCBiZSBFZGl0IFZpZXcgLT4gVGFicyAtPiBTdWJ2aWV3LiBGb3IgZXhhbXBsZSBBdHRlbmRhbmNlLT5BY2NydWFsIEJhbGFuY2UgLT4gVmlldy5cblx0XHQvLyBUaGUgdG9wIGljb25zIGFyZSBlZGl0IHZpZXcgZm9yIEFjY3J1YWxCYWxhbmNlVmlldy5cblx0XHQvLyBUaGUgaWNvbnMgd2l0aGluIEFjY3J1YWwgdGFiIGFyZSBzZWVuIGFzIGEgbWFpbiBtZW51IGZvciBBY2NydWFsVmlldy5cblx0XHQvLyBMZXRzIGFkZCB0aGVzZSBvY2N1cmFuY2VzIGludG8gYW5vdGhlciB0eXBlLlxuXG5cdFx0Ly8gR2V0IElEXG5cdFx0cmV0dXJuX29iamVjdC5pZCA9IENvbnRleHRNZW51TWFuYWdlci5nZW5lcmF0ZU1lbnVJZCggcmV0dXJuX29iamVjdC5tZW51X3R5cGUsIHJldHVybl9vYmplY3QucGFyZW50X2lkICk7XG5cblx0XHRyZXR1cm4gcmV0dXJuX29iamVjdDtcblx0fVxuXG5cdHBhcnNlQ29udGV4dE1lbnVFZGl0Vmlld0F0dHJpYnV0ZXMoKSB7XG5cdFx0Ly8gRGVzaWduZWQgdG8gYmUgb3ZlcnJpZGVuIGJ5IHZpZXdzIGlmIGJlaGF2aW91ciBuZWVkcyB0byBiZSBkaWZmZXJlbnQuXG5cdFx0Ly8gQWxsIHRoZSBlZGl0X3ZpZXcgc3R5bGUgd2luZG93cy4gQWx0aG91Z2ggdGhlIGVkaXRfb25seSBvbmVzIGhhdmUgYSBzbGlnaHRseSBkaWZmZXJlbnQgdGhpcy51aV9pZCB2YWx1ZSwgYnV0IHRoZSBjb2RlIGlzIHRoZSBzYW1lLlxuXHRcdGlmKCAhdGhpcy5lZGl0X3ZpZXdfdGFiICkge1xuXHRcdFx0Ly8gSWYgbW91bnQgcG9pbnQgSVMgbmVlZGVkIChub3QganVzdCBtZW51IElEKSwgdGhlbiB0aGlzIGlzIGEgYnVnLiBDaGVjayBpZiBidWlsZENvbnRleHRNZW51IGlzIG5vdCBjYWxsZWQgYmVmb3JlIGVkaXRfdmlld190YWIgcG9wdWxhdGVkIChjb21tb24gaW4gdmlld3Mgb3ZlcnJpZGluZyBCYXNlVmlldyBmdW5jdGlvbnMgbGlrZSBvcGVuRWRpdFZpZXcuXG5cdFx0XHREZWJ1Zy5UZXh0KCAnV2FybmluZzogVW5hYmxlIHRvIGdldCBmdWxsIGNvbnRleHQgbWVudSBtb3VudCBkYXRhLCBlZGl0X3ZpZXdfdGFiIG1pc3NpbmcuIE1pZ2h0IGJlIG9rIGlmIG1vdW50IHBvaW50IG5vdCBuZWVkZWQuIENoZWNrIGlmIGJ1aWxkQ29udGV4dE1lbnUgaXMgbm90IGNhbGxlZCBiZWZvcmUgZWRpdF92aWV3X3RhYiBwb3B1bGF0ZWQgKGNvbW1vbiBpbiB2aWV3cyBvdmVycmlkaW5nIEJhc2VWaWV3IGZ1bmN0aW9ucyBsaWtlIG9wZW5FZGl0VmlldyAoJysgdGhpcy52aWV3SWQgKycvJysgdGhpcy51aV9pZCArJyknLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdwYXJzZUNvbnRleHRNZW51RWRpdFZpZXdBdHRyaWJ1dGVzJywgMTAgKTtcblx0XHR9XG5cdFx0aWYoICF0aGlzLnVpX2lkICkge1xuXHRcdFx0RGVidWcuRXJyb3IoICdXYXJuaW5nOiBVbmFibGUgdG8gZ2V0IGZ1bGwgY29udGV4dCBtZW51IG1vdW50IGRhdGEsIHVpX2lkIG1pc3NpbmcuICgnKyB0aGlzLnZpZXdJZCArJy8nKyB0aGlzLnVpX2lkICsnKScsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ3BhcnNlQ29udGV4dE1lbnVFZGl0Vmlld0F0dHJpYnV0ZXMnLCAxICk7XG5cdFx0fVxuXHRcdHJldHVybiB7XG5cdFx0XHRwYXJlbnRfbW91bnRfcG9pbnQ6IHRoaXMuZWRpdF92aWV3X3RhYiwgLy8gTm90ZTogV2hlbiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhlIGVkaXRfdmlld190YWIgbWlnaHQgbm90IGJlIGJ1aWx0IHlldCwgc28gcGFyZW50IG1vdW50IGNvdWxkIGJlIG51bGwsIHRoYXRzIG9rIGlmIG1vdW50IHBvaW50IG5vdCBuZWVkZWQgeWV0LlxuXHRcdFx0cGFyZW50X2lkOiB0aGlzLnVpX2lkICsgJ19lZGl0X3ZpZXdfdGFiJyxcblx0XHRcdG1lbnVfdHlwZTogJ2VkaXR2aWV3X2NvbnRleHRtZW51Jyxcblx0XHR9XG5cdH1cblx0cGFyc2VDb250ZXh0TWVudU1haW5WaWV3QXR0cmlidXRlcygpIHtcblx0XHQvLyBEZXNpZ25lZCB0byBiZSBvdmVycmlkZW4gYnkgdmlld3MgaWYgYmVoYXZpb3VyIG5lZWRzIHRvIGJlIGRpZmZlcmVudC5cblx0XHQvLyBNYWluIHZpZXdzXG5cblx0XHRpZiggIXRoaXMudWlfaWQgKSB7XG5cdFx0XHREZWJ1Zy5FcnJvciggJ1dhcm5pbmc6IFVuYWJsZSB0byBnZXQgZnVsbCBjb250ZXh0IG1lbnUgbW91bnQgZGF0YSwgdWlfaWQgbWlzc2luZy4gKCcrIHRoaXMudmlld0lkICsnLycrIHRoaXMudWlfaWQgKycpJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAncGFyc2VDb250ZXh0TWVudUVkaXRWaWV3QXR0cmlidXRlcycsIDEgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFyZW50X21vdW50X3BvaW50OiAkKCB0aGlzLmVsICksXG5cdFx0XHRwYXJlbnRfaWQ6IHRoaXMudWlfaWQsXG5cdFx0XHRtZW51X3R5cGU6ICdsaXN0dmlld19jb250ZXh0bWVudScsXG5cdFx0fVxuXHR9XG5cblx0cGFyc2VDb250ZXh0TWVudUVkaXRTdWJWaWV3VGFiQXR0cmlidXRlcygpIHtcblx0XHQvLyBEZXNpZ25lZCB0byBiZSBvdmVycmlkZW4gYnkgdmlld3MgaWYgYmVoYXZpb3VyIG5lZWRzIHRvIGJlIGRpZmZlcmVudC5cblx0XHQvLyBCYXNlZCBvbiBtYWluX2NvbnRleHRtZW51XG5cblx0XHRpZiggIXRoaXMudWlfaWQgKSB7XG5cdFx0XHREZWJ1Zy5FcnJvciggJ1dhcm5pbmc6IFVuYWJsZSB0byBnZXQgZnVsbCBjb250ZXh0IG1lbnUgbW91bnQgZGF0YSwgdWlfaWQgbWlzc2luZy4gKCcrIHRoaXMudmlld0lkICsnLycrIHRoaXMudWlfaWQgKycpJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAncGFyc2VDb250ZXh0TWVudUVkaXRWaWV3QXR0cmlidXRlcycsIDEgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0cGFyZW50X21vdW50X3BvaW50OiAkKCB0aGlzLmVsICksXG5cdFx0XHRwYXJlbnRfaWQ6IHRoaXMudWlfaWQsXG5cdFx0XHRtZW51X3R5cGU6ICdzdWJ2aWV3X2NvbnRleHRtZW51Jyxcblx0XHR9XG5cdH1cblxuXHRnZXREZWZhdWx0Q29udGV4dE1lbnVNb2RlbCgpIHtcblxuXHRcdHZhciBkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbCA9IHtcblx0XHRcdCdncm91cHMnOiB7XG5cdFx0XHRcdCdlZGl0b3InOiB7XG5cdFx0XHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRWRpdG9yJyApLFxuXHRcdFx0XHRcdGlkOiAnZWRpdG9yJyxcblx0XHRcdFx0XHRzb3J0X29yZGVyOiAxMDAwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdCduYXZpZ2F0aW9uJzoge1xuXHRcdFx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ05hdmlnYXRpb24nICksXG5cdFx0XHRcdFx0aWQ6ICduYXZpZ2F0aW9uJyxcblx0XHRcdFx0XHRzb3J0X29yZGVyOiA4MDAwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdCdvdGhlcic6IHtcblx0XHRcdFx0XHRsYWJlbDogJC5pMThuLl8oICdPdGhlcicgKSxcblx0XHRcdFx0XHRpZDogJ290aGVyJyxcblx0XHRcdFx0XHRzb3J0X29yZGVyOiA5MDAwXG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cblx0XHRcdCdpY29ucyc6IHt9XG5cdFx0fTtcblxuXHRcdGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsWydpY29ucyddWydhZGQnXSA9IHtcblx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ05ldycgKSxcblx0XHRcdGlkOiAnYWRkJyxcblx0XHRcdGdyb3VwOiAnZWRpdG9yJyxcblx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1hZGRfYmxhY2tfMjRkcCcsXG5cdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0c29ydF9vcmRlcjogMTAwMFxuXHRcdH07XG5cblx0XHRkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbFsnaWNvbnMnXVsndmlldyddID0ge1xuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnVmlldycgKSxcblx0XHRcdGlkOiAndmlldycsXG5cdFx0XHRncm91cDogJ2VkaXRvcicsXG5cdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tdmlzaWJpbGl0eV9ibGFja18yNGRwJyxcblx0XHRcdHNob3dfb25fcmlnaHRfY2xpY2s6IHRydWUsXG5cdFx0XHRzb3J0X29yZGVyOiAxMDEwXG5cdFx0fTtcblxuXHRcdGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsWydpY29ucyddWydlZGl0J10gPSB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdFZGl0JyApLFxuXHRcdFx0aWQ6ICdlZGl0Jyxcblx0XHRcdGdyb3VwOiAnZWRpdG9yJyxcblx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1lZGl0X2JsYWNrXzI0ZHAnLFxuXHRcdFx0c2hvd19vbl9yaWdodF9jbGljazogdHJ1ZSxcblx0XHRcdHNvcnRfb3JkZXI6IDEwMjAsXG5cdFx0XHQvL21pbl93aWR0aDogJzg1JyAvKiBNYXRjaCB3aXRoIG1hc3NfZWRpdCBzbyB0aGV5IGNhbiB0b2dnbGUgd2l0aG91dCBtb3ZpbmcgYW55IG1lbnUgaXRlbXMgaW4gVUkgKi9cblx0XHR9O1xuXG5cdFx0ZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWxbJ2ljb25zJ11bJ21hc3NfZWRpdCddID0ge1xuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnTWFzcyBFZGl0JyApLFxuXHRcdFx0aWQ6ICdtYXNzX2VkaXQnLFxuXHRcdFx0Z3JvdXA6ICdlZGl0b3InLFxuXHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLWVkaXRfbm90ZV9ibGFja18yNGRwJyxcblx0XHRcdHNob3dfb25fcmlnaHRfY2xpY2s6IHRydWUsXG5cdFx0XHR2aXNpYmxlOiBmYWxzZSwgLy8gRW5zdXJlcyBNYXNzIEVkaXQgaXMgbm90IHNob3duIGF0IHN0YXJ0IHRvZ2V0aGVyIHdpdGggRWRpdC4gV2Ugb25seSB3YW50IG9uZSBvciB0aGUgb3RoZXIuXG5cdFx0XHRzb3J0X29yZGVyOiAxMDMwLFxuXHRcdFx0Ly9taW5fd2lkdGg6ICc4NScgLyogTWF0Y2ggd2l0aCBlZGl0IHNvIHRoZXkgY2FuIHRvZ2dsZSB3aXRob3V0IG1vdmluZyBhbnkgbWVudSBpdGVtcyBpbiBVSSAqL1xuXHRcdH07XG5cblx0XHRkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbFsnaWNvbnMnXVsnZGVsZXRlX2ljb24nXSA9IHtcblx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ0RlbGV0ZScgKSxcblx0XHRcdGlkOiAnZGVsZXRlX2ljb24nLFxuXHRcdFx0YWN0aW9uX2dyb3VwOiAnZGVsZXRlJyxcblx0XHRcdGdyb3VwOiAnZWRpdG9yJyxcblx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1kZWxldGVfYmxhY2tfMjRkcCcsXG5cdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0c29ydF9vcmRlcjogMTA0MFxuXHRcdH07XG5cblx0XHRkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbFsnaWNvbnMnXVsnZGVsZXRlX2FuZF9uZXh0J10gPSB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdEZWxldGUgJiBOZXh0JyApLFxuXHRcdFx0aWQ6ICdkZWxldGVfYW5kX25leHQnLFxuXHRcdFx0YWN0aW9uX2dyb3VwOiAnZGVsZXRlJyxcblx0XHRcdGdyb3VwOiAnZWRpdG9yJyxcblx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1kZWxldGVfYmxhY2tfMjRkcCcsXG5cdFx0XHRzb3J0X29yZGVyOiAxMDUwXG5cdFx0fTtcblxuXHRcdGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsWydpY29ucyddWydjb3B5J10gPSB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdDb3B5JyApLFxuXHRcdFx0aWQ6ICdjb3B5Jyxcblx0XHRcdGFjdGlvbl9ncm91cDogJ2NvcHknLFxuXHRcdFx0Z3JvdXA6ICdlZGl0b3InLFxuXHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLWNvbnRlbnRfY29weV9ibGFja18yNGRwJyxcblx0XHRcdHNob3dfb25fcmlnaHRfY2xpY2s6IHRydWUsXG5cdFx0XHRzb3J0X29yZGVyOiAxMDYwXG5cdFx0fTtcblxuXHRcdGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsWydpY29ucyddWydjb3B5X2FzX25ldyddID0ge1xuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnQ29weSBhcyBOZXcnICksXG5cdFx0XHRpZDogJ2NvcHlfYXNfbmV3Jyxcblx0XHRcdGFjdGlvbl9ncm91cDogJ2NvcHknLFxuXHRcdFx0Z3JvdXA6ICdlZGl0b3InLFxuXHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLWNvbnRlbnRfY29weV9ibGFja18yNGRwJyxcblx0XHRcdHNob3dfb25fcmlnaHRfY2xpY2s6IHRydWUsXG5cdFx0XHRzb3J0X29yZGVyOiAxMDcwXG5cdFx0fTtcblxuXHRcdGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsWydpY29ucyddWydzYXZlJ10gPSB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdTYXZlJyApLFxuXHRcdFx0aWQ6ICdzYXZlJyxcblx0XHRcdGFjdGlvbl9ncm91cDogJ3NhdmUnLFxuXHRcdFx0Z3JvdXA6ICdlZGl0b3InLFxuXHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLXNhdmVfYmxhY2tfMjRkcCcsXG5cdFx0XHRzaG93X29uX3JpZ2h0X2NsaWNrOiB0cnVlLFxuXHRcdFx0c29ydF9vcmRlcjogMTA4MFxuXHRcdH07XG5cblx0XHRkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbFsnaWNvbnMnXVsnc2F2ZV9hbmRfY29udGludWUnXSA9IHtcblx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1NhdmUgJiBDb250aW51ZScgKSxcblx0XHRcdGlkOiAnc2F2ZV9hbmRfY29udGludWUnLFxuXHRcdFx0YWN0aW9uX2dyb3VwOiAnc2F2ZScsXG5cdFx0XHRncm91cDogJ2VkaXRvcicsXG5cdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tc2F2ZV9ibGFja18yNGRwJyxcblx0XHRcdHNvcnRfb3JkZXI6IDEwOTBcblx0XHR9O1xuXG5cdFx0ZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWxbJ2ljb25zJ11bJ3NhdmVfYW5kX25leHQnXSA9IHtcblx0XHRcdGxhYmVsOiAkLmkxOG4uXyggJ1NhdmUgJiBOZXh0JyApLFxuXHRcdFx0aWQ6ICdzYXZlX2FuZF9uZXh0Jyxcblx0XHRcdGFjdGlvbl9ncm91cDogJ3NhdmUnLFxuXHRcdFx0Z3JvdXA6ICdlZGl0b3InLFxuXHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLXNhdmVfYmxhY2tfMjRkcCcsXG5cdFx0XHRzb3J0X29yZGVyOiAxMTAwXG5cdFx0fTtcblxuXHRcdGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsWydpY29ucyddWydzYXZlX2FuZF9jb3B5J10gPSB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdTYXZlICYgQ29weScgKSxcblx0XHRcdGlkOiAnc2F2ZV9hbmRfY29weScsXG5cdFx0XHRhY3Rpb25fZ3JvdXA6ICdzYXZlJyxcblx0XHRcdGdyb3VwOiAnZWRpdG9yJyxcblx0XHRcdHZ1ZV9pY29uOiAndHRpY29uIHR0aWNvbi1zYXZlX2JsYWNrXzI0ZHAnLFxuXHRcdFx0c29ydF9vcmRlcjogMTExMFxuXHRcdH07XG5cblx0XHRkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbFsnaWNvbnMnXVsnc2F2ZV9hbmRfbmV3J10gPSB7XG5cdFx0XHRsYWJlbDogJC5pMThuLl8oICdTYXZlICYgTmV3JyApLFxuXHRcdFx0aWQ6ICdzYXZlX2FuZF9uZXcnLFxuXHRcdFx0YWN0aW9uX2dyb3VwOiAnc2F2ZScsXG5cdFx0XHRncm91cDogJ2VkaXRvcicsXG5cdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tc2F2ZV9ibGFja18yNGRwJyxcblx0XHRcdHNvcnRfb3JkZXI6IDExMjBcblx0XHR9O1xuXG5cdFx0ZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWxbJ2ljb25zJ11bJ2NhbmNlbCddID0ge1xuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnQ2FuY2VsJyApLFxuXHRcdFx0aWQ6ICdjYW5jZWwnLFxuXHRcdFx0Z3JvdXA6ICdlZGl0b3InLFxuXHRcdFx0dnVlX2ljb246ICd0dGljb24gdHRpY29uLWNhbmNlbF9ibGFja18yNGRwJyxcblx0XHRcdHNvcnRfb3JkZXI6IDExMzBcblx0XHR9O1xuXG5cdFx0ZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWxbJ2ljb25zJ11bJ2V4cG9ydF9leGNlbCddID0ge1xuXHRcdFx0bGFiZWw6ICQuaTE4bi5fKCAnRXhwb3J0JyApLFxuXHRcdFx0aWQ6ICdleHBvcnRfZXhjZWwnLFxuXHRcdFx0bWVudV9hbGlnbjogJ3JpZ2h0Jyxcblx0XHRcdGFjdGlvbl9ncm91cDogJ2ltcG9ydF9leHBvcnQnLFxuXHRcdFx0Z3JvdXA6ICdvdGhlcicsXG5cdFx0XHR2dWVfaWNvbjogJ3R0aWNvbiB0dGljb24tZmlsZV91cGxvYWRfYmxhY2tfMjRkcCcsXG5cdFx0XHRzb3J0X29yZGVyOiA5MDAwLFxuXHRcdFx0bWVudV9mb3JjZV9hY3RpdmU6IHRydWVcblx0XHR9O1xuXG5cdFx0cmV0dXJuIGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsO1xuXHR9XG5cblx0Ly8gT3ZlcnJpZGVuIGJ5IFZpZXdDb250cm9sbGVycyB3aXRoIGN1c3RvbSBjb250ZXh0IG1lbnVzLlxuXHRnZXRDdXN0b21Db250ZXh0TWVudU1vZGVsKCkge1xuXHRcdHZhciBjb250ZXh0X21lbnVfbW9kZWwgPSB7XG5cdFx0XHRncm91cHM6IHt9LFxuXHRcdFx0ZXhjbHVkZTogW10sXG5cdFx0XHRpbmNsdWRlOiBbJ2RlZmF1bHQnXVxuXHRcdH07XG5cblx0XHRyZXR1cm4gY29udGV4dF9tZW51X21vZGVsO1xuXHR9XG5cdHBhcnNlQ3VzdG9tQ29udGV4dE1vZGVsRm9yRWRpdFZpZXdzKCBjb250ZXh0X21lbnVfbW9kZWwgKSB7XG5cblx0XHQvLyAjVnVlQ29udGV4dE1lbnUjIC0gQ29tbWVudGluZyBvdXQgbG9naWMgYmVsb3cgYXMgd2Ugd2FudCB0byBoYXZlIHRoZSBtZW51IHR5cGUgbG9naWMgaW4gb25lIHBsYWNlIChCYXNlVkMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMpXG5cdFx0Ly8gaWYoIHRoaXMuaXNfYWRkXG5cdFx0Ly8gXHR8fCB0aGlzLmlzX3ZpZXdpbmdcblx0XHQvLyBcdHx8IHRoaXMuaXNfZWRpdFxuXHRcdC8vIFx0fHwgdGhpcy5pc19tYXNzX2VkaXRpbmdcblx0XHQvLyBcdHx8IHRoaXMuaXNfbWFzc19hZGRpbmcgLy8gTm90IHRlc3RlZCwgYnV0IGFzIGFsbCB0aGUgb3RoZXJzIGZyb20gc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUgYXJlIG5vdyBoZXJlLCBtaWdodCBhcyB3ZWxsIGFkZCBpdC5cblx0XHQvLyBcdHx8IHRoaXMuZWRpdF9vbmx5X21vZGVcblx0XHQvLyBcdHx8IExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPT09ICd2aWV3X2RldGFpbCdcblx0XHQvLyApIHtcblx0XHRpZiggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLm1lbnVfdHlwZSA9PT0gJ2VkaXR2aWV3X2NvbnRleHRtZW51JyApIHtcblx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLnB1c2goICdjYW5jZWwnICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGNvbnRleHRfbWVudV9tb2RlbDtcblx0fVxuXHRwYXJzZUN1c3RvbUNvbnRleHRNb2RlbEZvclN1YlZpZXdzKCBjb250ZXh0X21lbnVfbW9kZWwgKSB7XG5cdFx0Ly8gSWYgYSB2aWV3IGRvZXMgbm90IHdhbnQgdGhpcywgb3ZlcnJpZGUgdGhlIGZ1bmN0aW9uIGluIHRoYXQgdmlldyBhbmQganVzdCByZXR1cm4gdGhlIHVudG91Y2hlZCBvYmplY3QuXG5cdFx0Ly8gI1Z1ZUNvbnRleHRNZW51I1N1YlZpZXdzIyBDb21tZW50aW5nIG91dCB0aGUgbG9naWMgYmVsb3cgYXMgd2Ugc2hvdWxkIGp1c3QgaGF2ZSB0aGUgY29udHJvbGxpbmcgbG9naWMgaW4gb25lIHBsYWNlIChCYXNlVkMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMpXG5cblx0XHQvLyBpZiggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLm1lbnVfdHlwZSA9PT0gJ3N1YnZpZXdfY29udGV4dG1lbnUnXG5cdFx0Ly8gXHR8fCAodGhpcy5zdWJfdmlld19tb2RlXG5cdFx0Ly8gXHQmJiAhdGhpcy5pc19lZGl0XG5cdFx0Ly8gXHQmJiAhdGhpcy5pc192aWV3aW5nXG5cdFx0Ly8gXHQmJiBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uICE9PSAndmlldycgLy8gVG8gZW5zdXJlIHZpZXcgc3RhdGUgaXMgY2FycmllZCBmb3J3YXJkIGFjcm9zcyBzdWJ2aWV3IGxvYWRzLCBhcyBBY2NydWFsIEJhbGFuY2UgLT4gQWNjcnVhbCBWaWV3IHJlY29yZCByZXN1bHRzIGluIHRoaXMuaXNfdmlld2luZyA9PT0gZmFsc2UuXG5cdFx0Ly8gXHQmJiBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uICE9PSAnZWRpdCcgLy8gTm90ZTogU2VlIGlmIHRoZXNlIGxhc3QgMiBjaGVja3MgYXJlIHN0aWxsIG5lZWRlZCBhZnRlciBzdWJ2aWV3X2NvbnRleHRtZW51IGNoZWNrIGFkZGl0aW9uLlxuXHRcdC8vICkpIHsgLy8gVE9ETzogRG9lcyBub3Qgc2VlbSB0byB3b3JrIGZvciBBdWRpdCBsb2csIGFzIGlzX3ZpZXdpbmcgaXMgZGVsaWJlcmF0ZWx5IHNldCB0byBmYWxzZS5cblx0XHRpZiggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLm1lbnVfdHlwZSA9PT0gJ3N1YnZpZXdfY29udGV4dG1lbnUnICkge1xuXHRcdFx0Y29udGV4dF9tZW51X21vZGVsLmV4Y2x1ZGUucHVzaCggJ2NhbmNlbCcgKTsgLy8gTmVlZGVkIGFzIHN1YnZpZXcgZ3JpZCBtZW51cyBkb250IG5lZWQgdG8gYmUgYWJsZSB0byBjbG9zZSB0aGUgY3VycmVudCB3aW5kb3c7IHRoZSBtYWluIGNvbnRleHQgbWVudSBzaG91bGQgZG8gdGhhdC5cblx0XHR9XG5cblx0XHRyZXR1cm4gY29udGV4dF9tZW51X21vZGVsO1xuXHR9XG5cblx0YnVpbGRDb250ZXh0TWVudU1vZGVscygpIHtcblx0XHQvLyBOb3RlOiBDdXJyZW50bHkgaWNvbnMgbWlnaHQgc3RpbGwgYmUgaGlkZGVuIGJ5IHRoZSBwZXJtaXNzaW9ucyBjb2RlLCBkdWUgdG8gdGhlICdpbnZpc2libGUtaW1hZ2UnIGNsYXNzLCBlc3BlY2lhbGx5IHdpdGggdGhpcy5lZGl0X29ubHlfbW9kZS4gU2VlIEJhc2VWaWV3Q29udHJvbGxlci5zZXREZWZhdWx0TWVudUFkZEljb24oKSBhcyBhbiBleGFtcGxlLlxuXG5cdFx0bGV0IGljb25fY291bnQgPSAxO1xuXHRcdGxldCBjb250ZXh0X21lbnVfbW9kZWwgPSB0aGlzLmdldEN1c3RvbUNvbnRleHRNZW51TW9kZWwoKTtcblxuXHRcdC8vIE92ZXJyaWRlIGZvciBlZGl0IHZpZXdzLlxuXHRcdGNvbnRleHRfbWVudV9tb2RlbCA9IHRoaXMucGFyc2VDdXN0b21Db250ZXh0TW9kZWxGb3JFZGl0Vmlld3MoIGNvbnRleHRfbWVudV9tb2RlbCApO1xuXG5cdFx0Ly8gT3ZlcnJpZGUgZm9yIHN1YnZpZXdzLCBhcyB3ZSB3YW50IHRvIHJlbW92ZSBDYW5jZWwuIFRoaXMgaXMgZ2xvYmFsLCBwZXJoYXBzIHJlZmFjdG9yIGludG8gdGhlIGluZGl2aWR1YWwgZ2V0Q3VzdG9tQ29udGV4dE1lbnVNb2RlbCBidXQgdGhhdCBtZWFucyBkdXBsaWNhdGluZyB0aGUgY29kZSBpbiAxMDArIHBsYWNlcy5cblx0XHRjb250ZXh0X21lbnVfbW9kZWwgPSB0aGlzLnBhcnNlQ3VzdG9tQ29udGV4dE1vZGVsRm9yU3ViVmlld3MoIGNvbnRleHRfbWVudV9tb2RlbCApO1xuXG5cdFx0aWYgKCBjb250ZXh0X21lbnVfbW9kZWwgJiYgKCBjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZSB8fCBjb250ZXh0X21lbnVfbW9kZWwuZXhjbHVkZSApICkge1xuXHRcdFx0Ly9Db250ZXh0IE1lbnVcblxuXHRcdFx0bGV0IGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsID0gdGhpcy5nZXREZWZhdWx0Q29udGV4dE1lbnVNb2RlbCgpO1xuXG5cdFx0XHRsZXQgZmluYWxfY29udGV4dF9tZW51X21vZGVsID0geyAnaWNvbnMnOiB7fSwgJ2dyb3Vwcyc6IHt9IH07XG5cblx0XHRcdGlmICggIWNvbnRleHRfbWVudV9tb2RlbC5ncm91cHMgKSB7XG5cdFx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5ncm91cHMgPSB7fTtcblx0XHRcdH1cblxuXHRcdFx0Ly9EZWZhdWx0IHRvIGluY2x1ZGluZyBhbGwgZGVmYXVsdCBpY29ucy5cblx0XHRcdGlmICggIWNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlICkge1xuXHRcdFx0XHRjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZSA9IFsnZGVmYXVsdCddO1xuXHRcdFx0fVxuXG5cdFx0XHQvL0lmIHdlIGRvbid0IGluY2x1ZGUgZGVmYXVsdCwgYXNzdW1lIHdlIHdhbnQgdG8gaW5jbHVkZSBhbGwgZGVmYXVsdCBpY29ucy5cblx0XHRcdGlmICggY29udGV4dF9tZW51X21vZGVsLmluY2x1ZGUuaW5kZXhPZiggJ2RlZmF1bHQnICkgPT09IC0xICkge1xuXHRcdFx0XHRjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZS51bnNoaWZ0KCAnZGVmYXVsdCcgKTsgLy8gQWRkIHRvIGZyb250LCBzbyBjdXN0b20gaWNvbnMgY2FuIG92ZXJyaWRlIGEgZGVmYXVsdCBpY29uIGlkLlxuXHRcdFx0fVxuXG5cdFx0XHQvL0Fzc2lnbiBkZWZhdWx0IGdyb3Vwcy5cblx0XHRcdGZvciAoIGxldCB4IGluIGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsLmdyb3VwcyApIHtcblx0XHRcdFx0ZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWwuZ3JvdXBzW3hdLnN1Yl9tZW51cyA9IFtdO1xuXG5cdFx0XHRcdGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5ncm91cHNbeF0gPSBkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbC5ncm91cHNbeF07XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIGxldCB4IGluIGNvbnRleHRfbWVudV9tb2RlbC5ncm91cHMgKSB7XG5cdFx0XHRcdGNvbnRleHRfbWVudV9tb2RlbC5ncm91cHNbeF0uc3ViX21lbnVzID0gW107XG5cblx0XHRcdFx0ZmluYWxfY29udGV4dF9tZW51X21vZGVsLmdyb3Vwc1t4XSA9IGNvbnRleHRfbWVudV9tb2RlbC5ncm91cHNbeF07XG5cdFx0XHR9XG5cblx0XHRcdC8vRmlsdGVyIGdyb3Vwcy9pY29uc1xuXHRcdFx0aWYgKCBjb250ZXh0X21lbnVfbW9kZWwuaGFzT3duUHJvcGVydHkoICdpbmNsdWRlJyApICkge1xuXHRcdFx0XHRpZiAoIGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLmNvbnN0cnVjdG9yICE9PSBBcnJheSApIHtcblx0XHRcdFx0XHRjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZSA9IEFycmF5KCBjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Zm9yICggbGV0IGkgaW4gY29udGV4dF9tZW51X21vZGVsLmluY2x1ZGUgKSB7XG5cdFx0XHRcdFx0bGV0IGN1cnJlbnRfaW5jbHVkZV9lbGVtZW50ID0gY29udGV4dF9tZW51X21vZGVsLmluY2x1ZGVbaV07XG5cdFx0XHRcdFx0aWYoIGNvbnRleHRfbWVudV9tb2RlbC5pbmNsdWRlLmhhc093blByb3BlcnR5KCBpICkpIHtcblx0XHRcdFx0XHRcdGlmICggY3VycmVudF9pbmNsdWRlX2VsZW1lbnQgPT0gJ2RlZmF1bHQnICkge1xuXHRcdFx0XHRcdFx0XHREZWJ1Zy5UZXh0KCAnSW5jbHVkaW5nIEFsbCBEZWZhdWx0IEljb25zLi4uJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnYnVpbGRDb250ZXh0TWVudU1vZGVscycsIDExICk7XG5cblx0XHRcdFx0XHRcdFx0Zm9yICggbGV0IHggaW4gZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnMgKSB7XG5cdFx0XHRcdFx0XHRcdFx0YWRkSWNvblRvRmluYWxNb2RlbCggZGVmYXVsdF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0gKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlb2YgY3VycmVudF9pbmNsdWRlX2VsZW1lbnQgIT09ICdvYmplY3QnICYmIGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsLmljb25zW2N1cnJlbnRfaW5jbHVkZV9lbGVtZW50XSApIHtcblx0XHRcdFx0XHRcdFx0XHRhZGRJY29uVG9GaW5hbE1vZGVsKCBkZWZhdWx0X2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1tjdXJyZW50X2luY2x1ZGVfZWxlbWVudF0gKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRhZGRJY29uVG9GaW5hbE1vZGVsKCBjdXJyZW50X2luY2x1ZGVfZWxlbWVudCApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0ZnVuY3Rpb24gYWRkSWNvblRvRmluYWxNb2RlbCggaWNvbiApIHtcblx0XHRcdFx0aWYoICFpY29uLnNvcnRfb3JkZXIgJiYgaWNvbi5ncm91cCApIHtcblx0XHRcdFx0XHRpY29uLnNvcnRfb3JkZXIgPSBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuZ3JvdXBzWyBpY29uLmdyb3VwIF0uc29ydF9vcmRlcjsgLy8gUmF0aGVyIHRoYW4gc2V0dGluZyB0aGUgZGVmYXVsdCB0byAxMDAwLCBsZXRzIHNldCBpdCB0byB0aGUgc3RhcnQgb2YgdGhlIGljb24ncyBncm91cCwgc28gaXQgYXBwZWFycyBpbiByb3VnaGx5IHRoZSByaWdodCBhcmVhIG9mIHRoZSBtZW51LiBGaXhlcyBlLmcuIFRpbWVTaGVldCAmIEV4cG9ydCBpbiBFbXBsb3llZS0+RW1wbG95ZWVzLlxuXHRcdFx0XHR9XG5cdFx0XHRcdC8vIFRPRE86IEFsc28gbmVlZCBzY2VuYXJpbyBmb3Igd2hlbiB0aGVyZSBpcyBubyBzb3J0X29yZGVyIGFuZCBubyBncm91cC4gQ3VycmVudGx5IHRoaXMgaXMgY2F1Z2h0IGFzIGEgY29uc29sZSBlcnJvciB2aWEgY2hlY2tzIGluIENvbnRleHRNZW51TWFuYWdlci5jb252ZXJ0QmFja0JvbmVNZW51TW9kZWxUb1ByaW1lVnVlLnNvcnRfY29tcGFyZVxuXG5cdFx0XHRcdGljb24uYWRkX29yZGVyID0gaWNvbl9jb3VudDsgLy8gcmF0aGVyIHRoYW4gY2FsY3VsYXRpbmcgbGVuZ3RoIGVhY2ggdGltZSwganVzdCB0cmFjayBhZGRpdGlvbnMsIGFzIGFsbCBpY29ucyBzaG91bGQgYmUgYWRkZWQgdGhyb3VnaCBoZXJlIGFueXdheS5cblx0XHRcdFx0ZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW2ljb24uaWRdID0gaWNvbjtcblx0XHRcdFx0aWNvbl9jb3VudCsrO1xuXG5cdFx0XHRcdHJldHVybiBpY29uO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyAjMjY0NCBJbmNsdWRlIGFycmF5IGlzIGEgbWl4IG9mIGljb24gaWQgc3RyaW5ncyBhbmQgb2JqZWN0cywgdGhpcyBmdW5jdGlvbiBmbGF0dGVucyBpdCB0byBhbiBhcnJheSBvZiBzdHJpbmdzIGZvciBpZCBjb21wYXJpc2lvbi5cblx0XHRcdGZ1bmN0aW9uIGZsYXR0ZW5NaXhlZElkT2JqZWN0QXJyYXkoIGFycmF5ICkge1xuXHRcdFx0XHRyZXR1cm4gYXJyYXkubWFwKCBmdW5jdGlvbiggaXRlbSApIHtcblx0XHRcdFx0XHRyZXR1cm4gaXRlbS5pZCB8fCBpdGVtO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHRcdGxldCB0bXBfaW5jbHVkZWRfaWNvbl9pZHMgPSBmbGF0dGVuTWl4ZWRJZE9iamVjdEFycmF5KCBjb250ZXh0X21lbnVfbW9kZWwuaW5jbHVkZSApO1xuXG5cdFx0XHQvL011c3QgZ28gYWZ0ZXIgaW5jbHVkZSwgc28gdGhleSBjYW4gaW5jbHVkZSBhIGZldyBpY29ucywgdGhlbiBleGNsdWRlIGFsbC5cblx0XHRcdGlmICggY29udGV4dF9tZW51X21vZGVsLmhhc093blByb3BlcnR5KCAnZXhjbHVkZScgKSApIHtcblx0XHRcdFx0aWYgKCBjb250ZXh0X21lbnVfbW9kZWwuZXhjbHVkZS5jb25zdHJ1Y3RvciAhPT0gQXJyYXkgKSB7XG5cdFx0XHRcdFx0Y29udGV4dF9tZW51X21vZGVsLmV4Y2x1ZGUgPSBBcnJheSggY29udGV4dF9tZW51X21vZGVsLmV4Y2x1ZGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGZvciAoIGxldCBqIGluIGNvbnRleHRfbWVudV9tb2RlbC5leGNsdWRlICkge1xuXHRcdFx0XHRcdGlmKCBjb250ZXh0X21lbnVfbW9kZWwuZXhjbHVkZS5oYXNPd25Qcm9wZXJ0eSggaiApKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNvbnRleHRfbWVudV9tb2RlbC5leGNsdWRlW2pdID09ICdkZWZhdWx0JyApIHtcblx0XHRcdFx0XHRcdFx0RGVidWcuVGV4dCggJ0V4Y2x1ZGluZyBBbGwgRGVmYXVsdCBJY29ucy4uLicsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2J1aWxkQ29udGV4dE1lbnVNb2RlbHMnLCAxMCApO1xuXG5cdFx0XHRcdFx0XHRcdGZvciAoIGxldCB4IGluIGRlZmF1bHRfY29udGV4dF9tZW51X21vZGVsLmljb25zICkge1xuXHRcdFx0XHRcdFx0XHRcdGlmICggdG1wX2luY2x1ZGVkX2ljb25faWRzLmluZGV4T2YoIHggKSA9PT0gLTEgKSB7IC8vTWFrZSBzdXJlIHdlIGRvbid0IGV4Y2x1ZGUgb25lIHRoYXQgaXMgaW5jbHVkZWQuIENvbXBhcmUgYWdhaW5zdCBmbGF0dGVuZWQvZXh0cmFjdGVkIGluY2x1ZGUgYXJyYXksIG90aGVyd2lzZSB0eXBlcyBkbyBub3QgbWF0Y2ggYW5kIGFsbCBkZWZhdWx0IGljb25zIGFyZSByZW1vdmVkIHJlZ2FyZGxlc3MgaWYgdGhleSBleGlzdCBpbiBpbmNsdWRlLlxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0gKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGRlbGV0ZSBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF07XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRsZXQgZXhjbHVkZV9pY29uX2lkID0gY29udGV4dF9tZW51X21vZGVsLmV4Y2x1ZGVbal07XG5cdFx0XHRcdFx0XHRcdGlmICggZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW2V4Y2x1ZGVfaWNvbl9pZF0gKSB7XG5cdFx0XHRcdFx0XHRcdFx0ZGVsZXRlIGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1tleGNsdWRlX2ljb25faWRdO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vQnVpbGQgTWVudVxuXHRcdFx0bGV0IGdyb3VwcyA9IHt9O1xuXHRcdFx0Zm9yICggbGV0IHggaW4gZmluYWxfY29udGV4dF9tZW51X21vZGVsLmdyb3VwcyApIHtcblx0XHRcdFx0Z3JvdXBzW3hdID0gZmluYWxfY29udGV4dF9tZW51X21vZGVsLmdyb3Vwc1t4XTtcblx0XHRcdFx0RGVidWcuVGV4dCggJ0NyZWF0aW5nIFJpYmJvbiBNZW51IEdyb3VwOiAnICsgZmluYWxfY29udGV4dF9tZW51X21vZGVsLmdyb3Vwc1t4XS5sYWJlbCwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnYnVpbGRDb250ZXh0TWVudU1vZGVscycsIDExICk7XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIGxldCB4IGluIGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29ucyApIHtcblxuXHRcdFx0XHQvL1JlcGxhY2UgZ3JvdXAgc3RyaW5nIHdpdGggb2JqZWN0LlxuXHRcdFx0XHRpZiAoIGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1t4XSAmJiBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0uZ3JvdXAgKSB7XG5cdFx0XHRcdFx0aWYgKCBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0uZ3JvdXAuY29uc3RydWN0b3IgPT09IFN0cmluZyApIHtcblx0XHRcdFx0XHRcdGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1t4XS5ncm91cCA9IGdyb3Vwc1tmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0uZ3JvdXBdO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoIHR5cGVvZiBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0uZ3JvdXAgPT09ICdvYmplY3QnICkge1xuXHRcdFx0XHRcdFx0Ly9UaGUgMm5kIHRpbWUgdGhlIGVkaXQgdmlldyBpcyBvcGVuZWQsIGljb25zIG1hbnVhbGx5IHBhc3NlZCBpbiB0aHJvdWdoICdpbmNsdWRlJyBhbHJlYWR5IGhhdmUgdGhlIGdyb3VwcyBjb252ZXJ0ZWQgdG8gb2JqZWN0cywgYnV0IHRoZSBpY29ucyBkb24ndCBhcHBlYXIgdW50aWwgd2UgcmUtYXNzaWduIHRoZSBncm91cCBvYmplY3QgYWdhaW4uXG5cdFx0XHRcdFx0XHRmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0uZ3JvdXAgPSBncm91cHNbZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW3hdLmdyb3VwLmdldCggJ2lkJyApXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1t4XS5oYXNPd25Qcm9wZXJ0eSggJ3Blcm1pc3Npb25fcmVzdWx0JyApID09IGZhbHNlICkge1xuXHRcdFx0XHRcdGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1t4XS5wZXJtaXNzaW9uX3Jlc3VsdCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCAhZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW3hdLmhhc093blByb3BlcnR5KCAncGVybWlzc2lvbicgKSA9PSBmYWxzZSApIHtcblx0XHRcdFx0XHRmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0ucGVybWlzc2lvbiA9IG51bGw7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHREZWJ1Zy5UZXh0KCAnQ3JlYXRpbmcgUmliYm9uIE1lbnUgSWNvbjogJyArIGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1t4XS5sYWJlbCwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnYnVpbGRDb250ZXh0TWVudU1vZGVscycsIDExICk7XG5cbi8qXHRcdFx0XHQvLyBUT0RPOiBUaGlzIG5vdCBhbiBpZGVhbCB3YXkgdG8gZG8gaXQsIGJ1dCBub3Qgd29ydGggY2hhbmdpbmcgdW50aWwgYSBiaWdnZXIgcmVmYWN0b3Igb2YgdGhlIGNvbnRleHQgbWVudSBpcyBkb25lIGF0IGEgbGF0ZXIgZGF0ZS5cblx0XHRcdFx0aWYgKCBmaW5hbF9jb250ZXh0X21lbnVfbW9kZWwuaWNvbnNbeF0uaXRlbXMgJiYgZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW3hdLml0ZW1zLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0Ly8gV2UgdXNlIGl0ZW0gdG8gc3RvcmUgdGhlIHByZSBjb252ZXJzaW9uIGFuZCBwb3N0IGNvbnZlcnNpb24gZGF0YS4gVGhlcmVmb3JlIHdlIG11c3QgcmUtYXNzaWduIHRvIGEgdGVtcCB2YXIsIGFuZCByZXNldC5cblx0XHRcdFx0XHRsZXQgaXRlbXNfdG9fYWRkID0gZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW3hdLml0ZW1zO1xuXG5cdFx0XHRcdFx0Ly8gU3RpbGwgc3RvcmUgdGhlIG9yaWdpbmFsIGl0ZW1zIHNvIHRoYXQgdGhlIG5ldyBWdWUgTWVudSBjYW4gcGFyc2UgdGhlc2UuXG5cdFx0XHRcdFx0ZmluYWxfY29udGV4dF9tZW51X21vZGVsLmljb25zW3hdLm9yaWdpbmFsX2l0ZW1zID0gaXRlbXNfdG9fYWRkO1xuXG5cdFx0XHRcdFx0Ly8gUmVzZXQgdGhlIGl0ZW1zIGF0dHJpYnV0ZSB0byBhbiBlbXB0eSBhcnJheSwgcmVhZHkgZm9yIFJpYmJvblN1Yk1lbnVOYXZJdGVtIHRvIHVzZSBsYXRlciBvbi4gU3RpbGwgbmVlZHMgY2xlYXJpbmcgdG8gZW1wdHkgYXJyYXkgaW4gQ29udGV4dE1lbnVNYW5hZ2VyIG9uY2UgdGhlIHJpYmJvbm1lbnUgaXMgZG9uZSB3aXRoIGl0LlxuXHRcdFx0XHRcdGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbC5pY29uc1t4XS5pdGVtcyA9IFtdO1xuXHRcdFx0XHR9Ki9cblx0XHRcdH1cblxuXHRcdFx0Ly8gI1Z1ZUNvbnRleHRNZW51IyBQYXNzIHRoZSBmaW5hbCBjb250ZXh0IG1lbnUgbW9kZWwgdG8gdGhlIFZ1ZSBjb250ZXh0IG1lbnUuXG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuYnVpbGRDb250ZXh0TWVudU1vZGVsRnJvbUJhY2tib25lKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGZpbmFsX2NvbnRleHRfbWVudV9tb2RlbCwgdGhpcyApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vTGVnYWN5IGZhbGxiYWNrIHdoZW4gbm8gY29udGV4dCBtZW51IG1vZGVsIGlzIGRlZmluZWQuXG5cdFx0XHRHbG9iYWwuc2VuZEVycm9yUmVwb3J0KCAnQ29udGV4dE1lbnVNb2RlbCBlcnJvci4gTm8gdmFsaWQgY29udGV4dG1lbnUgbW9kZWwgZGVmaW5lZC4nICk7XG5cdFx0fVxuXHR9XG5cblx0dW5tb3VudENvbnRleHRNZW51KCkge1xuXHRcdC8vIFRoaXMgc2hvdWxkIGJlIGFibGUgdG8gaGFuZGxlIHZhcmlvdXMgbWVudSdzIGFzIHRoZSBkZXRlcm1pbmUgbWVudSBpZCBmdW5jdGlvbiB3aWxsIGlkZW50aWZ5IHRoZSByaWdodCBtZW51ICh2aWV3LCBlZGl0IGV0Yylcblx0XHRDb250ZXh0TWVudU1hbmFnZXIudW5tb3VudENvbnRleHRNZW51KCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKTtcblx0fVxuXG5cdGJ1aWxkQ29udGV4dE1lbnUoIHNldEZvY3VzICkge1xuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmIHRoaXMuZWRpdF9vbmx5X21vZGUgPT0gdHJ1ZSAmJiBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fZWRpdF9vbmx5X2NvbnRyb2xsZXIgJiYgTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX2VkaXRfb25seV9jb250cm9sbGVyLnZpZXdJZCAhPSBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fZWRpdF9vbmx5X2NvbnRyb2xsZXIudmlld0lkICkgeyAvLyAjMjU0MiAtIHByZXZlbnQgZWFybHkgbWVudSBzZXR1cCBmb3Igdmlld3MgdGhhdCBoYXZlIG5vdCBiZWVuIGxvYWRlZCBpbnRvIG1lbW9yeSB5ZXQuXG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHNldEZvY3VzICkgKSB7XG5cdFx0XHRzZXRGb2N1cyA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCAhdGhpcy5zdWJfdmlld19tb2RlICkge1xuXHRcdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3N1Yl9jb250cm9sbGVyID0gbnVsbDsgLy9DbGVhbiBzdWIgY29udHJvbGxlciBpZiBjdXJyZW50IHZpZXcgaXMgYSBtYWluIHZpZXdcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9XaGVuIG9uIGEgc3ViIHZpZXcgbW9kZSB0YWIgd2Ugd2FudCB0byBkaXNhYmxlIGNlcnRhaW4gY29udGV4dCBtZW51IGJ1dHRvbnMgb2YgdGhlIHBhcmVudCB2aWV3LlxuXHRcdFx0Ly9UaGlzIGlzIHRvIGhlbHAgcHJldmVudCB1c2VycyBmcm9tIHVzaW5nIGNvbnRleHQgbWVudSBidXR0b25zIGZvciB0aGUgd3JvbmcgdmlldyBhbmQgZGVsZXRpbmcvY29weWluZyByZWNvcmRzIHRoZXkgZGlkIG5vdCBpbnRlbmQgdG8gdXNlLlxuXHRcdFx0dGhpcy5vblN1YlZpZXdNb2RlRGlzYWJsZVBhcmVudENvbnRleHRNZW51QnV0dG9ucygpO1xuXHRcdH1cblxuXHRcdC8vIFZ1ZSBDb250ZXh0IE1lbnUgaW5pdGlhbGl6YXRpb24gLSAjMjgzOFxuXHRcdC8vIENoZWNrcyBmb3IgZXhpc3RpbmcgbWVudSwgYmVjYXVzZSBmb3IgYW4gZWRpdF92aWV3LCB3ZSBkb250IHdhbnQgdG8gc3RhcnQgYSBuZXcgbWVudSwgd2Ugd2FudCB0byByZS11c2UgaXQuXG5cdFx0Ly8gT3RoZXJ3aXNlIHdlIGVuZCB1cCB0cmVhdGluZyBlZGl0IG1lbnVzIGxpa2UgbmV3IHZpZXdzLCB3aGljaCBpcyBtb3JlIGNvbXBsZXggZ2l2ZW4gdGhlIGh0bWwgdGVtcGxhdGVzIChyZXBvcnQgZWRpdCB2aWV3cyBhcmUgdW5pcXVlLCBhcyB3ZSBub3cgaGF2ZSBhIGNvbW1vbiB0ZW1wbGF0ZSkuXG5cdFx0bGV0IG1lbnVfYXR0cmlidXRlcyA9IHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKTtcblxuXHRcdGlmKCBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudSggbWVudV9hdHRyaWJ1dGVzLmlkICkgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdC8vICNWdWVDb250ZXh0TWVudSNEeW5hbWljLUVkaXRWaWV3XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuY3JlYXRlQW5kTW91bnRNZW51KCBtZW51X2F0dHJpYnV0ZXMuaWQsIG1lbnVfYXR0cmlidXRlcy5wYXJlbnRfbW91bnRfcG9pbnQsIHRoaXMgKTtcblxuXHRcdFx0aWYoIG1lbnVfYXR0cmlidXRlcyAmJiBtZW51X2F0dHJpYnV0ZXMucGFyZW50X21vdW50X3BvaW50ICkge1xuXHRcdFx0XHQvLyAjVnVlQ29udGV4dE1lbnUjY29udGV4dC1ib3JkZXIgY3JlYXRpb24gdG8gcHV0IGEgYm9yZGVyIGFyb3VuZCBhIGNvbnRleHQgbWVudSBhbmQgdGhlIGNvbnRlbnRzIGl0IHJlbGF0ZXMgdG8uIFRoaXMgd2lsbCBoZWxwIHVzZXJzIHVuZGVyc3RhbmQgd2hpY2ggY29udGV4dCBtZW51IGJlbG9uZ3MgdG8gd2hhdCBpZiB0aGVyZSBpcyBtb3JlIHRoYW4gb25lIG1lbnUgb24gdGhlIHBhZ2UuXG5cdFx0XHRcdHZhciBjb250ZXh0X3BhcmVudCA9IG1lbnVfYXR0cmlidXRlcy5wYXJlbnRfbW91bnRfcG9pbnQ7IC8vICQoJy5lZGl0LXZpZXctdGFiLWJhcicpO1xuXHRcdFx0XHR2YXIgY29udGV4dF9sYWJlbCA9IHRoaXMuY29udGV4dF9tZW51X25hbWU7XG5cblx0XHRcdFx0Y29udGV4dF9wYXJlbnQucHJlcGVuZCgnPHNwYW4gY2xhc3M9XCJjb250ZXh0LWJvcmRlci1sYWJlbFwiPicrIGNvbnRleHRfbGFiZWwgKyc8L3NwYW4+Jyk7XG5cdFx0XHRcdGNvbnRleHRfcGFyZW50LndyYXBJbm5lcignPGRpdiBjbGFzcz1cImNvbnRleHQtYm9yZGVyXCI+PC9kaXY+Jyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBJZiBtb3VudCBwb2ludCBpcyBudWxsLCB0aGVuIHRoaXMgaXMgYSBidWcuIENoZWNrIGlmIGJ1aWxkQ29udGV4dE1lbnUgaXMgbm90IGNhbGxlZCBiZWZvcmUgZWRpdF92aWV3X3RhYiBwb3B1bGF0ZWQgKGNvbW1vbiBpbiB2aWV3cyBvdmVycmlkaW5nIEJhc2VWaWV3IGZ1bmN0aW9ucyBsaWtlIG9wZW5FZGl0Vmlldy5cblx0XHRcdFx0RGVidWcuRXJyb3IoICdFcnJvciBjcmVhdGluZyBjb250ZXh0LWJvcmRlciBmb3IgJyt0aGlzLnZpZXdJZCsnICgnKyBtZW51X2F0dHJpYnV0ZXMuaWQgKycvJysgdGhpcy51aV9pZCArJyknLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdidWlsZENvbnRleHRNZW51JywgMTAgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gaWYoICggdGhpcy5pc19hZGQgfHwgdGhpcy5pc19lZGl0IHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSAmJiB0aGlzLmVkaXRfdmlld190YWIgfHwgTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9PT0gJ3ZpZXdfZGV0YWlsJyApIHsgLy8gUkVNRU1CRVIgVE8gVVBEQVRFIGRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzISFcblx0XHRcdC8vIFx0Ly8gI1Z1ZUNvbnRleHRNZW51I0R5bmFtaWMtRWRpdFZpZXcgLSBDb25zb2xpZGF0ZSB0aGlzLCBhcyBWaWV3IGlzIG5vdyBpbiAxIHBsYWNlLCBhbmQgRWRpdFZpZXcgaW4gMiBwbGFjZXMuIDwtLSAjVE9ETzogaXMgdGhpcyBjb21tZW50IHN0aWxsIHZhbGlkPyBTZWFyY2ggdGhlIHRhZy5cblx0XHRcdC8vIFx0Ly8gUG9wLXVwIGVkaXQgdmlld3MsIHdoaWNoIG92ZXJsYXkgYWNyb3NzIGFuIHVucmVsYXRlZCB2aWV3ICggYXBwZWFyIGFueXdoZXJlIGJhc2ljYWxseSApLlxuXHRcdFx0Ly8gXHR0aGlzLmNvbnRleHRfZWRpdF9vbmx5X21lbnVfaWQgPSBDb250ZXh0TWVudU1hbmFnZXIuY3JlYXRlQW5kTW91bnRNZW51KCBtZW51X2F0dHJpYnV0ZXMuaWQsIHRoaXMuZWRpdF92aWV3X3RhYiwgdGhpcyApO1xuXHRcdFx0Ly8gfSBlbHNlIGlmKCB0aGlzLnVpX2lkICkge1xuXHRcdFx0Ly8gXHQvLyBOb3JtYWwgVmlld3Ncblx0XHRcdC8vIFx0dGhpcy5jb250ZXh0X21lbnVfaWQgPSBDb250ZXh0TWVudU1hbmFnZXIuY3JlYXRlQW5kTW91bnRNZW51KCBtZW51X2F0dHJpYnV0ZXMuaWQsICQoICR0aGlzLmVsICksIHRoaXMgKTtcblx0XHRcdC8vIH0gIGVsc2Uge1xuXHRcdFx0Ly8gXHQvLyBJZiBlYWNoIHZpZXcgaGFzIGEgdW5pcXVlIGNvbnRleHQgbWVudSwgdGhlbiB0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIGFzIGNvbnRleHQgbWVudSBzaG91bGQgb25seSBiZSBpbml0aWF0ZWQgb25jZS5cblx0XHRcdC8vIFx0Ly8gSG93ZXZlciwgdGhlcmUgYXJlIG1hbnkgY2FzZXMgd2hlcmUgdGFicyByZXBlYXRlZGx5IGNhbGwgdGhpcy5idWlsZENvbnRleHRNZW51LCB3aGlsc3Qga2VlcGluZyB0aGUgc2FtZSB2aWV3IGNvbnRyb2xsZXIsIHNvIHRoaXMgaXMgbm93IGEgd2FybmluZyByYXRoZXIgdGhhbiBhbiBlcnJvci5cblx0XHRcdC8vIFx0RGVidWcuRXJyb3IoICdFcnJvciBkdXJpbmcgY29udGV4dCBtZW51IG1vdW50LiBWaWV3IHN0YXRlIGZvciAoICcrIHRoaXMudmlld0lkICsnICkgZG9lcyBub3QgbWF0Y2ggb3B0aW9ucy4nLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdidWlsZENvbnRleHRNZW51JywgMSApO1xuXHRcdFx0Ly8gfVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBUaGlzIG1pZ2h0IGJlIG5vcm1hbCBmb3Igc2l0dWF0aW9ucyBsaWtlIGNsb3NpbmcgRWRpdCBWaWV3cywgd2hlcmUgdGhlIG1lbnUgd2lsbCBhbHJlYWR5IGV4aXN0IGluIHRoZSBtYWluIHZpZXcuXG5cdFx0XHREZWJ1Zy5XYXJuKCAnQ29udGV4dCBNZW51IE1hbmFnZXIgKCcrIG1lbnVfYXR0cmlidXRlcy5pZCArJykgYWxyZWFkeSBleGlzdHMgZm9yOiAnKyB0aGlzLnZpZXdJZCArJyAoJysgdGhpcy51aV9pZCArJyknLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdidWlsZENvbnRleHRNZW51JywgMTAgKTtcblx0XHR9XG5cblx0XHR0aGlzLmJ1aWxkQ29udGV4dE1lbnVNb2RlbHMoKTtcblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50U2hvd25Db250ZXh0TWVudU5hbWUgPSB0aGlzLmNvbnRleHRfbWVudV9uYW1lID8gdGhpcy5jb250ZXh0X21lbnVfbmFtZSA6IG1lbnVfYXR0cmlidXRlcy5wYXJlbnRfaWQ7XG5cblx0fVxuXG5cdGdldENvbnRleHRNZW51R3JvdXBCeU5hbWUoIG1lbnUsIG5hbWUsIG5hbWVfcHJlZml4ICkge1xuXHRcdHZhciBncm91cDtcblx0XHRpZiAoIG5hbWVfcHJlZml4ID09IHVuZGVmaW5lZCApIHtcblx0XHRcdG5hbWVfcHJlZml4ID0gdGhpcy52aWV3SWQ7XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbWVudS5hdHRyaWJ1dGVzLnN1Yl9tZW51X2dyb3Vwcy5sZW5ndGg7IGkrKyApIHtcblx0XHRcdGlmICggbWVudS5hdHRyaWJ1dGVzLnN1Yl9tZW51X2dyb3Vwc1tpXS5pZCA9PSBuYW1lX3ByZWZpeCArIG5hbWUgKSB7XG5cdFx0XHRcdGdyb3VwID0gbWVudS5hdHRyaWJ1dGVzLnN1Yl9tZW51X2dyb3Vwc1tpXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZ3JvdXA7XG5cdH1cblxuXHRvblJlcG9ydE1lbnVDbGljayggaWQgKSB7XG5cdH1cblxuXHQvL092ZXJyaWRkZW4gaW4gUmVwb3J0QmFzZVZpZXdDb250cm9sbGVyLlxuXHRvbkNvbnRleHRNZW51Q2xpY2soIGNvbnRleHRfYnRuLCBtZW51X25hbWUgKSB7XG5cdFx0Ly8gVnVlIG5vdGVzOiBMdWNraWx5IHdoZW4gVnVlIGNhbGxzIHRoaXMgbWVudSwgaXQgZG9lcyBub3QgbmVlZCBjb250ZXh0X2J0biwgYXMgbW9zdCBwbGFjZXMgdGhhdCB1c2UgdGhpcyBmdW5jdGlvbiBoYXZlIHRoZSBHbG9iYWwuaXNTZXQoIG1lbnVfbmFtZSApIGNoZWNrIHRvIGp1c3QgdXNlIG1lbnVfbmFtZSBhcyB0aGUgaWQuIEhvd2V2ZXIsIE1lc3NhZ2VDb250cm9sVkMgZG9lcyB1c2UgaXQuXG5cdFx0dmFyIGlkO1xuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBtZW51X25hbWUgKSApIHtcblx0XHRcdGlkID0gbWVudV9uYW1lO1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdGlmICggY29udGV4dF9idG4uZGlzYWJsZWQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdC8vVGhpcyBmbGFnIGlzIHR1cm5lZCBvZmYgaW4gUHJvZ3Jlc3NCYXJNYW5hZ2VyOjpjbG9zZU92ZXJsYXksIG9yIDIgc2Vjb25kcyB3aGljaGV2ZXIgaGFwcGVucyBmaXJzdC4gVXNlIDIgc2Vjb25kcyBhcyBvdmVyc2VhcyB1c2VycyBjb3VsZCBzZWUgaW50ZXJtaXR0YW50IDIgc2Vjb25kIGxhdGVuY2llcyBhbmQgZG91YmxlIGNsaWNrIFNhdmUgaWNvbnMuXG5cdFx0aWYgKCB3aW5kb3cuY2xpY2tQcm9jZXNzaW5nID09IHRydWUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdpbmRvdy5jbGlja1Byb2Nlc3NpbmcgPSB0cnVlO1xuXHRcdFx0d2luZG93LmNsaWNrUHJvY2Vzc2luZ0hhbmRsZSA9IHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0Ly9GSVhNRTogQ2hlY2sgdG8gc2VlIGlmIHRoZSBwcm9ncmVzcyBiYXIgaXMgdmlzaWJsZSBiZWNhdXNlIGEgQVBJIGNhbGwgaXMgdGFraW5nIGEgbG9uZyB0aW1lLCBhbmQgaWYgc28ga2VlcCB0aGUgb3ZlcmxheSB1cCBsb25nZXIuXG5cdFx0XHRcdGlmICggd2luZG93LmNsaWNrUHJvY2Vzc2luZyA9PSB0cnVlICkge1xuXHRcdFx0XHRcdHdpbmRvdy5jbGlja1Byb2Nlc3NpbmcgPSBmYWxzZTtcblx0XHRcdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTtcblx0XHRcdFx0XHRUVFByb21pc2Uud2FpdCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCBHbG9iYWwuY2FsY0RlYm91bmNlV2FpdFRpbWVCYXNlZE9uTmV0d29yayggMjAwMCApICk7XG5cdFx0fVxuXG5cdFx0Ly9EZWJ1Zy5UZXh0KCAnQ29udGV4dCBNZW51IENsaWNrOiAnKyBpZCwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnb25Db250ZXh0TWVudUNsaWNrJywgMTAgKTtcblxuXHRcdC8qKlxuXHRcdCAqICBIZXJlIHdoZXJlIHlvdSBzZWUgUHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKSBpdCBpcyBob3cgd2UgcHJldmVudCBkb3VibGVjbGljayBmcm9tIGZpcmluZyB0d28gc2luZ2xlIGNsaWNrc1xuXHRcdCAqL1xuXG5cdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRjYXNlICdhZGQnOlxuXHRcdFx0XHR0aGlzLm9uQWRkQ2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd2aWV3Jzpcblx0XHRcdFx0dGhpcy5vblZpZXdDbGljaygpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3NhdmUnOlxuXHRcdFx0XHR0aGlzLm9uU2F2ZUNsaWNrKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnc2F2ZV9hbmRfbmV4dCc6XG5cdFx0XHRcdHRoaXMub25TYXZlQW5kTmV4dENsaWNrKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnc2F2ZV9hbmRfY29udGludWUnOlxuXHRcdFx0XHR0aGlzLm9uU2F2ZUFuZENvbnRpbnVlKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnc2F2ZV9hbmRfbmV3Jzpcblx0XHRcdFx0dGhpcy5vblNhdmVBbmROZXdDbGljaygpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3NhdmVfYW5kX2NvcHknOlxuXHRcdFx0XHR0aGlzLm9uU2F2ZUFuZENvcHkoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdlZGl0Jzpcblx0XHRcdFx0dGhpcy5vbkVkaXRDbGljaygpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ21hc3NfZWRpdCc6XG5cdFx0XHRcdHRoaXMub25NYXNzRWRpdENsaWNrKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZGVsZXRlX2ljb24nOlxuXHRcdFx0XHR0aGlzLm9uRGVsZXRlQ2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdkZWxldGVfYW5kX25leHQnOlxuXHRcdFx0XHR0aGlzLm9uRGVsZXRlQW5kTmV4dENsaWNrKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnY29weSc6XG5cdFx0XHRcdHRoaXMub25Db3B5Q2xpY2soKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdjb3B5X2FzX25ldyc6XG5cdFx0XHRcdHRoaXMub25Db3B5QXNOZXdDbGljaygpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2NhbmNlbCc6XG5cdFx0XHRcdHRoaXMub25DYW5jZWxDbGljaygpO1xuXHRcdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdleHBvcnRfZXhjZWwnOlxuXHRcdFx0XHR0aGlzLm9uRXhwb3J0Q2xpY2soICdleHBvcnQnICsgdGhpcy5hcGkua2V5X25hbWUgKTtcblx0XHRcdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnbWFwJzpcblx0XHRcdFx0dGhpcy5vbk1hcENsaWNrKCk7XG5cdFx0XHRcdFByb2dyZXNzQmFyLmNsb3NlT3ZlcmxheSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHRoaXMub25DdXN0b21Db250ZXh0Q2xpY2soIGlkLCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTsgLy9GSVhNRTogVGhpcyBtYXkgYmUgY2xvc2luZyB0aGUgb3ZlcmxheSB0b28gc29vbiwgYWxsb3dpbmcgZG91YmxlLWNsaWNrcyB0byBnZXQgdGhyb3VnaC4gRm9yIGV4YW1wbGUgd2hlbiBpbiBSZXF1ZXN0IEF1dGhvcml6YXRpb25zIGFuZCBoYW1tZXIgY2xpY2tpbmcgXCJBdXRob3JpemVcIi5cblx0XHRcdFx0Ly9EZWJ1Zy5UZXh0KCAnQ29udGV4dCBNZW51IENsaWNrOiAnKyBpZCArJyBPdmVybGF5IGNsb3NpbmcuLi4nLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvbkNvbnRleHRNZW51Q2xpY2snLCAxMCApO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHRHbG9iYWwudHJpZ2dlckFuYWx5dGljc0NvbnRleHRNZW51Q2xpY2soIGNvbnRleHRfYnRuLCBtZW51X25hbWUgKTtcblx0fVxuXG5cdG9uQ3VzdG9tQ29udGV4dENsaWNrKCBpZCApIHtcblx0XHRyZXR1cm4gZmFsc2U7IC8vRkFMU0UgdGVsbHMgb25Db250ZXh0TWVudUNsaWNrKCkgdG8ga2VlcCBwcm9jZXNzaW5nLlxuXHR9XG5cblx0b25OYXZpZ2F0aW9uQ2xpY2soIGlkICkge1xuXHRcdHRoaXMub25Db250ZXh0TWVudUNsaWNrKCBpZCApO1xuXHR9XG5cblx0Z2V0Q3VycmVudEFQSSgpIHtcblx0XHRyZXR1cm4gdGhpcy5hcGk7XG5cdH1cblxuXHRzZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSggc3RhdGUgKSB7XG5cdFx0dGhpcy5pc192aWV3aW5nID0gZmFsc2U7XG5cdFx0dGhpcy5pc192aWV3aW5nX2RldGFpbCA9IGZhbHNlOyAvL0NsaWNrZWQgXCJWaWV3IERldGFpbFwiIG9uIGF1ZGl0IGxvZy4gU2VwYXJhdGUgbG9naWMgZnJvbSByZWd1bGFyIHZpZXcuXG5cdFx0dGhpcy5pc19lZGl0ID0gZmFsc2U7XG5cdFx0dGhpcy5pc19hZGQgPSBmYWxzZTtcblx0XHR0aGlzLmlzX21hc3NfZWRpdGluZyA9IGZhbHNlO1xuXHRcdHRoaXMuaXNfbWFzc19hZGRpbmcgPSBmYWxzZTtcblx0XHRzd2l0Y2ggKCBzdGF0ZSApIHtcblx0XHRcdGNhc2UgJ3ZpZXcnOlxuXHRcdFx0XHR0aGlzLmlzX3ZpZXdpbmcgPSB0cnVlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3ZpZXdfZGV0YWlsJzpcblx0XHRcdFx0dGhpcy5pc192aWV3aW5nX2RldGFpbCA9IHRydWU7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnbmV3Jzpcblx0XHRcdFx0dGhpcy5pc19hZGQgPSB0cnVlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2VkaXQnOlxuXHRcdFx0XHR0aGlzLmlzX2VkaXQgPSB0cnVlO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ21hc3NfZWRpdCc6XG5cdFx0XHRcdHRoaXMuaXNfbWFzc19lZGl0aW5nID0gdHJ1ZTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHQvLyBjYXNlICdtYXNzX2FkZCc6XG5cdFx0XHQvLyBcdC8vdGhpcy5pc19hZGQgPSB0cnVlO1xuXHRcdFx0Ly8gXHR0aGlzLmlzX21hc3NfYWRkaW5nID0gdHJ1ZTtcblx0XHRcdC8vIFx0YnJlYWs7XG5cblx0XHR9XG5cblx0XHRMb2NhbENhY2hlRGF0YS5wcmV2aW91c19kb2luZ19jb250ZXh0X2FjdGlvbiA9IExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb247XG5cdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9IHN0YXRlO1xuXHR9XG5cblx0cmV2ZXJ0RWRpdFZpZXdTdGF0ZSgpIHtcblx0XHR0aGlzLnNldEN1cnJlbnRFZGl0Vmlld1N0YXRlKCBMb2NhbENhY2hlRGF0YS5wcmV2aW91c19kb2luZ19jb250ZXh0X2FjdGlvbiA/IExvY2FsQ2FjaGVEYXRhLnByZXZpb3VzX2RvaW5nX2NvbnRleHRfYWN0aW9uIDogJycgKTtcblx0fVxuXG5cdG9uQWRkQ2xpY2soIHNob3dfc2F2ZV9hbmRfY29udGludWUgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLnNldEN1cnJlbnRFZGl0Vmlld1N0YXRlKCAnbmV3JyApO1xuXHRcdCR0aGlzLm9wZW5FZGl0VmlldygpO1xuXHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogdW5kZWZpbmVkIGlzIG5vdCBhIGZ1bmN0aW9uIGluIC9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9OC4wLjAtMjAxNDExMTctMTExMTQwIGxpbmUgODk3XG5cdFx0aWYgKCAkdGhpcy5hcGkgJiYgdHlwZW9mICR0aGlzLmFwaVsnZ2V0JyArICR0aGlzLmFwaS5rZXlfbmFtZSArICdEZWZhdWx0RGF0YSddID09PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0JHRoaXMuYXBpWydnZXQnICsgJHRoaXMuYXBpLmtleV9uYW1lICsgJ0RlZmF1bHREYXRhJ10oIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0JHRoaXMub25BZGRSZXN1bHQoIHJlc3VsdCApO1xuXHRcdFx0XHRcdGlmICggc2hvd19zYXZlX2FuZF9jb250aW51ZSApIHtcblx0XHRcdFx0XHRcdC8vSXNzdWUgIzMxMTEgLSBJZiB1c2VyIGlzIG9uIGEgc3VidmlldyB0aGUgdGFiIHdpbGwgYXBwZWFyIGJsYW5rIGFuZCB0aGUgU2F2ZSBhbmQgQ29udGludWUgYnV0dG9uIHdpbGwgbm90IHNob3cgdW5sZXNzIHVzZXIgc3dpdGNoZXMgdG8gYW5vdGhlciB0YWIuXG5cdFx0XHRcdFx0XHQvL0JlY2F1c2Ugb2YgdGhhdCB3aGVuIGNvbWluZyBmcm9tIGEgXCJTYXZlICYgTmV3XCIgYWN0aW9uLCB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0byBzaG93IHRoZSBTYXZlIGFuZCBDb250aW51ZSBidXR0b24uXG5cdFx0XHRcdFx0XHQkdGhpcy5zaG93U2F2ZUFuZENvbnRpbnVlQnV0dG9uKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fVxuXHR9XG5cblx0b25BZGRSZXN1bHQoIHJlc3VsdCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciByZXN1bHRfZGF0YSA9IHt9O1xuXG5cdFx0aWYgKCByZXN1bHQuZ2V0UmVzdWx0ICkge1xuXHRcdFx0cmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vaWYgbm90IGFuIGFwaSByZXN1bHQsIGFzc3VtZSBvYmplY3QgaXMgYWxyZWFkeSB0aGUgcmVzdWx0IG9mIGEgY2FsbCB0byBnZXRSZXN1bHQoKSBhbmQgd2Ugd2lsbCB1c2UgaXQgdmVyYmF0aW0uXG5cdFx0XHQvL3VzZWZ1bCBmb3IgcGFzc2luZyBpbiBkZWZhdWx0IHZhbHVlcyB3aGVuIGFkZGluZyBuZXcgcmVjb3JkcyBiZWZvcmUgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQuXG5cdFx0XHRyZXN1bHRfZGF0YSA9IHJlc3VsdDtcblx0XHR9XG5cblx0XHRpZiAoICFyZXN1bHRfZGF0YSB8fCByZXN1bHRfZGF0YSA9PT0gdHJ1ZSApIHtcblx0XHRcdHJlc3VsdF9kYXRhID0gW107XG5cdFx0fVxuXG5cdFx0cmVzdWx0X2RhdGEuY29tcGFueSA9IExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfY29tcGFueS5uYW1lO1xuXG5cdFx0aWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICYmICR0aGlzLnBhcmVudF9rZXkgKSB7XG5cdFx0XHRyZXN1bHRfZGF0YVskdGhpcy5wYXJlbnRfa2V5XSA9ICR0aGlzLnBhcmVudF92YWx1ZTtcblx0XHR9XG5cblx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID0gcmVzdWx0X2RhdGE7XG5cdFx0JHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cdH1cblxuXHRvbkRlbGV0ZUFuZE5leHRDbGljaygpIHtcblx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoIEdsb2JhbC5kZWxldGVfY29uZmlybV9tZXNzYWdlLCBudWxsLCBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0Ly8gVXNpbmcgYW4gYW5vbnltb3VzIGZ1bmN0aW9uIGluc3RlYWQgb2YgcmVmZXJlbmNlLCB0byBlbnN1cmUgZHVyaW5nIGRlYnVnZ2luZyBpdCBpcyBjbGVhciB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBmcm9tIERlbGV0ZUFuZE5leHQsIGFuZCBub3QganVzdCBEZWxldGUuXG5cdFx0XHR0aGlzLmRvRGVsZXRlQ2xpY2soIHJlc3VsdCwgJ2RlbGV0ZV9hbmRfbmV4dCcgKTtcblx0XHR9LmJpbmQoIHRoaXMgKSApO1xuXHR9XG5cblx0cmVzZXROYXZpZ2F0aW9uU291cmNlRGF0YSgpIHtcblx0fVxuXG5cdGdldERlbGV0ZVNlbGVjdGVkUmVjb3JkSWQoKSB7XG5cdFx0dmFyIHJldHZhbCA9IFtdO1xuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXHRcdFx0cmV0dmFsLnB1c2goIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKS5zbGljZSgpOyAvL1VzZSAuc2xpY2UoKSB0byBtYWtlIGEgY29weSBvZiB0aGUgSURzLlxuXHRcdFx0aWYgKCBncmlkX3NlbGVjdGVkX2lkX2FycmF5Lmxlbmd0aCApIHtcblx0XHRcdFx0cmV0dmFsID0gZ3JpZF9zZWxlY3RlZF9pZF9hcnJheTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHZhbCA9IG51bGw7XG5cdFx0XHR9XG5cblx0XHR9XG5cdFx0cmV0dXJuIHJldHZhbDtcblx0fVxuXG5cdGRvRGVsZXRlQ2xpY2soIHJlc3VsdCwgZGVsZXRlX3R5cGUgKSB7XG5cdFx0aWYgKCByZXN1bHQgKSB7XG5cdFx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdFx0dmFyIHJlbW92ZV9pZHMgPSB0aGlzLmdldERlbGV0ZVNlbGVjdGVkUmVjb3JkSWQoKTtcblx0XHRcdGlmICggcmVtb3ZlX2lkcyA9PT0gW10gKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoIGRlbGV0ZV90eXBlID8gZGVsZXRlX3R5cGUgOiAnZGVsZXRlJyApO1xuXHRcdFx0cmV0dXJuIHRoaXMuZG9EZWxldGVBUElDYWxsKCByZW1vdmVfaWRzICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0fVxuXHR9XG5cblx0ZG9EZWxldGVBUElDYWxsKCByZW1vdmVfaWRzLCBjYWxsYmFjayApIHtcblx0XHR2YXIgY3VycmVudF9hcGkgPSB0aGlzLmdldEN1cnJlbnRBUEkoKTtcblxuXHRcdGlmICggIWNhbGxiYWNrICkge1xuXHRcdFx0Y2FsbGJhY2sgPSB7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdHRoaXMub25EZWxldGVSZXN1bHQoIHJlc3VsdCwgcmVtb3ZlX2lkcyApO1xuXHRcdFx0XHR9LmJpbmQoIHRoaXMgKVxuXHRcdFx0fTtcblx0XHR9XG5cdFx0cmV0dXJuIGN1cnJlbnRfYXBpWydkZWxldGUnICsgY3VycmVudF9hcGkua2V5X25hbWVdKCByZW1vdmVfaWRzLCBjYWxsYmFjayApO1xuXHR9XG5cblx0b25EZWxldGVDbGljaygpIHtcblx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoIEdsb2JhbC5kZWxldGVfY29uZmlybV9tZXNzYWdlLCBudWxsLCB0aGlzLmRvRGVsZXRlQ2xpY2suYmluZCggdGhpcyApICk7XG5cdH1cblxuXHRvbkRlbGV0ZVJlc3VsdCggcmVzdWx0LCByZW1vdmVfaWRzICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXG5cdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPT09ICdkZWxldGVfYW5kX25leHQnICkge1xuXHRcdFx0XHQvLyBzdG9yZSB0aGUgaW5kZXggb2YgdGhlIGN1cnJlbnQgaXRlbSwgYmVmb3JlIHJlZnJlc2hpbmcgdGhlIHNlYXJjaCBhbmQgbG9zaW5nIHRoZSBjdXJyZW50IGNvbnRleHQgZHVlIHRvIHRoZSBkZWxldGVkIHJlY29yZHNcblx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9IHRoaXMubmF2aWdhdGlvbi5nZXROZXh0U2VsZWN0SXRlbUlkKCk7XG5cblx0XHRcdFx0Ly8gcmVmcmVzaCB0aGUgZ3JpZCB0byBnZXQgdGhlIGN1cnJlbnQgZGF0YXNldCBub3cgdGhhdCByZWNvcmRzIGhhdmUgYmVlbiBkZWxldGVkXG5cdFx0XHRcdCR0aGlzLnNlYXJjaCggZmFsc2UsIG51bGwsIG51bGwsIGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0dmFyIGN1cnJlbnRfZ3JpZF9zb3VyY2UgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0XHRpZiAoICQudHlwZSggY3VycmVudF9ncmlkX3NvdXJjZSApICE9PSAnYXJyYXknIHx8IGN1cnJlbnRfZ3JpZF9zb3VyY2UubGVuZ3RoIDwgMSApIHtcblx0XHRcdFx0XHRcdC8vIGlmIGFmdGVyIGRlbGV0ZSwgdGhlcmUgYXJlIG5vIG1vcmUgcmVjb3JkcyBpbiB0aGUgc2VhcmNoLCBjbG9zZSBlZGl0IHZpZXdcblx0XHRcdFx0XHRcdCR0aGlzLnJlbW92ZUVkaXRWaWV3KCk7XG5cdFx0XHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0XHRcdFx0Ly8gVE9ETzogU2hvdWxkIHRoZSBhYm92ZSBub3Qgc2ltdWxhdGUgYSBjYW5jZWwgY2xpY2s/IENvdWxkIGJlIGFuIGFyZWEgZm9yIGZ1cnRoZXIgcmVmYWN0b3IuXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vIHRoZXJlIGFyZSBzdGlsbCByZWNvcmRzLCBsb2FkIHRoZSBuZXcgZGF0YVxuXHRcdFx0XHRcdFx0JHRoaXMubmF2aWdhdGlvbi5zZXRTb3VyY2VEYXRhKCBjdXJyZW50X2dyaWRfc291cmNlICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5uYXZpZ2F0aW9uLnNldFBhZ2VyRGF0YSggJHRoaXMucGFnZXJfZGF0YSApO1xuXG5cdFx0XHRcdFx0XHQvLyBpZiB0aGVyZSBpcyBhIHZhbGlkIGlkIG9uIHRoZSBuZXh0IHJlY29yZCB0byBsb2FkLCBkbyBpdFxuXHRcdFx0XHRcdFx0aWYgKCAkdGhpcy5yZWZyZXNoX2lkICkge1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5vblJpZ2h0T3JMZWZ0QXJyb3dDbGlja0NhbGxCYWNrKCAkdGhpcy5yZWZyZXNoX2lkICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBubyB2YWxpZCBuZXh0IHJlY29yZCwgc2ltdWxhdGUgYSBjYW5jZWwgY2xpY2suXG5cdFx0XHRcdFx0XHRcdCR0aGlzLm9uQ2FuY2VsQ2xpY2soKTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0JHRoaXMub25EZWxldGVBbmROZXh0RG9uZSggcmVzdWx0ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdFx0JHRoaXMub25EZWxldGVEb25lKCByZXN1bHQgKTtcblx0XHRcdFx0aWYgKCAkdGhpcy5lZGl0X3ZpZXcgJiYgTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9PT0gJ2RlbGV0ZScgKSB7XG5cdFx0XHRcdFx0JHRoaXMucmVtb3ZlRWRpdFZpZXcoKTtcblx0XHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCAhJHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHRcdCR0aGlzLnNldEN1cnJlbnRFZGl0Vmlld1N0YXRlKCAnJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIElmIHNvbWUgdmFsaWQgcmVjb3JkcyB3ZXJlIGRlbGV0ZWQsIHdlIG5lZWQgdG8gcmVmcmVzaCB0aGUgc2VhcmNoIGdyaWQuXG5cdFx0XHRpZiAoIHJlc3VsdC5nZXRSZWNvcmREZXRhaWxzKCkudmFsaWQgJiYgcmVzdWx0LmdldFJlY29yZERldGFpbHMoKS52YWxpZCA+IDAgKSB7XG5cdFx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0fVxuXHRcdFx0JHRoaXMucmV2ZXJ0RWRpdFZpZXdTdGF0ZSgpO1xuXHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93RXJyb3JBbGVydCggcmVzdWx0ICk7XG5cdFx0fVxuXHR9XG5cblx0cmVtb3ZlRGVsZXRlZFJvd3MoIHJlbW92ZV9pZHMgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHQkLmVhY2goIHJlbW92ZV9pZHMsIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHQkdGhpcy5ncmlkLmdyaWQuZGVsZXRlUm93KCB2YWx1ZSApO1xuXHRcdFx0JHRoaXMucGFnaW5nX3dpZGdldC5taW51cygpO1xuXG5cdFx0fSApO1xuLy9cbi8vXHRcdGlmICggdGhpcy5ncmlkLmdldEdyaWRQYXJhbSggJ2RhdGEnICkubGVuZ3RoID09PSAwICkge1xuLy9cdFx0XHR0aGlzLnNlYXJjaCgpO1xuLy9cdFx0fVxuXG4vL1x0XHR0aGlzLnNlYXJjaCgpO1xuXG4vL1x0XHR2YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKTtcbi8vXHRcdHZhciBncmlkX3NlbGVjdGVkX2xlbmd0aCA9IGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkubGVuZ3RoO1xuLy9cbi8vXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPT09IDAgKSB7XG4vL1x0XHRcdHRoaXMuc2VhcmNoKCk7XG4vL1x0XHR9XG5cdH1cblxuXHRjbGVhck5hdmlnYXRpb25EYXRhKCkge1xuXHRcdGlmICggdGhpcy5uYXZpZ2F0aW9uICYmIHRoaXMubmF2aWdhdGlvbi5zZXRTb3VyY2VEYXRhICkge1xuXHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFNvdXJjZURhdGEoIG51bGwgKTtcblx0XHR9XG5cdH1cblxuXHRvblNhdmVBbmRDb3B5KCBpZ25vcmVXYXJuaW5nICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBpZ25vcmVXYXJuaW5nICkgKSB7XG5cdFx0XHRpZ25vcmVXYXJuaW5nID0gZmFsc2U7XG5cdFx0fVxuXHRcdHRoaXMuaXNfYWRkID0gdHJ1ZTtcblx0XHR0aGlzLmlzX2NoYW5nZWQgPSBmYWxzZTtcblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ3NhdmVfYW5kX2NvcHknO1xuXHRcdHZhciByZWNvcmQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0cmVjb3JkID0gdGhpcy51bmlmb3JtVmFyaWFibGUoIHJlY29yZCApO1xuXG5cdFx0dGhpcy5jbGVhck5hdmlnYXRpb25EYXRhKCk7XG5cdFx0dGhpcy5hcGlbJ3NldCcgKyB0aGlzLmFwaS5rZXlfbmFtZV0oIHJlY29yZCwgZmFsc2UsIGlnbm9yZVdhcm5pbmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHQkdGhpcy5vblNhdmVBbmRDb3B5UmVzdWx0KCByZXN1bHQgKTtcblx0XHRcdFx0JHRoaXMuY2xlYXJTdWJWaWV3Q29udHJvbGxlcnMoKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvblNhdmVBbmRDb3B5UmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRpZiAoIHJlc3VsdF9kYXRhID09PSB0cnVlICYmICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQ7XG5cdFx0XHR9IGVsc2UgaWYgKCBUVFVVSUQuaXNVVUlEKCByZXN1bHRfZGF0YSApICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC56ZXJvX2lkICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC5ub3RfZXhpc3RfaWQgKSB7XG5cdFx0XHRcdCR0aGlzLnJlZnJlc2hfaWQgPSByZXN1bHRfZGF0YTtcblx0XHRcdH1cblx0XHRcdCR0aGlzLnNlYXJjaCggZmFsc2UgKTtcblx0XHRcdCR0aGlzLm9uQ29weUFzTmV3Q2xpY2soKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRoaXMuc2V0RXJyb3JNZW51KCk7XG5cdFx0XHQkdGhpcy5zZXRFcnJvclRpcHMoIHJlc3VsdCApO1xuXG5cdFx0fVxuXHR9XG5cblx0b25TYXZlQW5kTmV3Q2xpY2soIGlnbm9yZVdhcm5pbmcgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIGlnbm9yZVdhcm5pbmcgKSApIHtcblx0XHRcdGlnbm9yZVdhcm5pbmcgPSBmYWxzZTtcblx0XHR9XG5cdFx0dGhpcy5zZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSggJ25ldycgKTtcblx0XHR2YXIgcmVjb3JkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkO1xuXHRcdHJlY29yZCA9IHRoaXMudW5pZm9ybVZhcmlhYmxlKCByZWNvcmQgKTtcblx0XHR0aGlzLmFwaVsnc2V0JyArIHRoaXMuYXBpLmtleV9uYW1lXSggcmVjb3JkLCBmYWxzZSwgaWdub3JlV2FybmluZywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdCR0aGlzLm9uU2F2ZUFuZE5ld1Jlc3VsdCggcmVzdWx0ICk7XG5cdFx0XHRcdGlmICggJHRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdFx0XHQkdGhpcy5jbGVhclN1YlZpZXdDb250cm9sbGVycyggZmFsc2UgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5jbGVhclN1YlZpZXdDb250cm9sbGVycyggdHJ1ZSApO1xuXHRcdFx0XHRcdCR0aGlzLnNob3dTYXZlQW5kQ29udGludWVCdXR0b24oKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uU2F2ZUFuZE5ld1Jlc3VsdCggcmVzdWx0ICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0aWYgKCByZXN1bHRfZGF0YSA9PT0gdHJ1ZSAmJiAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB7XG5cdFx0XHRcdCR0aGlzLnJlZnJlc2hfaWQgPSAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkO1xuXG5cdFx0XHR9IGVsc2UgaWYgKCBUVFVVSUQuaXNVVUlEKCByZXN1bHRfZGF0YSApICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC56ZXJvX2lkICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC5ub3RfZXhpc3RfaWQgKSB7IC8vIGFzIG5ld1xuXHRcdFx0XHQkdGhpcy5yZWZyZXNoX2lkID0gcmVzdWx0X2RhdGE7XG5cdFx0XHR9XG5cblx0XHRcdCR0aGlzLnNhdmVJbnNpZGVFZGl0b3JEYXRhKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMuc2VhcmNoKCBmYWxzZSApO1xuXHRcdFx0XHQkdGhpcy5vbkFkZENsaWNrKCB0cnVlICk7XG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdCR0aGlzLnNldEVycm9yTWVudSgpO1xuXHRcdFx0JHRoaXMuc2V0RXJyb3JUaXBzKCByZXN1bHQgKTtcblxuXHRcdH1cblx0fVxuXG5cdG9uU2F2ZUFuZENvbnRpbnVlKCBpZ25vcmVXYXJuaW5nICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBpZ25vcmVXYXJuaW5nICkgKSB7XG5cdFx0XHRpZ25vcmVXYXJuaW5nID0gZmFsc2U7XG5cdFx0fVxuXHRcdC8vU2V0dGluZyBpc19hZGQgZmFsc2UgdG9vIGVhcmx5IGNhbiBjYXVzZSBkZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpIHRvIGhhdmUgdW5leHBlY3RlZCBzaWRlIGVmZmVjdHMuIEhvd2V2ZXIgbm90IHNldHRpbmcgaXQgaGVyZSBtaWdodCBoYXZlIG90aGVyIHNpZGUgZWZmZWN0cy5cblx0XHQvLyR0aGlzLmlzX2FkZCA9IGZhbHNlO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnc2F2ZV9hbmRfY29udGludWUnO1xuXHRcdHZhciByZWNvcmQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0cmVjb3JkID0gdGhpcy51bmlmb3JtVmFyaWFibGUoIHJlY29yZCApO1xuXG5cdFx0dGhpcy5kb1NhdmVBUElDYWxsKCByZWNvcmQsIGlnbm9yZVdhcm5pbmcsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHQkdGhpcy5vblNhdmVBbmRDb250aW51ZVJlc3VsdCggcmVzdWx0ICk7XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvblNhdmVBbmRDb250aW51ZVJlc3VsdCggcmVzdWx0ICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCByZXN1bHQuaXNWYWxpZCgpICkge1xuXHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0aWYgKCByZXN1bHRfZGF0YSA9PT0gdHJ1ZSAmJiAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB7XG5cdFx0XHRcdCR0aGlzLnJlZnJlc2hfaWQgPSAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkO1xuXG5cdFx0XHR9IGVsc2UgaWYgKCByZXN1bHRfZGF0YSAmJiBUVFVVSUQuaXNVVUlEKCByZXN1bHRfZGF0YSApICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC56ZXJvX2lkICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC5ub3RfZXhpc3RfaWQgKSB7XG5cdFx0XHRcdCR0aGlzLnJlZnJlc2hfaWQgPSByZXN1bHRfZGF0YTtcblxuXHRcdFx0fVxuXG5cdFx0XHQkdGhpcy5zYXZlSW5zaWRlRWRpdG9yRGF0YSggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLnNlYXJjaCggZmFsc2UgKTtcblx0XHRcdFx0JHRoaXMub25FZGl0Q2xpY2soICR0aGlzLnJlZnJlc2hfaWQsIHRydWUgKTtcblx0XHRcdFx0JHRoaXMub25TYXZlQW5kQ29udGludWVEb25lKCByZXN1bHQgKTtcblx0XHRcdH0gKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkdGhpcy5zZXRFcnJvclRpcHMoIHJlc3VsdCApO1xuXHRcdFx0JHRoaXMuc2V0RXJyb3JNZW51KCk7XG5cdFx0fVxuXHR9XG5cblx0b25TYXZlQW5kTmV4dENsaWNrKCBpZ25vcmVXYXJuaW5nICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBpZ25vcmVXYXJuaW5nICkgKSB7XG5cdFx0XHRpZ25vcmVXYXJuaW5nID0gZmFsc2U7XG5cdFx0fVxuXHRcdHRoaXMuaXNfYWRkID0gZmFsc2U7XG5cdFx0dGhpcy5pc19jaGFuZ2VkID0gZmFsc2U7XG5cblx0XHR2YXIgY3VycmVudF9hcGkgPSB0aGlzLmdldEN1cnJlbnRBUEkoKTtcblx0XHR2YXIgcmVjb3JkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnc2F2ZV9hbmRfbmV4dCc7XG5cdFx0cmVjb3JkID0gdGhpcy51bmlmb3JtVmFyaWFibGUoIHJlY29yZCApO1xuXHRcdGN1cnJlbnRfYXBpWydzZXQnICsgY3VycmVudF9hcGkua2V5X25hbWVdKCByZWNvcmQsIGZhbHNlLCBpZ25vcmVXYXJuaW5nLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0JHRoaXMub25TYXZlQW5kTmV4dFJlc3VsdCggcmVzdWx0ICk7XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvblNhdmVBbmROZXh0UmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRpZiAoIHJlc3VsdF9kYXRhID09PSB0cnVlICYmICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQ7XG5cdFx0XHR9IGVsc2UgaWYgKCByZXN1bHRfZGF0YSAmJiBUVFVVSUQuaXNVVUlEKCByZXN1bHRfZGF0YSApICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC56ZXJvX2lkICYmIHJlc3VsdF9kYXRhICE9IFRUVVVJRC5ub3RfZXhpc3RfaWQgKSB7XG5cdFx0XHRcdCR0aGlzLnJlZnJlc2hfaWQgPSByZXN1bHRfZGF0YTtcblx0XHRcdH1cblxuXHRcdFx0JHRoaXMuc2F2ZUluc2lkZUVkaXRvckRhdGEoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5vblJpZ2h0QXJyb3dDbGljaygpO1xuXHRcdFx0XHQkdGhpcy5zZWFyY2goIGZhbHNlICk7XG5cdFx0XHRcdCR0aGlzLm9uU2F2ZUFuZE5leHREb25lKCByZXN1bHQgKTtcblx0XHRcdH0gKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkdGhpcy5zZXRFcnJvck1lbnUoKTtcblx0XHRcdCR0aGlzLnNldEVycm9yVGlwcyggcmVzdWx0ICk7XG5cblx0XHR9XG5cdH1cblxuXHR1bmlmb3JtVmFyaWFibGUoIHJlY29yZHMgKSB7XG5cdFx0cmV0dXJuIHJlY29yZHM7XG5cdH1cblxuXHRzYXZlSW5zaWRlRWRpdG9yRGF0YSggY2FsbGJhY2sgKSB7XG5cdFx0Ly9vdmVycmlkZSB0aGlzIHN0dWIgZnVuY3Rpb24gd2hlcmUgbmVlZWQuIEJyb3VnaHQgaW4gdG8gY29uc29saWRhdGUgdGhvc2UgdmlldyBjb250cm9sbGVycyB0aGF0IHVzZWQgdGhpcy5cblx0XHQvKiBEZXYgTm90ZTogIzI2NDQgSWYgaXNzdWVzIGhhcHBlbiwgcmVhZCB0aGlzOlxuXHRcdMKgKiBGdW5jdGlvbnMgc3VjaCBhcyBvblNhdmVBbmROZXh0UmVzdWx0KCkgaGFkIGEgc2F2ZUluc2lkZUVkaXRvckRhdGEgY2FsbCwgYnV0IHRoZSBiYXNlIHZpZXcgZGlkIG5vdCwgYnV0IHRoZSByZXN0IG9mIHRoZSBmdW5jdGlvbiB3YXMgdGhlIHNhbWUuXG5cdFx0ICogRHVyaW5nIHJlZmFjdG9yIG9mIHRoZXNlIGZ1bmN0aW9ucyBsaWtlIHNhdmUgYW5kIG5leHQgcmVzdWx0IGludG8gdGhlIGJhc2UgdmlldywgYSBzdHViIG9mIHNhdmVJbnNpZGVFZGl0b3IgaGFkIHRvIGJlIGNyZWF0ZWQgYXMgaXQgd2FzIG5vdCB0aGVyZSBwcmV2aW91c2x5LlxuXHRcdCAqL1xuXG5cdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0Q2hhbmdlZEZpZWxkcygpIHtcblx0XHR2YXIgcmV0dmFsID0ge307XG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmVkaXRfdmlld191aV9kaWMgKSB7XG5cdFx0XHRpZiAoICF0aGlzLmVkaXRfdmlld191aV9kaWMuaGFzT3duUHJvcGVydHkoIGtleSApICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdHZhciB3aWRnZXQgPSB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XTtcblxuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHdpZGdldC5pc0NoZWNrZWQgKSApIHtcblx0XHRcdFx0aWYgKCB3aWRnZXQuaXNDaGVja2VkKCkgJiYgd2lkZ2V0LmdldEVuYWJsZWQoKSApIHtcblx0XHRcdFx0XHRyZXR2YWxba2V5XSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldOyAvLyBOb3RlOiBTb21lIHZpZXcgY29udHJvbGxlcnMgdXNlIHdpZGdldC5nZXRWYWx1ZSgpIGluc3RlYWQgb2YgY3VycmVudF9lZGl0X3JlY29yZFtrZXldXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gcmV0dmFsO1xuXHR9XG5cblx0Ly8gb3ZlcnJpZGRlbiBpbiB2aWV3IGNvbnRyb2xsZXJzIHdoZXJlIG5lZWRlZFxuXHQvLyB0aGlzIGJhc2UgdmVyc2lvbiB3aWxsIHNpbXBseSBleHRyYWN0IGFuZCBkdXBsaWNhdGUgY3VycmVudCBlZGl0IHJlY29yZCBpZiBhbiBhcnJheSBvZiB1c2VyX2lkJ3MgZXhpc3Rcblx0Ly8gcGFyZW50IGZ1bmN0aW9uIHNob3VsZCBjaGVjayB0byBjb25maXJtIHRoaXMuaXNfbWFzc19hZGRpbmcgaXMgdHJ1ZVxuXHRidWlsZE1hc3NBZGRSZWNvcmQoIHJlY29yZCApIHtcblx0XHR2YXIgcmV0dmFsO1xuXHRcdGlmICggR2xvYmFsLmlzQXJyYXkoIHJlY29yZC51c2VyX2lkICkgJiYgcmVjb3JkLnVzZXJfaWQubGVuZ3RoID4gMCApIHtcblx0XHRcdHJldHZhbCA9IFtdO1xuXHRcdFx0JC5lYWNoKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCwgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblxuXHRcdFx0XHR2YXIgY29tbW9uUmVjb3JkID0gR2xvYmFsLmNsb25lKCByZWNvcmQgKTtcblx0XHRcdFx0Y29tbW9uUmVjb3JkLnVzZXJfaWQgPSB2YWx1ZTtcblx0XHRcdFx0cmV0dmFsLnB1c2goIGNvbW1vblJlY29yZCApO1xuXG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHZhbCA9IHJlY29yZDtcblx0XHR9XG5cblx0XHRyZXR1cm4gcmV0dmFsO1xuXHR9XG5cblx0YnVpbGRNYXNzRWRpdFNhdmVSZWNvcmQoIG1hc3NfZWRpdF9yZWNvcmRfaWRzLCBjaGFuZ2VkX2ZpZWxkcyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBtYXNzX3JlY29yZHMgPSBbXTtcblxuXHRcdCQuZWFjaCggbWFzc19lZGl0X3JlY29yZF9pZHMsIGZ1bmN0aW9uKCBpbmRleCwgdmFsdWUgKSB7XG5cdFx0XHR2YXIgY29tbW9uX3JlY29yZCA9IEdsb2JhbC5jbG9uZSggY2hhbmdlZF9maWVsZHMgKTtcblx0XHRcdGNvbW1vbl9yZWNvcmQuaWQgPSB2YWx1ZTtcblx0XHRcdGNvbW1vbl9yZWNvcmQgPSAkdGhpcy51bmlmb3JtVmFyaWFibGUoIGNvbW1vbl9yZWNvcmQgKTtcblx0XHRcdG1hc3NfcmVjb3Jkcy5wdXNoKCBjb21tb25fcmVjb3JkICk7XG5cdFx0fSApO1xuXG5cdFx0cmV0dXJuIG1hc3NfcmVjb3Jkcztcblx0fVxuXG5cdG9uU2F2ZUNsaWNrKCBpZ25vcmVXYXJuaW5nICkge1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggaWdub3JlV2FybmluZyApICkge1xuXHRcdFx0aWdub3JlV2FybmluZyA9IGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciByZWNvcmQ7XG5cdFx0Ly9TZXR0aW5nIGlzX2FkZCBmYWxzZSB0b28gZWFybHkgY2FuIGNhdXNlIGRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkgdG8gaGF2ZSB1bmV4cGVjdGVkIHNpZGUgZWZmZWN0cy4gSG93ZXZlciBub3Qgc2V0dGluZyBpdCBoZXJlIG1pZ2h0IGhhdmUgb3RoZXIgc2lkZSBlZmZlY3RzLlxuXHRcdC8vdGhpcy5pc19hZGQgPSBmYWxzZTtcblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ3NhdmUnO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdHZhciBjaGFuZ2VkX2ZpZWxkcyA9IHRoaXMuZ2V0Q2hhbmdlZEZpZWxkcygpO1xuXHRcdFx0cmVjb3JkID0gdGhpcy5idWlsZE1hc3NFZGl0U2F2ZVJlY29yZCggdGhpcy5tYXNzX2VkaXRfcmVjb3JkX2lkcywgY2hhbmdlZF9maWVsZHMgKTtcblxuXHRcdH0gZWxzZSBpZiAoIHRoaXMuaXNfbWFzc19hZGRpbmcgKSB7XG5cdFx0XHRyZWNvcmQgPSB0aGlzLmJ1aWxkTWFzc0FkZFJlY29yZCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVjb3JkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkO1xuXHRcdFx0cmVjb3JkID0gdGhpcy51bmlmb3JtVmFyaWFibGUoIHJlY29yZCApO1xuXHRcdH1cblxuXHRcdHRoaXMuZG9TYXZlQVBJQ2FsbCggcmVjb3JkLCBpZ25vcmVXYXJuaW5nICk7XG5cdH1cblxuXHRkb1NhdmVBUElDYWxsKCByZWNvcmQsIGlnbm9yZVdhcm5pbmcsIGNhbGxiYWNrICkge1xuXHRcdHZhciBjdXJyZW50X2FwaSA9IHRoaXMuZ2V0Q3VycmVudEFQSSgpO1xuXG5cdFx0aWYgKCAhY2FsbGJhY2sgKSB7XG5cdFx0XHRjYWxsYmFjayA9IHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0dGhpcy5vblNhdmVSZXN1bHQoIHJlc3VsdCApO1xuXHRcdFx0XHR9LmJpbmQoIHRoaXMgKVxuXHRcdFx0fTtcblx0XHR9XG5cblx0XHQvL2N1cnJlbnRfYXBpLnNldElzSWRlbXBvdGVudCggdHJ1ZSApOyAvL0ZvcmNlIHRvIGlkZW1wb3RlbnQgQVBJIGNhbGwgdG8gYXZvaWQgZHVwbGljYXRlIG5ldHdvcmsgcmVxdWVzdHMgZnJvbSBjYXVzaW5nIGVycm9ycyBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG5cdFx0cmV0dXJuIGN1cnJlbnRfYXBpWydzZXQnICsgY3VycmVudF9hcGkua2V5X25hbWVdKCByZWNvcmQsIGZhbHNlLCBpZ25vcmVXYXJuaW5nLCBjYWxsYmFjayApO1xuXHR9XG5cblx0b25TYXZlUmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHQvL1NldHRpbmcgaXNfYWRkIGZhbHNlIHRvbyBlYXJseSBjYW4gY2F1c2UgZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKSB0byBoYXZlIHVuZXhwZWN0ZWQgc2lkZSBlZmZlY3RzLiBIb3dldmVyIG5vdCBzZXR0aW5nIGl0IGhlcmUgbWlnaHQgaGF2ZSBvdGhlciBzaWRlIGVmZmVjdHMuXG5cdFx0XHQvLyR0aGlzLmlzX2FkZCA9IGZhbHNlO1xuXHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0aWYgKCAhdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdFx0aWYgKCByZXN1bHRfZGF0YSA9PT0gdHJ1ZSAmJiAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB7XG5cdFx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQ7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIFRUVVVJRC5pc1VVSUQoIHJlc3VsdF9kYXRhICkgJiYgcmVzdWx0X2RhdGEgIT0gVFRVVUlELnplcm9faWQgJiYgcmVzdWx0X2RhdGEgIT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0XHQkdGhpcy5yZWZyZXNoX2lkID0gcmVzdWx0X2RhdGE7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9IG51bGw7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIG9uX3NhdmVfZG9uZV9yZXN1bHQgPSAkdGhpcy5vblNhdmVEb25lKCByZXN1bHQgKTsgLy9wb3N0IGhvb2sgZm9yIG9uU2F2ZVJlc3VsdFxuXHRcdFx0aWYgKCBvbl9zYXZlX2RvbmVfcmVzdWx0ID09IHVuZGVmaW5lZCB8fCBvbl9zYXZlX2RvbmVfcmVzdWx0ID09IHRydWUgKSB7XG5cdFx0XHRcdCR0aGlzLnJlbW92ZUVkaXRWaWV3KCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCR0aGlzLnNldEVycm9yVGlwcyggcmVzdWx0ICk7XG5cdFx0XHQkdGhpcy5zZXRFcnJvck1lbnUoKTtcblx0XHR9XG5cdH1cblxuXHQvL3Bvc3QgaG9vayBmb3Igb25TYXZlUmVzdWx0XG5cdG9uU2F2ZURvbmUoIHJlc3VsdCApIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdG9uU2F2ZUFuZENvbnRpbnVlRG9uZSggcmVzdWx0ICkge1xuXHR9XG5cblx0b25TYXZlQW5kTmV4dERvbmUoIHJlc3VsdCApIHtcblx0fVxuXG5cdG9uRGVsZXRlRG9uZSggcmVzdWx0ICkge1xuXHRcdHRoaXMucmVtb3ZlRGVsZXRlZFJvd3MoKTtcblx0fVxuXG5cdG9uRGVsZXRlQW5kTmV4dERvbmUoIHJlc3VsdCApIHtcblx0fVxuXG5cdG9uTWFzc0VkaXRDbGljaygpIHtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy5zZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSggJ21hc3NfZWRpdCcgKTtcblx0XHQkdGhpcy5vcGVuRWRpdFZpZXcoKTtcblx0XHR2YXIgZmlsdGVyID0ge307XG5cdFx0dmFyIGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkgPSB0aGlzLmdldEdyaWRTZWxlY3RJZEFycmF5KCk7XG5cdFx0dmFyIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID0gZ3JpZF9zZWxlY3RlZF9pZF9hcnJheS5sZW5ndGg7XG5cdFx0dGhpcy5tYXNzX2VkaXRfcmVjb3JkX2lkcyA9IFtdO1xuXG5cdFx0JC5lYWNoKCBncmlkX3NlbGVjdGVkX2lkX2FycmF5LCBmdW5jdGlvbiggaW5kZXgsIHZhbHVlICkge1xuXHRcdFx0JHRoaXMubWFzc19lZGl0X3JlY29yZF9pZHMucHVzaCggdmFsdWUgKTtcblx0XHR9ICk7XG5cblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEgPSB7fTtcblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEuaWQgPSB0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzO1xuXG5cdFx0dGhpcy5hcGlbJ2dldENvbW1vbicgKyB0aGlzLmFwaS5rZXlfbmFtZSArICdEYXRhJ10oIGZpbHRlciwge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdHZhciByZXN1bHRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRpZiAoICFyZXN1bHRfZGF0YSApIHtcblx0XHRcdFx0XHRyZXN1bHRfZGF0YSA9IFtdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JHRoaXMuYXBpWydnZXRPcHRpb25zJ10oICd1bmlxdWVfY29sdW1ucycsIHtcblx0XHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnVuaXF1ZV9jb2x1bW5zID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdFx0JHRoaXMuYXBpWydnZXRPcHRpb25zJ10oICdsaW5rZWRfY29sdW1ucycsIHtcblx0XHRcdFx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQxICkge1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLmxpbmtlZF9jb2x1bW5zID0gcmVzdWx0MS5nZXRSZXN1bHQoKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoICR0aGlzLmxpbmtlZF9jb2x1bW5zID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly90aGVyZSBhcmUgbm8gY29sdW1ucywgeW91IHNob3VsZCBiZSBhbiBlbXB0eSBhcnJheS5cblx0XHRcdFx0XHRcdFx0XHRcdCR0aGlzLmxpbmtlZF9jb2x1bW5zID0gW107XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGlmICggJHRoaXMuc3ViX3ZpZXdfbW9kZSAmJiAkdGhpcy5wYXJlbnRfa2V5ICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmVzdWx0X2RhdGFbJHRoaXMucGFyZW50X2tleV0gPSAkdGhpcy5wYXJlbnRfdmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHJlc3VsdF9kYXRhO1xuXHRcdFx0XHRcdFx0XHRcdCR0aGlzLmluaXRFZGl0VmlldygpO1xuXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0Lypcblx0ICogVmlldyBDbGljayBoYW5kbGVycyAtIFN0YXJ0XG5cdCAqL1xuXHRnZXRWaWV3U2VsZWN0ZWRSZWNvcmRJZCggcmVjb3JkICkge1xuXHRcdHZhciByZXR2YWwgPSBmYWxzZTtcblx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKTtcblx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9sZW5ndGggPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5Lmxlbmd0aDtcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCByZWNvcmQgKSApIHtcblx0XHRcdC8vSGFuZGxlIGNhc2VzIHdoZXJlIHJlY29yZCBvYmplY3QgaXMgcGFzc2VkIGluLCBzbyB3ZSBjYW4gZXh0cmFjdCB0aGUgc3RyaW5nIElELlxuXHRcdFx0Ly8gIEFzIHdlbGwgd2hlcmUgdGhlIHN0cmluZyBJRCBpcyBwYXNzZWQgaW4gZGlyZWN0bHkgYXMgYSBVVUlEIGFuZCBhY2NlcHQgdGhhdCB0b28uXG5cdFx0XHQvLyAgVGhpcyBpcyByZXF1aXJlZCB0byBoYW5kbGUgTXlBY2NvdW50IC0+IFJlcXVlc3QgQXV0aG9yaXphdGlvbiwgdmlldyBhbnkgcmVjb3JkLCB0aGVuIHJlZnJlc2ggdGhlIGJyb3dzZXIuXG5cdFx0XHRpZiAoIEdsb2JhbC5pc09iamVjdCggcmVjb3JkICkgJiYgcmVjb3JkLmlkICkge1xuXHRcdFx0XHRyZXR2YWwgPSByZWNvcmQuaWQ7XG5cdFx0XHR9IGVsc2UgaWYgKCBHbG9iYWwuaXNTdHJpbmcoIHJlY29yZCApICYmIFRUVVVJRC5pc1VVSUQoIHJlY29yZCApICkge1xuXHRcdFx0XHRyZXR2YWwgPSByZWNvcmQ7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPiAwICkge1xuXHRcdFx0XHRyZXR2YWwgPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5WzBdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dmFsID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gcmV0dmFsO1xuXHR9XG5cblx0ZG9WaWV3QVBJQ2FsbCggZmlsdGVyLCBhcGlfYXJncyApIHtcblx0XHR2YXIgY2FsbGJhY2sgPSB7IG9uUmVzdWx0OiB0aGlzLmhhbmRsZVZpZXdBUElDYWxsYmFja1Jlc3VsdC5iaW5kKCB0aGlzICkgfTtcblx0XHRpZiAoIGFwaV9hcmdzICkge1xuXHRcdFx0Ly8gSWYgYXBpX2FyZ3Mgc3BlY2lmaWVkLCB1c2UgYXBpX2FyZ3MuZmlsdGVyLCBhbmQgaWdub3JlIGZ1bmN0aW9uIGZpbHRlciBwYXJhbWV0ZXIuXG5cdFx0XHRhcGlfYXJncy5wdXNoKCBjYWxsYmFjayApO1xuXHRcdFx0cmV0dXJuIHRoaXMuYXBpWydnZXQnICsgdGhpcy5hcGkua2V5X25hbWVdLmFwcGx5KCB0aGlzLmFwaSwgYXBpX2FyZ3MgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHRoaXMuYXBpWydnZXQnICsgdGhpcy5hcGkua2V5X25hbWVdKCBmaWx0ZXIsIGNhbGxiYWNrICk7XG5cdFx0fVxuXHR9XG5cblx0aGFuZGxlVmlld0FQSUNhbGxiYWNrUmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyIHJlc3VsdF9kYXRhO1xuXHRcdGlmICggcmVzdWx0ICYmIHJlc3VsdC5nZXRSZXN1bHQgKSB7XG5cdFx0XHRyZXN1bHRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0Ly9EbyBhbnkgcmVzdWx0IG1hbmlwdWxhdGlvbiBwcm9jZXNzZXMgaGVyZSwgc3VjaCBhcyBjb21iaW5pbmcgSURzIHRvZ2V0aGVyIGludG8gYSBjb21wb3NpdGUuXG5cdFx0XHRyZXN1bHRfZGF0YSA9IHRoaXMucHJvY2Vzc0FQSUNhbGxiYWNrUmVzdWx0KCByZXN1bHRfZGF0YSApO1xuXG5cdFx0XHRpZiAoICFyZXN1bHRfZGF0YSApIHtcblx0XHRcdFx0cmVzdWx0X2RhdGEgPSBbXTtcblx0XHRcdH1cblxuXHRcdFx0cmVzdWx0X2RhdGEgPSByZXN1bHRfZGF0YVswXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9EbyBub3QgY2FsbCBwcm9jZXNzQVBJQ2FsbGJhY2tSZXN1bHQoKSBoZXJlIGFzIHdlIGFzc3VtZSBhbGwgcHJvY2Vzc2luZyBoYXMgYmVlbiBjb21wbGV0ZWQgZWFybGllci5cblx0XHRcdHJlc3VsdF9kYXRhID0gcmVzdWx0O1xuXHRcdH1cblxuXHRcdGlmICggIXJlc3VsdF9kYXRhICkge1xuXHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93QWxlcnQoICQuaTE4bi5fKCAnUmVjb3JkIGRvZXMgbm90IGV4aXN0LicgKSApO1xuXHRcdFx0cmV0dXJuIHRoaXMub25DYW5jZWxDbGljaygpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kb1ZpZXdDbGlja1Jlc3VsdCggcmVzdWx0X2RhdGEgKTtcblx0XHR9XG5cdH1cblxuXHRkb1ZpZXdDbGlja1Jlc3VsdCggcmVzdWx0X2RhdGEgKSB7XG5cdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID0gcmVzdWx0X2RhdGE7XG5cdFx0dGhpcy5pbml0RWRpdFZpZXcoKTtcblx0XHRyZXR1cm4gdGhpcy5jbGVhckN1cnJlbnRTZWxlY3RlZFJlY29yZCgpO1xuXHR9XG5cblx0b25WaWV3Q2xpY2soIHJlY29yZCwgbm9SZWZyZXNoVUkgKSB7XG5cdFx0dGhpcy5zZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSggJ3ZpZXcnICk7XG5cdFx0dGhpcy5vcGVuRWRpdFZpZXcoKTtcblxuXHRcdHZhciByZWNvcmRfaWQgPSB0aGlzLmdldFZpZXdTZWxlY3RlZFJlY29yZElkKCByZWNvcmQgKTtcblx0XHRpZiAoIEdsb2JhbC5pc0ZhbHNlT3JOdWxsKCByZWNvcmRfaWQgKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5zZXRDdXJyZW50U2VsZWN0ZWRSZWNvcmQoIHJlY29yZF9pZCApO1xuXG5cdFx0dmFyIGZpbHRlciA9IHRoaXMuZ2V0QVBJRmlsdGVycygpO1xuXG5cdFx0cmV0dXJuIHRoaXMuZG9WaWV3QVBJQ2FsbCggZmlsdGVyICk7XG5cdH1cblxuXHRzZXRDdXJyZW50U2VsZWN0ZWRSZWNvcmQoIHJlY29yZCApIHtcblx0XHRpZiAoIHJlY29yZCApIHtcblx0XHRcdHRoaXMuY3VycmVudF9zZWxlY3RlZF9yZWNvcmQgPSByZWNvcmQ7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRnZXRDdXJyZW50U2VsZWN0ZWRSZWNvcmQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY3VycmVudF9zZWxlY3RlZF9yZWNvcmQ7XG5cdH1cblxuXHRjbGVhckN1cnJlbnRTZWxlY3RlZFJlY29yZCgpIHtcblx0XHRkZWxldGUgdGhpcy5jdXJyZW50X3NlbGVjdGVkX3JlY29yZDtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdC8vIGRvIHdlIG5lZWQgdGhpcywgTWlrZSBjcmVhdGVkIGl0IGJ1dCBjaGVjayB3aXRoIGhpbSwgYXMgaXQgbWF5IGhhdmUganVzdCBiZWVuIGEgcG90ZW50aWFsIGlkZWEsIG5vdCB1c2VkLlxuXHRnZXRSZWNvcmRJZEZyb21SZWNvcmQoIG9iamVjdCApIHtcblx0XHRpZiAoIEdsb2JhbC5pc09iamVjdCggb2JqZWN0ICkgKSB7XG5cdFx0XHRyZXR1cm4gb2JqZWN0X2lkO1xuXHRcdH0gZWxzZSBpZiAoIEdsb2JhbC5pc1N0cmluZyggb2JqZWN0ICkgKSB7XG5cdFx0XHRyZXR1cm4gb2JqZWN0O1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qXG5cdCAqIFZpZXcgQ2xpY2sgaGFuZGxlcnMgLSBFbmRcblx0ICovXG5cblx0Lypcblx0ICogQ29tbW9uIGJldHdlZW4gVmlldyBhbmQgRWRpdFxuXHQgKi9cblx0cHJvY2Vzc0FQSUNhbGxiYWNrUmVzdWx0KCByZXN1bHRfZGF0YSApIHtcblx0XHRyZXR1cm4gcmVzdWx0X2RhdGE7XG5cdH1cblxuXHRnZXRBUElGaWx0ZXJzKCkge1xuXHRcdC8vIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24gaWYgdmlldyByZXF1aXJlcyBtb3JlIGZpbHRlcnNcblx0XHR2YXIgcmVjb3JkX2lkID0gdGhpcy5nZXRDdXJyZW50U2VsZWN0ZWRSZWNvcmQoKTtcblx0XHR2YXIgZmlsdGVyID0ge307XG5cblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEgPSB7fTtcblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEuaWQgPSBbcmVjb3JkX2lkXTtcblxuXHRcdHJldHVybiBmaWx0ZXI7XG5cdH1cblxuXHQvKlxuXHQgKiBFZGl0IENsaWNrIGhhbmRsZXJzIC0gU3RhcnRcblx0ICovXG5cdGdldEVkaXRTZWxlY3RlZFJlY29yZElkKCByZWNvcmQgKSB7XG5cdFx0dmFyIHJldHZhbCA9IGZhbHNlO1xuXHRcdHZhciBncmlkX3NlbGVjdGVkX2lkX2FycmF5ID0gdGhpcy5nZXRHcmlkU2VsZWN0SWRBcnJheSgpO1xuXHRcdHZhciBncmlkX3NlbGVjdGVkX2xlbmd0aCA9IGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkubGVuZ3RoO1xuXG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHJlY29yZCApICkge1xuXHRcdFx0Ly9IYW5kbGUgY2FzZXMgd2hlcmUgcmVjb3JkIG9iamVjdCBpcyBwYXNzZWQgaW4sIHNvIHdlIGNhbiBleHRyYWN0IHRoZSBzdHJpbmcgSUQuXG5cdFx0XHQvLyAgQXMgd2VsbCB3aGVyZSB0aGUgc3RyaW5nIElEIGlzIHBhc3NlZCBpbiBkaXJlY3RseSBhcyBhIFVVSUQgYW5kIGFjY2VwdCB0aGF0IHRvby5cblx0XHRcdC8vICBUaGlzIGlzIHJlcXVpcmVkIHRvIGhhbmRsZSBlZGl0aW5nIGFueSByZWNvcmQsIHRoZW4gcmVmcmVzaCB0aGUgYnJvd3Nlci5cblx0XHRcdGlmICggR2xvYmFsLmlzT2JqZWN0KCByZWNvcmQgKSAmJiByZWNvcmQuaWQgKSB7XG5cdFx0XHRcdHJldHZhbCA9IHJlY29yZC5pZDtcblx0XHRcdH0gZWxzZSBpZiAoIEdsb2JhbC5pc1N0cmluZyggcmVjb3JkICkgJiYgVFRVVUlELmlzVVVJRCggcmVjb3JkICkgKSB7XG5cdFx0XHRcdHJldHZhbCA9IHJlY29yZDtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9DaGVjayBmb3IgaXNfdmlld2luZyBhbmQgaXNfZWRpdCBhcyB0aGUgc3RhdGUgbWF5IGhhdmUgY2hhbmdlZCBmcm9tIHZpZXdpbmcgdG8gZWRpdGluZyBpbW1lZGlhdGVseSBiZWZvcmUgaXQgZ290IGhlcmUuXG5cdFx0XHQvLyAgVGVzdCB0aGlzIHdpdGg6IEF0dGVuZGFuY2UgLT4gVGltZVNoZWV0LCBFZGl0IFB1bmNoLCBjbGljayBTdGF0aW9uIGZpZWxkIHRvIHZpZXcgdGhlIHN0YXRpb24sIHRoZW4gY2xpY2sgXCJFZGl0XCIgaWNvbi5cblx0XHRcdGlmICggKCB0aGlzLmlzX3ZpZXdpbmcgfHwgdGhpcy5pc19lZGl0ICkgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdFx0cmV0dmFsID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkO1xuXHRcdFx0fSBlbHNlIGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPiAwICkge1xuXHRcdFx0XHRyZXR2YWwgPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5WzBdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dmFsID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHJldHZhbDtcblx0fVxuXG5cdGRvRWRpdEFQSUNhbGwoIGZpbHRlciwgYXBpX2FyZ3MsIGNhbGxiYWNrICkge1xuXHRcdGlmICggIWNhbGxiYWNrICkge1xuXHRcdFx0Y2FsbGJhY2sgPSB7IG9uUmVzdWx0OiB0aGlzLmhhbmRsZUVkaXRBUElDYWxsYmFja1Jlc3VsdC5iaW5kKCB0aGlzICkgfTtcblx0XHR9XG5cdFx0aWYgKCBhcGlfYXJncyApIHtcblx0XHRcdC8vIElmIGFwaV9hcmdzIHNwZWNpZmllZCwgdXNlIGFwaV9hcmdzLmZpbHRlciwgYW5kIGlnbm9yZSBmdW5jdGlvbiBmaWx0ZXIgcGFyYW1ldGVyLlxuXHRcdFx0YXBpX2FyZ3MucHVzaCggY2FsbGJhY2sgKTtcblx0XHRcdHJldHVybiB0aGlzLmFwaVsnZ2V0JyArIHRoaXMuYXBpLmtleV9uYW1lXS5hcHBseSggdGhpcy5hcGksIGFwaV9hcmdzICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB0aGlzLmFwaVsnZ2V0JyArIHRoaXMuYXBpLmtleV9uYW1lXSggZmlsdGVyLCBjYWxsYmFjayApO1xuXHRcdH1cblx0fVxuXG5cdGhhbmRsZUVkaXRBUElDYWxsYmFja1Jlc3VsdCggcmVzdWx0ICkge1xuXHRcdHZhciByZXN1bHRfZGF0YTtcblx0XHRpZiAoIHJlc3VsdC5nZXRSZXN1bHQgKSB7XG5cdFx0XHRyZXN1bHRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0Ly9EbyBhbnkgcmVzdWx0IG1hbmlwdWxhdGlvbiBwcm9jZXNzZXMgaGVyZSwgc3VjaCBhcyBjb21iaW5pbmcgSURzIHRvZ2V0aGVyIGludG8gYSBjb21wb3NpdGUuXG5cdFx0XHRyZXN1bHRfZGF0YSA9IHRoaXMucHJvY2Vzc0FQSUNhbGxiYWNrUmVzdWx0KCByZXN1bHRfZGF0YSApO1xuXG5cdFx0XHRpZiAoICFyZXN1bHRfZGF0YSApIHtcblx0XHRcdFx0cmVzdWx0X2RhdGEgPSBbXTtcblx0XHRcdH1cblxuXHRcdFx0cmVzdWx0X2RhdGEgPSByZXN1bHRfZGF0YVswXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9EbyBub3QgY2FsbCBwcm9jZXNzQVBJQ2FsbGJhY2tSZXN1bHQoKSBoZXJlIGFzIHdlIGFzc3VtZSBhbGwgcHJvY2Vzc2luZyBoYXMgYmVlbiBjb21wbGV0ZWQgZWFybGllci5cblx0XHRcdHJlc3VsdF9kYXRhID0gcmVzdWx0O1xuXHRcdH1cblx0XHRpZiAoICFyZXN1bHRfZGF0YSApIHtcblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0FsZXJ0KCAkLmkxOG4uXyggJ1JlY29yZCBkb2VzIG5vdCBleGlzdC4nICkgKTtcblx0XHRcdHJldHVybiB0aGlzLm9uQ2FuY2VsQ2xpY2soKTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc3ViX3ZpZXdfbW9kZSAmJiB0aGlzLnBhcmVudF9rZXkgKSB7XG5cdFx0XHRyZXN1bHRfZGF0YVt0aGlzLnBhcmVudF9rZXldID0gdGhpcy5wYXJlbnRfdmFsdWU7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmRvRWRpdENsaWNrUmVzdWx0KCByZXN1bHRfZGF0YSApO1xuXHR9XG5cblx0ZG9FZGl0Q2xpY2tSZXN1bHQoIHJlc3VsdF9kYXRhICkge1xuXHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHJlc3VsdF9kYXRhO1xuXHRcdHRoaXMuaW5pdEVkaXRWaWV3KCk7XG5cdH1cblxuXHRvbkVkaXRDbGljayggcmVjb3JkX2lkLCBub1JlZnJlc2hVSSApIHtcblx0XHR0aGlzLnNldEN1cnJlbnRFZGl0Vmlld1N0YXRlKCAnZWRpdCcgKTtcblx0XHR0aGlzLm9wZW5FZGl0VmlldygpO1xuXG5cdFx0cmVjb3JkX2lkID0gdGhpcy5nZXRFZGl0U2VsZWN0ZWRSZWNvcmRJZCggcmVjb3JkX2lkICk7XG5cdFx0aWYgKCBHbG9iYWwuaXNGYWxzZU9yTnVsbCggcmVjb3JkX2lkICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuc2V0Q3VycmVudFNlbGVjdGVkUmVjb3JkKCByZWNvcmRfaWQgKTtcblxuXHRcdHZhciBmaWx0ZXIgPSB0aGlzLmdldEFQSUZpbHRlcnMoKTtcblxuXHRcdHJldHVybiB0aGlzLmRvRWRpdEFQSUNhbGwoIGZpbHRlciApO1xuXHR9XG5cblx0Lypcblx0ICogRWRpdCBDbGljayBoYW5kbGVycyAtIEVuZFxuXHQgKi9cblxuXHRvbkNvcHlDbGljaygpIHtcblx0XHRpZiAoIHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKS5sZW5ndGggPiAxICkge1xuXHRcdFx0Ly9XYXJuIHVzZXIgaWYgdGhleSBhcmUgdHJ5aW5nIHRvIGNvcHkgbXVsdGlwbGUgcmVjb3Jkcy5cblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0NvbmZpcm1BbGVydCggR2xvYmFsLmNvcHlfbXVsdGlwbGVfY29uZmlybV9tZXNzYWdlLCBudWxsLCAoIGFuc3dlciApID0+IHtcblx0XHRcdFx0aWYgKCBhbnN3ZXIgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0dGhpcy5kb0NvcHlDbGljaygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuZG9Db3B5Q2xpY2soKTtcblx0XHR9XG5cdH1cblxuXHRkb0NvcHlDbGljaygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBjb3B5SWRzID0gW107XG5cdFx0JHRoaXMuaXNfYWRkID0gZmFsc2U7XG5cdFx0aWYgKCAkdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRjb3B5SWRzLnB1c2goICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKTtcblx0XHRcdGlmICggdGhpcy5pc19jaGFuZ2VkICkge1xuXHRcdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoIEdsb2JhbC5tb2RpZnlfYWxlcnRfbWVzc2FnZSwgbnVsbCwgZnVuY3Rpb24oIGZsYWcgKSB7XG5cdFx0XHRcdFx0aWYgKCBmbGFnID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuaXNfY2hhbmdlZCA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0JHRoaXMuX2NvbnRpbnVlRG9Db3B5KCBjb3B5SWRzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFByb2dyZXNzQmFyLmNsb3NlT3ZlcmxheSgpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5fY29udGludWVEb0NvcHkoIGNvcHlJZHMgKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29weUlkcyA9ICR0aGlzLmdldEdyaWRTZWxlY3RJZEFycmF5KCkuc2xpY2UoKTtcblx0XHRcdCR0aGlzLl9jb250aW51ZURvQ29weSggY29weUlkcyApO1xuXHRcdH1cblx0fVxuXG5cdF9jb250aW51ZURvQ29weSggY29weUlkcyApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdFByb2dyZXNzQmFyLnNob3dPdmVybGF5KCk7XG5cblx0XHQvLyR0aGlzLmFwaS5zZXRJc0lkZW1wb3RlbnQoIHRydWUgKTsgLy9Gb3JjZSB0byBpZGVtcG90ZW50IEFQSSBjYWxsIHRvIGF2b2lkIGR1cGxpY2F0ZSBuZXR3b3JrIHJlcXVlc3RzIGZyb20gY2F1c2luZyBlcnJvcnMgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuXHRcdCR0aGlzLmFwaVsnY29weScgKyAkdGhpcy5hcGkua2V5X25hbWVdKCBjb3B5SWRzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0JHRoaXMub25Db3B5UmVzdWx0KCByZXN1bHQgKTtcblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uQ29weVJlc3VsdCggcmVzdWx0ICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHQkdGhpcy5zZWFyY2goKTtcblx0XHRcdGlmICggJHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHQkdGhpcy5yZW1vdmVFZGl0VmlldygpO1xuXHRcdFx0fVxuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93RXJyb3JBbGVydCggcmVzdWx0ICk7XG5cblx0XHRcdGlmICggcmVzdWx0LmdldFJlY29yZERldGFpbHMoKS50b3RhbCA+IDEgKSB7XG5cdFx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdG9uQ29weUFzTmV3Q2xpY2soKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHRoaXMuaXNfY2hhbmdlZCApIHtcblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0NvbmZpcm1BbGVydCggR2xvYmFsLm1vZGlmeV9hbGVydF9tZXNzYWdlLCBudWxsLCBmdW5jdGlvbiggZmxhZyApIHtcblx0XHRcdFx0aWYgKCBmbGFnID09PSB0cnVlICkge1xuXHRcdFx0XHRcdCR0aGlzLl9jb250aW51ZURvQ29weUFzTmV3KCk7XG5cdFx0XHRcdFx0aWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuY2xlYXJTdWJWaWV3Q29udHJvbGxlcnMoIGZhbHNlICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vSXNzdWUgIzMwMDkgLSBDb3B5IGFzIG5ldyBjb3VsZCBjYXVzZSBibGFuayB0YWJzIG9yIG9sZCBkYXRhIHRvIGJlIHNob3duIGluc3RlYWQgb2YgU2F2ZSBhbmQgQ29udGludWUgYnV0dG9uLlxuXHRcdFx0XHRcdFx0JHRoaXMuY2xlYXJTdWJWaWV3Q29udHJvbGxlcnMoIHRydWUgKTtcblx0XHRcdFx0XHRcdCR0aGlzLnNob3dTYXZlQW5kQ29udGludWVCdXR0b24oKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX2NvbnRpbnVlRG9Db3B5QXNOZXcoKTtcblx0XHRcdGlmICggdGhpcy5zdWJfdmlld19tb2RlICkge1xuXHRcdFx0XHR0aGlzLmNsZWFyU3ViVmlld0NvbnRyb2xsZXJzKCBmYWxzZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly9Jc3N1ZSAjMzAwOSAtIENvcHkgYXMgbmV3IGNvdWxkIGNhdXNlIGJsYW5rIHRhYnMgb3Igb2xkIGRhdGEgdG8gYmUgc2hvd24gaW5zdGVhZCBvZiBTYXZlIGFuZCBDb250aW51ZSBidXR0b24uXG5cdFx0XHRcdHRoaXMuY2xlYXJTdWJWaWV3Q29udHJvbGxlcnMoIHRydWUgKTtcblx0XHRcdFx0dGhpcy5zaG93U2F2ZUFuZENvbnRpbnVlQnV0dG9uKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Y29weUFzTmV3UmVzZXRJZHMoIGRhdGEgKSB7XG5cdFx0Ly9vdmVycmlkZSB3aGVyZSBuZWVkZWQuXG5cdFx0ZGF0YS5pZCA9ICcnO1xuXHRcdHJldHVybiBkYXRhO1xuXHR9XG5cblx0c2hvd1NhdmVBbmRDb250aW51ZUJ1dHRvbigpIHtcblx0XHRpZiAoIHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0bGV0IHNhdmVfYW5kX2NvbnRpbnVlX2J1dHRvbnMgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLnNhdmUtYW5kLWNvbnRpbnVlLWRpdicgKTtcblx0XHRcdGlmICggc2F2ZV9hbmRfY29udGludWVfYnV0dG9ucyApIHtcblx0XHRcdFx0c2F2ZV9hbmRfY29udGludWVfYnV0dG9ucy5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0fVxuXHRcdH1cbiAgICB9XG5cblx0Y2xlYXJTdWJWaWV3Q29udHJvbGxlcnMoIGZvcmNlICkge1xuXHRcdC8vSXNzdWUgIzI5MTUgLSBTdWIgdmlldyBjb250cm9sbGVycyBzaG91bGQgbm90IGJlIGNsZWFyZWQgd2hpbGUgdGhlIHVzZXIgaXMgb24gYSBzdWIgdmlldy4gRm9yIGV4YW1wbGUgd2hlbiB0aGUgdXNlclxuXHRcdC8vY2xpY2tzIFwiQ29weSBhcyBOZXdcIiBvbiBhIHJlY29yZCBpbiB0aGUgc3ViIHZpZXcgYW5kIGZpbmlzaGVzIHVzaW5nIHRoYXQgc3ViIHZpZXcgdGhleSBhcmUgcmV0dXJuZWQgdG9cblx0XHQvL3RoZSBwcmltYXJ5IGNvbnRyb2xsZXIgYW5kIGlmIGRhdGEgaXMgd2lwZWQgaW4gdGhhdCBzY2VuYXJpbyB0aGUgdGFiIHdvdWxkIGJlIGJsYW5rLlxuXHRcdGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3N1Yl9jb250cm9sbGVyID09IG51bGwgfHwgZm9yY2UgKSB7XG5cdFx0XHQvL0lzc3VlICMyOTEzIC0gU3ViIHZpZXcgZGF0YSB3b3VsZCByZW1haW4gb24gYSB2aWV3IGlmIGEgdXNlciB2aWV3ZWQgYSBzdWIgdmlldyB0YWIgYmVmb3JlIGNsaWNraW5nIFwiQ29weSBhcyBOZXdcIiwgXCJTYXZlICYgTmV3XCIgYW5kIHNpbWlsYXIgc2F2aW5nIGFjdGlvbnMuXG5cdFx0XHQvL0NsZWFyaW5nIG91dCB0aGUgc3ViIHZpZXcgY29udHJvbGxlcnMgYWltcyB0byBwcmV2ZW50IGFueSBvbGQgZGF0YSBmcm9tIHJlbWFpbmluZy5cblx0XHRcdC8vSWYgdGhpcyBkb2VzIG5vdCBoYXBwZW4gdGhlIHN1YiB2aWV3IEhUTUwgd291bGQgcmVtYWluIGFuZCBvdmVybGFwIHdpdGggdGhlIFwiU2F2ZSAmIENvbnRpbnVlXCIgbWVzc2FnZSBhbmQgaW4gZ2VuZXJhbCBzaG93IG5vIGxvbmdlciByZWxldmFudCBkYXRhLlxuXHRcdFx0Zm9yICggdmFyIHByb3BlcnR5IGluIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXIgKSB7XG5cdFx0XHRcdGlmICggcHJvcGVydHkubWF0Y2goICdzdWJfKFthLXpfXSopdmlld19jb250cm9sbGVyJyApICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXJbcHJvcGVydHldICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXJbcHJvcGVydHldLiRlbCApIHtcblx0XHRcdFx0XHREZWJ1Zy5UZXh0KCBwcm9wZXJ0eSwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnb25TYXZlQW5kTmV4dENsaWNrJywgOSApO1xuXHRcdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXJbcHJvcGVydHldLiRlbC5yZW1vdmUoKTtcblx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fcHJpbWFyeV9jb250cm9sbGVyW3Byb3BlcnR5XSA9IG51bGw7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRnZXRDb3B5QXNOZXdGaWx0ZXIoIGZpbHRlciApIHtcblx0XHQvLyBvdmVycmlkZSB3aGVyZSBuZWVkZWQuXG5cdFx0cmV0dXJuIGZpbHRlcjtcblx0fVxuXG5cdF9jb250aW51ZURvQ29weUFzTmV3KCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy5zZXRDdXJyZW50RWRpdFZpZXdTdGF0ZSggJ25ldycgKTtcblx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uID0gJ2NvcHlfYXNfbmV3JztcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCB0aGlzLmVkaXRfdmlldyApICkge1xuXHRcdFx0dGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID0gdGhpcy5jb3B5QXNOZXdSZXNldElkcyggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cdFx0XHR2YXIgbmF2aWdhdGlvbl9kaXYgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLm5hdmlnYXRpb24tZGl2JyApO1xuXHRcdFx0bmF2aWdhdGlvbl9kaXYuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0dGhpcy5zZXRFZGl0TWVudSgpO1xuXHRcdFx0dGhpcy5zZXRUYWJTdGF0dXMoKTsgLy8gU2hvdyB0YWJzIGJhc2VkIG9uIHBlcm1pc3Npb24uIHNldEN1cnJlbnRFZGl0UmVjb3JkRGF0YSBoYXMgZnVuY3Rpb25zIHRvIHNldCBieSByZWNvcmQgdHlwZS4gU2VlICMyNjg3IC0gc2V0VGFiU3RhdHVzKCkgbXVzdCBnbyBiZWZvcmUgc2V0Q3VycmVudEVkaXRSZWNvcmREYXRhKCksIG90aGVyd2lzZSBQcmVtaXVtIFBvbGljeSBUYWJzIGluY29ycmVjdGx5IHNob3duLlxuXHRcdFx0Ly9Jc3N1ZSAjMjkxMyAtIFdoZW4gdXNpbmcgY29weSBhbmQgc2F2ZSBhY3Rpb25zIChcIkNvcHkgQXMgTmV3XCIsIFwiU2F2ZSAmIENvcHlcIiwgZXRjKSBvbiB2aWV3cyB3aXRoIHN1YiB2aWV3cyBzdWNoIGFzIFwiUGF5IFBlcmlvZHNcIiBvbiBQYXkgUGVyaW9kIFNjaGVkdWxlc1xuXHRcdFx0Ly90aGUgc3ViIHZpZXcgdGFiIG1pZ2h0IGFwcGVhciBibGFuay4gVGhpcyBpcyBiZWNhdXNlIHRoZXNlIGNvcHkgZnVuY3Rpb25zIGRvIG5vdCBnbyB0aHJvdWdoIHRoZSBzYW1lIG9yZGVyIG9mIGV2ZW50cyBhcyBhIHJlZ3VsYXIgYWRkIGNsaWNrLlxuXHRcdFx0Ly9CZWNhdXNlIG9mIHRoYXQgd2UgbmVlZCB0byBjYWxsIG9uVGFiU2hvdygpIHRvIG1ha2Ugc3VyZSB0aGUgY29kZSB0aGF0IGNyZWF0ZXMgdGhlIFwiU2F2ZSBhbmQgY29udGludWVcIiBtZXNzYWdlIGFuZCBidXR0b24gdHJpZ2dlcnMuXG5cdFx0XHR0aGlzLm9uVGFiU2hvdygpO1xuXHRcdFx0aWYgKCAhdGhpcy5lZGl0b3IgKSB7XG5cdFx0XHRcdC8vICMyNjg3IGlmIGFuIGVkaXRvciBleGlzdHMgaW4gdGhlIHZpZXcvdGFicywgd2UgZG8gbm90IHdhbnQgdG8gY2FsbCBzZXRDdXJyZW50RWRpdFJlY29yZERhdGEoKSBhcyBpdCB3aXBlcyBvdXQgdGhlIGVkaXRvciBkYXRhIGluIG9uZSBvZiBpdHMgY2hpbGQgZnVuY3Rpb25zIGluaXRJbnNpZGVFZGl0b3JEYXRhKCkuXG5cdFx0XHRcdHRoaXMuc2V0Q3VycmVudEVkaXRSZWNvcmREYXRhKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmlzX2NoYW5nZWQgPSBmYWxzZTtcblx0XHRcdFByb2dyZXNzQmFyLmNsb3NlT3ZlcmxheSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgZmlsdGVyID0ge307XG5cdFx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKTtcblx0XHRcdHZhciBncmlkX3NlbGVjdGVkX2xlbmd0aCA9IGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkubGVuZ3RoO1xuXHRcdFx0aWYgKCBncmlkX3NlbGVjdGVkX2xlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZElkID0gZ3JpZF9zZWxlY3RlZF9pZF9hcnJheVswXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0FsZXJ0KCAkLmkxOG4uXyggJ05vIHNlbGVjdGVkIHJlY29yZCcgKSApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEgPSB7fTtcblx0XHRcdGZpbHRlci5maWx0ZXJfZGF0YS5pZCA9IFtzZWxlY3RlZElkXTtcblxuXHRcdFx0ZmlsdGVyID0gdGhpcy5nZXRDb3B5QXNOZXdGaWx0ZXIoIGZpbHRlciApO1xuXG5cdFx0XHR0aGlzLmFwaVsnZ2V0JyArIHRoaXMuYXBpLmtleV9uYW1lXSggZmlsdGVyLCB7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdCR0aGlzLm9uQ29weUFzTmV3UmVzdWx0KCByZXN1bHQgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblx0fVxuXG5cdG9uQ29weUFzTmV3UmVzdWx0KCByZXN1bHQgKSB7XG5cdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXG5cdFx0aWYgKCB0eXBlb2YgcmVzdWx0X2RhdGEgIT0gJ29iamVjdCcgKSB7XG5cdFx0XHR0aGlzLm9uQWRkQ2xpY2soKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLm9wZW5FZGl0VmlldygpOyAvLyBQdXQgaXQgaGVyZSBpcyB0byBhdm9pZCBpZiB0aGUgc2VsZWN0ZWQgb25lIGlzIG5vdCBleGlzdGVkIGluIGRhdGEgb3IgaGF2ZSBkZWxldGVkIGJ5IG90aGVyIHByYWdyYW0uIGluIHRoaXMgY2FzZSwgdGhlIGVkaXQgdmlldyBzaG91bGQgbm90IGJlIG9wZW5kLlxuXG5cdFx0cmVzdWx0X2RhdGEgPSByZXN1bHRfZGF0YVswXTtcblxuXHRcdHJlc3VsdF9kYXRhID0gdGhpcy5jb3B5QXNOZXdSZXNldElkcyggcmVzdWx0X2RhdGEgKTtcblxuXHRcdGlmICggdGhpcy5zdWJfdmlld19tb2RlICYmIHRoaXMucGFyZW50X2tleSApIHtcblx0XHRcdHJlc3VsdF9kYXRhW3RoaXMucGFyZW50X2tleV0gPSB0aGlzLnBhcmVudF92YWx1ZTtcblx0XHR9XG5cblx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgPSByZXN1bHRfZGF0YTtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0JCggJy5QdW5jaGVzRWRpdFZpZXcgLmVkaXQtdmlldy10YWItYmFyJyApLmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0JCggJy5QdW5jaGVzRWRpdFZpZXcgLmVkaXQtdmlldy10YWInICkuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHQkdGhpcy5pbml0RWRpdFZpZXcoKTtcblx0fVxuXG5cdC8qXG5cdCAxLiBKb2IgaXMgc3dpdGNoZWQuXG5cdCAyLiBJZiBhIFRhc2sgaXMgYWxyZWFkeSBzZWxlY3RlZCAoYW5kIGl0cyBub3QgVGFzaz0wKSwga2VlcCBpdCBzZWxlY3RlZCAqaWYgaXRzIGF2YWlsYWJsZSogaW4gdGhlIG5ld2x5IHBvcHVsYXRlZCBUYXNrIGxpc3QuXG5cdCAzLiBJZiB0aGUgdGFzayBzZWxlY3RlZCBpcyAqbm90KiBhdmFpbGFibGUgaW4gdGhlIFRhc2sgbGlzdCwgb3IgdGhlIHNlbGVjdGVkIFRhc2s9MCwgdGhlbiBjaGVjayB0aGUgZGVmYXVsdF9pdGVtX2lkIGZpZWxkIGZyb20gdGhlIEpvYiBhbmQgaWYgaXRzICpub3QqIDAgYWxzbywgc2VsZWN0IHRoYXQgVGFzayBieSBkZWZhdWx0LlxuXG5cdCAnam9iJyBhcmd1bWVudCBtdXN0IGJlIGFuIG9iamVjdCwgb3IgZmFsc2UvbnVsbFxuXHQgKi9cblx0c2V0Sm9iSXRlbVZhbHVlV2hlbkpvYkNoYW5nZWQoIGpvYiwgam9iX2l0ZW1faWRfY29sX25hbWUsIGZpbHRlcl9kYXRhICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHRpZiAoIGpvYl9pdGVtX2lkX2NvbF9uYW1lID09IHVuZGVmaW5lZCApIHtcblx0XHRcdGpvYl9pdGVtX2lkX2NvbF9uYW1lID0gJ2pvYl9pdGVtX2lkJztcblx0XHR9XG5cblx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCBzZXQgcHJvcGVydHkgJ2pvYl9pdGVtX2lkJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUwMTI2JnVzZXJfaWQ9NTQyODYgbGluZSA2Nzg1XG5cdFx0aWYgKCAhJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhJHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaXRlbV9pZF9jb2xfbmFtZV0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0VFRQcm9taXNlLmFkZCggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdzZXRKb2JJdGVtVmFsdWVXaGVuSm9iQ2hhbmdlZCcgKTtcblxuXHRcdGlmICggZmlsdGVyX2RhdGEgPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0ZmlsdGVyX2RhdGEgPSB7IHN0YXR1c19pZDogMTAgfTtcblx0XHR9XG5cblx0XHRpZiAoIGpvYiAhPSB1bmRlZmluZWQgJiYgam9iICE9IGZhbHNlICkge1xuXHRcdFx0ZmlsdGVyX2RhdGFbJ2pvYl9pZCddID0gam9iLmlkOyAvL0Fsd2F5cyBmaWx0ZXIgYnkgam9iXG5cdFx0fVxuXG5cdFx0dmFyIGpvYl9pdGVtX3dpZGdldCA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbam9iX2l0ZW1faWRfY29sX25hbWVdO1xuXHRcdHZhciBjdXJyZW50X2pvYl9pdGVtX2lkID0gam9iX2l0ZW1fd2lkZ2V0LmdldFZhbHVlKCk7XG5cdFx0am9iX2l0ZW1fd2lkZ2V0LnNldFNvdXJjZURhdGEoIG51bGwgKTtcblx0XHRqb2JfaXRlbV93aWRnZXQuc2V0Q2hlY2tCb3goIHRydWUgKTtcblx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2pvYl9pdGVtX3F1aWNrX3NlYXJjaCddLnNldENoZWNrQm94KCB0cnVlICk7XG5cblx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSBmaWx0ZXJfZGF0YTtcblx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2pvYl9pdGVtX2lkX2NvbF9uYW1lXS5zZXREZWZhdWx0QXJncyggYXJncyApO1xuXG5cdFx0Ly9NYWtlIHN1cmUgaWYgY3VycmVudCB0YXNrIGlzIHNlbGVjdGVkLCB0aGF0IGl0cyBzdGlsbCBhdmFpbGFibGUgb24gdGhlIG5ldyBqb2IuXG5cdFx0aWYgKCBjdXJyZW50X2pvYl9pdGVtX2lkICYmIGN1cnJlbnRfam9iX2l0ZW1faWQgIT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHR2YXIgbmV3X2FyZyA9IEdsb2JhbC5jbG9uZSggYXJncyApO1xuXHRcdFx0Ly9XZSBhcmUgY2hlY2tpbmcgaWYgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgcmVjb3JkIHZhbGlkYXRlcyBhZ2FpbnN0IHRoZSBqb2IgY29zdGluZyBjcml0ZXJpYS5cblx0XHRcdC8vVG8gYXZvaWQgaXNzdWVzIHdpdGggcGFnaW5hdGlvbiB3ZSBhcmUgb25seSBjaGVja2luZyBhZ2FpbnN0IHRoZSBjdXJyZW50IHNlbGVjdGVkIHJlY29yZC5cblx0XHRcdG5ld19hcmcuZmlsdGVyX2RhdGEuaWQgPSBjdXJyZW50X2pvYl9pdGVtX2lkO1xuXHRcdFx0bmV3X2FyZy5maWx0ZXJfZGF0YS5qb2JfaWQgPSBqb2IuaWQ7XG5cdFx0XHRuZXdfYXJnLmZpbHRlcl9jb2x1bW5zID0gJHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaXRlbV9pZF9jb2xfbmFtZV0uZ2V0Q29sdW1uRmlsdGVyKCk7XG5cdFx0XHQkdGhpcy5qb2JfaXRlbV9hcGkuZ2V0Sm9iSXRlbSggbmV3X2FyZywge1xuXHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCBzZXQgcHJvcGVydHkgJ2pvYl9pdGVtX2lkJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUwMTI2JnVzZXJfaWQ9NTQyODYgbGluZSA2Nzg1XG5cdFx0XHRcdFx0aWYgKCAhJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApIHtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdC8vRGF0YSBtdXN0IGJlIGFuIGFycmF5IG9mIGFsbG93ZWQgaWQuIElmIG5vIHJlc3VsdHMsIGRhdGEgbWlnaHQgYmUgdHJ1ZSBvciBmYWxzZSBmcm9tIHRoZSBBUEkuXG5cdFx0XHRcdFx0Ly9Db252ZXJ0IHRoaXMgdG8gYW4gYXJyYXkgc28gdGhhdCBkYXRhIGNhbiBjb250YWluIFRUVVVJRC5ub3RfZXhpc3RfaWQuXG5cdFx0XHRcdFx0Ly9UaGlzIGFsbG93cyB1c2VycyB0byBzdGlsbCBzZWxlY3QgXCJkZWZhdWx0XCIgb3IgYSBkaWZmZXJlbnQgb3B0aW9uIHRoYXQgaXMgbm90IGEgbm9ybWFsIHJlY29yZC5cblx0XHRcdFx0XHRpZiAoICFBcnJheS5pc0FycmF5KCBkYXRhICkgKSB7XG5cdFx0XHRcdFx0XHRkYXRhID0gW107XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBjdXJyZW50X2pvYl9pdGVtX2lkID09PSBUVFVVSUQubm90X2V4aXN0X2lkICkge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdXNoKCB7IGlkOiBUVFVVSUQubm90X2V4aXN0X2lkIH0gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGN1cnJlbnRfam9iX2l0ZW1faWQgPT09IC0yICkge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdXNoKCB7IGlkOiAtMiB9ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBkYXRhLmxlbmd0aCA9PSAwICkge1xuXHRcdFx0XHRcdFx0c2V0RGVmYXVsdERhdGEoIGpvYl9pdGVtX2lkX2NvbF9uYW1lICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0c2V0RGVmYXVsdERhdGEoIGpvYl9pdGVtX2lkX2NvbF9uYW1lICk7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gc2V0RGVmYXVsdERhdGEoIGpvYl9pdGVtX2lkX2NvbF9uYW1lICkge1xuXHRcdFx0aWYgKCBqb2JfaXRlbV9pZF9jb2xfbmFtZSA9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGpvYl9pdGVtX2lkX2NvbF9uYW1lID0gJ2pvYl9pdGVtX2lkJztcblx0XHRcdH1cblx0XHRcdGlmICggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5oYXNPd25Qcm9wZXJ0eSggam9iX2l0ZW1faWRfY29sX25hbWUgKSApIHtcblx0XHRcdFx0am9iX2l0ZW1fd2lkZ2V0LnNldFZhbHVlKCBqb2IuZGVmYXVsdF9pdGVtX2lkICk7XG5cdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbam9iX2l0ZW1faWRfY29sX25hbWVdID0gam9iLmRlZmF1bHRfaXRlbV9pZDtcblxuXHRcdFx0XHRpZiAoIGpvYi5kZWZhdWx0X2l0ZW1faWQgPT09IGZhbHNlIHx8IGpvYi5kZWZhdWx0X2l0ZW1faWQgPT09IDAgfHwgam9iLmRlZmF1bHRfaXRlbV9pZCA9PT0gVFRVVUlELnplcm9faWQgfHwgam9iLmRlZmF1bHRfaXRlbV9pZCA9PT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljLmpvYl9pdGVtX3F1aWNrX3NlYXJjaC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRqb2JfaXRlbV93aWRnZXQuc2V0VmFsdWUoICcnICk7XG5cdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbam9iX2l0ZW1faWRfY29sX25hbWVdID0gZmFsc2U7XG5cdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWMuam9iX2l0ZW1fcXVpY2tfc2VhcmNoLnNldFZhbHVlKCAnJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdzZXRKb2JJdGVtVmFsdWVXaGVuSm9iQ2hhbmdlZCcgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRKb2JWYWx1ZVdoZW5Dcml0ZXJpYUNoYW5nZWQoIGpvYl9pZF9jb2xfbmFtZSwgZmlsdGVyX2RhdGEgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHNldCBwcm9wZXJ0eSAnam9iX2lkJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUwMTI2JnVzZXJfaWQ9NTQyODYgbGluZSA2Nzg1XG5cdFx0aWYgKCAhJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhJHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaWRfY29sX25hbWVdICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBqb2Jfd2lkZ2V0ID0gJHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaWRfY29sX25hbWVdO1xuXHRcdHZhciBjdXJyZW50X2pvYl9pZCA9IGpvYl93aWRnZXQuZ2V0VmFsdWUoKTtcblx0XHRqb2Jfd2lkZ2V0LnNldFNvdXJjZURhdGEoIG51bGwgKTtcblx0XHRqb2Jfd2lkZ2V0LnNldENoZWNrQm94KCB0cnVlICk7XG5cdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljWydqb2JfaXRlbV9xdWlja19zZWFyY2gnXS5zZXRDaGVja0JveCggdHJ1ZSApO1xuXG5cdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRhcmdzLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaWRfY29sX25hbWVdLnNldERlZmF1bHRBcmdzKCBhcmdzICk7XG5cblx0XHQvL01ha2Ugc3VyZSBpZiBjdXJyZW50IGpvYiBpcyBzZWxlY3RlZCwgYW5kIHRoYXQgaXRzIHN0aWxsIGF2YWlsYWJsZSBhZnRlciBuZXcgY3JpdGVyaWEuXG5cdFx0aWYgKCBjdXJyZW50X2pvYl9pZCAmJiBjdXJyZW50X2pvYl9pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdHZhciBuZXdfYXJnID0gR2xvYmFsLmNsb25lKCBhcmdzICk7XG5cdFx0XHQvL1dlIGFyZSBjaGVja2luZyBpZiB0aGUgY3VycmVudCBzZWxlY3RlZCByZWNvcmQgdmFsaWRhdGVzIGFnYWluc3QgdGhlIGpvYiBjb3N0aW5nIGNyaXRlcmlhLlxuXHRcdFx0Ly9UbyBhdm9pZCBpc3N1ZXMgd2l0aCBwYWdpbmF0aW9uIHdlIGFyZSBvbmx5IGNoZWNraW5nIGFnYWluc3QgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgcmVjb3JkLlxuXHRcdFx0bmV3X2FyZy5maWx0ZXJfZGF0YS5pZCA9IGN1cnJlbnRfam9iX2lkO1xuXHRcdFx0bmV3X2FyZy5maWx0ZXJfY29sdW1ucyA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbam9iX2lkX2NvbF9uYW1lXS5nZXRDb2x1bW5GaWx0ZXIoKTtcblx0XHRcdCR0aGlzLmpvYl9hcGkuZ2V0Sm9iKCBuZXdfYXJnLCB7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHNldCBwcm9wZXJ0eSAnam9iX2lkJyBvZiBudWxsIGluIC9pbnRlcmZhY2UvaHRtbDUvIyFtPVRpbWVTaGVldCZkYXRlPTIwMTUwMTI2JnVzZXJfaWQ9NTQyODYgbGluZSA2Nzg1XG5cdFx0XHRcdFx0aWYgKCAhJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApIHtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdC8vRGF0YSBtdXN0IGJlIGFuIGFycmF5IG9mIGFsbG93ZWQgaWQuIElmIG5vIHJlc3VsdHMsIGRhdGEgbWlnaHQgYmUgdHJ1ZSBvciBmYWxzZSBmcm9tIHRoZSBBUEkuXG5cdFx0XHRcdFx0Ly9Db252ZXJ0IHRoaXMgdG8gYW4gYXJyYXkgc28gdGhhdCBkYXRhIGNhbiBjb250YWluIFRUVVVJRC5ub3RfZXhpc3RfaWQuXG5cdFx0XHRcdFx0Ly9UaGlzIGFsbG93cyB1c2VycyB0byBzdGlsbCBzZWxlY3QgXCJkZWZhdWx0XCIgb3IgYSBkaWZmZXJlbnQgb3B0aW9uIHRoYXQgaXMgbm90IGEgbm9ybWFsIHJlY29yZC5cblx0XHRcdFx0XHRpZiAoICFBcnJheS5pc0FycmF5KCBkYXRhICkgKSB7XG5cdFx0XHRcdFx0XHRkYXRhID0gW107XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBjdXJyZW50X2pvYl9pZCA9PT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0XHRcdGRhdGEucHVzaCggeyBpZDogVFRVVUlELm5vdF9leGlzdF9pZCB9ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBjdXJyZW50X2pvYl9pZCA9PT0gLTIgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLnB1c2goIHsgaWQ6IC0yIH0gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGRhdGEubGVuZ3RoID09IDAgKSB7XG5cdFx0XHRcdFx0XHRzZXREZWZhdWx0RGF0YSggam9iX2lkX2NvbF9uYW1lICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0c2V0RGVmYXVsdERhdGEoIGpvYl9pZF9jb2xfbmFtZSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHNldERlZmF1bHREYXRhKCBqb2JfaWRfY29sX25hbWUgKSB7XG5cdFx0XHRpZiAoIGpvYl9pZF9jb2xfbmFtZSA9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGpvYl9pZF9jb2xfbmFtZSA9ICdqb2JfaWQnO1xuXHRcdFx0fVxuXHRcdFx0am9iX3dpZGdldC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbam9iX2lkX2NvbF9uYW1lXSA9IGZhbHNlO1xuXHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpYy5qb2JfcXVpY2tfc2VhcmNoLnNldFZhbHVlKCAnJyApO1xuXHRcdH1cblx0fVxuXG5cdG9uSm9iUXVpY2tTZWFyY2goIGtleSwgdmFsdWUsIGpvYl9pZF9maWVsZCwgam9iX2l0ZW1faWRfZmllbGQsIGZpbHRlcl9kYXRhICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHR2YXIgYXJncyA9IHt9O1xuXG5cdFx0VFRQcm9taXNlLmFkZCggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvbkpvYlF1aWNrU2VhcmNoJyApO1xuXG5cdFx0aWYgKCBqb2JfaWRfZmllbGQgPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0am9iX2lkX2ZpZWxkID0gJ2pvYl9pZCc7XG5cdFx0fVxuXHRcdGlmICggam9iX2l0ZW1faWRfZmllbGQgPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0am9iX2l0ZW1faWRfZmllbGQgPSAnam9iX2l0ZW1faWQnO1xuXHRcdH1cblxuXHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnc2V0VmFsdWUnIG9mIHVuZGVmaW5lZCBpbiAvaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE0MTIyMiZ1c2VyX2lkPTEzNTY2IGxpbmUgNjY4NlxuXHRcdGlmICggISR0aGlzLmVkaXRfdmlld191aV9kaWMgfHwgISR0aGlzLmVkaXRfdmlld191aV9kaWNbam9iX2lkX2ZpZWxkXSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIGtleSA9PT0gJ2pvYl9xdWlja19zZWFyY2gnICkge1xuXHRcdFx0YXJncy5maWx0ZXJfZGF0YSA9IHsgbWFudWFsX2lkOiB2YWx1ZSwgdXNlcl9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLnVzZXJfaWQsIHN0YXR1c19pZDogJzEwJyB9O1xuXG5cdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5icmFuY2hfaWQgKSB7XG5cdFx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEucHVuY2hfYnJhbmNoX2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmJyYW5jaF9pZDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuZGVwYXJ0bWVudF9pZCApIHtcblx0XHRcdFx0YXJncy5maWx0ZXJfZGF0YS5wdW5jaF9kZXBhcnRtZW50X2lkID0gdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmRlcGFydG1lbnRfaWQ7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuam9iX2FwaS5nZXRKb2IoIGFyZ3MsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnc2V0VmFsdWUnIG9mIHVuZGVmaW5lZCBpbiAvaW50ZXJmYWNlL2h0bWw1LyMhbT1UaW1lU2hlZXQmZGF0ZT0yMDE0MTIyMiZ1c2VyX2lkPTEzNTY2IGxpbmUgNjY4NlxuXHRcdFx0XHRcdGlmICggISR0aGlzLmVkaXRfdmlld191aV9kaWMgfHwgISR0aGlzLmVkaXRfdmlld191aV9kaWNbam9iX2lkX2ZpZWxkXSApIHtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0XHRpZiAoIHJlc3VsdF9kYXRhLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2pvYl9pZF9maWVsZF0uc2V0VmFsdWUoIHJlc3VsdF9kYXRhWzBdLmlkICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2pvYl9pZF9maWVsZF0gPSByZXN1bHRfZGF0YVswXS5pZDtcblx0XHRcdFx0XHRcdCR0aGlzLnNldEpvYkl0ZW1WYWx1ZVdoZW5Kb2JDaGFuZ2VkKCByZXN1bHRfZGF0YVswXSwgam9iX2l0ZW1faWRfZmllbGQsIGZpbHRlcl9kYXRhICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbam9iX2lkX2ZpZWxkXS5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbam9iX2lkX2ZpZWxkXSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0JHRoaXMuc2V0Sm9iSXRlbVZhbHVlV2hlbkpvYkNoYW5nZWQoIGZhbHNlLCBqb2JfaXRlbV9pZF9maWVsZCwgZmlsdGVyX2RhdGEgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvbkpvYlF1aWNrU2VhcmNoJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2pvYl9xdWlja19zZWFyY2gnXS5zZXRDaGVja0JveCggdHJ1ZSApO1xuXHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaWRfZmllbGRdLnNldENoZWNrQm94KCB0cnVlICk7XG5cdFx0fSBlbHNlIGlmICgga2V5ID09PSAnam9iX2l0ZW1fcXVpY2tfc2VhcmNoJyApIHtcblx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7IG1hbnVhbF9pZDogdmFsdWUsIGpvYl9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2pvYl9pZF9maWVsZF0sIHN0YXR1c19pZDogJzEwJyB9O1xuXG5cdFx0XHR0aGlzLmpvYl9pdGVtX2FwaS5nZXRKb2JJdGVtKCBhcmdzLCB7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ3NldFZhbHVlJyBvZiB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS8jIW09VGltZVNoZWV0JmRhdGU9MjAxNDEyMjImdXNlcl9pZD0xMzU2NiBsaW5lIDY2ODZcblx0XHRcdFx0XHRpZiAoICEkdGhpcy5lZGl0X3ZpZXdfdWlfZGljIHx8ICEkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2pvYl9pdGVtX2lkX2ZpZWxkXSApIHtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0aWYgKCByZXN1bHRfZGF0YS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaXRlbV9pZF9maWVsZF0uc2V0VmFsdWUoIHJlc3VsdF9kYXRhWzBdLmlkICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2pvYl9pdGVtX2lkX2ZpZWxkXSA9IHJlc3VsdF9kYXRhWzBdLmlkO1xuXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbam9iX2l0ZW1faWRfZmllbGRdLnNldFZhbHVlKCAnJyApO1xuXHRcdFx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtqb2JfaXRlbV9pZF9maWVsZF0gPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvbkpvYlF1aWNrU2VhcmNoJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1snam9iX2l0ZW1fcXVpY2tfc2VhcmNoJ10uc2V0Q2hlY2tCb3goIHRydWUgKTtcblx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1tqb2JfaXRlbV9pZF9maWVsZF0uc2V0Q2hlY2tCb3goIHRydWUgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZXBhcnRtZW50VmFsdWVXaGVuQnJhbmNoQ2hhbmdlZCggZGVwYXJ0bWVudCwgZGVwYXJ0bWVudF9pZF9jb2xfbmFtZSwgZmlsdGVyX2RhdGEgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdGlmICggZGVwYXJ0bWVudF9pZF9jb2xfbmFtZSA9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRkZXBhcnRtZW50X2lkX2NvbF9uYW1lID0gJ2RlcGFydG1lbnRfaWQnO1xuXHRcdH1cblxuXHRcdGlmICggISR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgISR0aGlzLmVkaXRfdmlld191aV9kaWNbZGVwYXJ0bWVudF9pZF9jb2xfbmFtZV0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGRlcGFydG1lbnRfd2lkZ2V0ID0gJHRoaXMuZWRpdF92aWV3X3VpX2RpY1tkZXBhcnRtZW50X2lkX2NvbF9uYW1lXTtcblx0XHR2YXIgY3VycmVudF9kZXBhcnRtZW50X2lkID0gZGVwYXJ0bWVudF93aWRnZXQuZ2V0VmFsdWUoKTtcblx0XHRkZXBhcnRtZW50X3dpZGdldC5zZXRTb3VyY2VEYXRhKCBudWxsICk7XG5cdFx0ZGVwYXJ0bWVudF93aWRnZXQuc2V0Q2hlY2tCb3goIHRydWUgKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5maWx0ZXJfZGF0YSA9IGZpbHRlcl9kYXRhO1xuXHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbZGVwYXJ0bWVudF9pZF9jb2xfbmFtZV0uc2V0RGVmYXVsdEFyZ3MoIGFyZ3MgKTtcblxuXHRcdC8vTWFrZSBzdXJlIGlmIGN1cnJlbnQgZGVwYXJ0bWVudCBpcyBzZWxlY3RlZCwgdGhhdCBpdHMgc3RpbGwgYXZhaWxhYmxlIG9uIHRoZSBuZXcgam9iLlxuXHRcdGlmICggY3VycmVudF9kZXBhcnRtZW50X2lkICYmIGN1cnJlbnRfZGVwYXJ0bWVudF9pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdHZhciBuZXdfYXJnID0gR2xvYmFsLmNsb25lKCBhcmdzICk7XG5cdFx0XHQvL1dlIGFyZSBjaGVja2luZyBpZiB0aGUgY3VycmVudCBzZWxlY3RlZCByZWNvcmQgdmFsaWRhdGVzIGFnYWluc3QgdGhlIGpvYiBjb3N0aW5nIGNyaXRlcmlhLlxuXHRcdFx0Ly9UbyBhdm9pZCBpc3N1ZXMgd2l0aCBwYWdpbmF0aW9uIHdlIGFyZSBvbmx5IGNoZWNraW5nIGFnYWluc3QgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgcmVjb3JkLlxuXHRcdFx0bmV3X2FyZy5maWx0ZXJfZGF0YS5pZCA9IGN1cnJlbnRfZGVwYXJ0bWVudF9pZDtcblx0XHRcdG5ld19hcmcuZmlsdGVyX2NvbHVtbnMgPSAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2RlcGFydG1lbnRfaWRfY29sX25hbWVdLmdldENvbHVtbkZpbHRlcigpO1xuXHRcdFx0JHRoaXMuZGVwYXJ0bWVudF9hcGkuZ2V0RGVwYXJ0bWVudCggbmV3X2FyZywge1xuXHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblxuXHRcdFx0XHRcdGlmICggISR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIGRhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0XHQvL0RhdGEgbXVzdCBiZSBhbiBhcnJheSBvZiBhbGxvd2VkIGlkLiBJZiBubyByZXN1bHRzLCBkYXRhIG1pZ2h0IGJlIHRydWUgb3IgZmFsc2UgZnJvbSB0aGUgQVBJLlxuXHRcdFx0XHRcdC8vQ29udmVydCB0aGlzIHRvIGFuIGFycmF5IHNvIHRoYXQgZGF0YSBjYW4gY29udGFpbiBUVFVVSUQubm90X2V4aXN0X2lkLlxuXHRcdFx0XHRcdC8vVGhpcyBhbGxvd3MgdXNlcnMgdG8gc3RpbGwgc2VsZWN0IFwiZGVmYXVsdFwiIG9yIGEgZGlmZmVyZW50IG9wdGlvbiB0aGF0IGlzIG5vdCBhIG5vcm1hbCByZWNvcmQuXG5cdFx0XHRcdFx0aWYgKCAhQXJyYXkuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdFx0ZGF0YSA9IFtdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggY3VycmVudF9kZXBhcnRtZW50X2lkID09PSBUVFVVSUQubm90X2V4aXN0X2lkICkge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdXNoKCB7IGlkOiBUVFVVSUQubm90X2V4aXN0X2lkIH0gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGN1cnJlbnRfZGVwYXJ0bWVudF9pZCA9PT0gLTIgKSB7XG5cdFx0XHRcdFx0XHRkYXRhLnB1c2goIHsgaWQ6IC0yIH0gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGRhdGEubGVuZ3RoID09PSAwICkge1xuXHRcdFx0XHRcdFx0c2V0RGVmYXVsdERhdGEoIGRlcGFydG1lbnRfaWRfY29sX25hbWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZXREZWZhdWx0RGF0YSggZGVwYXJ0bWVudF9pZF9jb2xfbmFtZSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHNldERlZmF1bHREYXRhKCBkZXBhcnRtZW50X2lkX2NvbF9uYW1lICkge1xuXHRcdFx0aWYgKCBkZXBhcnRtZW50X2lkX2NvbF9uYW1lID09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0ZGVwYXJ0bWVudF9pZF9jb2xfbmFtZSA9ICdkZXBhcnRtZW50X2lkJztcblx0XHRcdH1cblx0XHRcdGlmICggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5oYXNPd25Qcm9wZXJ0eSggZGVwYXJ0bWVudF9pZF9jb2xfbmFtZSApICkge1xuXHRcdFx0XHRkZXBhcnRtZW50X3dpZGdldC5zZXRWYWx1ZSggZGVwYXJ0bWVudC5kZWZhdWx0X2l0ZW1faWQgKTtcblx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtkZXBhcnRtZW50X2lkX2NvbF9uYW1lXSA9IGRlcGFydG1lbnQuZGVmYXVsdF9pdGVtX2lkO1xuXG5cdFx0XHRcdGlmICggZGVwYXJ0bWVudC5kZWZhdWx0X2l0ZW1faWQgPT09IGZhbHNlIHx8IGRlcGFydG1lbnQuZGVmYXVsdF9pdGVtX2lkID09PSAwIHx8IGRlcGFydG1lbnQuZGVmYXVsdF9pdGVtX2lkID09PSBUVFVVSUQuemVyb19pZCB8fCBkZXBhcnRtZW50LmRlZmF1bHRfaXRlbV9pZCA9PT0gVFRVVUlELm5vdF9leGlzdF9pZCApIHtcblx0XHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljLmpvYl9pdGVtX3F1aWNrX3NlYXJjaC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZXBhcnRtZW50X3dpZGdldC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtkZXBhcnRtZW50X2lkX2NvbF9uYW1lXSA9IGZhbHNlO1xuXHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljLmpvYl9pdGVtX3F1aWNrX3NlYXJjaC5zZXRWYWx1ZSggJycgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRQdW5jaFRhZ1ZhbHVlc1doZW5Dcml0ZXJpYUNoYW5nZWQoIGZpbHRlcl9kYXRhLCBwdW5jaF90YWdfaWRfY29sX25hbWUgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdGlmICggISR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgISR0aGlzLmVkaXRfdmlld191aV9kaWNbcHVuY2hfdGFnX2lkX2NvbF9uYW1lXSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgcHVuY2hfdGFnX3dpZGdldCA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbcHVuY2hfdGFnX2lkX2NvbF9uYW1lXTtcblx0XHR2YXIgY3VycmVudF9wdW5jaF90YWdfaWRzID0gcHVuY2hfdGFnX3dpZGdldC5nZXRWYWx1ZSgpO1xuXHRcdHB1bmNoX3RhZ193aWRnZXQuc2V0U291cmNlRGF0YSggbnVsbCApO1xuXG5cdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRhcmdzLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0cHVuY2hfdGFnX3dpZGdldC5zZXREZWZhdWx0QXJncyggYXJncyApO1xuXG5cdFx0Ly9NYWtlIHN1cmUgaWYgY3VycmVudCBwdW5jaCB0YWdzIGFyZSBzZWxlY3RlZCwgdGhhdCB0aGV5IGFyZSBzdGlsbCBhdmFpbGFibGUgb24gdGhlIG5ldyBwdW5jaCB0YWcgbGlzdC5cblx0XHRpZiAoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcyAmJiBjdXJyZW50X3B1bmNoX3RhZ19pZHMubGVuZ3RoID4gMCApIHtcblx0XHRcdHZhciBuZXdfYXJnID0gR2xvYmFsLmNsb25lKCBhcmdzICk7XG5cdFx0XHRuZXdfYXJnLmZpbHRlcl9kYXRhLmlkID0gY3VycmVudF9wdW5jaF90YWdfaWRzO1xuXHRcdFx0Ly9EaXNhYmxpbmcgcGFnaW5nIHRvIHRoZSBBUEkgKCRkaXNhYmxlX3BhZ2luZyA9IHRydWUpIHNvIHRoYXQgdGhlIHVzZXIgY2FuIGhhdmUgbW9yZSBwdW5jaCB0YWdzIHNlbGVjdGVkIHRoYW4gdGhlaXIgcHJlZmVyZW5jZSBmb3IgaXRlbXMgcGVyIHBhZ2UuXG5cdFx0XHQvL090aGVyd2lzZSBpZiB0aGV5IGhhdmUgNyBwdW5jaCB0YWdzIHNlbGVjdGVkIGFuZCB0aGVpciBwcmVmZXJlbmNlIGlzIDUsIHRoZSBhcGkgd291bGQgb25seSByZXR1cm4gNSBhbmQgMiB3b3VsZCBiZSBsb3N0IGFuZCB1bnNlbGVjdGVkLlxuXHRcdFx0JHRoaXMucHVuY2hfdGFnX2FwaS5nZXRQdW5jaFRhZyggbmV3X2FyZywgdHJ1ZSx7XG5cdFx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcHVuY2hfdGFnX3Jlc3VsdCApIHtcblx0XHRcdFx0XHRpZiAoICEkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciBkYXRhID0gcHVuY2hfdGFnX3Jlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHRcdC8vRGF0YSBtdXN0IGJlIGFuIGFycmF5IG9mIGFsbG93ZWQgcHVuY2ggdGFncy4gSWYgbm8gcmVzdWx0cywgZGF0YSBtaWdodCBiZSB0cnVlIG9yIGZhbHNlIGZyb20gdGhlIEFQSS5cblx0XHRcdFx0XHQvL0NvbnZlcnQgdGhpcyB0byBhbiBhcnJheSBzbyB0aGF0IGRhdGEgY2FuIGNvbnRhaW4gVFRVVUlELm5vdF9leGlzdF9pZC5cblx0XHRcdFx0XHQvL1RoaXMgYWxsb3dzIHVzZXJzIHRvIHN0aWxsIHNlbGVjdCBcImRlZmF1bHRcIiBvciBhIGRpZmZlcmVudCBvcHRpb24gdGhhdCBpcyBub3QgYSBwdW5jaCB0YWcuXG5cdFx0XHRcdFx0aWYgKCAhQXJyYXkuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdFx0ZGF0YSA9IFtdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggZGF0YSApICYmIEFycmF5LmlzQXJyYXkoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcyApICYmIGN1cnJlbnRfcHVuY2hfdGFnX2lkcy5pbmNsdWRlcyggVFRVVUlELm5vdF9leGlzdF9pZCApICkge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdXNoKCB7IGlkOiBUVFVVSUQubm90X2V4aXN0X2lkIH0gKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIEFycmF5LmlzQXJyYXkoIGRhdGEgKSAmJiBkYXRhLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcyAhPT0gVFRVVUlELnplcm9faWQgJiYgY3VycmVudF9wdW5jaF90YWdfaWRzLmxlbmd0aCA+IDAgJiYgJHRoaXMuc2hvdWxkVXBkYXRlUHVuY2hUYWdzKCBjdXJyZW50X3B1bmNoX3RhZ19pZHMsIGRhdGEgKSApIHtcblx0XHRcdFx0XHRcdFx0Ly9NZXJnZSBpbiB1c2VycyBsYXN0IHNlbGVjdGVkIHB1bmNoIHRhZ3MgaW4gY2FzZSB0aGV5IHN3aXRjaGVkIGJhY2sgdG8gdGhhdCBzZWxlY3Rpb24uXG5cdFx0XHRcdFx0XHRcdC8vRXhhbXBsZTogVGhleSBoYXZlIHNlbGVjdGVkIGEgTmV3IFlvcmsgYnJhbmNoIHB1bmNoIHRhZyBidXQgc3dpdGNoIHRoZWlyIHNlbGVjdGlvbiB0byBhIGRpZmZlcmVudCBicmFuY2hcblx0XHRcdFx0XHRcdFx0Ly9hbmQgdGhlbiBiYWNrIHRvIE5ldyBZb3JrLiBJbiB0aGF0IGNhc2Ugd2Ugc2hvdWxkIHJlc2VsZWN0IHRoZSBOZXcgWW9yayBwdW5jaCB0YWcuXG5cdFx0XHRcdFx0XHRcdGN1cnJlbnRfcHVuY2hfdGFnX2lkcyA9IF8udW5pb24oIGN1cnJlbnRfcHVuY2hfdGFnX2lkcywgJHRoaXMucHJldmlvdXNfcHVuY2hfdGFnX3NlbGVjdGlvbiApO1xuXHRcdFx0XHRcdFx0XHQvL0NvbXBhcmUgY3VycmVudCBzZWxlY3RlZCBwdW5jaCB0YWdzIGFuZCB0aGUgbGlzdCBvZiBwdW5jaCB0YWdzIGZyb20gdGhlIEFQSSBhbmQgcmVtb3ZlIGludmFsaWQgcHVuY2ggdGFncy5cblx0XHRcdFx0XHRcdFx0dmFyIGludGVyc2VjdGVkX3ZhbHVlcyA9IGN1cnJlbnRfcHVuY2hfdGFnX2lkcy5maWx0ZXIoIHB1bmNoX3RhZ19pZCA9PiBkYXRhLnNvbWUoIHB1bmNoX3RhZyA9PiBwdW5jaF90YWdfaWQgPT09IHB1bmNoX3RhZy5pZCApICk7XG5cdFx0XHRcdFx0XHRcdHB1bmNoX3RhZ193aWRnZXQuc2V0VmFsdWUoIGludGVyc2VjdGVkX3ZhbHVlcyApO1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW3B1bmNoX3RhZ19pZF9jb2xfbmFtZV0gPSBpbnRlcnNlY3RlZF92YWx1ZXM7XG5cdFx0XHRcdFx0XHRcdC8vVXBkYXRlIG1hbnVhbCBJRHMgaW4gcHVuY2hfdGFnX3F1aWNrX3NlYXJjaC5cblx0XHRcdFx0XHRcdFx0dmFyIHB1bmNoX3RhZ19tYW51YWxfaWRzID0gZGF0YS5maWx0ZXIoIHB1bmNoX3RhZyA9PiBpbnRlcnNlY3RlZF92YWx1ZXMuaW5jbHVkZXMoIHB1bmNoX3RhZy5pZCApICkubWFwKCAoIHsgbWFudWFsX2lkIH0gKSA9PiBtYW51YWxfaWQgKTtcblx0XHRcdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1sncHVuY2hfdGFnX3F1aWNrX3NlYXJjaCddLnNldFZhbHVlKCBwdW5jaF90YWdfbWFudWFsX2lkcy5qb2luKCkgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0c2V0RGVmYXVsdERhdGEoIHB1bmNoX3RhZ19pZF9jb2xfbmFtZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdHNldERlZmF1bHREYXRhKCBwdW5jaF90YWdfaWRfY29sX25hbWUgKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBzZXREZWZhdWx0RGF0YSggcHVuY2hfdGFnX2lkX2NvbF9uYW1lICkge1xuXHRcdFx0aWYgKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmhhc093blByb3BlcnR5KCBwdW5jaF90YWdfaWRfY29sX25hbWUgKSApIHtcblx0XHRcdFx0cHVuY2hfdGFnX3dpZGdldC5zZXRWYWx1ZSggJHRoaXMuZGVmYXVsdF9wdW5jaF90YWcgKTtcblx0XHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtwdW5jaF90YWdfaWRfY29sX25hbWVdID0gJHRoaXMuZGVmYXVsdF9wdW5jaF90YWc7XG5cblx0XHRcdFx0aWYgKCAkdGhpcy5kZWZhdWx0X3B1bmNoX3RhZy5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpYy5wdW5jaF90YWdfcXVpY2tfc2VhcmNoLnNldFZhbHVlKCAnJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHB1bmNoX3RhZ193aWRnZXQuc2V0VmFsdWUoICcnICk7XG5cdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbcHVuY2hfdGFnX2lkX2NvbF9uYW1lXSA9IGZhbHNlO1xuXHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljLnB1bmNoX3RhZ19xdWlja19zZWFyY2guc2V0VmFsdWUoICcnICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0c2hvdWxkVXBkYXRlUHVuY2hUYWdzKCBjdXJyZW50X3B1bmNoX3RhZ19pZHMsIGRhdGEgKSB7XG5cdFx0Ly9JZiB0aGUgY3VycmVudCBzZWxlY3RlZCBwdW5jaCB0YWdzIGFuZCBwcmV2aW91c2x5IHVzZXIgc2VsZWN0ZWQgcHVuY2ggdGFncyBkbyBub3QgbWF0Y2ggd2Ugc2hvdWxkIGNoZWNrIGFuZCB1cGRhdGUuXG5cdFx0aWYgKCBBcnJheS5pc0FycmF5KCB0aGlzLnByZXZpb3VzX3B1bmNoX3RhZ19zZWxlY3Rpb24gKSAmJiB0aGlzLnByZXZpb3VzX3B1bmNoX3RhZ19zZWxlY3Rpb24uZXZlcnkoIHB1bmNoX3RhZyA9PiBjdXJyZW50X3B1bmNoX3RhZ19pZHMuaW5jbHVkZXMoIHB1bmNoX3RhZyApICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdC8vSWYgdGhlIGRhdGEgcmV0dXJuZWQgZnJvbSB0aGUgQVBJIGRvZXMgbm90IGNvbnRhaW4gZXZlcnkgY3VycmVudGx5IHNlbGVjdGVkIHB1bmNoIHRhZyB0aGVuIHdlIG5lZWQgdG8gcmVtb3ZlIGludmFsaWQgdGFncy5cblx0XHRpZiAoIGN1cnJlbnRfcHVuY2hfdGFnX2lkcy5ldmVyeSggcHVuY2hfdGFnX2lkID0+IGRhdGEuc29tZSggcHVuY2hfdGFnID0+IHB1bmNoX3RhZy5pZCA9PT0gcHVuY2hfdGFnX2lkICkgKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHRzZXRQdW5jaFRhZ1F1aWNrU2VhcmNoTWFudWFsSWRzKCBwdW5jaF90YWdzLCBnZXRfcmVhbF9kYXRhICkge1xuXHRcdGlmICggcHVuY2hfdGFncyA9PSBmYWxzZSB8fCAhdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydwdW5jaF90YWdfcXVpY2tfc2VhcmNoJ10gfHwgKCBBcnJheS5pc0FycmF5KCBwdW5jaF90YWdzICkgJiYgcHVuY2hfdGFncy5sZW5ndGggPT09IDAgKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHB1bmNoX3RhZ3MgPT09IFRUVVVJRC5ub3RfZXhpc3RfaWQgfHwgKCBBcnJheS5pc0FycmF5KCBwdW5jaF90YWdzICkgJiYgcHVuY2hfdGFncy5pbmNsdWRlcyggVFRVVUlELm5vdF9leGlzdF9pZCApICkgKSB7XG5cdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnXS5zZXRWYWx1ZSggJycgKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIGdldF9yZWFsX2RhdGEgKSB7XG5cdFx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSB7IGlkOiBwdW5jaF90YWdzIH07XG5cdFx0XHR0aGlzLnB1bmNoX3RhZ19hcGkuZ2V0UHVuY2hUYWcoIGFyZ3MsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdFx0dmFyIG1hbnVhbF9pZHMgPSBbXTtcblxuXHRcdFx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRtYW51YWxfaWRzLnB1c2goIGRhdGFbaV0ubWFudWFsX2lkICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljICYmICR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnXSApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbJ3B1bmNoX3RhZ19xdWlja19zZWFyY2gnXS5zZXRWYWx1ZSggbWFudWFsX2lkcy5qb2luKCkgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIG1hbnVhbF9pZHMgPSBbXTtcblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHB1bmNoX3RhZ3MubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdG1hbnVhbF9pZHMucHVzaCggcHVuY2hfdGFnc1tpXS5tYW51YWxfaWQgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLmVkaXRfdmlld191aV9kaWMgJiYgdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydwdW5jaF90YWdfcXVpY2tfc2VhcmNoJ10gKSB7XG5cdFx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1sncHVuY2hfdGFnX3F1aWNrX3NlYXJjaCddLnNldFZhbHVlKCBtYW51YWxfaWRzLmpvaW4oKSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdG9uUHVuY2hUYWdRdWlja1NlYXJjaCggdmFsdWUsIGZpbHRlcl9kYXRhLCBwdW5jaF90YWdfaWRfY29sX25hbWUgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBhcmdzID0ge307XG5cblx0XHRpZiAoICEkdGhpcy5lZGl0X3ZpZXdfdWlfZGljIHx8ICEkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW3B1bmNoX3RhZ19pZF9jb2xfbmFtZV0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0YXJncy5maWx0ZXJfZGF0YSA9IGZpbHRlcl9kYXRhO1xuXHRcdGFyZ3MuZmlsdGVyX2RhdGEubWFudWFsX2lkID0gdmFsdWUuc3BsaXQoICcsJyApO1xuXG5cdFx0dGhpcy5wdW5jaF90YWdfYXBpLkdldFB1bmNoVGFnKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0aWYgKCAhJHRoaXMuZWRpdF92aWV3X3VpX2RpYyB8fCAhJHRoaXMuZWRpdF92aWV3X3VpX2RpY1twdW5jaF90YWdfaWRfY29sX25hbWVdICkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciByZXN1bHRfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW3B1bmNoX3RhZ19pZF9jb2xfbmFtZV0uc2V0U291cmNlRGF0YSggbnVsbCApO1xuXG5cdFx0XHRcdGlmICggcmVzdWx0X2RhdGEubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHR2YXIgcHVuY2hfdGFncyA9IHJlc3VsdF9kYXRhLm1hcCggcHVuY2hfdGFnID0+IHB1bmNoX3RhZy5pZCApO1xuXHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbcHVuY2hfdGFnX2lkX2NvbF9uYW1lXS5zZXRWYWx1ZSggcHVuY2hfdGFncyApO1xuXHRcdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbcHVuY2hfdGFnX2lkX2NvbF9uYW1lXSA9IHB1bmNoX3RhZ3M7XG5cdFx0XHRcdFx0JHRoaXMucHJldmlvdXNfcHVuY2hfdGFnX3NlbGVjdGlvbiA9IHB1bmNoX3RhZ3M7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1twdW5jaF90YWdfaWRfY29sX25hbWVdLnNldFZhbHVlKCAnJyApO1xuXHRcdFx0XHRcdCR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRbcHVuY2hfdGFnX2lkX2NvbF9uYW1lXSA9IGZhbHNlO1xuXHRcdFx0XHRcdCR0aGlzLnByZXZpb3VzX3B1bmNoX3RhZ19zZWxlY3Rpb24gPSBbXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlbGV0ZSBhcmdzWydtYW51YWxfaWQnXTtcblxuXHRcdFx0fVxuXHRcdH0gKTtcblxuXHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1sncHVuY2hfdGFnX3F1aWNrX3NlYXJjaCddLnNldENoZWNrQm94KCB0cnVlICk7XG5cdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljW3B1bmNoX3RhZ19pZF9jb2xfbmFtZV0uc2V0Q2hlY2tCb3goIHRydWUgKTtcblx0fVxuXG5cdGdldFB1bmNoVGFnRmlsdGVyRGF0YSgpIHtcblx0XHRpZiAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC51c2VyX2lkICkge1xuXHRcdFx0cmV0dXJuIHt9O1xuXHRcdH1cblxuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHtcblx0XHRcdHN0YXR1c19pZDogMTAsXG5cdFx0XHR1c2VyX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQudXNlcl9pZCxcblx0XHRcdGJyYW5jaF9pZDogdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmJyYW5jaF9pZCxcblx0XHRcdGRlcGFydG1lbnRfaWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5kZXBhcnRtZW50X2lkLFxuXHRcdFx0am9iX2lkOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuam9iX2lkLFxuXHRcdFx0am9iX2l0ZW1faWQ6IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5qb2JfaXRlbV9pZFxuXHRcdH07XG5cblx0XHRyZXR1cm4gZmlsdGVyX2RhdGE7XG5cdH1cblxuXHRvbkNhbmNlbENsaWNrKCBmb3JjZV9ub19jb25maXJtLCBjYW5jZWxfYWxsLCBjYWxsYmFjayApIHtcblx0XHRUVFByb21pc2UuYWRkKCAnYmFzZScsICdvbkNhbmNlbENsaWNrJyApO1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0Ly8jMjM0MiBUaGlzIGxvZ2ljIGlzIGFsc28gaW4gb25TdWJNZW51Q2xpY2sgY2xpY2sgaW4gUmliYm9uVmlld0NvbnRyb2xsZXJcblx0XHRpZiAoICFmb3JjZV9ub19jb25maXJtXG5cdFx0XHQmJlxuXHRcdFx0KFxuXHRcdFx0XHQkdGhpcy5pc19jaGFuZ2VkID09IHRydWVcblx0XHRcdFx0fHwgKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fcHJpbWFyeV9jb250cm9sbGVyICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXIuZWRpdF92aWV3ICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXIuaXNfY2hhbmdlZCA9PSB0cnVlIClcblx0XHRcdFx0fHwgKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fcmVwb3J0X2NvbnRyb2xsZXIgJiYgTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3JlcG9ydF9jb250cm9sbGVyLmlzX2NoYW5nZWQgPT0gdHJ1ZSApXG5cdFx0XHRcdHx8ICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX2VkaXRfb25seV9jb250cm9sbGVyICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9lZGl0X29ubHlfY29udHJvbGxlci5pc19jaGFuZ2VkID09IHRydWUgKVxuXHRcdFx0XHR8fCAoIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9zdWJfY29udHJvbGxlciAmJiBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fc3ViX2NvbnRyb2xsZXIuZWRpdF92aWV3ICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9zdWJfY29udHJvbGxlci5pc19jaGFuZ2VkID09IHRydWUgKVxuXG5cdFx0XHQpICkge1xuXHRcdFx0dGhpcy5jb25maXJtX29uX2V4aXQgPSB0cnVlO1xuXHRcdH1cblxuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gPSAnY2FuY2VsJztcblx0XHRpZiAoIHRoaXMuY29uZmlybV9vbl9leGl0ID09IHRydWUgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoIEdsb2JhbC5tb2RpZnlfYWxlcnRfbWVzc2FnZSwgbnVsbCwgZnVuY3Rpb24oIGNsaWNrZWRfeWVzICkge1xuXHRcdFx0XHRpZiAoIGNsaWNrZWRfeWVzID09PSB0cnVlICkge1xuXHRcdFx0XHRcdGRvTmV4dCggZm9yY2Vfbm9fY29uZmlybSwgY2FuY2VsX2FsbCwgY2FsbGJhY2sgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRUVFByb21pc2UucmVqZWN0KCAnYmFzZScsICdvbkNhbmNlbENsaWNrJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvTmV4dCggZm9yY2Vfbm9fY29uZmlybSwgY2FuY2VsX2FsbCwgY2FsbGJhY2sgKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBkb05leHQoIGZvcmNlX25vX2NvbmZpcm0sIGNhbmNlbF9hbGwsIGNhbGxiYWNrICkge1xuXHRcdFx0aWYgKCAhJHRoaXMuZWRpdF92aWV3ICYmICR0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIgJiYgJHRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdFx0JHRoaXMucGFyZW50X3ZpZXdfY29udHJvbGxlci5pc19jaGFuZ2VkID0gZmFsc2U7XG5cdFx0XHRcdCR0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIuY29uZmlybV9vbl9leGl0ID0gZmFsc2U7XG5cdFx0XHRcdCR0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIuYnVpbGRDb250ZXh0TWVudSggdHJ1ZSApO1xuXHRcdFx0XHQkdGhpcy5wYXJlbnRfdmlld19jb250cm9sbGVyLm9uQ2FuY2VsQ2xpY2soIHRydWUgKTsgLy9Gb3JjZSBubyBjb25maXJtIHNvIHdlIGRvbid0IGdldCB0d28gbWVzc2FnZXMgd2hlbiBjYW5jZWxsaW5nIGZyb20gRWRpdCBFbXBsb3llZSAtPiBXYWdlICh0YWIpIC0+IEVkaXQgV2FnZS5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCR0aGlzLnJlbW92ZUVkaXRWaWV3KCB0cnVlICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggY2FuY2VsX2FsbCApIHtcblx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fZWRpdF9vbmx5X2NvbnRyb2xsZXIgKSB7XG5cdFx0XHRcdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX2VkaXRfb25seV9jb250cm9sbGVyLm9uQ2FuY2VsQ2xpY2soIGZvcmNlX25vX2NvbmZpcm0sIGNhbmNlbF9hbGwgKTtcblx0XHRcdFx0fSBlbHNlIGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3N1Yl9jb250cm9sbGVyICYmIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9zdWJfY29udHJvbGxlci5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRcdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3N1Yl9jb250cm9sbGVyLm9uQ2FuY2VsQ2xpY2soIGZvcmNlX25vX2NvbmZpcm0sIGNhbmNlbF9hbGwgKTtcblx0XHRcdFx0fSBlbHNlIGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlciAmJiBMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fcHJpbWFyeV9jb250cm9sbGVyLmVkaXRfdmlldyApIHtcblx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS5jdXJyZW50X29wZW5fcHJpbWFyeV9jb250cm9sbGVyLm9uQ2FuY2VsQ2xpY2soIGZvcmNlX25vX2NvbmZpcm0sIGNhbmNlbF9hbGwgKTtcblx0XHRcdFx0fSBlbHNlIGlmICggTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3JlcG9ydF9jb250cm9sbGVyICkge1xuXHRcdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9yZXBvcnRfY29udHJvbGxlci5vbkNhbmNlbENsaWNrKCBmb3JjZV9ub19jb25maXJtLCBjYW5jZWxfYWxsICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHR9XG5cblx0XHRcdEdsb2JhbC5zZXRVSUluaXRDb21wbGV0ZSgpO1xuXHRcdFx0VFRQcm9taXNlLnJlc29sdmUoICdiYXNlJywgJ29uQ2FuY2VsQ2xpY2snICk7XG5cdFx0fVxuXHR9XG5cblx0Ly9Eb24ndCBjYWxsIHN1cGVyIGlmIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24uXG5cdG9uRm9ybUl0ZW1DaGFuZ2UoIHRhcmdldCwgZG9Ob3RWYWxpZGF0ZSApIHtcblx0XHQvLyBFcnJvcjogVHlwZUVycm9yOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgaXMgdW5kZWZpbmVkIGluIGludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj05LjAuNy0yMDE2MDIwMi0xMTMyNDQgbGluZSAxNjkxXG5cdFx0aWYgKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuc2V0SXNDaGFuZ2VkKCB0YXJnZXQgKTtcblx0XHR0aGlzLnNldE1hc3NFZGl0aW5nRmllbGRzV2hlbkZvcm1DaGFuZ2UoIHRhcmdldCApO1xuXHRcdHZhciBrZXkgPSB0YXJnZXQuZ2V0RmllbGQoKTtcblx0XHR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSA9IHRhcmdldC5nZXRWYWx1ZSgpO1xuXG5cdFx0aWYgKCAhZG9Ob3RWYWxpZGF0ZSApIHtcblx0XHRcdHRoaXMudmFsaWRhdGUoKTtcblx0XHR9XG5cdH1cblxuXHRzZXRJc0NoYW5nZWQoIHRhcmdldCApIHtcblx0XHR2YXIga2V5ID0gdGFyZ2V0LmdldEZpZWxkKCk7XG5cdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gIT0gdGFyZ2V0LmdldFZhbHVlKCkgKSB7XG5cdFx0XHR0aGlzLmlzX2NoYW5nZWQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXG5cdG9uRm9ybUl0ZW1LZXlVcCggdGFyZ2V0ICkge1xuXHR9XG5cblx0b25Gb3JtSXRlbUtleURvd24oIHRhcmdldCApIHtcblx0fVxuXG5cdHNldE1hc3NFZGl0aW5nRmllbGRzV2hlbkZvcm1DaGFuZ2UoIHRhcmdldCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdHZhciBmaWVsZCA9IHRhcmdldC5nZXRGaWVsZCgpO1xuXHRcdFx0dmFyIGxpbmtlZF9maWVsZHMgPSBbXTtcblx0XHRcdHZhciBpc19saW5rZWRfZmllbGQgPSBmYWxzZTtcblx0XHRcdCQuZWFjaCggdGhpcy5saW5rZWRfY29sdW1ucywgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdFx0aWYgKCB2YWx1ZSAhPT0gZmllbGQgKSB7XG5cdFx0XHRcdFx0bGlua2VkX2ZpZWxkcy5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlzX2xpbmtlZF9maWVsZCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0aWYgKCBpc19saW5rZWRfZmllbGQgKSB7XG5cdFx0XHRcdCQuZWFjaCggbGlua2VkX2ZpZWxkcywgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblx0XHRcdFx0XHR2YXIgaXNfY2hlY2tlZCA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbZmllbGRdLmlzQ2hlY2tlZCgpO1xuXHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNbdmFsdWVdLnNldENoZWNrQm94KCBpc19jaGVja2VkICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdGluaXRFZGl0Vmlld1RhYnMoIHRhYl9vcHRpb25zICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYoIHRhYl9vcHRpb25zID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHR0YWJfb3B0aW9ucyA9IHtcblx0XHRcdFx0YWN0aXZhdGU6IGZ1bmN0aW9uKCBlLCB1aSApIHtcblx0XHRcdFx0XHRpZiAoICEkdGhpcy5lZGl0X3ZpZXdfdGFiIHx8ICEkdGhpcy5lZGl0X3ZpZXdfdGFiLmlzKCAnOnZpc2libGUnICkgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0JHRoaXMub25UYWJTaG93KCBlLCB1aSApO1xuXHRcdFx0XHRcdEdsb2JhbC50cmlnZ2VyQW5hbHl0aWNzVGFicyggZSwgdWkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuc2V0VGFiT1Zpc2liaWxpdHkoIGZhbHNlICk7XG5cblx0XHR0aGlzLmVkaXRfdmlld190YWIgPSB0aGlzLmVkaXRfdmlld190YWIudGFicyggdGFiX29wdGlvbnMgKTtcblxuXHRcdHRoaXMuZWRpdF92aWV3X3RhYi5vZmYoICdjbGljaycgKS5vbiggJ2NsaWNrJywgZnVuY3Rpb24oIGUgKSB7XG5cdFx0XHQkdGhpcy5vblRhYkluZGV4Q2hhbmdlKCBlICk7XG5cdFx0fSApO1xuXHR9XG5cblx0c2V0VGFiSHRtbCggdGFiX21vZGVsICkge1xuXG5cdFx0Ly8gVE9ETzogR28gb2ZmIHRhYl9tb2RlbCBub3QgbGFiZWxzLiBXaWxsIG5lZWQgdG8gZG8gdGhpcyBhbnl3YXksIGFzIHdlIHRyaWdnZXIgZWFybGllci5cblx0XHQvLyBIVE1MMkpTIFRPRE86IEZvciBub3cgdGhpcyB3aWxsIGp1c3QgZ2VuZXJhdGUgdGhlIHRhYiBsYWJlbHMsIGFuZCBvbmNlIHRoYXQgd29ya3MsIHdlIG1vdmUgb24gdG8gdGhlIHRhYiBjb250ZW50IGRpdidzLlxuXHRcdC8vIFRPRE86IFRoaXMgbmVlZHMgdG8gYmUgdHJpZ2dlcmVkIHNvb25lciBpbiBCYXNlVmlldy5pbml0RWRpdFZpZXdVSSBhcyBjdXJyZW50bHkgaXQgaGFwcGVucyBhZnRlciB0aGUgLnRhYnMoKSBpbml0aWFsaXphdGlvbiBhbmQgY2F1c2luZyB0aGUgY2xhc3Mgc3R5bGVzIGZvciB0YWJzIG5vdCB0byBiZSBhZGRlZCB0byB0aGUgcmlnaHQgdGFiIGVsZW1zLCBhcyB0aGV5IGRpZCBub3QgZXhpc3QgYXQgdGhlIHRpbWUgdG8gYmUgYWRkZWQuXG5cdFx0Ly8gTWF5YmUgZGlyZWN0bHkgaW50byBpbml0RWRpdFZpZXdVSSwgYXMgdGhlcmVzIG9ubHkgMTEgb3ZlcnJpZGVzIGZvciB0aGF0LlxuXG5cdFx0dmFyIHRhYl9iYXJfbGFiZWxzID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5lZGl0LXZpZXctdGFiLWJhci1sYWJlbCcgKTtcblx0XHR2YXIgdGFiX2Jhcl9jb250ZW50OyAvLyBpbnNlcnQgYWZ0ZXIgdGhlIGxhYmVsIGVsZW1lbnQuXG5cdFx0Ly8gZmluZCB0aGUgaHRtbCBmaXJzdCwgYW5kIGNoZWNrIGlmIGl0cyBub3QgYWxyZWFkeSBzZXQuXG5cdFx0aWYoIHRhYl9iYXJfbGFiZWxzLmNoaWxkcmVuKCkubGVuZ3RoID09PSAwICkgeyAvLyBUT0RPOiBQZXJoYXBzIGluIGZ1dHVyZSBhbHNvIGNvdW50IG51bWJlciBvZiBjaGlsZHJlbiBhbmQgY29tcGFyZSBhZ2FpbnN0IGxhYmVscy4gSWYgbm90IG1hdGNoaW5nLCBjbGVhciBhbmQgc3RhcnQgYWdhaW4uXG5cdFx0XHQvLyBObyBsYWJlbCBlbGVtZW50cyBmb3VuZCwgbGlrZWx5IHVzaW5nIHRoZSBuZXcgdGVtcGxhdGluZyBsb2dpYy4gQ29udGludWUgdG8gZ2VuZXJhdGUgdGhlIHRhYiBodG1sLlxuXG5cdFx0XHQvLyBOb3Rlc1xuXHRcdFx0LyogRnJpIERlYyAxN1xuXHRcdFx0VE9ETzpcblx0XHRcdC0gMS4gW0RvbmVdLiBGaXJzdCBhZGQgdGhlIHNhdmUgYW5kIGNvbnRpbnVlIGRpdnMgaW50byB0ZW1wbGF0ZXMgYXMgaWYgc3Vidmlldy5cblx0XHRcdFx0MWIuIEZpeCBzdWJ2aWV3IHN0YXRlIGlzc3VlcyBvbiBFbXBsb3llZS0+RW1wbG95ZWVzIHRhYnMuXG5cdFx0XHQtIDIuIHRoZW4gaGFyZGNvZGUgdGhlIGhpZXJhcmNoeSBiZWhhdmlvdXIgaW50byBpdHMgdGFiX21vZGVsXG5cdFx0XHQtIDMuIGFsc28gaGFyZGNvZGUgcG90ZW50aWFsbHkgYXVkaXQsIGJ1dCBpdCBtaWdodCBiZSBjb3ZlcmVkIGJ5IDEuXG5cdFx0XHQtIDQuIHF1YWxpZmFjdGlvbnMgdGFiIGhhcmRjb2RlZCB3aXRoIHRoZSBzdWJ2aWV3IHRoaW5ncy5cblx0XHRcdC0gNS4gc29ydCBvdXQgdGhlIGZpcnN0LWNvbHVtbiBzZWNvbmQgY29sdW1uLlxuXHRcdFx0LS0tIGVpdGhlciBoYXJkY29kZSBpbnRvIHRoZSB0YWJfbW9kZWwgZm9yIG51bWJlciBvZiBjb2x1bW5zIG9yXG5cdFx0XHQtLS0gY291bnQgdGhlIG51bWJlciBvZiBjaGlsZCBlbGVtZW50cyBpbiBzZWNvbmQgY29sdW1uLCBhbmQgaWYgemVybywgcmVtb3ZlLFxuXHRcdFx0XHRhbmQgdGhlbiBhZGQgZnVsbCB3aWR0aCBpbnRvIHRoZSBmaXJzdCBjb2x1bW4gZWxlbWVudC5cblx0XHRcdC0gNi4gd2hhdCB3YXMgdGhlIHN1YnZpZXdjb250cm9sbGVyIGVycm9ycyBvbiBzb21lIHRhYnMuIG1pZ2h0IGJlIHNvbHZlZCBieSAxLiBjaGVjayBlbXBsb3llZSB2aWV3IHRhYnMuXG5cdFx0XHQgKi9cblxuXHRcdFx0Ly8gc2VhcmNoIGZvciAnZmlyc3QtY29sdW1uIGZ1bGwnIC0gNzMrIGZpbGVzXG5cdFx0XHQvLyBzZWFyY2ggZm9yICdzZWNvbmQtY29sdW1uJyAtIDI3IGZpbGVzXG5cdFx0XHQvLyB0aGVyZWZvcmUgZmlyc3QtY29sdW1uIGZ1bGwgd2lkdGggd2lsbCBiZSBkZWZhdWx0LCBhbmQgc2Vjb25kIGNvbHVtbiB3aWxsIGJlIHNwZWNpZmllZCBpbiB2aWV3IGNvbnRyb2xsZXIsIHRvIGF2b2lkIGxvdHMgb2YgYXZvaWRhYmxlIGVkaXRpbmcgb2YgdmlldyBmaWxlcy5cblx0XHRcdGZvciAoIGxldCB0YWJfaWQgaW4gdGFiX21vZGVsICkge1xuXHRcdFx0XHQvLyBDcmVhdGUgYW5kIGluc2VydCB0aGUgbGFiZWwgZWxlbWVudHMuXG5cdFx0XHRcdHZhciBuZXdfdGFiX2xhYmVsX2xpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2xpJyApO1xuXHRcdFx0XHR2YXIgbmV3X3RhYl9sYWJlbF9saV9hID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2EnICk7XG5cdFx0XHRcdG5ld190YWJfbGFiZWxfbGlfYS5zZXRBdHRyaWJ1dGUoJ3JlZicsIHRhYl9pZCApO1xuXHRcdFx0XHRuZXdfdGFiX2xhYmVsX2xpX2Euc2V0QXR0cmlidXRlKCdocmVmJywgJyMnICsgdGFiX2lkICk7XG5cdFx0XHRcdG5ld190YWJfbGFiZWxfbGkuYXBwZW5kQ2hpbGQoIG5ld190YWJfbGFiZWxfbGlfYSApO1xuXG5cdFx0XHRcdHRhYl9iYXJfbGFiZWxzLmFwcGVuZCggbmV3X3RhYl9sYWJlbF9saSApOyAvLyBqUXVlcnkgYXBwZW5kKClcblx0XHRcdFx0Ly8gVE9ETzogQ291bGQgYWxzbyBkaXJlY3RseSBzZXQgdGhlIGxhYmVsIHZhbHVlIHBhcnQgaGVyZSB0b28gaW4gZnV0dXJlLlxuXHRcdFx0fVxuXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIERvIG5vdGhpbmcsIGxhYmVscyBhbHJlYWR5IGV4aXN0LCBsaWtlbHkgZnJvbSBsZWdhY3kgaHRtbCB0ZW1wbGF0ZSBsb2FkaW5nLlxuXHRcdH1cblxuXHRcdHZhciB0YWJfYmFyX3BhcmVudCA9IHRhYl9iYXJfbGFiZWxzLnBhcmVudCgpO1xuXHRcdHZhciB0YWJfYmFyX2NvbnRlbnRfZGl2cyA9IHRhYl9iYXJfcGFyZW50LmZpbmQoICcuZWRpdC12aWV3LXRhYi1vdXRzaWRlJyApO1xuXG5cdFx0aWYoIHRhYl9iYXJfY29udGVudF9kaXZzLmNoaWxkcmVuKCkubGVuZ3RoID09PSAwICkge1xuXHRcdFx0Ly8gQ3JlYXRlIGFuZCBpbnNlcnQgdGhlIHRhYiBjb250ZW50IGRpdnNcblxuXG5cdFx0XHRmb3IgKCBsZXQgdGFiX2lkIGluIHRhYl9tb2RlbCApIHtcblx0XHRcdFx0Ly8gQ3JlYXRlIGFuZCBpbnNlcnQgdGhlIGxhYmVsIGVsZW1lbnRzLlxuXHRcdFx0XHRsZXQgdGFiX2NvbnRlbnRfaHRtbCA9ICcnO1xuXHRcdFx0XHRsZXQgdGFiID0gdGFiX21vZGVsWyB0YWJfaWQgXTtcblx0XHRcdFx0bGV0IGlzX3N1Yl92aWV3ID0gaW5mZXJTdWJWaWV3RnJvbVRhYiggdGFiICk7IC8vIFRPRE86IEhUTUwySlM6IEltcHJvdmUgdGhpcyB0byBhdm9pZCBpbmZlcnJpbmcsIGJ5IGFkZGluZyBpc19zdWJfdmlldyB0byByZWxldmFudCB0YWIgbW9kZWxzLlxuXG5cdFx0XHRcdGlmKCB0YWIuaHRtbF90ZW1wbGF0ZSApIHtcblx0XHRcdFx0XHQvLyBodG1sIHRlbXBsYXRlIHByb3ZpZGVkIGFzIG92ZXJyaWRlLCBkbyBub3QgdXNlIEh0bWxUZW1wbGF0ZXNHbG9iYWwuIE9ubHkgdXNlZCBmb3IgY29tcGxleCBvbmUtb2ZmIHRhYiBodG1sJ3MuXG5cdFx0XHRcdFx0dGFiX2NvbnRlbnRfaHRtbCA9IHRhYi5odG1sX3RlbXBsYXRlO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRhYl9jb250ZW50X2h0bWwgPSAkKCBIdG1sVGVtcGxhdGVzR2xvYmFsLmdlbmVyaWNUYWIoe1xuXHRcdFx0XHRcdFx0dGFiX2lkOiB0YWJfaWQsXG5cdFx0XHRcdFx0XHRpc19tdWx0aV9jb2x1bW46IHRhYi5pc19tdWx0aV9jb2x1bW4gPyB0cnVlIDogZmFsc2UsXG5cdFx0XHRcdFx0XHRzaG93X3Blcm1pc3Npb25fZGl2OiB0YWIuc2hvd19wZXJtaXNzaW9uX2RpdiA/IHRydWUgOiBmYWxzZSxcblx0XHRcdFx0XHRcdGlzX3N1Yl92aWV3OiBpc19zdWJfdmlldyAvLyB0byBjb252ZXJ0IHVuZGVmaW5lZCdzIHRvIGZhbHNlXG5cdFx0XHRcdFx0fSkpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGFiX2Jhcl9wYXJlbnQuYXBwZW5kKCB0YWJfY29udGVudF9odG1sICk7IC8vIEluc2VydCBlYWNoIG5ldyB0YWIgY29udGVudCBhdCB0aGUgZW5kIG9mIHRhYl9iYXIgZGl2IChhbmQgYWZ0ZXIgdGhlIHVsLmVkaXQtdmlldy10YWItYmFyLWxhYmVsIGVsZW1lbnQsIGFuZCBvdGhlciB0YWIgY29udGVudHMuKVxuXHRcdFx0fVxuXG5cdFx0XHQvLyB0YWJfYmFyLmFwcGVuZCggJCggSHRtbFRlbXBsYXRlc0dsb2JhbC5hdWRpdFRhYigpKSApOyAvLyBhZnRlciBhbGwgdGhlIHRhYiBjb250ZW50cywgYWRkIHRoZSBhdWRpdCB0YWIuIChUT0RPOiBoYW5kbGUgc2l0dWF0aW9ucyB3aGVyZSBhdWRpdCBub3QgbmVlZGVkKS4gQXVjdHVhbGx5LCBhdWRpdCBzaG91bGQgYmUgaW4gdGhlIGxpc3Qgb2YgdGFicyBhbHJlYWR5LiBjb21tZW50IG91dCBmb3Igbm93LlxuXG5cdFx0XHQvLyBzd2l0Y2ggKCB0YWJfcmVmX2tleSApIHtcblx0XHRcdC8vIFx0Y2FzZSB4OlxuXHRcdFx0Ly8gXHRcdC8vIGNvZGUgYmxvY2tcblx0XHRcdC8vIFx0XHRicmVhaztcblx0XHRcdC8vIFx0Y2FzZSB5OlxuXHRcdFx0Ly8gXHRcdC8vIGNvZGUgYmxvY2tcblx0XHRcdC8vIFx0XHRicmVhaztcblx0XHRcdC8vIFx0ZGVmYXVsdDpcblx0XHRcdC8vIFx0Ly8gY29kZSBibG9ja1xuXHRcdFx0Ly8gfVxuXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIHRhYl9iYXJfY29udGVudF9kaXZzLmxlbmd0aCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwXG5cdFx0XHQvLyBEbyBub3RoaW5nLCBhbmQgbm8gaHRtbCB3aWxsIGJlIGFmZmVjdGVkLlxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGluZmVyU3ViVmlld0Zyb21UYWIoIHRhYiApIHtcblx0XHRcdGlmICggdGFiLmlzX3N1Yl92aWV3ID09IHRydWUgKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXHRcdFx0aWYoIHRhYi5pbml0X2NhbGxiYWNrID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGluaXRfY2FsbGJhY2tfc3RyaW5nID0gdGFiLmluaXRfY2FsbGJhY2sgfHwgJyc7XG5cdFx0XHR2YXIgaW5mZXJfc3Vidmlld190YWJfc3RhdGUgPSBpbml0X2NhbGxiYWNrX3N0cmluZy50b0xvd2VyQ2FzZSgpLmluZGV4T2YoICdzdWInICkgIT09IC0xO1xuXHRcdFx0aWYgKCBpbmZlcl9zdWJ2aWV3X3RhYl9zdGF0ZSA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0Ly8gVGhpcyBvbmUgaXMgYSBsaXR0bGUgbW9yZSBleHBlcmltZW50YWwgKGFzc3VtZXMgYWxsIHN1YiB2aWV3cyBoYXZlIGluaXQgY2FsbGJhY2sgZnVuY3Rpb25zIG5hbWVkIHdpdGggJ3N1YicpLCBidXQgbWlnaHQgd29yayBhcyB0ZW1wb3JhcnkgZHVyaW5nIHJlZmFjdG9yLlxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTm90aGluZyBtYXRjaGVkLCByZXR1cm4gZmFsc2UgYnkgZGVmYXVsdC5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRzZXRUYWJMYWJlbHMoIHNvdXJjZSApIHtcblx0XHRmb3IgKCB2YXIga2V5IGluIHNvdXJjZSApIHtcblx0XHRcdHRoaXMuZWRpdF92aWV3LmZpbmQoICdhW3JlZj0nICsga2V5ICsgJ10nICkudGV4dCggc291cmNlW2tleV0gKTtcblx0XHR9XG5cdH1cblxuXHRnZXRUYWJNb2RlbCgpIHtcblx0XHRyZXR1cm4gdGhpcy50YWJfbW9kZWw7XG5cdH1cblxuXHRzZXRUYWJNb2RlbCggbW9kZWwgKSB7XG5cdFx0dmFyIHRhYl9sYWJlbHMgPSB7fTtcblxuXHRcdGZvciAoIHZhciBpIGluIG1vZGVsICkge1xuXHRcdFx0Ly9JZiB0aGUgbW9kZWwgaXMgXCJ0cnVlXCIsIHRoZW4gdXNlIGRlZmF1bHQgbW9kZWxzIGZvciBhdWRpdC9hdHRhY2htZW50IHRhYnMuXG5cdFx0XHRpZiAoIGkgPT0gJ3RhYl9hdWRpdCcgJiYgbW9kZWxbaV0gPT09IHRydWUgKSB7XG5cdFx0XHRcdG1vZGVsWyd0YWJfYXVkaXQnXSA9IHtcblx0XHRcdFx0XHQnbGFiZWwnOiAkLmkxOG4uXyggJ0F1ZGl0JyApLFxuXHRcdFx0XHRcdCdpbml0X2NhbGxiYWNrJzogJ2luaXRTdWJMb2dWaWV3Jyxcblx0XHRcdFx0XHQnZGlzcGxheV9vbl9tYXNzX2VkaXQnOiBmYWxzZSxcblx0XHRcdFx0XHQnZGlzcGxheV9vbl9hZGQnOiBmYWxzZVxuXHRcdFx0XHR9O1xuXHRcdFx0fSBlbHNlIGlmICggaSA9PSAndGFiX2F0dGFjaG1lbnQnICYmIG1vZGVsW2ldID09PSB0cnVlICkge1xuXHRcdFx0XHRtb2RlbFsndGFiX2F0dGFjaG1lbnQnXSA9IHtcblx0XHRcdFx0XHQnbGFiZWwnOiAkLmkxOG4uXyggJ0F0dGFjaG1lbnQnICksXG5cdFx0XHRcdFx0J2luaXRfY2FsbGJhY2snOiAnaW5pdFN1YkRvY3VtZW50VmlldycsXG5cdFx0XHRcdFx0J2Rpc3BsYXlfb25fbWFzc19lZGl0JzogZmFsc2Vcblx0XHRcdFx0fTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBtb2RlbFtpXS5oYXNPd25Qcm9wZXJ0eSggJ2xhYmVsJyApICYmIG1vZGVsW2ldLmxhYmVsICE9ICcnICkge1xuXHRcdFx0XHR0YWJfbGFiZWxzW2ldID0gbW9kZWxbaV0ubGFiZWw7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy50YWJfbW9kZWwgPSBtb2RlbDtcblx0XHR0aGlzLnNldFRhYkh0bWwoIG1vZGVsICk7XG5cdFx0dGhpcy5pbml0RWRpdFZpZXdUYWJzKCk7XG5cdFx0dGhpcy5zZXRUYWJMYWJlbHMoIHRhYl9sYWJlbHMgKTtcblxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0b25UYWJTaG93KCBlLCB1aSApIHtcblx0XHRpZiAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGtleSA9IHRoaXMuZ2V0RWRpdFZpZXdUYWJJbmRleCgpO1xuXHRcdHRoaXMuZWRpdEZpZWxkUmVzaXplKCBrZXkgKTtcblxuXHRcdHZhciB0YWJfbW9kZWwgPSB0aGlzLmdldFRhYk1vZGVsKCk7XG5cblx0XHRpZiAoIHRhYl9tb2RlbCAhPSBudWxsICkge1xuXHRcdFx0aWYgKCB1aSAmJiB1aS5vbGRUYWIgKSB7XG5cdFx0XHRcdHZhciBwcmV2X3RhYl9uYW1lID0gdWkub2xkVGFiLmZpbmQoICdhJyApWzBdLmdldEF0dHJpYnV0ZSggJ2hyZWYnICkuc3Vic3RyaW5nKCAxICk7XG5cdFx0XHRcdGlmICggdGFiX21vZGVsW3ByZXZfdGFiX25hbWVdICYmIHRhYl9tb2RlbFtwcmV2X3RhYl9uYW1lXS5oYXNPd25Qcm9wZXJ0eSggJ29uX2V4aXRfY2FsbGJhY2snICkgJiYgdGFiX21vZGVsW3ByZXZfdGFiX25hbWVdLm9uX2V4aXRfY2FsbGJhY2sgIT0gJycgKSB7XG5cdFx0XHRcdFx0dGhpc1t0YWJfbW9kZWxbcHJldl90YWJfbmFtZV0ub25fZXhpdF9jYWxsYmFja10oIHByZXZfdGFiX25hbWUgKTsgLy9DYWxsIG1hcHBlZCBmdW5jdGlvbiB0byBpbml0aWFsaXplIHRoZSB0YWIuXG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly9SZUZhY3RvcmVkIHBhdGggdG8gaGFuZGxlIHRhYnMgYmFzZWQgb24gYSB0YWIgbW9kZWwgbWFwcGluZyBkZWZpbmVkIGluIGVhY2ggdmlldyBjbGFzcy5cblx0XHRcdC8vVGhpcyBhYnN0cmFjdHMgdGhlIGVudHJ5IHBvaW50IGZvciBhbGwgdGFicyBpbml0aWFsaXphdGlvbnMgdG8gaGVscCB3aXRoIGhpZGluZy9zaG93aW5nIHRoZW0gYW5kIHRvIHJlZHVjZSBjb2RlIGR1cGxpY2F0aW9uLlxuXHRcdFx0dmFyIHRhYl9uYW1lID0gbnVsbDtcblx0XHRcdHZhciBzdWJfdmlld19kaXYgPSBudWxsO1xuXG5cdFx0XHR2YXIgdGFiX2JhciA9IHRoaXMuZWRpdF92aWV3LmZpbmQoICcuZWRpdC12aWV3LXRhYi1iYXIgbGkudWktdGFicy1hY3RpdmUnICkuZmluZCggJ2EnICk7XG5cdFx0XHRpZiAoIHRhYl9iYXIubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0dGFiX25hbWUgPSB0YWJfYmFyWzBdLmdldEF0dHJpYnV0ZSggJ2hyZWYnICkuc3Vic3RyaW5nKCAxICk7IC8vUmVtb3ZlIHRoZSAnIyc7XG5cdFx0XHRcdHN1Yl92aWV3X2RpdiA9IHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnIycgKyB0YWJfbmFtZSApLmZpbmQoICcuZmlyc3QtY29sdW1uLXN1Yi12aWV3JyApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHN1Yl92aWV3X2RpdiAmJiBzdWJfdmlld19kaXYubGVuZ3RoID4gMCAmJiB0aGlzLnRhYl9tb2RlbFt0YWJfbmFtZV0gJiYgIXRoaXMudGFiX21vZGVsW3RhYl9uYW1lXS5pbml0aWFsaXplZCApIHsgLy9Pbmx5IGhpZGUgZ3JpZCBvbiBmaXJzdCBpbml0aWFsaXphdGlvbiBhcyBpdCBoYXMgdG8gbG9hZCBhbGwgdGhlIGRhdGEuIE90aGVyd2lzZSB0aGUgMm5kIHRpbWUgdGhlIHVzZXIgZ29lcyB0byB0aGUgdGFiIHRoZXkgd2lsbCBzZWUgc29tZSBtaW5vciBcImZsYXNoaW5nXCJcblx0XHRcdFx0VFRQcm9taXNlLmFkZCggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvblRhYlNob3cnICk7XG5cdFx0XHRcdFRUUHJvbWlzZS53YWl0KCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ29uVGFiU2hvdycsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHN1Yl92aWV3X2Rpdi5jc3MoICdvcGFjaXR5JywgJzEnICk7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRzdWJfdmlld19kaXYuY3NzKCAnb3BhY2l0eScsICcwJyApOyAvL0hpZGUgdGhlIGdyaWQgd2hpbGUgaXRzIGxvYWRpbmcvc2l6aW5nLlxuXHRcdFx0XHR0aGlzLnRhYl9tb2RlbFt0YWJfbmFtZV0uaW5pdGlhbGl6ZWQgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRhYl9tb2RlbFt0YWJfbmFtZV0gKSB7XG5cdFx0XHRcdC8vdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjJysgdGFiX25hbWUgKS5maW5kKCAnLmZpcnN0LWNvbHVtbi1zdWItdmlldycgKS5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0XHQvL0NhbGwgdGhlIGluaXRfY2FsbGJhY2sgZXZlbiBpZiB3ZSBhcmUgZWRpdGluZyBhbiBleGlzdGluZyByZWNvcmQgb3IgY3JlYXRpbmcgYSBuZXcgb25lLlxuXHRcdFx0XHQvLyBBcyBzb21lIHZpZXdzIChpZTogT3ZlclRpbWUgUG9saWN5KSBuZWVkIHRvIGNvbnRyb2wgd2hhdHMgc2hvd24gb24gZWFjaCB0YWIgcmVnYXJkbGVzcyBvZiBpZiB3ZSBhcmUgZWRpdGluZyBvciBhZGRpbmcuXG5cdFx0XHRcdGlmICggdGFiX21vZGVsW3RhYl9uYW1lXS5oYXNPd25Qcm9wZXJ0eSggJ2luaXRfY2FsbGJhY2snICkgJiYgdGFiX21vZGVsW3RhYl9uYW1lXS5pbml0X2NhbGxiYWNrICE9ICcnICkge1xuXHRcdFx0XHRcdHRoaXNbdGFiX21vZGVsW3RhYl9uYW1lXS5pbml0X2NhbGxiYWNrXSggdGFiX25hbWUgKTsgLy9DYWxsIG1hcHBlZCBmdW5jdGlvbiB0byBpbml0aWFsaXplIHRoZSB0YWIuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly9Bc3N1bWUgcHJpbWFyeSB0YWIgYW5kIGJ1aWxkIGNvbnRleHQgbWVudS5cblx0XHRcdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgIT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjJysgdGFiX25hbWUgKS5maW5kKCAnLmZpcnN0LWNvbHVtbi1zdWItdmlldycgKS5jc3MoICdkaXNwbGF5JywgJ25vbmUnICk7IC8vVGhpcyB3b3VsZCBwcmV2ZW50IHRoZSBncmlkIGZyb20gc2hvd2luZyBpbiBBdHRlbmRhbmNlIC0+IFRpbWVTaGVldCwgQWNjdW11bGF0ZWQgVGltZSB2aWV3LlxuXHRcdFx0XHRcdFx0Ly90aGlzLmVkaXRfdmlld190YWIuZmluZCggJyMnKyB0YWJfbmFtZSApLmZpbmQoICcuZmlyc3QtY29sdW1uLXN1Yi12aWV3JyApLmNzcyggJ2Rpc3BsYXknLCAnYmxvY2snICk7XG5cdFx0XHRcdFx0XHR0aGlzLnNob3dTYXZlQW5kQ29udGludWVCdXR0b24oKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdFx0Ly8gXHQvL3RoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnIycrIHRhYl9uYW1lICkuZmluZCggJy5maXJzdC1jb2x1bW4tc3ViLXZpZXcnICkuY3NzKCAnZGlzcGxheScsICdibG9jaycgKTtcblx0XHRcdFx0Ly8gXHRpZiAoIHRhYl9tb2RlbFt0YWJfbmFtZV0uaGFzT3duUHJvcGVydHkoJ2luaXRfY2FsbGJhY2snKSAmJiB0YWJfbW9kZWxbdGFiX25hbWVdLmluaXRfY2FsbGJhY2sgIT0gJycgKSB7XG5cdFx0XHRcdC8vIFx0XHR0aGlzW3RhYl9tb2RlbFt0YWJfbmFtZV0uaW5pdF9jYWxsYmFja10oIHRhYl9uYW1lICk7IC8vQ2FsbCBtYXBwZWQgZnVuY3Rpb24gdG8gaW5pdGlhbGl6ZSB0aGUgdGFiLlxuXHRcdFx0XHQvLyBcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIFx0XHQvL0Fzc3VtZSBwcmltYXJ5IHRhYiBhbmQgYnVpbGQgY29udGV4dCBtZW51LlxuXHRcdFx0XHQvLyBcdFx0dGhpcy5idWlsZENvbnRleHRNZW51KCB0cnVlICk7XG5cdFx0XHRcdC8vIFx0XHR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHRcdC8vIFx0fVxuXHRcdFx0XHQvLyB9IGVsc2Uge1xuXHRcdFx0XHQvLyBcdC8vdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjJysgdGFiX25hbWUgKS5maW5kKCAnLmZpcnN0LWNvbHVtbi1zdWItdmlldycgKS5jc3MoICdkaXNwbGF5JywgJ25vbmUnICk7IC8vVGhpcyB3b3VsZCBwcmV2ZW50IHRoZSBncmlkIGZyb20gc2hvd2luZyBpbiBBdHRlbmRhbmNlIC0+IFRpbWVTaGVldCwgQWNjdW11bGF0ZWQgVGltZSB2aWV3LlxuXHRcdFx0XHQvLyBcdC8vdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjJysgdGFiX25hbWUgKS5maW5kKCAnLmZpcnN0LWNvbHVtbi1zdWItdmlldycgKS5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0XHQvLyBcdHRoaXMuZWRpdF92aWV3LmZpbmQoICcuc2F2ZS1hbmQtY29udGludWUtZGl2JyApLmNzcyggJ2Rpc3BsYXknLCAnYmxvY2snICk7XG5cdFx0XHRcdC8vIH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vQXNzdW1lIHByaW1hcnkgdGFiIGFuZCBidWlsZCBjb250ZXh0IG1lbnUuXG5cdFx0XHRcdHRoaXMuYnVpbGRDb250ZXh0TWVudSggdHJ1ZSApO1xuXHRcdFx0XHR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vSGFuZGxlIG1vc3QgY2FzZXMgdGhhdCBvbmUgdGFiIGFuZCBvbiBhdWRpdCB0YWJcblx0XHRcdGlmICgga2V5ID09PSAxICkge1xuXG5cdFx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAhPSBUVFVVSUQuemVyb19pZCApIHtcblx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld190YWIuZmluZCggJyN0YWJfYXVkaXQnICkuZmluZCggJy5maXJzdC1jb2x1bW4tc3ViLXZpZXcnICkuY3NzKCAnZGlzcGxheScsICdibG9jaycgKTtcblx0XHRcdFx0XHR0aGlzLmluaXRTdWJMb2dWaWV3KCAndGFiX2F1ZGl0JyApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjdGFiX2F1ZGl0JyApLmZpbmQoICcuZmlyc3QtY29sdW1uLXN1Yi12aWV3JyApLmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0XHRcdFx0XHR0aGlzLnNob3dTYXZlQW5kQ29udGludWVCdXR0b24oKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmJ1aWxkQ29udGV4dE1lbnUoIHRydWUgKTtcblx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudSgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vV2hlbiBvdmVycmlkaW5nIHRoaXMgZnVuY3Rpb24sIGFsd2F5cyBjYWxsIHN1cGVyKCkgc28gaXQgY2FuIGhhbmRsZSB0YWJfYXVkaXQvdGFiX2F0dGFjaG1lbnQgb24gaXRzIG93bi5cblx0Y2hlY2tUYWJQZXJtaXNzaW9ucyggdGFiICkge1xuXHRcdHZhciByZXR2YWwgPSB0cnVlOyAvL01vc3QgdGFicyBhcmUgc2hvd24sIHNvIGRlZmF1bHQgdG8gdHJ1ZS5cblxuXHRcdHN3aXRjaCAoIHRhYiApIHtcblx0XHRcdGNhc2UgJ3RhYl9hdWRpdCc6XG5cdFx0XHRcdHJldHZhbCA9IHRoaXMuc3ViQXVkaXRWYWxpZGF0ZSgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3RhYl9hdHRhY2htZW50Jzpcblx0XHRcdFx0cmV0dmFsID0gdGhpcy5zdWJEb2N1bWVudFZhbGlkYXRlKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXR2YWw7XG5cdH1cblxuXHRzZXRUYWJTdGF0dXMoKSB7XG5cdFx0Ly8gZXhjZXB0aW9uIHRoYXQgZWRpdF92aWV3X3RhYiBpcyBudWxsXG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdGFiICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciB0YWJfbW9kZWwgPSB0aGlzLmdldFRhYk1vZGVsKCk7XG5cblx0XHRpZiAoIHRhYl9tb2RlbCAhPSBudWxsICkge1xuXHRcdFx0dmFyIHZpc2libGVfdGFiX2luZGV4ZXMgPSBBcnJheSgpO1xuXG5cdFx0XHQvL1JlRmFjdG9yZWQgcGF0aCB0byBoYW5kbGUgdGFicyBiYXNlZCBvbiBhIHRhYiBtb2RlbCBtYXBwaW5nIGRlZmluZWQgaW4gZWFjaCB2aWV3IGNsYXNzLlxuXHRcdFx0Ly9UaGlzIGFic3RyYWN0cyB0aGUgZW50cnkgcG9pbnQgZm9yIGFsbCB0YWJzIGluaXRpYWxpemF0aW9ucyB0byBoZWxwIHdpdGggaGlkaW5nL3Nob3dpbmcgdGhlbSBhbmQgdG8gcmVkdWNlIGNvZGUgZHVwbGljYXRpb24uXG5cdFx0XHRmb3IgKCB2YXIgaSBpbiB0YWJfbW9kZWwgKSB7XG5cdFx0XHRcdHZhciB0YWJfaW5kZXggPSAkKCB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJ3VsIGxpIGFbcmVmPVwiJyArIGkgKyAnXCJdJyApICkucGFyZW50KCkuaW5kZXgoKTtcblxuXHRcdFx0XHRpZiAoICggdGhpcy5pc19tYXNzX2VkaXRpbmcgJiYgdGFiX21vZGVsW2ldLmhhc093blByb3BlcnR5KCAnZGlzcGxheV9vbl9tYXNzX2VkaXQnICkgJiYgdGFiX21vZGVsW2ldLmRpc3BsYXlfb25fbWFzc19lZGl0ID09IGZhbHNlIClcblx0XHRcdFx0XHR8fCAoICggdGhpcy5pc19hZGQgfHwgdGhpcy5pc19tYXNzX2FkZGluZyApICYmIHRhYl9tb2RlbFtpXS5oYXNPd25Qcm9wZXJ0eSggJ2Rpc3BsYXlfb25fYWRkJyApICYmIHRhYl9tb2RlbFtpXS5kaXNwbGF5X29uX2FkZCA9PSBmYWxzZSApICkge1xuXHRcdFx0XHRcdCQoIHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAndWwgbGkgYVtyZWY9XCInICsgaSArICdcIl0nICkgKS5wYXJlbnQoKS5oaWRlKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLmNoZWNrVGFiUGVybWlzc2lvbnMoIGkgKSA9PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0JCggdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICd1bCBsaSBhW3JlZj1cIicgKyBpICsgJ1wiXScgKSApLnBhcmVudCgpLnNob3coKTtcblx0XHRcdFx0XHRcdHZpc2libGVfdGFiX2luZGV4ZXMucHVzaCggdGFiX2luZGV4ICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCQoIHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAndWwgbGkgYVtyZWY9XCInICsgaSArICdcIl0nICkgKS5wYXJlbnQoKS5oaWRlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vQWx3YXlzIHN0YXJ0IHdpdGggdGhlIGZpcnN0IHRhYiB0aGF0IGFjdHVhbGx5IGhhcyBwZXJtaXNzaW9ucyB0byBiZSBzaG93bi4gVGhpcyBpcyBpbXBvcnRhbnQgZm9yIHN1Yi12aWV3cyBsaWtlIEVkaXQgRW1wbG95ZWUsIFRheCwgTmV3IGljb24sIHdoZXJlIGl0IHNob3dzIG9ubHkgYSBzaW5nbGUgdGFiIHdoZXJlIHRoZXJlIGFyZSByZWFsbHkgNSsgdGFicyBqdXN0IGhpZGRlbi5cblx0XHRcdHZpc2libGVfdGFiX2luZGV4ZXMgPSB2aXNpYmxlX3RhYl9pbmRleGVzLnNvcnQoIGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0XHRyZXR1cm4gYSAtIGI7XG5cdFx0XHR9ICk7IC8vbnVtZXJpYyBzb3J0LlxuXG5cdFx0XHRpZiAoIHZpc2libGVfdGFiX2luZGV4ZXNbMF0gKSB7XG5cdFx0XHRcdHRoaXMuZWRpdF92aWV3X3RhYi50YWJzKCAnb3B0aW9uJywgJ2FjdGl2ZScsIHZpc2libGVfdGFiX2luZGV4ZXNbMF0gKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly9IYW5kbGUgbW9zdCBjYXNlcyB0aGF0IG9uZSB0YWIgYW5kIG9uIGF1ZGl0IHRhYlxuXHRcdFx0aWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblxuXHRcdFx0XHQkKCB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJ3VsIGxpIGFbcmVmPVwidGFiX2F1ZGl0XCJdJyApICkucGFyZW50KCkuaGlkZSgpO1xuXHRcdFx0XHR0aGlzLmVkaXRfdmlld190YWIudGFicyggJ29wdGlvbicsICdhY3RpdmUnLCAwICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0aWYgKCB0aGlzLnN1YkF1ZGl0VmFsaWRhdGUoKSApIHtcblx0XHRcdFx0XHQkKCB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJ3VsIGxpIGFbcmVmPVwidGFiX2F1ZGl0XCJdJyApICkucGFyZW50KCkuc2hvdygpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCQoIHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAndWwgbGkgYVtyZWY9XCJ0YWJfYXVkaXRcIl0nICkgKS5wYXJlbnQoKS5oaWRlKCk7XG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdGFiLnRhYnMoICdvcHRpb24nLCAnYWN0aXZlJywgMCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmVkaXRGaWVsZFJlc2l6ZSggMCApO1xuXHR9XG5cblx0b25UYWJJbmRleENoYW5nZSggZSApIHtcblx0XHRUVFByb21pc2UuYWRkKCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ29uVGFiSW5kZXhDaGFuZ2UnICk7XG5cdFx0VFRQcm9taXNlLndhaXQoKTtcblxuXHRcdGlmICggKCAhdGhpcy5zdWJfdmlld19tb2RlICYmICF0aGlzLmVkaXRfb25seV9tb2RlICkgfHwgdHlwZW9mIHRoaXMuaW5pdFJlcG9ydCA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0dmFyIGN1cnJlbnRfdXJsID0gd2luZG93LmxvY2F0aW9uLmhyZWY7XG5cblx0XHRcdGlmICggY3VycmVudF91cmwuaW5kZXhPZiggJyZ0YWInICkgPiAwICkge1xuXHRcdFx0XHRjdXJyZW50X3VybCA9IGN1cnJlbnRfdXJsLnN1YnN0cmluZyggMCwgY3VycmVudF91cmwuaW5kZXhPZiggJyZ0YWInICkgKTtcblx0XHRcdH1cblx0XHRcdHZhciB0YWJfbmFtZSA9IHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnLmVkaXQtdmlldy10YWItYmFyLWxhYmVsJyApLmNoaWxkcmVuKCkuZXEoIHRoaXMuZ2V0RWRpdFZpZXdUYWJJbmRleCgpICkudGV4dCgpO1xuXHRcdFx0dGFiX25hbWUgPSB0YWJfbmFtZS5yZXBsYWNlKCAvXFwvfFxccysvZywgJycgKTtcblx0XHRcdGN1cnJlbnRfdXJsID0gY3VycmVudF91cmwgKyAnJnRhYj0nICsgdGFiX25hbWU7XG5cblx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIGN1cnJlbnRfdXJsICk7XG5cblx0XHR9XG5cblx0XHR0aGlzLmhpZGVFcnJvclRpcHMoKTtcblx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvblRhYkluZGV4Q2hhbmdlJyApO1xuXHR9XG5cblx0aGlkZUVycm9yVGlwcygpIHtcblx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZWRpdF92aWV3X2Vycm9yX3VpX2RpYyApIHtcblx0XHRcdC8vIzI1ODEgLSBVbmNhdWdodCBUeXBlRXJyb3I6IHRoaXMuZWRpdF92aWV3X2Vycm9yX3VpX2RpY1trZXldLmhpZGVFcnJvclRpcCBpcyBub3QgYSBmdW5jdGlvblxuXHRcdFx0aWYgKCB0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWNba2V5XSAmJiB0eXBlb2YgdGhpcy5lZGl0X3ZpZXdfZXJyb3JfdWlfZGljW2tleV0uaGlkZUVycm9yVGlwID09ICdmdW5jdGlvbicgKSB7XG5cdFx0XHRcdHRoaXMuZWRpdF92aWV3X2Vycm9yX3VpX2RpY1trZXldLmhpZGVFcnJvclRpcCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLnJlbW92ZUVkaXRWaWV3RXJyb3JUaXAoKTtcblx0fVxuXG5cdC8vcmVtb3ZlZCB3b3JrYXJvdW5kcyBhbmQgY29tbWVudHMgZm9yIHF0aXAxIHdoZW4gdXBncmFkaW5nIHRvIHF0aXAyLlxuXHRyZW1vdmVFZGl0Vmlld0Vycm9yVGlwKCkge1xuXHRcdGlmICggJCggJy5xdGlwMi1lcnJvci10aXA6dmlzaWJsZScgKSApIHtcblx0XHRcdCQoICcucXRpcDItZXJyb3ItdGlwJyApLnJlbW92ZSgpO1xuXHRcdH1cblxuXHR9XG5cblx0cmVtb3ZlRWRpdFZpZXdXYXJuaW5nVGlwKCkge1xuXHRcdGlmICggJCggJy5xdGlwMi13YXJuaW5nLXRpcDp2aXNpYmxlJyApICkge1xuXHRcdFx0JCggJy5xdGlwMi13YXJuaW5nLXRpcCcgKS5yZW1vdmUoKTtcblx0XHR9XG5cdH1cblxuXHRvbkNvdW50cnlDaGFuZ2UoKSB7XG5cdFx0dmFyIHNlbGVjdFZhbCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1snY291bnRyeSddLmdldFZhbHVlKCk7XG5cdFx0dGhpcy5lU2V0UHJvdmluY2UoIHNlbGVjdFZhbCwgdHJ1ZSApO1xuXHRcdHRoaXMuY2xlYXJFcnJvclRpcHMoKTtcblx0XHR0aGlzLnNldEVkaXRNZW51KCk7XG5cdH1cblxuXHQvL01ha2Ugc3VyZSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgaXMgdXBkYXRlZCBiZWZvcmUgdmFsaWRhdGVcblx0dmFsaWRhdGUoIGFwaSApIHtcblx0XHRpZiAoIHRoaXMuZW5hYmxlX3ZhbGlkYXRpb24gKSB7XG5cdFx0XHQvL0FsbG93IGFsdGVybmF0ZSBhcGkgdG8gYmUgdmFsaWRhdGVkLlxuXHRcdFx0aWYgKCBhcGkgPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHR2YXIgYXBpID0gdGhpcy5hcGk7XG5cdFx0XHR9XG5cblx0XHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0XHR2YXIgcmVjb3JkID0ge307XG5cdFx0XHRpZiAoIHRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZWRpdF92aWV3X3VpX2RpYyApIHtcblxuXHRcdFx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dmFyIHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldO1xuXHRcdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB3aWRnZXQuaXNDaGVja2VkICkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHdpZGdldC5pc0NoZWNrZWQoKSAmJiB3aWRnZXQuZ2V0RW5hYmxlZCgpICkge1xuXHRcdFx0XHRcdFx0XHRyZWNvcmRba2V5XSA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldOyAvLyBOb3RlOiBTb21lIHZpZXcgY29udHJvbGxlcnMgdXNlIHdpZGdldC5nZXRWYWx1ZSgpIGluc3RlYWQgb2YgY3VycmVudF9lZGl0X3JlY29yZFtrZXldXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZWNvcmQgPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0XHR9XG5cdFx0XHRyZWNvcmQgPSB0aGlzLnVuaWZvcm1WYXJpYWJsZSggcmVjb3JkICk7XG5cdFx0XHRhcGlbJ3ZhbGlkYXRlJyArIGFwaS5rZXlfbmFtZV0oIHJlY29yZCwge1xuXHRcdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlc3VsdCApIHtcblx0XHRcdFx0XHQkdGhpcy52YWxpZGF0ZVJlc3VsdCggcmVzdWx0ICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0RGVidWcuVGV4dCggJ1ZhbGlkYXRpb24gZGlzYWJsZWQnLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICd2YWxpZGF0ZScsIDEwICk7XG5cdFx0fVxuXHR9XG5cblx0dmFsaWRhdGVSZXN1bHQoIHJlc3VsdCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdCR0aGlzLmNsZWFyRXJyb3JUaXBzKCk7IC8vQWx3YXlzIGNsZWFyIGVycm9yXG5cdFx0aWYgKCAhJHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggIXJlc3VsdCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHJlc3VsdC5pc1ZhbGlkKCkgKSB7XG5cdFx0XHQkdGhpcy5lZGl0X3ZpZXcuYXR0ciggJ3ZhbGlkYXRlX2NvbXBsZXRlJywgdHJ1ZSApO1xuXHRcdFx0JHRoaXMuc2V0RWRpdE1lbnUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRoaXMuc2V0RXJyb3JNZW51KCk7XG5cdFx0XHQkdGhpcy5zZXRFcnJvclRpcHMoIHJlc3VsdCwgdGhpcy5zaG93X3dhcm5pbmdfd2hlbl92YWxpZGF0aW9uICk7XG5cblx0XHR9XG5cdH1cblxuXHRjbGVhckVycm9yVGlwcygpIHtcblxuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5lZGl0X3ZpZXdfZXJyb3JfdWlfZGljICkge1xuXHRcdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnY2xlYXJFcnJvclN0eWxlJyBvZiB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj04LjAuMC0yMDE0MTExNy0xMTExNDAgbGluZSAxNzc5XG5cdFx0XHRpZiAoICF0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWMuaGFzT3duUHJvcGVydHkoIGtleSApIHx8ICF0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWNba2V5XSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWNba2V5XS5jbGVhckVycm9yU3R5bGUoKTtcblx0XHR9XG5cblx0XHQvLyBFcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnaW50ZXJmYWNlcycgb2YgdW5kZWZpbmVkIGluIGludGVyZmFjZS9odG1sNS9mcmFtZXdvcmsvanF1ZXJ5LnF0aXAubWluLmpzP3Y9OS4wLjAtMjAxNTA5MTgtMjIxOTA2IGxpbmUgMTVcblx0XHR0aGlzLnJlbW92ZUVkaXRWaWV3RXJyb3JUaXAoKTtcblx0XHR0aGlzLnJlbW92ZUVkaXRWaWV3V2FybmluZ1RpcCgpO1xuXHRcdCQoICcuZXJyb3ItdGFiJyApLnJlbW92ZUNsYXNzKCAnZXJyb3ItdGFiJyApO1xuXHRcdCQoICcuZXJyb3ItdGFiLWhpZGUnICkucmVtb3ZlQ2xhc3MoICdlcnJvci10YWItaGlkZScgKTtcblx0XHQkKCAnLndhcm5pbmctdGFiJyApLnJlbW92ZUNsYXNzKCAnd2FybmluZy10YWInICk7XG5cdFx0JCggJy53YXJuaW5nLXRhYi1oaWRlJyApLnJlbW92ZUNsYXNzKCAnd2FybmluZy10YWItaGlkZScgKTtcblx0XHQvLyBDbGVhciBwdWxzZSBvbiB0YWJzXG5cdFx0aWYgKCB0aGlzLnB1bHNlX3RpbWVfZGljICkge1xuXHRcdFx0Zm9yICggdmFyIGtleTEgaW4gdGhpcy5wdWxzZV90aW1lX2RpYyApIHtcblx0XHRcdFx0Y2xlYXJJbnRlcnZhbCggdGhpcy5wdWxzZV90aW1lX2RpY1trZXkxXSApO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5wdWxzZV90aW1lX2RpYyA9IHt9O1xuXHRcdH1cblx0XHR0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWMgPSB7fTtcblxuXHRcdCQoICcucXRpcCAucXRpcDItZXJyb3ItdGlwJyApLnJlbW92ZSgpO1xuXHR9XG5cblx0Ly9PdmVycmlkZSB0aGlzIGlmIG1vcmUgdGhhbiBvbmUgdGFiXG5cdHNldEVycm9yVGlwcyggcmVzdWx0LCBzaG93X3dhcm5pbmcgKSB7XG5cdFx0dGhpcy5jbGVhckVycm9yVGlwcygpO1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggc2hvd193YXJuaW5nICkgKSB7XG5cdFx0XHRzaG93X3dhcm5pbmcgPSB0cnVlO1xuXHRcdH1cblxuXHRcdC8vRXJyb3I6IFVuYWJsZSB0byBnZXQgcHJvcGVydHkgJ2ZpbmQnIG9mIHVuZGVmaW5lZCBvciBudWxsIHJlZmVyZW5jZSBpbiBodHRwOi8vdGltZWNsb2NrOjgwODUvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTcuNC4zLTIwMTQwOTI2LTEwNTgyNyBsaW5lIDE3Njlcblx0XHRpZiAoICF0aGlzLmVkaXRfdmlld190YWIgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGRldGFpbHMgPSByZXN1bHQuZ2V0RGV0YWlscygpO1xuXHRcdC8vIE9ubHkgY2hlY2sgZmlyc3QgaXRlbVxuXHRcdC8vIEVycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCBjYWxsIG1ldGhvZCAnaGFzT3duUHJvcGVydHknIG9mIHVuZGVmaW5lZCBpbiAvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTkuMC4wLTIwMTUwODIyLTEzNDI1OSBsaW5lIDE4Nzlcblx0XHQvLyBaZXJvIGlzIG5vdCBhbHdheXMgdGhlIGZpcnN0IGVsZW1lbnQ7XG5cdFx0dmFyIGZpcnN0X2VsID0gMDtcblx0XHRmb3IgKCB2YXIgZmlyc3RfZWwgaW4gZGV0YWlscyApIHtcblx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdGlmICggZGV0YWlscyAmJiBkZXRhaWxzW2ZpcnN0X2VsXSAmJiBkZXRhaWxzW2ZpcnN0X2VsXS5oYXNPd25Qcm9wZXJ0eSggJ2Vycm9yJyApICkge1xuXHRcdFx0dGhpcy5zZXRFcnJvclRpcHNFcnJvciggcmVzdWx0ICk7XG5cdFx0fSBlbHNlIGlmICggZGV0YWlscyAmJiBkZXRhaWxzW2ZpcnN0X2VsXSAmJiBkZXRhaWxzW2ZpcnN0X2VsXS5oYXNPd25Qcm9wZXJ0eSggJ3dhcm5pbmcnICkgKSB7IC8vRXJyb3I6IFR5cGVFcnJvcjogZGV0YWlsc1swXSBpcyB1bmRlZmluZWQgaW4gaHR0cHM6Ly9ncmVlbmFjcmVzLnRpbWV0cmV4LmNvbS9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9OS4wLjAtMjAxNTA4MjItMTA1MTE4IGxpbmUgMTg4M1xuXHRcdFx0aWYgKCBzaG93X3dhcm5pbmcgKSB7XG5cdFx0XHRcdHRoaXMuc2V0RXJyb3JUaXBzV2FybmluZyggcmVzdWx0ICk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLnNldEVkaXRNZW51KCk7XG5cdFx0fSBlbHNlIGlmICggcmVzdWx0LmdldENvZGUoKSA9PSAnUEVSTUlTU0lPTicgfHwgcmVzdWx0LmdldENvZGUoKSA9PSAnVkFMSURBVElPTicgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dFcnJvckFsZXJ0KCByZXN1bHQgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gTWFrZSBzdXJlIGN1cnJlbnQgY29kZXMgd29yay5cblx0XHRcdHRoaXMuc2V0RXJyb3JUaXBzRXJyb3IoIHJlc3VsdCApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVycm9yVGlwc1dhcm5pbmcoIHJlc3VsdCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciB3aWRnZXQ7XG5cdFx0Ly8gd2hlbiBkbyB2YWxpZGF0aW9uLCBvbmx5IHNob3cgd2FybmluZyBubyBhbGVydFxuXHRcdHZhciAkY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9IExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb247IC8vIzI0NzQgLSBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uIGNhbiBjaGFuZ2UgdG8gXCJ2YWxpZGF0ZVwiIHdoaWxlIHdhaXRpbmcgZm9yIHVzZXIgdG8gcmVzcG9uZCB0byB3YXJuaW5nIGJveC5cblx0XHRpZiAoICRjdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uICE9ICd2YWxpZGF0ZScgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dXYXJuaW5nQWxlcnQoIHJlc3VsdCwgZnVuY3Rpb24oIGZsYWcgKSB7XG5cdFx0XHRcdGlmICggZmxhZyApIHtcblx0XHRcdFx0XHRzd2l0Y2ggKCAkY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiApIHtcblx0XHRcdFx0XHRcdGNhc2UgJ3NhdmUnOlxuXHRcdFx0XHRcdFx0XHQkdGhpcy5vblNhdmVDbGljayggdHJ1ZSApO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgJ3NhdmVfYW5kX2NvbnRpbnVlJzpcblx0XHRcdFx0XHRcdFx0JHRoaXMub25TYXZlQW5kQ29udGludWUoIHRydWUgKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlICdzYXZlX2FuZF9uZXh0Jzpcblx0XHRcdFx0XHRcdFx0JHRoaXMub25TYXZlQW5kTmV4dENsaWNrKCB0cnVlICk7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0Y2FzZSAnc2F2ZV9hbmRfY29weSc6XG5cdFx0XHRcdFx0XHRcdCR0aGlzLm9uU2F2ZUFuZENvcHkoIHRydWUgKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRjYXNlICduZXcnOlxuXHRcdFx0XHRcdFx0XHQkdGhpcy5vblNhdmVBbmROZXdDbGljayggdHJ1ZSApO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdGNhc2UgJ2F1dGhvcml6ZSc6IC8vQWxsb3cgdmFsaWRhdGlvbiB3YXJuaW5ncyB0byB3b3JrIHdoZW4gYXV0aG9yaXppbmcgUmVxdWVzdC9UaW1lU2hlZXQvRXhwZW5zZS5cblx0XHRcdFx0XHRcdFx0JHRoaXMub25BdXRob3JpemF0aW9uQ2xpY2soIHRydWUgKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCR0aGlzLnNob3dfd2FybmluZ193aGVuX3ZhbGlkYXRpb24gPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0Ly9FcnJvcjogVW5hYmxlIHRvIGdldCBwcm9wZXJ0eSAnd2FybmluZycgb2YgdW5kZWZpbmVkIG9yIG51bGwgcmVmZXJlbmNlXG5cdFx0dmFyIGVycm9yX2xpc3QgPSBbXTtcblx0XHRpZiAoIHJlc3VsdC5nZXREZXRhaWxzKCkubGVuZ3RoID09IDEgKSB7XG5cdFx0XHRlcnJvcl9saXN0ID0gcmVzdWx0LmdldERldGFpbHMoKVswXS53YXJuaW5nO1xuXHRcdH1cblx0XHR2YXIgZm91bmRfaW5fY3VycmVudF90YWIgPSBmYWxzZTtcblx0XHRmb3IgKCB2YXIga2V5IGluIGVycm9yX2xpc3QgKSB7XG5cdFx0XHRpZiAoICFlcnJvcl9saXN0Lmhhc093blByb3BlcnR5KCBrZXkgKSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV0gKSAmJiB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XS5jbG9zZXN0KCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgKS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHR3aWRnZXQgPSB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XTtcblx0XHRcdH0gZWxzZSBpZiAoIEdsb2JhbC5pc1NldCggdGhpcy5lZGl0X3ZpZXdfdWlfdmFsaWRhdGlvbl9maWVsZF9kaWNba2V5XSApICkge1xuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc0FycmF5KCB0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpY1trZXldICkgKSB7XG5cdFx0XHRcdFx0dmFyIGxlbiA9IHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljW2tleV0ubGVuZ3RoO1xuXHRcdFx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRcdFx0dmFyIGl0ZW0gPSB0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpY1trZXldW2ldO1xuXHRcdFx0XHRcdFx0aWYgKCBpdGVtLmNsb3Nlc3QoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCApLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHRcdHdpZGdldCA9IGl0ZW07XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmICggdGhpcy5lZGl0X3ZpZXdfdWlfdmFsaWRhdGlvbl9maWVsZF9kaWNba2V5XS5jbG9zZXN0KCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgKS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljW2tleV07XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIGtleS5pbmRleE9mKCAnX2lkJyApIDwgMCAmJiBHbG9iYWwuaXNTZXQoIHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXkgKyAnX2lkJ10gKSAmJiB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5ICsgJ19pZCddLmNsb3Nlc3QoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCApLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXkgKyAnX2lkJ107XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGlmICggZXJyb3JfbGlzdFtrZXldICkge1xuXHRcdFx0XHR2YXIgc2hvd19lcnJvciA9IGZhbHNlO1xuXHRcdFx0XHRpZiAoIHdpZGdldC5pcyggJzp2aXNpYmxlJyApICkge1xuXHRcdFx0XHRcdHNob3dfZXJyb3IgPSB0cnVlO1xuXHRcdFx0XHRcdGZvdW5kX2luX2N1cnJlbnRfdGFiID0gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggdHlwZW9mIHdpZGdldC5zZXRFcnJvclN0eWxlID09PSAnZnVuY3Rpb24nICkgeyAvL0ZpeCBKUyBleGNlcHRpb246IFVuY2F1Z2h0IFR5cGVFcnJvcjogd2lkZ2V0LnNldEVycm9yU3R5bGUgaXMgbm90IGEgZnVuY3Rpb25cblx0XHRcdFx0XHR3aWRnZXQuc2V0RXJyb3JTdHlsZSggZXJyb3JfbGlzdFtrZXldLCBzaG93X2Vycm9yLCB0cnVlICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdFx0dGhpcy5zaG93RXJyb3JTdGF0dXNPblRhYiggd2lkZ2V0LCBmYWxzZSApO1xuXHRcdFx0dGhpcy5lZGl0X3ZpZXdfZXJyb3JfdWlfZGljW2tleV0gPSB3aWRnZXQ7XG5cdFx0fVxuXHRcdGlmICggIWZvdW5kX2luX2N1cnJlbnRfdGFiICkge1xuXHRcdFx0dGhpcy5zaG93RWRpdFZpZXdFcnJvciggcmVzdWx0ICk7XG5cdFx0fVxuXHR9XG5cblx0c2hvd0Vycm9yU3RhdHVzT25UYWIoIHdpZGdldCwgaXNFcnJvciApIHtcblx0XHR2YXIgcGFyZW50Q29udGFpbmVyID0gd2lkZ2V0LnBhcmVudCgpO1xuXHRcdHZhciBpID0gMDtcblx0XHR3aGlsZSAoICFwYXJlbnRDb250YWluZXIuaGFzQ2xhc3MoICdlZGl0LXZpZXctdGFiLW91dHNpZGUnICkgJiYgaSA8IDUgKSB7XG5cdFx0XHRpID0gaSArIDE7XG5cdFx0XHRwYXJlbnRDb250YWluZXIgPSBwYXJlbnRDb250YWluZXIucGFyZW50KCk7XG5cdFx0fVxuXHRcdGlmICggcGFyZW50Q29udGFpbmVyLmhhc0NsYXNzKCAnZWRpdC12aWV3LXRhYi1vdXRzaWRlJyApICkge1xuXHRcdFx0dmFyIGlkID0gcGFyZW50Q29udGFpbmVyLmF0dHIoICdpZCcgKTtcblx0XHRcdHZhciB0YWIgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnYVtyZWY9XCInICsgaWQgKyAnXCJdJyApO1xuXHRcdFx0aWYgKCBpc0Vycm9yICkge1xuXHRcdFx0XHR0YWIucGFyZW50KCkuYWRkQ2xhc3MoICdlcnJvci10YWInICk7XG5cdFx0XHRcdHRoaXMuc3RhcnRQdWxzZSggaWQsIHRhYi5wYXJlbnQoKSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGFiLnBhcmVudCgpLmFkZENsYXNzKCAnd2FybmluZy10YWInICk7XG5cdFx0XHRcdHRoaXMuc3RhcnRQdWxzZSggaWQsIHRhYi5wYXJlbnQoKSwgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0c3RhcnRQdWxzZSggdGFiX2lkLCB0YXJnZXQsIGlzX3dhcm5pbmcgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoICF0aGlzLnB1bHNlX3RpbWVfZGljICkge1xuXHRcdFx0dGhpcy5wdWxzZV90aW1lX2RpYyA9IHt9O1xuXHRcdH1cblx0XHRpZiAoIHRoaXMucHVsc2VfdGltZV9kaWNbdGFiX2lkXSApIHtcblx0XHRcdGNsZWFuVGltZXIoIHRhYl9pZCApO1xuXHRcdH1cblx0XHR0aGlzLnB1bHNlX3RpbWVfZGljW3RhYl9pZF0gPSBzZXRJbnRlcnZhbCggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGlzX3dhcm5pbmcgKSB7XG5cdFx0XHRcdGlmICggdGFyZ2V0Lmhhc0NsYXNzKCAnd2FybmluZy10YWItaGlkZScgKSApIHtcblx0XHRcdFx0XHR0YXJnZXQucmVtb3ZlQ2xhc3MoICd3YXJuaW5nLXRhYi1oaWRlJyApO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCB0YXJnZXQuaGFzQ2xhc3MoICd3YXJuaW5nLXRhYicgKSApIHtcblx0XHRcdFx0XHR0YXJnZXQuYWRkQ2xhc3MoICd3YXJuaW5nLXRhYi1oaWRlJyApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNsZWFuVGltZXIoIHRhYl9pZCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIHRhcmdldC5oYXNDbGFzcyggJ2Vycm9yLXRhYi1oaWRlJyApICkge1xuXHRcdFx0XHRcdHRhcmdldC5yZW1vdmVDbGFzcyggJ2Vycm9yLXRhYi1oaWRlJyApO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCB0YXJnZXQuaGFzQ2xhc3MoICdlcnJvci10YWInICkgKSB7XG5cdFx0XHRcdFx0dGFyZ2V0LmFkZENsYXNzKCAnZXJyb3ItdGFiLWhpZGUnICk7XG5cdFx0XHRcdFx0Y2xlYW5UaW1lciggdGFiX2lkICk7XG5cdFx0XHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHRhcmdldC5oYXNDbGFzcyggJ2Vycm9yLXRhYi1oaWRlJyApICkge1xuXHRcdFx0XHRcdFx0XHR0YXJnZXQucmVtb3ZlQ2xhc3MoICdlcnJvci10YWItaGlkZScgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdCR0aGlzLnN0YXJ0UHVsc2UoIHRhYl9pZCwgdGFyZ2V0LCBpc193YXJuaW5nICk7XG5cdFx0XHRcdFx0fSwgMTcwMCApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNsZWFuVGltZXIoIHRhYl9pZCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSwgMjAwMCApO1xuXG5cdFx0ZnVuY3Rpb24gY2xlYW5UaW1lciggdGFiX2lkICkge1xuXHRcdFx0Y2xlYXJJbnRlcnZhbCggJHRoaXMucHVsc2VfdGltZV9kaWNbdGFiX2lkXSApO1xuXHRcdFx0JHRoaXMucHVsc2VfdGltZV9kaWNbdGFiX2lkXSA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0c2V0RXJyb3JUaXBzRXJyb3IoIHJlc3VsdCApIHtcblxuXHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogZGV0YWlsc1swXSBpcyB1bmRlZmluZWQgaW4gaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTkuMC4wLTIwMTUwODIyLTEwNTExOCBsaW5lIDE4ODNcblx0XHQvLyBaZXJvIGlzIG5vdCBhbHdheXMgdGhlIGZpcndzdCBpbmRleC5cblx0XHR2YXIgcmVzdWx0X2FycmF5ID0gcmVzdWx0LmdldERldGFpbHMoKSA/IHJlc3VsdC5nZXREZXRhaWxzKCkgOiB7fTtcblx0XHR2YXIgZmlyc3RfZWwgPSAwO1xuXHRcdGZvciAoIHZhciBmaXJzdF9lbCBpbiByZXN1bHRfYXJyYXkgKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdFx0dmFyIGVycm9yX2xpc3QgPSByZXN1bHRfYXJyYXkgPyByZXN1bHRfYXJyYXlbZmlyc3RfZWxdIDoge307XG5cdFx0dmFyIHdpZGdldDtcblx0XHRpZiAoIGVycm9yX2xpc3QgJiYgZXJyb3JfbGlzdC5oYXNPd25Qcm9wZXJ0eSggJ2Vycm9yJyApICkge1xuXHRcdFx0ZXJyb3JfbGlzdCA9IGVycm9yX2xpc3QuZXJyb3I7XG5cdFx0fVxuXHRcdHZhciBmb3VuZF9pbl9jdXJyZW50X3RhYiA9IGZhbHNlO1xuXHRcdGZvciAoIHZhciBrZXkgaW4gZXJyb3JfbGlzdCApIHtcblx0XHRcdGlmICggIWVycm9yX2xpc3QuaGFzT3duUHJvcGVydHkoIGtleSApICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XSApICYmIHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldLmNsb3Nlc3QoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCApLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldO1xuXHRcdFx0fSBlbHNlIGlmICggR2xvYmFsLmlzU2V0KCB0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpY1trZXldICkgKSB7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzQXJyYXkoIHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljW2tleV0gKSApIHtcblx0XHRcdFx0XHR2YXIgbGVuID0gdGhpcy5lZGl0X3ZpZXdfdWlfdmFsaWRhdGlvbl9maWVsZF9kaWNba2V5XS5sZW5ndGg7XG5cdFx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0XHR2YXIgaXRlbSA9IHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljW2tleV1baV07XG5cdFx0XHRcdFx0XHRpZiAoIGl0ZW0uY2xvc2VzdCggZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0ID0gaXRlbTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2UgaWYgKCB0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpY1trZXldLmNsb3Nlc3QoIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCApLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0d2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfdmFsaWRhdGlvbl9maWVsZF9kaWNba2V5XTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICgga2V5LmluZGV4T2YoICdfaWQnICkgPCAwICYmIEdsb2JhbC5pc1NldCggdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleSArICdfaWQnXSApICYmIHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXkgKyAnX2lkJ10uY2xvc2VzdCggZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0d2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleSArICdfaWQnXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCB3aWRnZXQuaXMoICc6dmlzaWJsZScgKSApIHtcblx0XHRcdFx0Ly8gRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogd2lkZ2V0LnNldEVycm9yU3R5bGUgaXMgbm90IGEgZnVuY3Rpb25cblx0XHRcdFx0aWYgKCB3aWRnZXQuc2V0RXJyb3JTdHlsZSAmJiB0eXBlb2Ygd2lkZ2V0LnNldEVycm9yU3R5bGUgPT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0XHR3aWRnZXQuc2V0RXJyb3JTdHlsZSggZXJyb3JfbGlzdFtrZXldLCB0cnVlICk7XG5cdFx0XHRcdFx0Zm91bmRfaW5fY3VycmVudF90YWIgPSB0cnVlO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdERlYnVnLlRleHQoICdFUlJPUjogd2lkZ2V0LnNldEVycm9yU3R5bGUgaXMgbm90IGEgZnVuY3Rpb24uJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCBudWxsLCAxMCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBFcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiB3aWRnZXQuc2V0RXJyb3JTdHlsZSBpcyBub3QgYSBmdW5jdGlvblxuXHRcdFx0XHRpZiAoIHdpZGdldC5zZXRFcnJvclN0eWxlICYmIHR5cGVvZiB3aWRnZXQuc2V0RXJyb3JTdHlsZSA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0XHRcdHdpZGdldC5zZXRFcnJvclN0eWxlKCBlcnJvcl9saXN0W2tleV0gKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHREZWJ1Zy5UZXh0KCAnRVJST1I6IHdpZGdldC5zZXRFcnJvclN0eWxlIGlzIG5vdCBhIGZ1bmN0aW9uLicsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgbnVsbCwgMTAgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0dGhpcy5zaG93RXJyb3JTdGF0dXNPblRhYiggd2lkZ2V0LCB0cnVlICk7XG5cdFx0XHR0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWNba2V5XSA9IHdpZGdldDtcblx0XHR9XG5cdFx0aWYgKCAhZm91bmRfaW5fY3VycmVudF90YWIgKSB7XG5cdFx0XHR0aGlzLnNob3dFZGl0Vmlld0Vycm9yKCByZXN1bHQgKTtcblx0XHR9XG5cdH1cblxuXHRzaG93RWRpdFZpZXdFcnJvciggcmVzdWx0ICkge1xuXHRcdHZhciBkZXRhaWxzID0gcmVzdWx0LmdldERldGFpbHMoKVswXTtcblx0XHR2YXIgaXNFcnJvciA9IHRydWU7XG5cdFx0Ly9FcnJvcjogVHlwZUVycm9yOiBkZXRhaWxzIGlzIHVuZGVmaW5lZCBpbiBpbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9OS4wLjAtMjAxNTA5MDgtMDgxNDUxIGxpbmUgMjA3OFxuXHRcdGlmICggIWRldGFpbHMgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmICggZGV0YWlscy5oYXNPd25Qcm9wZXJ0eSggJ2Vycm9yJyApICkge1xuXHRcdFx0ZGV0YWlscyA9IGRldGFpbHMuZXJyb3I7XG5cdFx0XHRpc0Vycm9yID0gdHJ1ZTtcblx0XHR9IGVsc2UgaWYgKCBkZXRhaWxzLmhhc093blByb3BlcnR5KCAnd2FybmluZycgKSApIHtcblx0XHRcdGlzRXJyb3IgPSBmYWxzZTtcblx0XHRcdGRldGFpbHMgPSBkZXRhaWxzLndhcm5pbmc7XG5cdFx0fVxuXHRcdHZhciBlcnJvcl9zdHJpbmcgPSAnJztcblx0XHR2YXIgYmFja2dyb3VuZF9jb2xvciA9IGlzRXJyb3IgPyAnI2NiMmUyZScgOiAnI2ZmZmYwMCc7XG5cdFx0dmFyIGNvbG9yID0gaXNFcnJvciA/ICcjZmZmJyA6ICcjMDAwJztcblx0XHR2YXIgYm9yZGVyX2NvbG9yID0gaXNFcnJvciA/ICcjQ0IyRTJFJyA6ICcjZTdiZTAwJztcblxuXHRcdGVycm9yX3N0cmluZyA9IEdsb2JhbC5jb252ZXJ0VmFsaWRhdGlvbkVycm9yVG9TdHJpbmcoIGRldGFpbHMgKTtcblxuXHRcdHRoaXMucmVtb3ZlRWRpdFZpZXdFcnJvclRpcCgpO1xuXHRcdHRoaXMuZWRpdF92aWV3LmZpbmQoJy51aS1oZWxwZXItcmVzZXQnKS5xdGlwKCB7XG5cdFx0XHRzaG93OiB7XG5cdFx0XHRcdHdoZW46IGZhbHNlLFxuXHRcdFx0XHRyZWFkeTogdHJ1ZVxuXHRcdFx0fSxcblx0XHRcdGV2ZW50czoge1xuXHRcdFx0XHRoaWRlOiBmdW5jdGlvbiggZXZlbnQsIGFwaSApIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0Y29udGVudDogZXJyb3Jfc3RyaW5nLFxuXHRcdFx0c3R5bGU6IHtcblx0XHRcdFx0Y2xhc3NlczogaXNFcnJvciA/ICdxdGlwMi1lcnJvci10aXAnIDogJ3F0aXAyLXdhcm5pbmctdGlwJywgLy91c2VkIGZvciBzdHlsaW5nIGFuZCByZW1vdmFsLlxuXHRcdFx0XHR0aXA6IHtcblx0XHRcdFx0XHRjb3JuZXI6ICdib3R0b20gY2VudGVyJ1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0cG9zaXRpb246IHtcblx0XHRcdFx0bXk6ICdib3R0b20gbGVmdCcsXG5cdFx0XHRcdGF0OiAndG9wIGNlbnRlcidcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRvcGVuRWRpdFZpZXcoKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHR0aGlzLmluaXRFZGl0Vmlld1VJKCB0aGlzLnZpZXdJZCwgdGhpcy5lZGl0X3ZpZXdfdHBsICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0VGFiT1Zpc2liaWxpdHkoIGZsYWcgKSB7XG5cdFx0dmFyIHRhYjAgPSAkKCB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJy5lZGl0LXZpZXctdGFiJyApWzBdICk7XG5cdFx0aWYgKCBmbGFnICkge1xuXHRcdFx0dGFiMC5jc3MoICdvcGFjaXR5JywgMSApO1xuXHRcdFx0dGhpcy5zZXRFZGl0Vmlld1RhYlNpemUoKTtcblx0XHRcdGlmICggdGhpcy5lZGl0X3ZpZXdfY2xvc2VfaWNvbiApIHtcblx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfY2xvc2VfaWNvbi5zaG93KCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAndWwgbGknICkuaGlkZSgpO1xuXHRcdFx0dGFiMC5jc3MoICdvcGFjaXR5JywgMCApO1xuXHRcdH1cblx0fVxuXG5cdC8vc2V0IHdpZGdldCBkaXNhYmxlYmlsaXR5IGlmIHZpZXcgbW9kZSBvciBlZGl0IG1vZGVcblx0c2V0RWRpdFZpZXdXaWRnZXRzTW9kZSgpIHtcblx0XHR2YXIgZGlkX2NsZWFuX2RpYyA9IHt9O1xuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5lZGl0X3ZpZXdfdWlfZGljICkge1xuXHRcdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdWlfZGljLmhhc093blByb3BlcnR5KCBrZXkgKSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR2YXIgd2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV07XG5cdFx0XHR3aWRnZXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0XHRcdHZhciBjb2x1bW4gPSB3aWRnZXQucGFyZW50KCkucGFyZW50KCkucGFyZW50KCk7XG5cdFx0XHR2YXIgdGFiX2lkID0gY29sdW1uLnBhcmVudCgpLmF0dHIoICdpZCcgKTtcblx0XHRcdGlmICggIWNvbHVtbi5oYXNDbGFzcyggJ3YtYm94JyApICkge1xuXHRcdFx0XHRpZiAoICFkaWRfY2xlYW5fZGljW3RhYl9pZF0gKSB7XG5cdFx0XHRcdFx0ZGlkX2NsZWFuX2RpY1t0YWJfaWRdID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKCB0aGlzLmlzX3ZpZXdpbmcgKSB7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB3aWRnZXQuc2V0RW5hYmxlZCApICkge1xuXHRcdFx0XHRcdHdpZGdldC5zZXRFbmFibGVkKCBmYWxzZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggd2lkZ2V0LnNldEVuYWJsZWQgKSApIHtcblx0XHRcdFx0XHR3aWRnZXQuc2V0RW5hYmxlZCggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly9DYWxsIHRoaXMgd2hlbiBlZGl0IHZpZXcgb3BlblxuXHRpbml0RWRpdFZpZXdVSSggdmlld19pZCwgZWRpdF92aWV3X2ZpbGVfbmFtZSApIHtcblx0XHRHbG9iYWwuc2V0VUlOb3RyZWFkeSgpO1xuXHRcdFRUUHJvbWlzZS5hZGQoICdpbml0JywgJ2luaXQnICk7XG5cdFx0VFRQcm9taXNlLndhaXQoKTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCB0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHRoaXMuZWRpdF92aWV3LnJlbW92ZSgpO1xuXHRcdH1cblxuXHRcdHRoaXMuZWRpdF92aWV3ID0gJCggR2xvYmFsLmxvYWRWaWV3U291cmNlKCB2aWV3X2lkLCBlZGl0X3ZpZXdfZmlsZV9uYW1lLCBudWxsLCB0cnVlICkgKTtcblxuXHRcdHRoaXMuZWRpdF92aWV3X3RhYiA9ICQoIHRoaXMuZWRpdF92aWV3LmZpbmQoICcuZWRpdC12aWV3LXRhYi1iYXInICkgKTtcblx0XHR0aGlzLmVkaXRfdmlld190YWIuY3NzKCAnb3BhY2l0eScsIDAgKTtcblxuXHRcdC8vR2l2ZSBlZHQgdmlldyB0YWIgYSBpZCwgc28gd2UgY2FuIGxvYWQgaXQgd2hlbiBwdXQgcmlnaHQgY2xpY2sgbWVudSBvbiBpdFxuXHRcdHRoaXMuZWRpdF92aWV3X3RhYi5hdHRyKCAnaWQnLCB0aGlzLnVpX2lkICsgJ19lZGl0X3ZpZXdfdGFiJyApO1xuXG5cdFx0Ly8gTW92ZWQgaW50byBnZW5lcmljIEJhc2VWaWV3LmluaXRFZGl0Vmlld1RhYnNcblx0XHQvLyB0aGlzLnNldFRhYk9WaXNpYmlsaXR5KCBmYWxzZSApO1xuXG5cdFx0Ly8gdGhpcy5lZGl0X3ZpZXdfdGFiID0gdGhpcy5lZGl0X3ZpZXdfdGFiLnRhYnMoIHtcblx0XHQvLyBcdGFjdGl2YXRlOiBmdW5jdGlvbiggZSwgdWkgKSB7XG5cdFx0Ly8gXHRcdGlmICggISR0aGlzLmVkaXRfdmlld190YWIgfHwgISR0aGlzLmVkaXRfdmlld190YWIuaXMoICc6dmlzaWJsZScgKSApIHtcblx0XHQvLyBcdFx0XHRyZXR1cm47XG5cdFx0Ly8gXHRcdH1cblx0XHQvL1xuXHRcdC8vIFx0XHQkdGhpcy5vblRhYlNob3coIGUsIHVpICk7XG5cdFx0Ly8gXHRcdEdsb2JhbC50cmlnZ2VyQW5hbHl0aWNzVGFicyggZSwgdWkgKTtcblx0XHQvLyBcdH1cblx0XHQvLyB9ICk7XG5cblx0XHQvLyB0aGlzLmVkaXRfdmlld190YWIub2ZmKCAnY2xpY2snICkub24oICdjbGljaycsIGZ1bmN0aW9uKCBlICkge1xuXHRcdC8vIFx0JHRoaXMub25UYWJJbmRleENoYW5nZSggZSApO1xuXHRcdC8vIH0gKTtcblxuXHRcdEdsb2JhbC5jb250ZW50Q29udGFpbmVyKCkuYXBwZW5kKCB0aGlzLmVkaXRfdmlldyApO1xuXG5cdFx0Ly8gTW92ZWQgdG8gYnVpbGRFZGl0Vmlld1VJLCBhcyB0aGUgaW5pdCBtaWdodCBvbmx5IGJlIGNhbGxlZCBvbmNlLCBhbmQgdGhlIGNvbnRleHQgbWVudSBuZWVkcyB0byBiZSByZWJ1aWx0IG9uIGV2ZXJ5IHZpZXcgYnVpbGQuXG5cdFx0Ly8gLy8gQWZ0ZXIgd2UgYWRkIHRoZSBlZGl0X3ZpZXcgdG8gdGhlIHBhZ2UsIGFkZCB0aGUgY29udGV4dCBtZW51IChWdWUgbmVlZHMgYSB2YWxpZCBpZCBpbiBkb20pXG5cdFx0Ly8gaWYoIENvbnRleHRNZW51TWFuYWdlci5nZXRNZW51KCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdC8vIFx0dGhpcy5idWlsZENvbnRleHRNZW51KCk7XG5cdFx0Ly8gfVxuXHRcdC8vICNWdWVDb250ZXh0TWVudSNEeW5hbWljLUVkaXRWaWV3IE9uY2UgZWRpdCB2aWV3IGh0bWwgaGFzIGxvYWRlZCBhbmQgbW91bnRlZCB0byBET00sIHRoZW4gaW5zZXJ0IGNvbnRhaW5lciBmb3IgY29udGV4dF9tZW51IGFuZCBpbml0aWFsaXNlIG1lbnUuXG5cblx0XHQvLyBUZXN0aW5nIHRvIHNlZSBpZiBqdXN0IGhhdmluZyB0aGUgY29kZSBpbiBidWlsZENvbnRleHRNZW51IGlzIGVub3VnaC5cblx0XHQvLyBpZiggIXRoaXMuZWRpdF92aWV3X2NvbnRleHRfbWVudSApIHtcblx0XHQvLyBcdHZhciBjb250ZXh0X21lbnVfaWQgPSAnY29udGV4dG1lbnUtJyArIHRoaXMuZWRpdF92aWV3X3RhYi5hdHRyKCAnaWQnICk7XG5cdFx0Ly8gXHR0aGlzLmVkaXRfdmlld19jb250ZXh0X21lbnUgPSBuZXcgQ29udGV4dE1lbnVNYW5hZ2VyKCBjb250ZXh0X21lbnVfaWQgKTsgLy8gI1Z1ZUNvbnRleHRNZW51IyBJbml0aWFsaXplIFZ1ZSBDb250ZXh0TWVudU1hbmFnZXIgaGVyZSBzbyB0aGF0IGVhY2ggdmlldyBoYXMgdGhlaXIgb3duIHVuaXF1ZSBvbmUuIEN1cnJlbnRseSB3ZSBhcmUgc2hhcmluZyBvbmUgY29udGV4dG1lbnUsIGJ1dCBtb3N0IHZpZXdzIHVzZSB0aGVpciBvd24gY29udGV4dCBtZW51IG1hbmFnZXIgaW5zdGFuY2UuIChOb3QgcmVxdWlyZWQsIGp1c3Qgc2ltcGxpZmllcyB0aGUgcmVmYWN0b3IgZm9yIG5vdywgYW5kIGl0IG1pZ2h0IGJlIHVzZWQgaW4gZnV0dXJlKS5cblx0XHQvL1xuXHRcdC8vIFx0Ly8gQ3JlYXRlIGR5bmFtaWMgY29udGFpbmVyIGZvciB0aGUgdnVlIGNvbnRleHQgbWVudVxuXHRcdC8vIFx0Ly8gdGhpcy5lZGl0X3ZpZXdfY29udGV4dF9tZW51LnNldENvbnRleHRNZW51SWQoICdjb250ZXh0bWVudS0nICsgdGhpcy5lZGl0X3ZpZXdfdGFiLmF0dHIoICdpZCcgKSApOyAvLyBUT0RPOiBQb3RlbnRpYWxseSBtb3ZlIHRoaXMgaW50byBwYXJhbSBmb3IgY29uc3RydWN0b3IuXG5cdFx0Ly8gXHR0aGlzLmVkaXRfdmlld190YWIucHJlcGVuZCgnPGRpdiBpZD1cIicrIHRoaXMuZWRpdF92aWV3X2NvbnRleHRfbWVudS5tZW51X2lkICsnXCI+PC9kaXY+Jyk7XG5cdFx0Ly9cblx0XHQvLyBcdC8vIENyZWF0ZSBhbmQgbW91bnQgdW5pcXVlIGNvbnRleHQgbWVudSBmb3IgdGhpcyB2aWV3LlxuXHRcdC8vIFx0dGhpcy5lZGl0X3ZpZXdfY29udGV4dF9tZW51Lm1vdW50Q29udGV4dE1lbnUoICcjJyArIHRoaXMuZWRpdF92aWV3X2NvbnRleHRfbWVudS5tZW51X2lkICk7XG5cdFx0Ly9cblx0XHQvLyB9IGVsc2Uge1xuXHRcdC8vIFx0Ly8gSWYgZWFjaCB2aWV3IGhhcyBhIHVuaXF1ZSBjb250ZXh0IG1lbnUsIHRoZW4gdGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCBhcyBjb250ZXh0IG1lbnUgc2hvdWxkIG9ubHkgYmUgaW5pdGlhdGVkIG9uY2UuXG5cdFx0Ly8gXHQvLyBIb3dldmVyLCB0aGVyZSBhcmUgbWFueSBjYXNlcyB3aGVyZSB0YWJzIHJlcGVhdGVkbHkgY2FsbCB0aGlzLmJ1aWxkQ29udGV4dE1lbnUsIHdoaWxzdCBrZWVwaW5nIHRoZSBzYW1lIHZpZXcgY29udHJvbGxlciwgc28gdGhpcyBpcyBub3cgYSB3YXJuaW5nIHJhdGhlciB0aGFuIGFuIGVycm9yLlxuXHRcdC8vIFx0RGVidWcuVGV4dCggJ0NvbnRleHQgTWVudSBNYW5hZ2VyIGFscmVhZHkgZXhpc3RzIGZvcjogJysgdGhpcy52aWV3SWQsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2J1aWxkQ29udGV4dE1lbnUnLCAxMCApO1xuXHRcdC8vIH1cblxuXHRcdHRoaXMuYnVpbGRFZGl0Vmlld1VJKCk7XG5cblx0XHQkdGhpcy5zZXRFZGl0Vmlld1RhYkhlaWdodCgpO1xuXHRcdFRUUHJvbWlzZS53YWl0KCAnaW5pdCcsICdpbml0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHQkKCAnLmVkaXQtdmlldy10YWItYmFyJyApLmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0fSApO1xuXHR9XG5cblx0c2V0RWRpdFZpZXdUYWJIZWlnaHQoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0fVxuXG5cdC8vQ2FsbCB0aGlzIGFmdGVyIGluaXRFZGl0Vmlld1VJLCB1c3VhbGx5IGFmdGVyIGN1cnJlbnRfZWRpdF9yZWNvcmQgaXMgc2V0XG5cdGluaXRFZGl0VmlldygpIHtcblx0XHR0aGlzLnNob3dfd2FybmluZ193aGVuX3ZhbGlkYXRpb24gPSBmYWxzZTtcblx0XHQvL1VuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2ZpbmQnIG9mIG51bGwgaW4gVGltZWhzZWV0IEF1dGhvcml6YXRpb24gdmlldyB3aGVuIHF1aWNrbHkgY2xpY2sgQ2FuY2VsIGZyb20gcmVwbGF5XG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdGFiICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnNldFVSTCgpO1xuXG5cdFx0Ly8gT3ZlcnJpZGVzIGZvcm0gd2l0aCBkYXRhIGZyb20gcHVzaCBub3RpZmljYXRpb24gYW5kIGh0dHAgZ2V0IHZhcmlhYmxlcy5cblx0XHR0aGlzLmZpbGxDdXJyZW50UmVjb3JkKCk7XG5cblx0XHR0aGlzLnNldEVkaXRNZW51KCk7IC8vVGhpcyBpcyBkb25lIGluIG9uVGFiZVNob3coKSBsYXRlciBvbiwgc28gaXQgY2FuIHByb2JhYmx5IGJlIHJlbW92ZWQgZnJvbSBoZXJlP1xuXHRcdC8vUmVtb3ZlIGNvdmVyIG9uY2UgZWRpdCBtZW51IGlzIHNldFxuXHRcdFByb2dyZXNzQmFyLmNsb3NlT3ZlcmxheSgpO1xuXG5cdFx0Ly9FcnJvcjogVW5hYmxlIHRvIGdldCBwcm9wZXJ0eSAnZmluZCcgb2YgdW5kZWZpbmVkIG9yIG51bGwgcmVmZXJlbmNlIGluIC9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9Ny40LjYtMjAxNDEwMjctMDc0MTI3IGxpbmUgMjA1NVxuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXdfdGFiICkge1xuXHRcdFx0dGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICd1bCBsaScgKS5zaG93KCk7IC8vIEFsbCB0YWJzIGFyZSBoaWRkZW4gd2hlbiBpbml0RWRpdFZpZXcgVUksIHNob3cgYWxsIG9mIHRoZW0gYmVmb3JlIHNldCBzdGF0dXNcblx0XHR9XG5cdFx0dGhpcy5zZXRUYWJTdGF0dXMoKTtcblx0XHR0aGlzLmNsZWFyRWRpdFZpZXdEYXRhKCk7XG5cdFx0dGhpcy5zZXRFZGl0Vmlld1dpZGdldHNNb2RlKCk7XG5cdFx0dGhpcy5zZXRFZGl0Vmlld0RhdGEoKTtcblx0XHR0aGlzLnNldEN1c3RvbUZpZWxkcygpO1xuXHRcdHRoaXMuc2V0Rm9jdXNUb0ZpcnN0SW5wdXQoKTtcblx0fVxuXG5cdHNldEN1c3RvbUZpZWxkcygpIHtcblx0XHR2YXIgcGFyZW50X3RhYmxlID0gdGhpcy5nZXRDdXN0b21GaWVsZFBhcmVudFRhYmxlKCk7XG5cblx0XHRpZiAoIEdsb2JhbC5nZXRGZWF0dXJlRmxhZyggJ2N1c3RvbV9maWVsZCcgKSA9PSBmYWxzZSB8fCBMb2NhbENhY2hlRGF0YS5nZXRDdXN0b21GaWVsZERhdGEoKS5wYXJlbnRfdGFibGVzLmluY2x1ZGVzKCBwYXJlbnRfdGFibGUgKSA9PSBmYWxzZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRUVFByb21pc2Uud2FpdCggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXRDdXN0b21GaWVsZHMnLCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggdGhpcy5jdXN0b21fZmllbGRzICkgKSB7XG5cdFx0XHRcdHRoaXMuY3VzdG9tX2ZpZWxkcy5mb3JFYWNoKCAoIGN1c3RvbV9maWVsZCApID0+IHtcblx0XHRcdFx0XHR0aGlzLmJ1aWxkQ3VzdG9tRmllbGRVSSggdGhpcy5nZXRQcmVmaXhlZEN1c3RvbUZpZWxkSUQoIGN1c3RvbV9maWVsZC5pZCApLCBjdXN0b21fZmllbGQubmFtZSwgY3VzdG9tX2ZpZWxkLnR5cGVfaWQsIGN1c3RvbV9maWVsZC5tZXRhX2RhdGEgKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHRoaXMuZWRpdEZpZWxkUmVzaXplKCAwICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMucmVzZXRMYXN0V2lkZ2V0U3R5bGUoKTtcblx0XHR9LmJpbmQoIHRoaXMgKSApO1xuXHR9XG5cblx0Z2V0UHJlZml4ZWRDdXN0b21GaWVsZElEKCBpZCApIHtcblx0XHRyZXR1cm4gJ2N1c3RvbV9maWVsZC0nICsgaWQ7XG5cdH1cblxuXHRnZXRDdXN0b21GaWVsZHNGb3JWaWV3KCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dmFyIHBhcmVudF90YWJsZSA9IHRoaXMuZ2V0Q3VzdG9tRmllbGRQYXJlbnRUYWJsZSgpO1xuXG5cdFx0aWYgKCBHbG9iYWwuZ2V0RmVhdHVyZUZsYWcoICdjdXN0b21fZmllbGQnICkgPT0gZmFsc2UgfHwgTG9jYWxDYWNoZURhdGEuZ2V0Q3VzdG9tRmllbGREYXRhKCkucGFyZW50X3RhYmxlcy5pbmNsdWRlcyggcGFyZW50X3RhYmxlICkgPT0gZmFsc2UgKSB7XG5cdFx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXRDdXN0b21GaWVsZHMnICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGZpbHRlciA9IHsgZmlsdGVyX2RhdGE6IHsgcGFyZW50X3RhYmxlOiBwYXJlbnRfdGFibGUsIHN0YXR1c19pZDogMTAgfSwgZmlsdGVyX3NvcnQ6IHsgZGlzcGxheV9vcmRlcjogJ2FzYycsIGNyZWF0ZWRfZGF0ZTogJ2FzYycsIGlkOiAnYXNjJyB9IH07XG5cblx0XHR0aGlzLmN1c3RvbV9maWVsZF9hcGkuZ2V0Q3VzdG9tRmllbGQoIGZpbHRlciwgdHJ1ZSwge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cdFx0XHRcdHZhciByZXNfZGF0YSA9IHJlc3VsdC5nZXRSZXN1bHQoKTtcblx0XHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCByZXNfZGF0YSApICkge1xuXHRcdFx0XHRcdCR0aGlzLmN1c3RvbV9maWVsZHMgPSByZXNfZGF0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdFRUUHJvbWlzZS5yZXNvbHZlKCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ2dldEN1c3RvbUZpZWxkcycgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRnZXRDdXN0b21GaWVsZFJlZmVyZW5jZUZpZWxkKCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGJ1aWxkQ3VzdG9tRmllbGRVSSggZmllbGQsIGxhYmVsLCB0eXBlX2lkLCBtZXRhX2RhdGEgKSB7XG5cblx0XHRpZiAoICF0eXBlX2lkICkge1xuXHRcdFx0cmV0dXJuOyAvL1VzZXIgZG9lcyBub3QgaGF2ZSBwZXJtaXNzaW9ucyB0byB1c2UgY3VzdG9tIGZpZWxkc1xuXHRcdH1cblxuXHRcdGZpZWxkID0gdGhpcy5jb252ZXJ0Q3VzdG9tRmllbGRGaWVsZElkKCB0eXBlX2lkLCBmaWVsZCApO1xuXG5cdFx0aWYgKCB0aGlzLmdldEN1c3RvbUZpZWxkUGFyZW50VGFibGUoKSA9PT0gJ3B1bmNoX2NvbnRyb2wnICkge1xuXHRcdFx0Ly9QZXJtaXNzaW9ucyBjYW4gYmUgZHluYW1pYyBmb3IgcHVuY2ggY29udHJvbCBjdXN0b20gZmllbGRzIGFuZCB3ZSBuZWVkIHRvIGNoZWNrIGZvciB0aGVtLlxuXHRcdFx0Ly9QZXJtaXNzaW9ucyBhcmUgZm9yIHRoZSBub24tJ19pZCcgY3VzdG9tIGZpZWxkcy5cblx0XHRcdGxldCBjdXN0b21fZmllbGRfaWQgPSBmaWVsZC5yZXBsYWNlKCAnX2lkJywgJycgKTtcblx0XHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHRoaXMucGVybWlzc2lvbl9pZCwgJ2VkaXRfJyArIGN1c3RvbV9maWVsZF9pZCApID09IGZhbHNlICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdGFiICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgdGFiMCA9ICQoIHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnLmVkaXQtdmlldy10YWItb3V0c2lkZScgKVswXSApO1xuXHRcdHZhciB0YWIwX2NvbHVtbjEgPSB0YWIwLmZpbmQoICcuZmlyc3QtY29sdW1uJyApO1xuXG5cdFx0aWYgKCAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2ZpZWxkXSApIHtcblx0XHRcdGZvcm1faXRlbV9pbnB1dCA9ICR0aGlzLmVkaXRfdmlld191aV9kaWNbZmllbGRdO1xuXHRcdFx0Zm9ybV9pdGVtX2lucHV0LnNldFZhbHVlKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2ZpZWxkXSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgZm9ybV9hcnJheSA9ICR0aGlzLmdldEN1c3RvbUZpZWxkRm9ybUlucHV0QnlUeXBlKCB0eXBlX2lkLCBmaWVsZCwgbWV0YV9kYXRhICk7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBmb3JtX2FycmF5WzBdO1xuXHRcdFx0bGV0IHdpZGdldF9jb250YWluZXIgPSBmb3JtX2FycmF5WzFdO1xuXG5cdFx0XHR2YXIgaW5wdXRfZGl2ID0gJHRoaXMuYWRkRWRpdEZpZWxkVG9Db2x1bW4oIGxhYmVsLCBmb3JtX2l0ZW1faW5wdXQsIHRhYjBfY29sdW1uMSwgJycsIHdpZGdldF9jb250YWluZXIgKTtcblx0XHRcdGlmICggdGhpcy5nZXRDdXN0b21GaWVsZFJlZmVyZW5jZUZpZWxkKCkgIT09IGZhbHNlICYmICR0aGlzLmVkaXRfdmlld191aV9kaWNbdGhpcy5nZXRDdXN0b21GaWVsZFJlZmVyZW5jZUZpZWxkKCldICE9IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0aW5wdXRfZGl2Lmluc2VydEJlZm9yZSggJHRoaXMuZWRpdF92aWV3X3VpX2RpY1t0aGlzLmdldEN1c3RvbUZpZWxkUmVmZXJlbmNlRmllbGQoKV0ucGFyZW50KCkucGFyZW50KCkgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKSB7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2ZpZWxkXSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRmb3JtX2l0ZW1faW5wdXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblxuXHRcdGlmICggJHRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdGZvcm1faXRlbV9pbnB1dC5zZXRFbmFibGVkKCBmYWxzZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0RW5hYmxlZCggdHJ1ZSApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0TWFzc0VkaXRNb2RlKCB0cnVlICk7XG5cdFx0fVxuXHR9XG5cblx0Y29udmVydEN1c3RvbUZpZWxkRmllbGRJZCggdHlwZV9pZCwgZmllbGQgKSB7XG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5nZXRDdXN0b21GaWVsZERhdGEoKS5jb252ZXJzaW9uX2ZpZWxkX3R5cGVzW3R5cGVfaWRdICkge1xuXHRcdFx0cmV0dXJuIGZpZWxkICsgJ19pZCc7XG5cdFx0fVxuXHRcdHJldHVybiBmaWVsZDtcblx0fVxuXG5cdGdldEN1c3RvbUZpZWxkRm9ybUlucHV0QnlUeXBlKCB0eXBlX2lkLCBmaWVsZCwgbWV0YV9kYXRhICkge1xuXHRcdGxldCBmb3JtX2l0ZW1faW5wdXQ7XG5cdFx0bGV0IHdpZGdldF9jb250YWluZXIgPSBudWxsO1xuXG5cdFx0dHlwZV9pZCA9IHBhcnNlSW50KCB0eXBlX2lkICk7IC8vU3dpdGNoIGlzIHN0cmljdCBvbiB0eXBlLCBzbyB3ZSBuZWVkIHRvIHBhcnNlSW50KClcblxuXHRcdHN3aXRjaCAoIHR5cGVfaWQgKSB7XG5cdFx0XHRjYXNlIDEwMDogLy9UZXh0XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVCApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHRJbnB1dCggeyBmaWVsZDogZmllbGQgfSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuY3NzKCAnbWluV2lkdGgnLCAzMDAgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIDExMDogLy9UZXh0YXJlYVxuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfQVJFQSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuVFRleHRBcmVhKCB7IGZpZWxkOiBmaWVsZCwgd2lkdGg6ICcxMDAlJyB9ICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA0MDA6IC8vSW50ZWdlclxuXHRcdFx0Y2FzZSA0MTA6IC8vRGVjaW1hbFxuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LlRUZXh0SW5wdXQoIHsgZmllbGQ6IGZpZWxkIH0gKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LmNzcyggJ21pbldpZHRoJywgMzAwICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA0MjA6IC8vQ3VycmVuY3lcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dElucHV0KCB7IGZpZWxkOiBmaWVsZCB9ICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5jc3MoICdtaW5XaWR0aCcsIDMwMCApO1xuXG5cdFx0XHRcdHZhciB3aWRnZXRDb250YWluZXIgPSAkKCAnPGRpdiBjbGFzcz1cXCd3aWRnZXQtaC1ib3hcXCc+PC9kaXY+JyApO1xuXHRcdFx0XHRsZXQgY3VycmVuY3kgPSAkKCAnPHNwYW4gY2xhc3M9XFwnd2lkZ2V0LWxlZnQtbGFiZWxcXCc+PC9zcGFuPicgKTtcblx0XHRcdFx0bGV0IGNvZGUgPSAkKCAnPHNwYW4gY2xhc3M9XFwnd2lkZ2V0LXJpZ2h0LWxhYmVsXFwnPjwvc3Bhbj4nICk7XG5cblx0XHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggY3VycmVuY3kgKTtcblx0XHRcdFx0d2lkZ2V0Q29udGFpbmVyLmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cdFx0XHRcdHdpZGdldENvbnRhaW5lci5hcHBlbmQoIGNvZGUgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIDUwMDogLy9DaGVja2JveFxuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkNIRUNLQk9YICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5UQ2hlY2tib3goIHsgZmllbGQ6IGZpZWxkIH0gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIDEwMDA6IC8vRGF0ZVxuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkRBVEVfUElDS0VSICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5URGF0ZVBpY2tlciggeyBmaWVsZDogZmllbGQgfSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgMTAxMDogLy9EYXRlIFJhbmdlXG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuREFURV9QSUNLRVIgKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LlRSYW5nZVBpY2tlciggeyBmaWVsZDogZmllbGQsIHZhbGlkYXRpb25fZmllbGQ6ICdkYXRlX3N0YW1wJyB9ICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAxMTAwOiAvL1RpbWVcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5USU1FX1BJQ0tFUiApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuVFRpbWVQaWNrZXIoIHsgZmllbGQ6IGZpZWxkIH0gKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIDExMTA6IC8vVGltZSBSYW5nZVxuXHRcdFx0XHQvL1RPRE86IEplcmVteSBUaW1lIFJhbmdlXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAxMjAwOiAvL0RhdGV0aW1lXG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuREFURV9QSUNLRVIgKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LlREYXRlUGlja2VyKCB7IGZpZWxkOiBmaWVsZCwgbW9kZTogJ2RhdGVfdGltZScgfSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgMTMwMDogLy9UaW1lIFVuaXRcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5UVGV4dElucHV0KCB7IGZpZWxkOiBmaWVsZCwgd2lkdGg6IDEyMCwgbW9kZTogJ3RpbWVfdW5pdCcsIG5lZWRfcGFyc2VyX3NlYzogdHJ1ZSB9ICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAyMTAwOiAvL1NpbmdsZS1zZWxlY3QgRHJvcGRvd25cblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5BV0VTT01FX0JPWCApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuQUNvbWJvQm94KCB7XG5cdFx0XHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiBmYWxzZSxcblx0XHRcdFx0XHRsYXlvdXRfbmFtZTogJ2dsb2JhbF9vcHRpb25fY29sdW1uJywgLy9OZWVkIGR5bmFtaWMgbGF5b3V0IG5hbWU/IGdsb2JhbF9vcHRpb25fY29sdW1uXG5cdFx0XHRcdFx0c2hvd19zZWFyY2hfaW5wdXRzOiB0cnVlLFxuXHRcdFx0XHRcdHNldF9lbXB0eTogdHJ1ZSxcblx0XHRcdFx0XHRmaWVsZDogZmllbGRcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQuc2V0U291cmNlRGF0YSggbWV0YV9kYXRhLnZhbGlkYXRpb24ubXVsdGlfc2VsZWN0X2l0ZW1zICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAyMTEwOiAvL011bHRpLXNlbGVjdCBEcm9wZG93blxuXHRcdFx0XHRmb3JtX2l0ZW1faW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YICk7XG5cdFx0XHRcdGZvcm1faXRlbV9pbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdFx0XHRhbGxvd19tdWx0aXBsZV9zZWxlY3Rpb246IHRydWUsXG5cdFx0XHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfb3B0aW9uX2NvbHVtbicsIC8vTmVlZCBkeW5hbWljIGxheW91dCBuYW1lPyBnbG9iYWxfb3B0aW9uX2NvbHVtblxuXHRcdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogdHJ1ZSxcblx0XHRcdFx0XHRzZXRfZW1wdHk6IHRydWUsXG5cdFx0XHRcdFx0ZmllbGQ6IGZpZWxkXG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0Zm9ybV9pdGVtX2lucHV0LnNldFNvdXJjZURhdGEoIG1ldGFfZGF0YS52YWxpZGF0aW9uLm11bHRpX3NlbGVjdF9pdGVtcyApO1xuXHRcdH1cblxuXHRcdHJldHVybiBbZm9ybV9pdGVtX2lucHV0LCB3aWRnZXRfY29udGFpbmVyXTtcblx0fVxuXG5cdHJlc2V0TGFzdFdpZGdldFN0eWxlKCkge1xuXG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdGFiIHx8ICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdH1cblxuXHRnZXRDdXN0b21GaWVsZFBhcmVudFRhYmxlKCkge1xuXHRcdC8vUHVuY2ggdmlld3MgZ2V0IHRoZWlyIGN1c3RvbSBmaWVsZHMgZnJvbSB0aGUgcHVuY2hfY29udHJvbCB0YWJsZS5cblx0XHRpZiAoIHRoaXMudGFibGVfbmFtZV9rZXkgPT09ICdwdW5jaCcgKSB7XG5cdFx0XHRyZXR1cm4gJ3B1bmNoX2NvbnRyb2wnO1xuXHRcdH0gZWxzZSBpZiAoIHRoaXMudmlld0lkID09PSAnVGltZVNoZWV0JyApIHsgLy9UaW1lc2hlZXQgdmlldyBkb2VzIG5vdCBkZWNsYXJlIGEgdGFibGVfbmFtZV9rZXlcblx0XHRcdHJldHVybiAncHVuY2hfY29udHJvbCc7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMudGFibGVfbmFtZV9rZXk7XG5cdH1cblxuXHRzZXRVUkwoKSB7XG5cdFx0dmFyIGEgPSAnJztcblx0XHRzd2l0Y2ggKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uICkge1xuXHRcdFx0Y2FzZSAnbmV3Jzpcblx0XHRcdGNhc2UgJ2VkaXQnOlxuXHRcdFx0Y2FzZSAndmlldyc6XG5cdFx0XHRcdGEgPSBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2NvcHlfYXNfbmV3Jzpcblx0XHRcdFx0YSA9ICduZXcnO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdFx0aWYgKCB0aGlzLmNhblNldFVSTCgpICkge1xuXG5cdFx0XHR2YXIgdGFiX25hbWUgPSB0aGlzLmVkaXRfdmlld190YWIgPyB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJy5lZGl0LXZpZXctdGFiLWJhci1sYWJlbCcgKS5jaGlsZHJlbigpLmVxKCB0aGlzLmdldEVkaXRWaWV3VGFiSW5kZXgoKSApLnRleHQoKSA6ICcnO1xuXHRcdFx0dGFiX25hbWUgPSB0YWJfbmFtZS5yZXBsYWNlKCAvXFwvfFxccysvZywgJycgKTtcblxuXHRcdFx0Ly9FcnJvcjogVW5hYmxlIHRvIGdldCBwcm9wZXJ0eSAnaWQnIG9mIHVuZGVmaW5lZCBvciBudWxsIHJlZmVyZW5jZSBpbiAvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTguMC4wLTIwMTQxMTE3LTEzMjk0MSBsaW5lIDIyMzRcblx0XHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdFx0aWYgKCBhICkge1xuXHRcdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmYT0nICsgYSArICcmaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCArICcmdGFiPScgKyB0YWJfbmFtZSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmaWQ9JyArIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0R2xvYmFsLnRyYWNrVmlldyggdGhpcy52aWV3SWQsIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICggYSApIHtcblxuXHRcdFx0XHRcdC8vRWRpdCBhIHJlY29yZCB3aGljaCBkb24ndCBoYXZlIGlkLCBzY2hlZHVsZSB2aWV3IFJlY3VycmluZyBTY2VkdWxlXG5cdFx0XHRcdFx0aWYgKCBhID09PSAnZWRpdCcgKSB7XG5cdFx0XHRcdFx0XHRHbG9iYWwuc2V0VVJMVG9Ccm93c2VyKCBHbG9iYWwuZ2V0QmFzZVVSTCgpICsgJyMhbT0nICsgdGhpcy52aWV3SWQgKyAnJmE9JyArICduZXcnICtcblx0XHRcdFx0XHRcdFx0JyZ0YWI9JyArIHRhYl9uYW1lICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCArICcmYT0nICsgYSArXG5cdFx0XHRcdFx0XHRcdCcmdGFiPScgKyB0YWJfbmFtZSApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyAnIyFtPScgKyB0aGlzLnZpZXdJZCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRjYW5TZXRVUkwoKSB7XG5cdFx0aWYgKCB0aGlzLnN1Yl92aWV3X21vZGUgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHNldEZvY3VzVG9GaXJzdElucHV0KCkge1xuXHRcdC8vRG8gbm90IHNldCBmb2N1cyB0byBmaXJzdCBpbnB1dCBpbiB1bml0IHRlc3QgbW9kZSBhcyBpdCBjYXVzZXMgYSBibGluayB0aGF0IGlzIGluY29uc2lzdGVudCBpbiBzY3JlZW5zaG90cy4gQWxzbyBkaXNhYmxlIG9uIG1vYmlsZSBtb2RlIHNvIGl0cyBub3QgYSBqYXJyaW5nIGV4cGVyaWVuY2Ugd2l0aCB0aGUgem9vbSBjaGFuZ2VzIG9uIGVhY2ggcGFnZVxuXHRcdGlmICggR2xvYmFsLlVOSVRfVEVTVF9NT0RFIHx8ICQoICdib2R5JyApLmhhc0NsYXNzKCAnbW9iaWxlLWRldmljZS1tb2RlJyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdGlmICggdGhpcy5zY3JpcHRfbmFtZSA9PT0gJ1NjaGVkdWxlVmlldycgKSB7XG5cdFx0XHRcdGlmICggdGhpcy5lZGl0X3ZpZXdfdWlfZGljLnN0YXJ0X3RpbWUgKSB7XG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljLnN0YXJ0X3RpbWUuY2hpbGRyZW4oKS5lcSggMCApLmZvY3VzKCk7XG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdWlfZGljLnN0YXJ0X3RpbWUuY2hpbGRyZW4oKS5lcSggMCApWzBdLnNlbGVjdCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZWRpdF92aWV3X3VpX2RpYyApIHtcblxuXHRcdFx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dmFyIHdpZGdldCA9IHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldO1xuXG5cdFx0XHRcdFx0aWYgKCB3aWRnZXQuaXMoICc6dmlzaWJsZScgKSA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdGlmICggd2lkZ2V0Lmhhc0NsYXNzKCAndC10ZXh0LWlucHV0JyApICYmICF3aWRnZXQuYXR0ciggJ3JlYWRvbmx5JyApICkge1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuZm9jdXMoKTtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0WzBdLnNlbGVjdCgpO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHdpZGdldC5oYXNDbGFzcyggJ3QtdGltZS1waWNrZXItZGl2JyApICYmICF3aWRnZXQuY2hpbGRyZW4oKS5lcSggMCApLmF0dHIoICdyZWFkb25seScgKSApIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LmNoaWxkcmVuKCkuZXEoIDAgKS5mb2N1cygpO1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuY2hpbGRyZW4oKS5lcSggMCApWzBdLnNlbGVjdCgpO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHdpZGdldC5oYXNDbGFzcyggJ3QtZGF0ZS1waWNrZXItZGl2JyApICYmICF3aWRnZXQuY2hpbGRyZW4oKS5lcSggMCApLmF0dHIoICdyZWFkb25seScgKSApIHtcblx0XHRcdFx0XHRcdFx0d2lkZ2V0LmNoaWxkcmVuKCkuZXEoIDAgKS5mb2N1cygpO1xuXHRcdFx0XHRcdFx0XHR3aWRnZXQuY2hpbGRyZW4oKS5lcSggMCApWzBdLnNlbGVjdCgpO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRpbml0TmF2aWdhdGlvbldpZGdldCggbmF2aWdhdGlvbl93aWRnZXRfZGl2ICkge1xuXHRcdGlmICggIXRoaXMubmF2aWdhdGlvbiApIHtcblx0XHRcdHRoaXMubmF2aWdhdGlvbiA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblx0XHRcdG5hdmlnYXRpb25fd2lkZ2V0X2Rpdi5hcHBlbmQoIHRoaXMubmF2aWdhdGlvbiApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRuYXZpZ2F0aW9uX3dpZGdldF9kaXYuYXBwZW5kKCB0aGlzLm5hdmlnYXRpb24gKTtcblx0XHR9XG5cdFx0dGhpcy5zZXROYXZpZ2F0aW9uQXJyb3dzU3RhdHVzKCk7XG5cdH1cblxuXHRidWlsZEVkaXRWaWV3VUkoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdC8vTm8gbmF2aWdhdGlvbiB3aGVuIGVkaXQgb25seSBtb2RlXG5cblx0XHQvLyAjVnVlQ29udGV4dE1lbnUjIEFmdGVyIHdlIGFkZCB0aGUgZWRpdF92aWV3IHRvIHRoZSBwYWdlIGluIGluaXRFZGl0Vmlld1VJKCksIGFkZCB0aGUgY29udGV4dCBtZW51IChWdWUgbmVlZHMgYSB2YWxpZCBpZCBpbiBkb20pXG5cdFx0aWYoIENvbnRleHRNZW51TWFuYWdlci5nZXRNZW51KCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dGhpcy5idWlsZENvbnRleHRNZW51KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdERlYnVnLldhcm4oICdDb250ZXh0IE1lbnUgKCcrIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCArJykgYWxyZWFkeSBleGlzdHMgZm9yOiAnKyB0aGlzLnZpZXdJZCwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnYnVpbGRFZGl0Vmlld1VJJywgMTAgKTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0aWYgKCAhdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdFx0dmFyIG5hdmlnYXRpb25fZGl2ID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5uYXZpZ2F0aW9uLWRpdicgKTtcblx0XHRcdFx0dmFyIGxhYmVsID0gbmF2aWdhdGlvbl9kaXYuZmluZCggJy5uYXZpZ2F0aW9uLWxhYmVsJyApO1xuXHRcdFx0XHR2YXIgbGVmdF9jbGljayA9IG5hdmlnYXRpb25fZGl2LmZpbmQoICcubGVmdC1jbGljaycgKTtcblx0XHRcdFx0dmFyIHJpZ2h0X2NsaWNrID0gbmF2aWdhdGlvbl9kaXYuZmluZCggJy5yaWdodC1jbGljaycgKTtcblx0XHRcdFx0dmFyIG5hdmlnYXRpb25fd2lkZ2V0X2RpdiA9IG5hdmlnYXRpb25fZGl2LmZpbmQoICcubmF2aWdhdGlvbi13aWRnZXQtZGl2JyApO1xuXHRcdFx0XHR0aGlzLmluaXROYXZpZ2F0aW9uV2lkZ2V0KCBuYXZpZ2F0aW9uX3dpZGdldF9kaXYgKTtcblx0XHRcdFx0bGVmdF9jbGljay5hdHRyKCAnc3JjJywgR2xvYmFsLmdldFJlYWxJbWFnZVBhdGgoICdpbWFnZXMvbGVmdF9hcnJvdy5zdmcnICkgKTtcblx0XHRcdFx0cmlnaHRfY2xpY2suYXR0ciggJ3NyYycsIEdsb2JhbC5nZXRSZWFsSW1hZ2VQYXRoKCAnaW1hZ2VzL3JpZ2h0X2Fycm93LnN2ZycgKSApO1xuXHRcdFx0XHRsYWJlbC50ZXh0KCB0aGlzLm5hdmlnYXRpb25fbGFiZWwgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmVkaXRfdmlld19jbG9zZV9pY29uID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5jbG9zZS1pY29uJyApO1xuXHRcdFx0dGhpcy5lZGl0X3ZpZXdfY2xvc2VfaWNvbi5oaWRlKCk7XG5cblx0XHRcdHRoaXMuZWRpdF92aWV3X2Nsb3NlX2ljb24uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5vbkNsb3NlSWNvbkNsaWNrKCk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYoIHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cblx0XHR9XG5cblx0XHR0aGlzLmVkaXRfdmlld191aV9kaWMgPSB7fTtcblx0XHR0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpYyA9IHt9O1xuXHRcdHRoaXMuZWRpdF92aWV3X2Zvcm1faXRlbV9kaWMgPSB7fTtcblx0XHR0aGlzLmVkaXRfdmlld19lcnJvcl91aV9kaWMgPSB7fTtcblx0fVxuXG5cdG9uQ2xvc2VJY29uQ2xpY2soKSB7XG5cdFx0dGhpcy5vbkNhbmNlbENsaWNrKCk7XG5cdFx0R2xvYmFsLnRyaWdnZXJBbmFseXRpY3NOYXZpZ2F0aW9uT3RoZXIoICdjbG9zZS1YJywgJ2NsaWNrJywgdGhpcy52aWV3SWQgKTtcblx0fVxuXG5cdHNldFdpZGdldFZpc2libGUoIHdpZGdldHMgKSB7XG5cdFx0dmFyIHdpZGdldCA9IHdpZGdldHM7XG5cdFx0aWYgKCBHbG9iYWwuaXNBcnJheSggd2lkZ2V0cyApICkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgd2lkZ2V0cy5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0d2lkZ2V0ID0gd2lkZ2V0c1tpXTtcblx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAxICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdpZGdldC5jc3MoICdvcGFjaXR5JywgMSApO1xuXHRcdH1cblx0fVxuXG5cdC8vd2lkZ2V0Q29udGFpbmVyOiBhZGQgd2lkZ2V0IHRvIGN1c3RvbSBjb250YWluZXJcblx0Ly9zYXZlRm9ybUl0ZW1EaXY6IGlmIGNhY2hlIGN1cnJlbnQgZm9ybUl0ZW1EaXYgYW5kIHVzZSBpdCBsYXRlclxuXHRhZGRFZGl0RmllbGRUb0NvbHVtbiggbGFiZWwsIHdpZGdldHMsIGNvbHVtbiwgZmlyc3RPckxhc3RSZWNvcmQsIHdpZGdldENvbnRhaW5lciwgc2F2ZUZvcm1JdGVtRGl2LCBzZXRSZXNpemVFdmVudCwgc2F2ZUZvcm1JdGVtRGl2S2V5LCBoYXNLZXlFdmVudCwgY3VzdG9tTGFiZWxXaWRnZXQgKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBmb3JtX2l0ZW0gPSAkKCBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggV2lkZ2V0TmFtZXNEaWMuRURJVF9WSUVXX0ZPUk1fSVRFTSApICk7XG5cdFx0dmFyIGZvcm1faXRlbV9sYWJlbF9kaXYgPSBmb3JtX2l0ZW0uZmluZCggJy5lZGl0LXZpZXctZm9ybS1pdGVtLWxhYmVsLWRpdicgKTtcblx0XHR2YXIgZm9ybV9pdGVtX2xhYmVsID0gZm9ybV9pdGVtLmZpbmQoICcuZWRpdC12aWV3LWZvcm0taXRlbS1sYWJlbCcgKTtcblx0XHR2YXIgZm9ybV9pdGVtX2lucHV0X2RpdiA9IGZvcm1faXRlbS5maW5kKCAnLmVkaXQtdmlldy1mb3JtLWl0ZW0taW5wdXQtZGl2JyApO1xuXHRcdHZhciB3aWRnZXQgPSB3aWRnZXRzO1xuXG5cdFx0aWYgKCBHbG9iYWwuaXNBcnJheSggd2lkZ2V0cyApICkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgd2lkZ2V0cy5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0d2lkZ2V0ID0gd2lkZ2V0c1tpXTtcblx0XHRcdFx0d2lkZ2V0LmNzcyggJ29wYWNpdHknLCAwICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdpZGdldC5jc3MoICdvcGFjaXR5JywgMCApO1xuXHRcdH1cblxuXHRcdGlmICggY3VzdG9tTGFiZWxXaWRnZXQgKSB7XG5cdFx0XHRmb3JtX2l0ZW1fbGFiZWwucGFyZW50KCkuYXBwZW5kKCBjdXN0b21MYWJlbFdpZGdldCApO1xuXHRcdFx0Zm9ybV9pdGVtX2xhYmVsLnJlbW92ZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3JtX2l0ZW1fbGFiZWwudGV4dCggbGFiZWwgKTsgLy8gUmVtb3ZlICc6JyB0byBtYXRjaCBGaWdtYSBkZXNpZ24uXG5cdFx0XHRpZiAoIGxhYmVsICYmIGxhYmVsLmluZGV4T2YoICdcXG4nICkgIT09IC0xICkge1xuXHRcdFx0XHRmb3JtX2l0ZW1fbGFiZWwuaHRtbCggZm9ybV9pdGVtX2xhYmVsLmh0bWwoKS5yZXBsYWNlKCAvXFxuL2csICc8YnI+JyApICk7IC8vQWxsb3cgbmV3bGluZXMgKFxcbikgdG8gYmUgYWNjZXB0ZWQgaW4gbGFiZWxzLiBVc2VkIGJ5IFQ0IFJlcG9ydC4gVXNlIHRoaXMgaW5zdGVhZCBvZiAuaHRtbCgpIGRpcmVjdGx5IGFzIGl0cyBpbnRyb2R1Y2VzIFhTU1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCB3aWRnZXRDb250YWluZXIgKSApIHtcblxuXHRcdFx0Zm9ybV9pdGVtX2lucHV0X2Rpdi5hcHBlbmQoIHdpZGdldENvbnRhaW5lciApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvcm1faXRlbV9pbnB1dF9kaXYuYXBwZW5kKCB3aWRnZXQgKTtcblx0XHR9XG5cblx0XHRjb2x1bW4uYXBwZW5kKCBmb3JtX2l0ZW0gKTtcblxuXHRcdC8vc2V0IGhlaWdodCB0byB0ZXh0IGFyZWFcblx0XHRpZiAoIGZvcm1faXRlbS5oZWlnaHQoKSA+IDM1ICkge1xuXHRcdFx0Zm9ybV9pdGVtX2xhYmVsX2Rpdi5jc3MoICdoZWlnaHQnLCBmb3JtX2l0ZW0uaGVpZ2h0KCkgKTtcblx0XHR9IGVsc2UgaWYgKCB3aWRnZXQuaGFzQ2xhc3MoICdhLWRyb3Bkb3duJyApICkge1xuXHRcdFx0Zm9ybV9pdGVtX2xhYmVsX2Rpdi5jc3MoICdoZWlnaHQnLCAyNDAgKTtcblx0XHR9XG5cblx0XHQvL3RoZXNlIGFyZW4ndCBoaXQgdW5pZm9ybWx5IGZvciBldmVyeSBmaWVsZCBzbyB0aGUgdmVydGljYWwgcmVzaXplIGV2ZW50cyB3aWxsIGJlIGRpc2FibGVkIGluIHVuaXQgdGVzdCBtb2RlLlxuXHRcdGlmICggc2V0UmVzaXplRXZlbnQgJiYgIUdsb2JhbC5VTklUX1RFU1RfTU9ERSApIHtcblx0XHRcdGZvcm1faXRlbS51bmJpbmQoICdyZXNpemUnICkuYmluZCggJ3Jlc2l6ZScsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQvL1doZW4gc3dpdGNoaW5nIHRhYnMsIHRoZSBoZWlnaHRzIGFyZSBhbGwgLTEsIHdoaWNoIGNhdXNlcyBcImZsYXNoaW5nXCIgd2hlbiB0aGUgdXNlciByZXR1cm5zIGJhY2sgdG8gdGhlIG9yaWdpbmFsIHRhYiBhbmQgYWxsIHRoZSBoZWlnaHRzIG5lZWQgdG8gYmUgc2V0IGFnYWluLlxuXHRcdFx0XHQvLyAgVG8gcHJldmVudCB0aGlzLCBvbmx5IGNoYW5nZSBoZWlnaHRzIGlmIHRoZXkgYXJlID4gMC5cblx0XHRcdFx0aWYgKCBmb3JtX2l0ZW1fbGFiZWxfZGl2LmhlaWdodCgpICE9PSBmb3JtX2l0ZW0uaGVpZ2h0KCkgJiYgZm9ybV9pdGVtLmhlaWdodCgpID4gMCApIHtcblx0XHRcdFx0XHRmb3JtX2l0ZW1fbGFiZWxfZGl2LmNzcyggJ2hlaWdodCcsIGZvcm1faXRlbS5oZWlnaHQoKSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0XHR3aWRnZXQudW5iaW5kKCAnc2V0U2l6ZScgKS5iaW5kKCAnc2V0U2l6ZScsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRmb3JtX2l0ZW1fbGFiZWxfZGl2LmNzcyggJ2hlaWdodCcsIHdpZGdldC5oZWlnaHQoKSArIDEwICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhbGFiZWwgKSB7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LnJlbW92ZSgpO1xuXHRcdFx0Zm9ybV9pdGVtX2xhYmVsX2Rpdi5yZW1vdmUoKTtcblxuXHRcdFx0Zm9ybV9pdGVtLmFwcGVuZCggd2lkZ2V0ICk7XG5cdFx0XHR3aWRnZXQuY3NzKCAnb3BhY2l0eScsIDEgKTtcblxuXHRcdFx0aWYgKCBzYXZlRm9ybUl0ZW1EaXYgJiYgc2F2ZUZvcm1JdGVtRGl2S2V5ICkge1xuXHRcdFx0XHR0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljW3NhdmVGb3JtSXRlbURpdktleV0gPSBmb3JtX2l0ZW07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHNhdmVGb3JtSXRlbURpdiApIHtcblxuXHRcdFx0aWYgKCBHbG9iYWwuaXNBcnJheSggd2lkZ2V0cyApICkge1xuXHRcdFx0XHR0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljW3dpZGdldHNbMF0uZ2V0RmllbGQoKV0gPSBmb3JtX2l0ZW07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljW3dpZGdldC5nZXRGaWVsZCgpXSA9IGZvcm1faXRlbTtcblx0XHRcdH1cblxuXHRcdH1cblx0XHRpZiAoIEdsb2JhbC5pc0FycmF5KCB3aWRnZXRzICkgKSB7XG5cblx0XHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHdpZGdldHMubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHdpZGdldCA9IHdpZGdldHNbaV07XG5cdFx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1t3aWRnZXQuZ2V0RmllbGQoKV0gPSB3aWRnZXQ7XG5cdFx0XHRcdHNldFZhbGlkYXRpb25EaWMoKTtcblxuXHRcdFx0XHR3aWRnZXQudW5iaW5kKCAnZm9ybUl0ZW1DaGFuZ2UnICkuYmluZCggJ2Zvcm1JdGVtQ2hhbmdlJywgZnVuY3Rpb24oIGUsIHRhcmdldCwgZG9Ob3RWYWxpZGF0ZSApIHtcblx0XHRcdFx0XHQkdGhpcy5vbkZvcm1JdGVtQ2hhbmdlKCB0YXJnZXQsIGRvTm90VmFsaWRhdGUgKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdGlmICggaGFzS2V5RXZlbnQgKSB7XG5cdFx0XHRcdFx0d2lkZ2V0LnVuYmluZCggJ2Zvcm1JdGVtS2V5VXAnICkuYmluZCggJ2Zvcm1JdGVtS2V5VXAnLCBmdW5jdGlvbiggZSwgdGFyZ2V0ICkge1xuXHRcdFx0XHRcdFx0JHRoaXMub25Gb3JtSXRlbUtleVVwKCB0YXJnZXQgKTtcblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHR3aWRnZXQudW5iaW5kKCAnZm9ybUl0ZW1LZXlEb3duJyApLmJpbmQoICdmb3JtSXRlbUtleURvd24nLCBmdW5jdGlvbiggZSwgdGFyZ2V0ICkge1xuXHRcdFx0XHRcdFx0JHRoaXMub25Gb3JtSXRlbUtleURvd24oIHRhcmdldCApO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNbd2lkZ2V0LmdldEZpZWxkKCldID0gd2lkZ2V0O1xuXHRcdFx0c2V0VmFsaWRhdGlvbkRpYygpO1xuXG5cdFx0XHR3aWRnZXQuYmluZCggJ2Zvcm1JdGVtQ2hhbmdlJywgZnVuY3Rpb24oIGUsIHRhcmdldCwgZG9Ob3RWYWxpZGF0ZSApIHtcblx0XHRcdFx0JHRoaXMub25Gb3JtSXRlbUNoYW5nZSggdGFyZ2V0LCBkb05vdFZhbGlkYXRlICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdGlmICggaGFzS2V5RXZlbnQgKSB7XG5cdFx0XHRcdHdpZGdldC5iaW5kKCAnZm9ybUl0ZW1LZXlVcCcsIGZ1bmN0aW9uKCBlLCB0YXJnZXQgKSB7XG5cdFx0XHRcdFx0JHRoaXMub25Gb3JtSXRlbUtleVVwKCB0YXJnZXQgKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHdpZGdldC5iaW5kKCAnZm9ybUl0ZW1LZXlEb3duJywgZnVuY3Rpb24oIGUsIHRhcmdldCApIHtcblx0XHRcdFx0XHQkdGhpcy5vbkZvcm1JdGVtS2V5RG93biggdGFyZ2V0ICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRmdW5jdGlvbiBzZXRWYWxpZGF0aW9uRGljKCkge1xuXHRcdFx0aWYgKCB3aWRnZXQuaGFzT3duUHJvcGVydHkoICdnZXRWYWxpZGF0aW9uRmllbGQnICkgJiYgd2lkZ2V0LmdldFZhbGlkYXRpb25GaWVsZCgpICkge1xuXHRcdFx0XHRpZiAoICR0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpY1t3aWRnZXQuZ2V0VmFsaWRhdGlvbkZpZWxkKCldICkge1xuXHRcdFx0XHRcdGlmICggIUdsb2JhbC5pc0FycmF5KCAkdGhpcy5lZGl0X3ZpZXdfdWlfdmFsaWRhdGlvbl9maWVsZF9kaWNbd2lkZ2V0LmdldFZhbGlkYXRpb25GaWVsZCgpXSApICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljW3dpZGdldC5nZXRWYWxpZGF0aW9uRmllbGQoKV0gPSBbJHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljW3dpZGdldC5nZXRWYWxpZGF0aW9uRmllbGQoKV0sIHdpZGdldF07XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV92YWxpZGF0aW9uX2ZpZWxkX2RpY1t3aWRnZXQuZ2V0VmFsaWRhdGlvbkZpZWxkKCldLnB1c2goIHdpZGdldCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfdmFsaWRhdGlvbl9maWVsZF9kaWNbd2lkZ2V0LmdldFZhbGlkYXRpb25GaWVsZCgpXSA9IHdpZGdldDtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZvcm1faXRlbTtcblx0fVxuXG5cdC8vU2V0IGZpZWxkcyBsYWJlbCB0byBzYW1lIHNpemVcblx0ZWRpdEZpZWxkUmVzaXplKCBpbmRleCApIHtcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBpbmRleCApICkge1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGluZGV4ID0gdGhpcy5nZXRFZGl0Vmlld1RhYkluZGV4KCk7XG5cdFx0fVxuXG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHRoaXMuZWRpdF92aWV3X3RhYnNbaW5kZXhdICkgJiYgIUdsb2JhbC5pc0ZhbHNlT3JOdWxsKCB0aGlzLmVkaXRfdmlld190YWJzW2luZGV4XSApICYmIHRoaXMuZWRpdF92aWV3X3RhYnNbaW5kZXhdLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHR2YXIgdGFiX2RpdiA9IHRoaXMuZWRpdF92aWV3X3RhYnNbaW5kZXhdO1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgdGFiX2Rpdi5sZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFyIHRhYl9jb2x1bW5fZGl2ID0gdGFiX2RpdltpXS5maW5kKCAnLmVkaXQtdmlldy1mb3JtLWl0ZW0tbGFiZWwtZGl2JyApO1xuXHRcdFx0XHR2YXIgdGFiX2NvbHVtbl9zdWJfZGl2ID0gdGFiX2RpdltpXS5maW5kKCAnLmVkaXQtdmlldy1mb3JtLWl0ZW0tc3ViLWxhYmVsLWRpdiA+IHNwYW4nICk7XG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCB0YWJfY29sdW1uX3N1Yl9kaXYgKSAmJiB0YWJfY29sdW1uX3N1Yl9kaXYubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0XHR0aGlzLnNldEVkaXRGaWVsZFNpemUoIHRhYl9jb2x1bW5fc3ViX2RpdiApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuc2V0RWRpdEZpZWxkU2l6ZSggdGFiX2NvbHVtbl9kaXYgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0RmllbGRTaXplKCB0YWJfY29sdW1uX2Rpdiwgd2lkdGggKSB7XG5cblx0XHRpZiAoIEdsb2JhbC5pc1NldCggd2lkdGggKSApIHtcblxuXHRcdFx0dGFiX2NvbHVtbl9kaXYuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCQoIHRoaXMgKS53aWR0aCggd2lkdGggKTtcblx0XHRcdH0gKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdHZhciBpdGVtX2xhYmVsX2Rpdl93aWR0aCA9IFtdO1xuXHRcdFx0dGFiX2NvbHVtbl9kaXYuZWFjaCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0aWYgKCAkKCB0aGlzICkud2lkdGgoKSA9PT0gMCApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCQoIHRoaXMgKS5jc3MoICd3aWR0aCcsICdhdXRvJyApO1xuXG5cdFx0XHRcdGl0ZW1fbGFiZWxfZGl2X3dpZHRoLnB1c2goICQoIHRoaXMgKS53aWR0aCgpICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdGl0ZW1fbGFiZWxfZGl2X3dpZHRoLnNvcnQoIGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0XHRyZXR1cm4gKCBiIC0gYSApO1xuXHRcdFx0fSApO1xuXG5cdFx0XHR0YWJfY29sdW1uX2Rpdi5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCBpdGVtX2xhYmVsX2Rpdl93aWR0aFswXSA+PSAwICkgeyAvLyAjMjcwMSAtIERvIG5vdCBzZXQgd2lkdGggaWYgdmFsdWUgaXMgbmVnYXRpdmUuIEhhcHBlbnMgd2hlbiB0cnlpbmcgdG8gY2FsY3VsYXRlIHdpZHRoIG9mIHNvbWV0aGluZyBvbiBhbm90aGVyIHRhYiBub3QgY3VycmVudGx5IHZpc2libGUuXG5cdFx0XHRcdFx0JCggdGhpcyApLndpZHRoKCBpdGVtX2xhYmVsX2Rpdl93aWR0aFswXSArIDEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblx0fVxuXG5cdHNldE5hdmlnYXRpb24oKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0Ly9FcnJvcjogVW5hYmxlIHRvIGdldCB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgJ2dldEdyaWRQYXJhbSc6IG9iamVjdCBpcyBudWxsIG9yIHVuZGVmaW5lZCBpbiAvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTguMC4wLTIwMTQxMjMwLTEwMzcyNSBsaW5lIDI1NzVcblx0XHRpZiAoICF0aGlzLmdyaWQgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFBvc3NpYmxlRGlzcGxheUNvbHVtbnMoIHRoaXMuYnVpbGREaXNwbGF5Q29sdW1uc0J5Q29sdW1uTW9kZWwoIHRoaXMuZ3JpZC5nZXRDb2x1bW5Nb2RlbCgpICksIHRoaXMuYnVpbGREaXNwbGF5Q29sdW1ucyggdGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucyApICk7XG5cdFx0dGhpcy5uYXZpZ2F0aW9uLnVuYmluZCggJ29uQ2xvc2UnICkuYmluZCggJ29uQ2xvc2UnLCAoKSA9PiB7XG5cdFx0XHR0aGlzLnNldE5hdmlnYXRpb25BcnJvd3NFbmFibGVkKCk7XG5cdFx0fSApO1xuXHRcdHRoaXMubmF2aWdhdGlvbi51bmJpbmQoICdmb3JtSXRlbUNoYW5nZScgKS5iaW5kKCAnZm9ybUl0ZW1DaGFuZ2UnLCBmdW5jdGlvbiggZSwgdGFyZ2V0ICkge1xuXG5cdFx0XHR2YXIga2V5ID0gdGFyZ2V0LmdldEZpZWxkKCk7XG5cdFx0XHR2YXIgbmV4dF9zZWxlY3RfaXRlbV9pZCA9IHRhcmdldC5nZXRWYWx1ZSgpO1xuXG5cdFx0XHRpZiAoICFuZXh0X3NlbGVjdF9pdGVtX2lkICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGlmICggbmV4dF9zZWxlY3RfaXRlbV9pZCAhPT0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblxuXHRcdFx0XHRpZiAoICR0aGlzLmlzX3ZpZXdpbmcgKSB7XG5cdFx0XHRcdFx0JHRoaXMub25WaWV3Q2xpY2soIG5leHRfc2VsZWN0X2l0ZW1faWQgKTsgLy9Eb250IHJlZnJlc2ggVUlcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5vbkVkaXRDbGljayggbmV4dF9zZWxlY3RfaXRlbV9pZCApOyAvL0RvbnQgcmVmcmVzaCBVSVxuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdFx0R2xvYmFsLnRyaWdnZXJBbmFseXRpY3NFZGl0Vmlld05hdmlnYXRpb24oICduYXZpZ2F0aW9uJywgJHRoaXMudmlld0lkICk7XG5cblx0XHR9ICk7XG5cdH1cblxuXHRjbGVhckVkaXRWaWV3RGF0YSgpIHtcblx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZWRpdF92aWV3X3VpX2RpYyApIHtcblx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBfLmlzRnVuY3Rpb24oIHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldLnNldEVtcHR5VmFsdWVBbmRTaG93TG9hZGluZyApICkge1xuXHRcdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XS5zZXRFbXB0eVZhbHVlQW5kU2hvd0xvYWRpbmcoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldLnNldFZhbHVlKCBudWxsICk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XS5jbGVhckVycm9yU3R5bGUoKTtcblx0XHR9XG5cdH1cblxuXHQvL0NhbGxlZCBhZnRlciBzZXQgY3VycmVudF9lZGl0X3JlY29yZFxuXHRzZXRFZGl0Vmlld0RhdGEoKSB7XG5cdFx0dGhpcy5pc19jaGFuZ2VkID0gZmFsc2U7XG5cdFx0dGhpcy5pbml0RWRpdFZpZXdEYXRhKCk7XG5cdFx0dGhpcy5pbml0VGFiRGF0YSgpO1xuXHRcdHRoaXMuc3dpdGNoVG9Qcm9wZXJUYWIoKTtcblx0fVxuXG5cdHN3aXRjaFRvUHJvcGVyVGFiKCkge1xuXHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpICYmXG5cdFx0XHRMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkuaGFzT3duUHJvcGVydHkoICd0YWInICkgJiZcblx0XHRcdExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS50YWIubGVuZ3RoID4gMCAmJlxuXHRcdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlci52aWV3SWQgPT09IHRoaXMudmlld0lkICkge1xuXG5cdFx0XHR2YXIgdGFyZ2V0X25vZGUgPSB0aGlzLmVkaXRfdmlld190YWIuZmluZCggJy5lZGl0LXZpZXctdGFiLWJhci1sYWJlbCcgKS5jaGlsZHJlbigpLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciB2YWx1ZSA9ICQoIHRoaXMgKS50ZXh0KCkucmVwbGFjZSggL1xcL3xcXHMrL2csICcnICk7XG5cdFx0XHRcdHJldHVybiB2YWx1ZSA9PT0gTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnRhYjtcblx0XHRcdH0gKTtcblxuXHRcdFx0dmFyIHRhcmdldF9pbmRleCA9IDA7XG5cdFx0XHRpZiAoIHRhcmdldF9ub2RlLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHRhcmdldF9ub2RlID0gJCggdGFyZ2V0X25vZGVbMF0gKTtcblx0XHRcdFx0dGFyZ2V0X2luZGV4ID0gdGFyZ2V0X25vZGUuaW5kZXgoKTtcblx0XHRcdH1cblx0XHRcdHRoaXMuZWRpdF92aWV3X3RhYi50YWJzKCAnb3B0aW9uJywgJ2FjdGl2ZScsIHRhcmdldF9pbmRleCApO1xuXHRcdH1cblx0fVxuXG5cdC8vQ2FsbCB0aGlzIGZyb20gc2V0RWRpdFZpZXdEYXRhXG5cdC8vIFRoaXMgaXMgY2FsbGVkIHRvIGluaXRpYWxpemUgZGF0YSBmb3IgdGhlIGZpcnN0L3ByaW1hcnkgdGFiLCBhbmQgaXMgY2FsbGVkIGZyb20gbWFueSB2aWV3cy4gU28gaXQgbmVlZHMgdG8gc3RheSBldmVuIGFmdGVyIGZ1bGx5IHJlZmFjdG9yZWQgdG8gdXNlIHRhYl9tb2RlbC5cblx0aW5pdFRhYkRhdGEoKSB7XG5cdFx0dmFyIHRhYl9tb2RlbCA9IHRoaXMuZ2V0VGFiTW9kZWwoKTtcblx0XHRpZiAoIHRhYl9tb2RlbCAhPSBudWxsICkge1xuXHRcdFx0dGhpcy5vblRhYlNob3coKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIGN1cnJlbnRfdGFiX2luZGV4ID0gdGhpcy5nZXRFZGl0Vmlld1RhYkluZGV4KCk7XG5cdFx0XHQvL0hhbmRsZSBtb3N0IGNhc2UgdGhhdCBvbmUgdGFiIGFuZCBvbmUgYXVkaXQgdGFiXG5cdFx0XHRpZiAoIGN1cnJlbnRfdGFiX2luZGV4ID09PSAxICkge1xuXHRcdFx0XHRpZiAoIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCAmJiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgIT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjdGFiX2F1ZGl0JyApLmZpbmQoICcuZmlyc3QtY29sdW1uLXN1Yi12aWV3JyApLmNzcyggJ2Rpc3BsYXknLCAnYmxvY2snICk7XG5cdFx0XHRcdFx0dGhpcy5pbml0U3ViTG9nVmlldyggJ3RhYl9hdWRpdCcgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLmVkaXRfdmlld190YWIuZmluZCggJyN0YWJfYXVkaXQnICkuZmluZCggJy5maXJzdC1jb2x1bW4tc3ViLXZpZXcnICkuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHRcdFx0XHRcdHRoaXMuc2hvd1NhdmVBbmRDb250aW51ZUJ1dHRvbigpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Z2V0RWRpdFZpZXdUYWJJbmRleCgpIHtcblx0XHRyZXR1cm4gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5lZGl0LXZpZXctdGFiLWJhciBsaS51aS10YWJzLWFjdGl2ZScgKS5pbmRleCgpO1xuXHR9XG5cblx0Z2V0RWRpdFZpZXdBY3RpdmVUYWJOYW1lKCkge1xuXHRcdGlmKCAhdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmVkaXRfdmlldy5maW5kKCAnLmVkaXQtdmlldy10YWItYmFyIGxpLnVpLXRhYnMtYWN0aXZlJyApLmF0dHIoICdhcmlhLWNvbnRyb2xzJyApO1xuXHR9XG5cblx0bmVlZFNob3dOYXZpZ2F0aW9uKCkge1xuXHRcdGlmICggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmIEdsb2JhbC5pc1NldCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkgJiYgdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvL0NhbGwgdGhpcyBmcm9tIHNldEVkaXRWaWV3RGF0YVxuXHRpbml0RWRpdFZpZXdEYXRhKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHQvL2FkZCB0aGlzLmdyaWQgdG8gZml4IGV4Y2VwdGlvblxuXHRcdC8vRXJyb3I6IFVuYWJsZSB0byBnZXQgcHJvcGVydHkgJ2dldEdyaWRQYXJhbScgb2YgdW5kZWZpbmVkIG9yIG51bGwgcmVmZXJlbmNlIGluIC9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9Ny40LjMtMjAxNDA5MjQtMDkwMTI5IGxpbmUgMjUyM1xuXHRcdGlmICggIXRoaXMuZWRpdF9vbmx5X21vZGUgJiYgdGhpcy5uYXZpZ2F0aW9uICYmIHRoaXMuZ3JpZCApIHtcblxuXHRcdFx0dmFyIGdyaWRfY3VycmVudF9wYWdlX2l0ZW1zID0gdGhpcy5ncmlkLmdldERhdGEoKTtcblxuXHRcdFx0dmFyIG5hdmlnYXRpb25fZGl2ID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5uYXZpZ2F0aW9uLWRpdicgKTtcblxuXHRcdFx0Ly9FcnJvcjogVHlwZUVycm9yOiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgaXMgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9OC4wLjAtMjAxNDEyMzAtMTAzNzI1IGxpbmUgMjY3M1xuXHRcdFx0aWYgKCB0aGlzLm5lZWRTaG93TmF2aWdhdGlvbigpICkge1xuXHRcdFx0XHRuYXZpZ2F0aW9uX2Rpdi5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0XHQvL1NldCBOYXZpZ2F0aW9uIEF3ZXNvbWVib3hcblxuXHRcdFx0XHQvLyMzMTc1IC0gR2V0IGN1cnJlbnQgbmF2aWdhdGlvbiBkYXRhIGlmIGl0IGV4aXN0cyBzbyB0aGF0IHdlIGRvIG5vdCBvdmVyd3JpdGUgaXQgd2hlbiBzd2l0Y2hpbmcgcmVjb3Jkcy5cblx0XHRcdFx0Ly9Gb3IgZXhhbXBsZSB3aGVuIGNsaWNraW5nIHRoZSByaWdodCBhcnJvdyBvbiB0aGUgbGFzdCByZWNvcmQgb2YgcGFnZSAxIGJyaW5ncyB5b3UgdG8gcGFnZSAyLiBQYWdlIDIgZGF0YSB3YXMgYmVpbmcgcmVzZXQuXG5cdFx0XHRcdC8vSW4gdGhhdCBzY2VuYXJpbyB3ZSB3YW50IHRvIGtlZXAgbmF2aWdhdGlvbiBkYXRhIGZyb20gcGFnZSAyIGFuZCBub3Qgb3ZlcndyaXRlIGl0IHdpdGggdGhlIGdyaWQgZGF0YSBmcm9tIHRoZSBsaXN0IHZpZXcuXG5cdFx0XHRcdGxldCBjdXJyZW50X25hdmlnYXRpb25fZGF0YSA9IHRoaXMubmF2aWdhdGlvbi5nZXRTb3VyY2VEYXRhKCk7XG5cdFx0XHRcdGxldCBjdXJyZW50X3BhZ2VyX2RhdGEgPSB0aGlzLm5hdmlnYXRpb24uZ2V0UGFnZXJEYXRhKCk7XG5cblx0XHRcdFx0Ly8jMjM0OSAtIHVwZGF0ZSBzb3VyY2UgZGF0YSBldmVyeSB0aW1lIHNvIHRoYXQgaXQgZG9lc24ndCBnbyB1bnJlZnJlc2hlZCBpbiB0aGUgY2FzZSBvZiBzYXZpbmcgYSBuZXcgcmVjb3JkIG9yIGRlbGV0aW5nIGV4aXRpbmdcblx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFNvdXJjZURhdGEoIGN1cnJlbnRfbmF2aWdhdGlvbl9kYXRhID8gY3VycmVudF9uYXZpZ2F0aW9uX2RhdGEgOiBncmlkX2N1cnJlbnRfcGFnZV9pdGVtcyApO1xuXHRcdFx0XHR0aGlzLm5hdmlnYXRpb24uc2V0UGFnZXJEYXRhKCBjdXJyZW50X3BhZ2VyX2RhdGEgPyBjdXJyZW50X3BhZ2VyX2RhdGE6IHRoaXMucGFnZXJfZGF0YSApO1xuXHRcdFx0XHQvL2luaXQgbmF2aWdhdGlvbiBvbmx5IHdoZW4gb3BlbiBlZGl0IHZpZXdcblx0XHRcdFx0aWYgKCAhdGhpcy5uYXZpZ2F0aW9uLmdldFNvdXJjZURhdGEoKSApIHtcblx0XHRcdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlclByZWZlcmVuY2UoKSApIHtcblx0XHRcdFx0XHRcdHRoaXMubmF2aWdhdGlvbi5zZXRSb3dQZXJQYWdlKCBMb2NhbENhY2hlRGF0YS5nZXRMb2dpblVzZXJQcmVmZXJlbmNlKCkuaXRlbXNfcGVyX3BhZ2UgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldFBhZ2VyRGF0YSggdGhpcy5wYWdlcl9kYXRhICk7XG5cblx0XHRcdFx0XHR2YXIgZGVmYXVsdF9hcmdzID0ge307XG5cdFx0XHRcdFx0ZGVmYXVsdF9hcmdzLmZpbHRlcl9kYXRhID0gR2xvYmFsLmNvbnZlcnRMYXlvdXRGaWx0ZXJUb0FQSUZpbHRlciggdGhpcy5zZWxlY3RfbGF5b3V0ICk7XG5cdFx0XHRcdFx0ZGVmYXVsdF9hcmdzLmZpbHRlcl9zb3J0ID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX3NvcnQ7XG5cdFx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLnNldERlZmF1bHRBcmdzKCBkZWZhdWx0X2FyZ3MgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMubmF2aWdhdGlvbi5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG5hdmlnYXRpb25fZGl2LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLnNldFVJV2lkZ2V0RmllbGRzVG9DdXJyZW50RWRpdFJlY29yZCgpO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5lZGl0X3ZpZXdfdWlfZGljICkge1xuXG5cdFx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly9KUyBFeGNlcHRpb246IFwidGhpcy51bmlxdWVfY29sdW1ucy5pbmRleE9mIGlzIG5vdCBhIGZ1bmN0aW9uXCJcblx0XHRcdFx0aWYgKCB0aGlzLnVuaXF1ZV9jb2x1bW5zICYmIHRoaXMudW5pcXVlX2NvbHVtbnMubGVuZ3RoID4gMCAmJiB0aGlzLnVuaXF1ZV9jb2x1bW5zLmluZGV4T2YoIGtleSApICE9IC0xICkge1xuXHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XS5jc3MoICdvcGFjaXR5JywgJzAnICk7XG5cdFx0XHRcdFx0aWYgKCAkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV0uc2V0RW5hYmxlZCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XS5zZXRFbmFibGVkKCBmYWxzZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoICR0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XS5zZXRNYXNzRWRpdE1vZGUgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV0uc2V0TWFzc0VkaXRNb2RlKCBmYWxzZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR2YXIgd2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV07XG5cdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHdpZGdldC5zZXRNYXNzRWRpdE1vZGUgKSApIHtcblx0XHRcdFx0XHRcdHdpZGdldC5zZXRNYXNzRWRpdE1vZGUoIHRydWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldLmNzcyggJ29wYWNpdHknLCAnMScgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZWRpdF92aWV3X3VpX2RpYyApIHtcblx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1trZXldLmNzcyggJ29wYWNpdHknLCAnMScgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLnNldE5hdmlnYXRpb25BcnJvd3NFbmFibGVkKCB0cnVlICk7XG5cblx0XHQvLyBDcmVhdGUgdGhpcyBmdW5jdGlvbiBhbG9uZSBiZWNhdXNlIG9mIHRoZSBjb2x1bW4gdmFsdWUgb2YgdmlldyBpcyBkaWZmZXJlbnQgZnJvbSBlYWNoIG90aGVyLCBzb21lIGNvbHVtbnMgbmVlZCB0byBiZSBoYW5kbGUgc3BlY2lhbGx5LiBhbmQgZWFzaWx5IHRvIHJld3JpdGUgdGhpcyBmdW5jdGlvbiBpbiBzdWItY2xhc3MuXG5cblx0XHR0aGlzLnNldEN1cnJlbnRFZGl0UmVjb3JkRGF0YSgpO1xuXG5cdFx0Ly9Jbml0ICpQbGVhc2Ugc2F2ZSB0aGlzIHJlY29yZCBiZWZvcmUgbW9kaWZ5aW5nIGFueSByZWxhdGVkIGRhdGEqIGJveFxuXHRcdHRoaXMuZWRpdF92aWV3LmZpbmQoICcuc2F2ZS1hbmQtY29udGludWUtZGl2JyApLlNhdmVBbmRDb250aW51ZUJveCggeyByZWxhdGVkX3ZpZXdfY29udHJvbGxlcjogdGhpcyB9ICk7XG5cdFx0dGhpcy5lZGl0X3ZpZXcuZmluZCggJy5zYXZlLWFuZC1jb250aW51ZS1kaXYnICkuY3NzKCAnZGlzcGxheScsICdub25lJyApO1xuXHR9XG5cblx0c2V0VUlXaWRnZXRGaWVsZHNUb0N1cnJlbnRFZGl0UmVjb3JkKCkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHQkdGhpcy5vbGRfY3VycmVudF9lZGl0X3JlY29yZCA9IEdsb2JhbC5jbG9uZSggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCApOyAvL1NhdmUgdGhlIGN1cnJlbnQgZWRpdCByZWNvcmQgYmVmb3JlIGFueSBjaGFuZ2VzIGFyZSBtYWRlIHNvIHdlIGNhbiBsYXRlciBjaGVjayB3aGF0IGZpZWxkcyBtYXkgaGF2ZSBjaGFuZ2VkLlxuXG5cdFx0aWYgKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkID09PSB0cnVlICkge1xuXHRcdFx0JHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IHt9O1xuXHRcdH07XG5cblx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuZWRpdF92aWV3X3VpX2RpYyApIHtcblx0XHRcdGlmICggIXRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuLy9cdFx0XHQvL1NldCBhbGwgVUkgZmllbGQgdG8gY3VycmVudCBlZGl0IHJlY29yZCwgd2UgbmVlZCB2YWxpZGF0ZSBhbGwgVUkgZmllbGQgd2hlbiBzYXZlIGFuZCB2YWxpZGF0ZVxuXHRcdFx0Ly91c2UgIT0gdG8gaW5nb3JlIHN0cmluZyBvciBudW1iZXIsIHZhbHVlIGZyb20gaHRtbCBpcyBzdHJpbmcuXG5cdFx0XHQvL0Vycm9yOiBUeXBlRXJyb3I6ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgaXMgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9OC4wLjAtMjAxNDExMTctMTIyNDUzIGxpbmUgMjcwMlxuXHRcdFx0aWYgKCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkICYmICFHbG9iYWwuaXNTZXQoICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSApICkge1xuXHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSBmYWxzZTtcblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXQgZGVmYXVsdCBkYXRhIGludG8gY3VycmVudF9lZGl0X3JlY29yZFxuXHQgKlxuXHQgKiBAcGFyYW0gY29sdW1uc0FyclxuXHQgKiBAcGFyYW0gZm9yY2Vcblx0ICpcblx0ICogaWYgZm9yY2UgaXMgdHJ1ZSBzZXQgdGhlIGN1cnJlbnRfZWRpdF9yZWNvcmQgYW5kIHBvcHVsYXRlIGVkaXRfdmlld191aV9kaWNcblx0ICogdGhpcyBpcyB1c2VkIGluIHZpZXcgY29udHJvbGxlcnMgKFJlcXVlc3RWaWV3Q29udHJvbGxlcjo6c2V0UmVxdWVzdEZvcm1EZWZhdWx0RGF0YSkgd2hlcmUgdGhlIGFwaSBjYWxsIGZvciBkZWZhdWx0IHZhbHVlcyBpcyBsYXRlXG5cdCAqXG5cdCAqL1xuXHRzZXREZWZhdWx0RGF0YSggY29sdW1uc0FyciwgZm9yY2UgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHQkLmVhY2goIGNvbHVtbnNBcnIsIGZ1bmN0aW9uKCBmaWVsZCwgdmFsdWUgKSB7XG5cdFx0XHRpZiAoIGZvcmNlICE9IHRydWUgJiYgR2xvYmFsLmlzU2V0KCAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2ZpZWxkXSApICkge1xuXHRcdFx0XHQvL2RvIG5vdGhpbmdcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICggZm9yY2UgPT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRpZiAoICR0aGlzLmVkaXRfdmlld191aV9kaWNbZmllbGRdICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1tmaWVsZF0uc2V0VmFsdWUoIHZhbHVlICk7XG5cdFx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2ZpZWxkXSA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2ZpZWxkXSA9IHZhbHVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0Y29sbGVjdFVJRGF0YVRvQ3VycmVudEVkaXRSZWNvcmQoKSB7XG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5lZGl0X3ZpZXdfdWlfZGljICkge1xuXHRcdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfdWlfZGljLmhhc093blByb3BlcnR5KCBrZXkgKSApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdHZhciB3aWRnZXQgPSB0aGlzLmVkaXRfdmlld191aV9kaWNba2V5XTtcblxuXHRcdFx0Ly9vbmx5IGNoZWNrIGRyb3Bkb3dubGlzdFxuXHRcdFx0aWYgKCAhd2lkZ2V0Lmhhc0NsYXNzKCAndC1zZWxlY3QnICkgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgdmFsdWUgPSB3aWRnZXQuZ2V0VmFsdWUoKTtcblxuLy9cdFx0XHQvL1NldCBhbGwgVUkgZmllbGQgdG8gY3VycmVudCBlZGl0IHJlY29yZCwgd2UgbmVlZCB2YWxpZGF0ZSBhbGwgVUkgZmllbGQgd2hlbiBzYXZlIGFuZCB2YWxpZGF0ZVxuXHRcdFx0Ly91c2UgIT0gdG8gaW5nb3JlIHN0cmluZyBvciBudW1iZXIsIHZhbHVlIGZyb20gaHRtbCBpcyBzdHJpbmcuXG5cdFx0XHQvL2lzIHZpc2libGUgbWFrZSBzdXJlIHRoZSB3aWRnZXQgaXMgc2hvd24gb24gc2NyZWVuIG9mIGN1cnJlbnQgc2VsZWN0IHR5cGVcblxuXHRcdFx0Ly9FcnJvcjogVHlwZUVycm9yOiB1bmRlZmluZWQgaXMgbm90IGFuIG9iamVjdCAoZXZhbHVhdGluZyAnJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldJykgaW4gL2ludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj04LjAuMC0yMDE0MTIzMC0xMjQ5MDYgbGluZSAyNzkyXG5cdFx0XHRpZiAoIHZhbHVlICYmICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgJiYgJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldICE9IHZhbHVlICkge1xuXG5cdFx0XHRcdGlmICggIXZhbHVlIHx8IHZhbHVlID09PSAnMCcgfHwgKCBHbG9iYWwuaXNBcnJheSggdmFsdWUgKSAmJiB2YWx1ZS5sZW5ndGggPT09IDAgKSApIHtcblx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSBmYWxzZTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gPSB2YWx1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRzZXRDdXJyZW50RWRpdFJlY29yZERhdGEoKSB7XG5cdFx0Ly9TZXQgY3VycmVudCBlZGl0IHJlY29yZCBkYXRhIHRvIGFsbCB3aWRnZXRzXG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKSB7XG5cblx0XHRcdGlmICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgd2lkZ2V0ID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljW2tleV07XG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggd2lkZ2V0ICkgKSB7XG5cdFx0XHRcdHN3aXRjaCAoIGtleSApIHtcblx0XHRcdFx0XHRjYXNlICdjb3VudHJ5JzogLy9wb3B1bGFyIGNhc2Vcblx0XHRcdFx0XHRcdHRoaXMuc2V0Q291bnRyeVZhbHVlKCB3aWRnZXQsIGtleSApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdHdpZGdldC5zZXRWYWx1ZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmNvbGxlY3RVSURhdGFUb0N1cnJlbnRFZGl0UmVjb3JkKCk7XG5cdFx0dGhpcy5zZXRFZGl0Vmlld0RhdGFEb25lKCk7XG5cdH1cblxuXHRzZXRDb3VudHJ5VmFsdWUoIHdpZGdldCwga2V5ICkge1xuXHRcdGlmICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZFsncHJvdmluY2UnXSApIHtcblx0XHRcdHRoaXMuZVNldFByb3ZpbmNlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmVTZXRQcm92aW5jZSggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkW2tleV0gKTtcblx0XHR9XG5cdFx0d2lkZ2V0LnNldFZhbHVlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRba2V5XSApO1xuXHR9XG5cblx0cHV0SW5wdXRUb0luc2lkZUZvcm1JdGVtKCBmb3JtX2l0ZW1faW5wdXQsIGxhYmVsICkge1xuXHRcdHZhciBmb3JtX2l0ZW0gPSAkKCBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggV2lkZ2V0TmFtZXNEaWMuRURJVF9WSUVXX1NVQl9GT1JNX0lURU0gKSApO1xuLy9cdFx0dmFyIGZvcm1faXRlbV9sYWJlbF9kaXYgPSBmb3JtX2l0ZW0uZmluZCggJy5lZGl0LXZpZXctZm9ybS1pdGVtLWxhYmVsLWRpdicgKTtcbi8vXG4vL1x0XHRmb3JtX2l0ZW1fbGFiZWxfZGl2LmF0dHIoICdjbGFzcycsICdlZGl0LXZpZXctZm9ybS1pdGVtLXN1Yi1sYWJlbC1kaXYnICk7XG5cblx0XHR2YXIgZm9ybV9pdGVtX2xhYmVsID0gZm9ybV9pdGVtLmZpbmQoICcuZWRpdC12aWV3LWZvcm0taXRlbS1sYWJlbCcgKTtcblx0XHR2YXIgZm9ybV9pdGVtX2lucHV0X2RpdiA9IGZvcm1faXRlbS5maW5kKCAnLmVkaXQtdmlldy1mb3JtLWl0ZW0taW5wdXQtZGl2JyApO1xuXHRcdGZvcm1faXRlbS5hZGRDbGFzcyggJ3JlbW92ZS1tYXJnaW4nICk7XG5cblx0XHRmb3JtX2l0ZW1fbGFiZWwudGV4dCggJC5pMThuLl8oIGxhYmVsICkgKTtcblxuXHRcdGZvcm1faXRlbV9pbnB1dF9kaXYuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblxuXHRcdHJldHVybiBmb3JtX2l0ZW07XG5cdH1cblxuXHQvL3NldCB0YWIgMCB2aXNpYmxlIGFmdGVyIGFsbCBkYXRhIHNldCBkb25lLiBUaGlzIGJlIGhpZGUgd2hlbiBpbml0IGVkaXQgdmlldyBkYXRhXG5cdHNldEVkaXRWaWV3RGF0YURvbmUoKSB7XG5cdFx0Ly8gUmVtb3ZlIHRoaXMgb24gMTQuOS4xNCBiZWNhdXNlIGFkZGluZyB0YWIgdXJsIHN1cHBvcnQsIG5lZCBzZXQgdXJsIHdoZW4gdGFiIGluZGV4IGNoYW5nZSBhbmRcblx0XHQvLyBuZWVkIGtub3cgd2FodCdzIGN1cnJlbnQgZG9pbmcgYWN0aW9uLiBTZWUgaWYgdGhpcyBjYXVzZSBhbnkgcHJvYmxlbVxuXHRcdC8vTG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9ICcnO1xuXHRcdHRoaXMuc2V0VGFiT1Zpc2liaWxpdHkoIHRydWUgKTtcblx0XHRUVFByb21pc2UucmVzb2x2ZSggJ2luaXQnLCAnaW5pdCcgKTtcblxuXHRcdCQoICcuZWRpdC12aWV3LXRhYi1iYXInICkuY3NzKCAnb3BhY2l0eScsIDEgKTtcblx0fVxuXG5cdHNldE5hdmlnYXRpb25BcnJvd3NTdGF0dXMoKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGxlZnRfYXJyb3cgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLmxlZnQtY2xpY2snICk7XG5cdFx0dmFyIHJpZ2h0X2Fycm93ID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5yaWdodC1jbGljaycgKTtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0bGVmdF9hcnJvdy5vZmYoICdjbGljaycgKS5vbiggJ2NsaWNrJywgR2xvYmFsLmRlYm91bmNlKCBmdW5jdGlvbiBOYXZpZ2F0aW9uTGVmdEFycm93Q2xpY2soIGUgKSB7XG5cdFx0XHRpZiAoICFsZWZ0X2Fycm93Lmhhc0NsYXNzKCAnZGlzYWJsZWQnICkgKSB7XG5cdFx0XHRcdCR0aGlzLm9uTGVmdEFycm93Q2xpY2soKTtcblx0XHRcdH1cblxuXHRcdH0sIEdsb2JhbC5jYWxjRGVib3VuY2VXYWl0VGltZUJhc2VkT25OZXR3b3JrKCksIHRydWUgKSApO1xuXG5cdFx0cmlnaHRfYXJyb3cub2ZmKCAnY2xpY2snICkub24oICdjbGljaycsIEdsb2JhbC5kZWJvdW5jZSggZnVuY3Rpb24gTmF2aWdhdGlvblJpZ2h0QXJyb3dDbGljayggZSApIHtcblx0XHRcdGlmICggIXJpZ2h0X2Fycm93Lmhhc0NsYXNzKCAnZGlzYWJsZWQnICkgKSB7XG5cdFx0XHRcdCR0aGlzLm9uUmlnaHRBcnJvd0NsaWNrKCk7XG5cdFx0XHR9XG5cblx0XHR9LCBHbG9iYWwuY2FsY0RlYm91bmNlV2FpdFRpbWVCYXNlZE9uTmV0d29yaygpLCB0cnVlICkgKTtcblx0fVxuXG5cdHNldE5hdmlnYXRpb25BcnJvd3NFbmFibGVkKCBjaGVja19zZWFyY2ggKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly9JZiBzZWFyY2ggZGF0YSBleGlzdHMsIHNlYXJjaCB3aGVuIG1ha2luZyBhIHJlY29yZCBjaGFuZ2UgdG8gZW5zdXJlIGFycm93IHN0YXR1cyB3aWxsIHJlZmxlY3QgdGhlIHNlYXJjaCByZXN1bHRcblx0XHRpZiAoIGNoZWNrX3NlYXJjaCAmJiB0aGlzLm5hdmlnYXRpb24gJiYgdHlwZW9mIHRoaXMubmF2aWdhdGlvbi5idWlsZFVuU2VsZWN0R3JpZEZpbHRlciA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0Ly9SdW4gdGhpcyBjb25kaXRpb24gZmlyc3QgdG8gYXZvaWQgZmxhc2hpbmcgYXJyb3dzIGVuYWJsaW5nL2Rpc2FibGluZy5cblx0XHRcdHZhciBkYXRhID0gdGhpcy5uYXZpZ2F0aW9uLmJ1aWxkVW5TZWxlY3RHcmlkRmlsdGVyKCk7XG5cdFx0XHRpZiAoIGRhdGEgJiYgZGF0YS5maWx0ZXJfZGF0YSAmJiBPYmplY3Qua2V5cyggZGF0YS5maWx0ZXJfZGF0YSApLmxlbmd0aCAhPT0gMCApIHtcblx0XHRcdFx0dGhpcy5uYXZpZ2F0aW9uLm9uQURyb3BEb3duU2VhcmNoKCAndW5zZWxlY3RfZ3JpZCcsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCAoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5zZXROYXZpZ2F0aW9uQXJyb3dzRW5hYmxlZCggZmFsc2UgKTtcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIGxlZnRfYXJyb3cgPSB0aGlzLmVkaXRfdmlldy5maW5kKCAnLmxlZnQtY2xpY2snICk7XG5cdFx0dmFyIHJpZ2h0X2Fycm93ID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy5yaWdodC1jbGljaycgKTtcblxuXHRcdGxlZnRfYXJyb3cucmVtb3ZlQ2xhc3MoICdkaXNhYmxlZCcgKTtcblx0XHRyaWdodF9hcnJvdy5yZW1vdmVDbGFzcyggJ2Rpc2FibGVkJyApO1xuXG5cdFx0Ly9UeXBlRXJyb3I6IHRoaXMubmF2aWdhdGlvbi5nZXRTZWxlY3RJbmRleCBpcyBub3QgYSBmdW5jdGlvblxuXHRcdC8vbmF2aWdhdGlvbiBjb3VsZCBub3QgYmUgaW5pdGlhbCBpbiBjYXNlcywgZm9yIGV4YW1wbGUgaW4gUmVxdWVzdCBuZXcgdmlld1xuXHRcdGlmICggIXRoaXMubmF2aWdhdGlvbiB8fCAhKCB0aGlzLm5hdmlnYXRpb24uaGFzT3duUHJvcGVydHkoICdnZXRTZWxlY3RJbmRleCcgKSApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBzZWxlY3RlZF9pbmRleCA9IHRoaXMubmF2aWdhdGlvbi5nZXRTZWxlY3RJbmRleCgpO1xuXHRcdHZhciBzb3VyY2VfZGF0YSA9IHRoaXMubmF2aWdhdGlvbi5nZXRTb3VyY2VEYXRhKCk7XG5cblx0XHRpZiAoICFzb3VyY2VfZGF0YSB8fCAoIEFycmF5LmlzQXJyYXkoIHNvdXJjZV9kYXRhICkgJiYgc291cmNlX2RhdGEubGVuZ3RoID09PSAwICkgKSB7XG5cdFx0XHQvL05vIHJlY29yZHMgaW4gbmF2aWdhdGlvbiBib3gsIHNvIG1ha2Ugc3VyZSBhcnJvd3MgYXJlIGRpc2JsZWQuXG5cdFx0XHRsZWZ0X2Fycm93LmFkZENsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHRyaWdodF9hcnJvdy5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBjdXJyZW50X3BhZ2VyX2RhdGEgPSB0aGlzLm5hdmlnYXRpb24uZ2V0UGFnZXJEYXRhKCk7XG5cblx0XHQvLyBJdCdzIHBvc3NpYmxlIHRoZSBuYXZpZ2F0aW9uIGRvbid0IGhhdmUgYSBwYWdlciBkYXRhLCBsaWtlIFRpbWVzaGVldCBlZGl0IHZpZXcsIHNvIGl0J3MgYmVjb21lIGEgbm8gcGFnZSBuYXZpZ2F0aW9uLlxuXHRcdGlmICggIWN1cnJlbnRfcGFnZXJfZGF0YSApIHtcblx0XHRcdGlmICggc2VsZWN0ZWRfaW5kZXggPT09IDAgKSB7XG5cdFx0XHRcdGxlZnRfYXJyb3cuYWRkQ2xhc3MoICdkaXNhYmxlZCcgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBzZWxlY3RlZF9pbmRleCA9PT0gc291cmNlX2RhdGEubGVuZ3RoIC0gMSApIHtcblx0XHRcdFx0cmlnaHRfYXJyb3cuYWRkQ2xhc3MoICdkaXNhYmxlZCcgKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBzZWxlY3RlZF9pbmRleCA9PT0gMCAmJiBjdXJyZW50X3BhZ2VyX2RhdGEuY3VycmVudF9wYWdlID09PSAxICkge1xuXHRcdFx0XHRsZWZ0X2Fycm93LmFkZENsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggc2VsZWN0ZWRfaW5kZXggPT09IHNvdXJjZV9kYXRhLmxlbmd0aCAtIDEgJiYgY3VycmVudF9wYWdlcl9kYXRhLmN1cnJlbnRfcGFnZSA9PT0gY3VycmVudF9wYWdlcl9kYXRhLmxhc3RfcGFnZV9udW1iZXIgKSB7XG5cdFx0XHRcdHJpZ2h0X2Fycm93LmFkZENsYXNzKCAnZGlzYWJsZWQnICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0b25MZWZ0QXJyb3dDbGljayggY2FuY2VsX2NhbGxiYWNrICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHRpZiAoIHRoaXMuaXNfY2hhbmdlZCApIHtcblx0XHRcdFRBbGVydE1hbmFnZXIuc2hvd0NvbmZpcm1BbGVydCggR2xvYmFsLm1vZGlmeV9hbGVydF9tZXNzYWdlLCBudWxsLCBmdW5jdGlvbiggZmxhZyApIHtcblx0XHRcdFx0aWYgKCBmbGFnID09PSB0cnVlICkge1xuXHRcdFx0XHRcdCR0aGlzLmlzX2NoYW5nZWQgPSBmYWxzZTtcblx0XHRcdFx0XHRkb0xlZnRBcnJvd0NsaWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0UHJvZ3Jlc3NCYXIuY2xvc2VPdmVybGF5KCk7XG5cdFx0XHR9ICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRvTGVmdEFycm93Q2xpY2soKTtcblx0XHR9XG5cblx0XHRHbG9iYWwudHJpZ2dlckFuYWx5dGljc0VkaXRWaWV3TmF2aWdhdGlvbiggJ2xlZnQtYXJyb3cnLCB0aGlzLnZpZXdJZCApO1xuXG5cdFx0ZnVuY3Rpb24gZG9MZWZ0QXJyb3dDbGljaygpIHtcblx0XHRcdHZhciBzZWxlY3RlZF9pbmRleCA9ICR0aGlzLm5hdmlnYXRpb24uZ2V0U2VsZWN0SW5kZXgoKTtcblx0XHRcdHZhciBzb3VyY2VfZGF0YSA9ICR0aGlzLm5hdmlnYXRpb24uZ2V0U291cmNlRGF0YSgpO1xuXHRcdFx0dmFyIGN1cnJlbnRfcGFnZXJfZGF0YSA9ICR0aGlzLm5hdmlnYXRpb24uZ2V0UGFnZXJEYXRhKCk7XG5cdFx0XHR2YXIgbmV4dF9zZWxlY3RfaXRlbTtcblx0XHRcdGlmICggc2VsZWN0ZWRfaW5kZXggPiAwICkge1xuXHRcdFx0XHRuZXh0X3NlbGVjdF9pdGVtID0gJHRoaXMubmF2aWdhdGlvbi5nZXRJdGVtQnlJbmRleCggc2VsZWN0ZWRfaW5kZXggLSAxICk7XG5cdFx0XHRcdCR0aGlzLm9uUmlnaHRPckxlZnRBcnJvd0NsaWNrQ2FsbEJhY2soIG5leHRfc2VsZWN0X2l0ZW0gKTtcblx0XHRcdH0gZWxzZSBpZiAoIHNlbGVjdGVkX2luZGV4ID09PSAwICYmIGN1cnJlbnRfcGFnZXJfZGF0YSAmJiBjdXJyZW50X3BhZ2VyX2RhdGEuY3VycmVudF9wYWdlID4gMSApIHtcblx0XHRcdFx0JHRoaXMubmF2aWdhdGlvbi5vbkFEcm9wRG93blNlYXJjaCggJ3Vuc2VsZWN0X2dyaWQnLCBjdXJyZW50X3BhZ2VyX2RhdGEuY3VycmVudF9wYWdlIC0gMSwgJ2xhc3QnLCBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdG5leHRfc2VsZWN0X2l0ZW0gPSByZXN1bHQ7XG5cdFx0XHRcdFx0JHRoaXMub25SaWdodE9yTGVmdEFycm93Q2xpY2tDYWxsQmFjayggbmV4dF9zZWxlY3RfaXRlbSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5vbkNhbmNlbENsaWNrKCBudWxsLCBudWxsLCBjYW5jZWxfY2FsbGJhY2sgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJlZnJlc2hDdXJyZW50UmVjb3JkKCkge1xuXHRcdHZhciBuZXh0X3NlbGVjdF9pdGVtID0gdGhpcy5uYXZpZ2F0aW9uLmdldEl0ZW1CeUluZGV4KCB0aGlzLm5hdmlnYXRpb24uZ2V0U2VsZWN0SW5kZXgoKSApO1xuXHRcdFByb2dyZXNzQmFyLnNob3dPdmVybGF5KCk7XG5cdFx0aWYgKCB0aGlzLmlzX3ZpZXdpbmcgKSB7XG5cdFx0XHR0aGlzLm9uVmlld0NsaWNrKCBuZXh0X3NlbGVjdF9pdGVtLmlkICk7IC8vRG9udCByZWZyZXNoIFVJXG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMub25FZGl0Q2xpY2soIG5leHRfc2VsZWN0X2l0ZW0uaWQgKTsgLy9Eb250IHJlZnJlc2ggVUlcblx0XHR9XG5cblx0XHR0aGlzLnNldE5hdmlnYXRpb25BcnJvd3NFbmFibGVkKCk7XG5cdH1cblxuXHQvL2V4aXN0cyBmb3IgUmVjdXJyaW5nU2NoZWR1bGVDb250cm9sVmlldyBkdWUgdG8gdGhlIHVuaXF1ZSB3YXkgd2UgaGFuZGxlIHRoZSBpZHMgdGhlcmUuIChDaGFuZ2U6IFRoYXQgdmlldyBubyBsb25nZXIgdXNlcyBjb21wb3NpdGUgSURzKVxuXHRnZXRSaWdodEFycm93Q2xpY2tTZWxlY3RlZEluZGV4KCBzZWxlY3RlZF9pbmRleCApIHtcblx0XHRyZXR1cm4gc2VsZWN0ZWRfaW5kZXg7XG5cdH1cblxuXHRvblJpZ2h0QXJyb3dDbGljayggY2FuY2VsX2NhbGxiYWNrICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCB0aGlzLmlzX2NoYW5nZWQgKSB7XG5cdFx0XHRUQWxlcnRNYW5hZ2VyLnNob3dDb25maXJtQWxlcnQoIEdsb2JhbC5tb2RpZnlfYWxlcnRfbWVzc2FnZSwgbnVsbCwgZnVuY3Rpb24oIGZsYWcgKSB7XG5cdFx0XHRcdGlmICggZmxhZyA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0XHQkdGhpcy5pc19jaGFuZ2VkID0gZmFsc2U7XG5cdFx0XHRcdFx0ZG9SaWdodEFycm93Q2xpY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTtcblx0XHRcdH0gKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZG9SaWdodEFycm93Q2xpY2soKTtcblx0XHR9XG5cblx0XHRHbG9iYWwudHJpZ2dlckFuYWx5dGljc0VkaXRWaWV3TmF2aWdhdGlvbiggJ3JpZ2h0LWFycm93JywgdGhpcy52aWV3SWQgKTtcblxuXHRcdGZ1bmN0aW9uIGRvUmlnaHRBcnJvd0NsaWNrKCkge1xuXHRcdFx0dmFyIHNlbGVjdGVkX2luZGV4ID0gJHRoaXMuZ2V0UmlnaHRBcnJvd0NsaWNrU2VsZWN0ZWRJbmRleCggJHRoaXMubmF2aWdhdGlvbi5nZXRTZWxlY3RJbmRleCgpICk7XG5cdFx0XHR2YXIgc291cmNlX2RhdGEgPSAkdGhpcy5uYXZpZ2F0aW9uLmdldFNvdXJjZURhdGEoKTtcblx0XHRcdHZhciBjdXJyZW50X3BhZ2VyX2RhdGEgPSAkdGhpcy5uYXZpZ2F0aW9uLmdldFBhZ2VyRGF0YSgpO1xuXHRcdFx0dmFyIG5leHRfc2VsZWN0X2l0ZW07XG5cdFx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdsZW5ndGgnIG9mIG51bGwgaW4gL2ludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj04LjAuMC0yMDE0MTIzMC0xMjU5MTkgbGluZSAyOTU2XG5cdFx0XHRpZiAoICFzb3VyY2VfZGF0YSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHNlbGVjdGVkX2luZGV4IDwgKCBzb3VyY2VfZGF0YS5sZW5ndGggLSAxICkgKSB7XG5cdFx0XHRcdC8vIG5leHRfc2VsZWN0X2l0ZW0gPSAkdGhpcy5uYXZpZ2F0aW9uLmdldEl0ZW1CeUluZGV4KCAoc2VsZWN0ZWRfaW5kZXggKyAxKSApO1xuXHRcdFx0XHRuZXh0X3NlbGVjdF9pdGVtID0gJHRoaXMubmF2aWdhdGlvbi5nZXRJdGVtQnlJbmRleCggJHRoaXMubmF2aWdhdGlvbi5nZXRTZWxlY3RJbmRleCgpICsgMSApO1xuXHRcdFx0XHQkdGhpcy5vblJpZ2h0T3JMZWZ0QXJyb3dDbGlja0NhbGxCYWNrKCBuZXh0X3NlbGVjdF9pdGVtICk7XG5cblx0XHRcdFx0Ly9FcnJvcjogVW5hYmxlIHRvIGdldCBwcm9wZXJ0eSAnY3VycmVudF9wYWdlJyBvZiB1bmRlZmluZWQgb3IgbnVsbCByZWZlcmVuY2UgaW4gaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTkuMC4wLTIwMTUxMDE2LTEwMjI1NCBsaW5lIDMyMDRcblx0XHRcdH0gZWxzZSBpZiAoIHNlbGVjdGVkX2luZGV4ID09PSAoIHNvdXJjZV9kYXRhLmxlbmd0aCAtIDEgKSAmJiBjdXJyZW50X3BhZ2VyX2RhdGEgJiYgY3VycmVudF9wYWdlcl9kYXRhLmN1cnJlbnRfcGFnZSA8IGN1cnJlbnRfcGFnZXJfZGF0YS5sYXN0X3BhZ2VfbnVtYmVyICkge1xuXHRcdFx0XHQkdGhpcy5uYXZpZ2F0aW9uLm9uQURyb3BEb3duU2VhcmNoKCAndW5zZWxlY3RfZ3JpZCcsIGN1cnJlbnRfcGFnZXJfZGF0YS5jdXJyZW50X3BhZ2UgKyAxLCAnZmlyc3QnLCBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHRcdG5leHRfc2VsZWN0X2l0ZW0gPSByZXN1bHQ7XG5cdFx0XHRcdFx0JHRoaXMub25SaWdodE9yTGVmdEFycm93Q2xpY2tDYWxsQmFjayggbmV4dF9zZWxlY3RfaXRlbSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkdGhpcy5vbkNhbmNlbENsaWNrKCBudWxsLCBudWxsLCBjYW5jZWxfY2FsbGJhY2sgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdG9uUmlnaHRPckxlZnRBcnJvd0NsaWNrQ2FsbEJhY2soIG5leHRfc2VsZWN0X2l0ZW0gKSB7XG5cdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHRpZiAoIHRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdHRoaXMub25WaWV3Q2xpY2soIG5leHRfc2VsZWN0X2l0ZW0gKTsgLy9Eb250IHJlZnJlc2ggVUlcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5vbkVkaXRDbGljayggbmV4dF9zZWxlY3RfaXRlbS5pZCApOyAvL0RvbnQgcmVmcmVzaCBVSVxuXHRcdH1cblx0XHR0aGlzLnNldE5hdmlnYXRpb25BcnJvd3NFbmFibGVkKCk7XG5cdFx0aWYgKCB0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyICkge1xuXHRcdFx0dGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5zZWFyY2goKTtcblx0XHR9XG5cdH1cblxuXHRzZXRQYXJlbnRDb250ZXh0TWVudUFmdGVyU3ViVmlld0Nsb3NlKCkge1xuXHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2J1aWxkQ29udGV4dE1lbnUnIG9mIG51bGwgaW4gL2ludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj03LjQuNi0yMDE0MTAyNy0wODUwMTYgbGluZSAyODg3XG5cdFx0aWYgKCAhdGhpcy5wYXJlbnRfdmlld19jb250cm9sbGVyICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMucGFyZW50X3ZpZXdfY29udHJvbGxlci5idWlsZENvbnRleHRNZW51KCk7XG5cblx0XHRpZiAoIHRoaXMucGFyZW50X3ZpZXdfY29udHJvbGxlci5lZGl0X3ZpZXcgKSB7XG5cdFx0XHR0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIuc2V0RWRpdE1lbnUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5wYXJlbnRfdmlld19jb250cm9sbGVyLnNldERlZmF1bHRNZW51KCk7XG5cdFx0fVxuXHR9XG5cblx0Ly9UaGlzIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gaXRzIG93biBpZiByZW1vdmVFZGl0VmlldyBpcyBjYXVzaW5nIGZsYXNoaW5nLlxuXHQvL1RoaXMgZnVuY3Rpb24gc2hvdWxkIG9ubHkgcmVhbGx5IGJlIGNhbGxlZCBmcm9tIG9uVmlld0NsaWNrIChzZWUgUmVxdWVzdFZpZXdDb21tb25Db250cm9sbGVyLmpzKVxuXHRjbGVhckVkaXRWaWV3KCkge1xuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHR0aGlzLmNsZWFyRXJyb3JUaXBzKCk7XG5cdFx0XHR0aGlzLmVkaXRfdmlldy5yZW1vdmUoKTtcblx0XHR9XG5cdFx0dGhpcy5lZGl0X3ZpZXcgPSBudWxsO1xuXHRcdHRoaXMuZWRpdF92aWV3X3RhYiA9IG51bGw7XG5cdH1cblxuXHRyZW1vdmVFZGl0VmlldygpIHtcblx0XHR0aGlzLnVubW91bnRDb250ZXh0TWVudSgpO1xuXHRcdHRoaXMuY2xlYXJFZGl0VmlldygpO1xuXHRcdHRoaXMuc2V0Q3VycmVudEVkaXRWaWV3U3RhdGUoICcnICk7XG5cdFx0dGhpcy5pc19jaGFuZ2VkID0gZmFsc2U7XG5cdFx0dGhpcy5jb25maXJtX29uX2V4aXQgPSBmYWxzZTtcblx0XHR0aGlzLm1hc3NfZWRpdF9yZWNvcmRfaWRzID0gW107XG5cblx0XHRpZiAoIHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHR2YXIgY3VycmVudF91cmwgPSB3aW5kb3cubG9jYXRpb24uaHJlZjtcblx0XHRcdGlmICggY3VycmVudF91cmwuaW5kZXhPZiggJyZzbScgKSA+IDAgKSB7XG5cdFx0XHRcdGN1cnJlbnRfdXJsID0gY3VycmVudF91cmwuc3Vic3RyaW5nKCAwLCBjdXJyZW50X3VybC5pbmRleE9mKCAnJnNtJyApICk7XG5cdFx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIGN1cnJlbnRfdXJsICk7XG5cdFx0XHR9XG5cblx0XHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9lZGl0X29ubHlfY29udHJvbGxlciA9IG51bGw7XG5cdFx0fVxuXG5cdFx0Ly8gcmVzZXQgcGFyZW50IGNvbnRleHQgbWVudSBpZiBlZGl0IG9ubHkgbW9kZVxuXG5cdFx0aWYgKCAhdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdC8vIzI3NzcgLSBJZiB0aGUgdXNlciBnb2VzIHRvIEVtcGxveWVlIC0+IEVtcGxveWVlcywgY2xpY2sgb24gV2FnZSB0YWIsIHRoZW4gZ29lcyB0byBFbXBsb3llZSAtPiBFbXBsb3llZXMgYWdhaW4sIHRoZSBDb250ZXh0IE1lbnUgd2lsbCBiZSBpbmNvcnJlY3QgYW5kIHN0aWxsIGJlIGZvciB0aGUgXCJXYWdlXCIgcmVjb3JkIGFuZCBub3QgdGhlIHByb3BlciBcIkVtcGxveWVlXCIgcmVjb3JkLlxuXHRcdFx0Ly9UaGlzIHRyaWVzIHRvIGRldGVjdCB3aGVuIHRoZSBjb250ZXh0IG1lbnUgZG9lc24ndCBtYXRjaCB0aGUgdmlldyBhbmQgZm9yY2VzIGl0IHRvIGJlIHJlYnVpbHQgY29tcGxldGVseS5cblxuXHRcdFx0dGhpcy5idWlsZENvbnRleHRNZW51KCB0cnVlICk7XG5cdFx0XHR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2V0UGFyZW50Q29udGV4dE1lbnVBZnRlclN1YlZpZXdDbG9zZSgpO1xuXHRcdH1cblx0XHR0aGlzLnJlU2V0VVJMKCk7XG5cdFx0Ly9JZiB0aGVyZSBpcyBhIGFjdGlvbiBpbiB1cmwsIGFkZCBpdCBiYWNrLiBTbyB3ZSBoYXZlIGNvcnJlY3QgdXJsIHdoZW4gc2V0IHRhYnMgdXJsc1xuXHRcdC8vVGhpcyBjYXVzZWQgYSBidWcgd2hlcmUgd2hlbmV2ZXIgc2F2aW5nIGEgcHVuY2ggb24gQXR0ZW5kYW5jZSAtPlRpbWVTaGVldCwgaXQgd291bGQgcmUtb3BlbiB0aGUgZWRpdCB2aWV3LCBzYW1lIHdpdGggbmF2aWdhdGluZyBiZXR3ZWVuIHdlZWtzLCBvciBldmVuIGRlbGV0aW5nIHB1bmNoZXMgaW4gc29tZSBjYXNlcy5cblx0XHQvL1RoaXMgbmVlZCB0byBwdXQgdW5kZXIgcmVTZXRVcmwgYW5kIG5lZWQgY2xlYW4gdXJsX2FncnMgdW50aWwgaXQgc2V0IGZyb20gb25WaWV3Q2hhbmdlIGluIHJvdXRlciBhZ2FpblxuXHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpICYmIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5hICkge1xuXHRcdFx0TG9jYWxDYWNoZURhdGEuY3VycmVudF9kb2luZ19jb250ZXh0X2FjdGlvbiA9IExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5hO1xuXHRcdH1cblxuXHRcdHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIgPSBudWxsO1xuXHRcdHRoaXMuZWRpdF92aWV3X3VpX2RpYyA9IHt9O1xuXHRcdHRoaXMuZWRpdF92aWV3X3VpX3ZhbGlkYXRpb25fZmllbGRfZGljID0ge307XG5cdFx0dGhpcy5lZGl0X3ZpZXdfZm9ybV9pdGVtX2RpYyA9IHt9O1xuXHRcdHRoaXMuZWRpdF92aWV3X2Vycm9yX3VpX2RpYyA9IHt9O1xuXHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IG51bGw7XG5cblx0XHRpZiAoIHRoaXMuc3ViX2RvY3VtZW50X3ZpZXdfY29udHJvbGxlciApIHtcblx0XHRcdHRoaXMuc3ViX2RvY3VtZW50X3ZpZXdfY29udHJvbGxlciA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0cmVTZXRVUkwoKSB7XG5cdFx0aWYgKCB0aGlzLmNhblNldFVSTCgpICkge1xuXHRcdFx0dmFyIGFyZ3MgPSAnIyFtPScgKyB0aGlzLnZpZXdJZDtcblx0XHRcdEdsb2JhbC5zZXRVUkxUb0Jyb3dzZXIoIEdsb2JhbC5nZXRCYXNlVVJMKCkgKyBhcmdzICk7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5zZXRBbGxVUkxBcmdzKCBHbG9iYWwuYnVpbGRBcmdEaWMoIGFyZ3Muc3BsaXQoICcmJyApICkgKTtcblx0XHR9XG5cdH1cblxuXHRnZXRHcmlkU2VsZWN0SWRBcnJheSgpIHtcblx0XHRpZiAoICF0aGlzLmdyaWQgKSB7XG5cdFx0XHRyZXR1cm4gW107IC8vUmV0dXJuIGVtcHR5IGFycmF5IHNvIC5sZW5ndGggb24gdGhlIHJlc3VsdCBkb2Vzbid0IGZhaWwgd2l0aCBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnbGVuZ3RoJyBvZiB1bmRlZmluZWRcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5ncmlkLmdldFNlbGVjdGVkUm93cygpO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVBZGRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBJZCApIHtcblx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcElkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUVkaXRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBfaWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXG5cdFx0Ly8gVXBkYXRlZCB0byB0b2dnbGUgd2l0aCBtYXNzIGVkaXQgaWNvbiBpbiBuZXcgbWVudSAtIE5vdGU6IFRoaXMgbG9naWMgaXMgZHVwbGljYXRlZCBpbiBUaW1lU2hlZXRWaWV3Q29udHJvbGxlci5cblx0XHRpZiAoIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID09PSAxICYmIHRoaXMuZWRpdE93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdFx0aWYgKCBncmlkX3NlbGVjdGVkX2xlbmd0aCAhPT0gMCApIHtcblx0XHRcdFx0Ly8gVGhpcyBlbnN1cmVzIHRoZSBlZGl0IGljb24gaXMgc3RpbGwgdmlzaWJsZSB3aGVuIG5vdGhpbmcgaXMgc2VsZWN0ZWQsIGJ1dCBzaG91bGQgc3RpbGwgYmUgZGlzYWJsZWQuICh0byBrZWVwIGNvbnNpc3RlbmN5IHdpdGggb2xkIGRlc2lnbilcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudVZpZXdJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBfaWQgKSB7XG5cdFx0aWYgKCAhdGhpcy52aWV3UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRpZiAoIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID09PSAxICYmIHRoaXMudmlld093bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSgpICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldERlZmF1bHRNZW51TWFzc0VkaXRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBJZCApIHtcblx0XHRpZiAoICF0aGlzLmVkaXRQZXJtaXNzaW9uVmFsaWRhdGUoIHBJZCApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblxuXHRcdC8vIHVwZGF0ZWQgdG8gdG9nZ2xlIHdpdGggbWFzcyBlZGl0IGljb24gaW4gbmV3IG1lbnVcblx0XHRpZiAoIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID4gMSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVDb3B5SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoLCBwSWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5jb3B5UGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPj0gMSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudURlbGV0ZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCwgcElkICkge1xuXHRcdGlmICggIXRoaXMuZGVsZXRlUGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPj0gMSAmJiB0aGlzLmRlbGV0ZU93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcElkICkgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVEZWxldGVBbmROZXh0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoLCBwSWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5kZWxldGVQZXJtaXNzaW9uVmFsaWRhdGUoIHBJZCApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0fVxuXG5cdHNldERlZmF1bHRNZW51U2F2ZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCwgcElkICkge1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVTYXZlQW5kTmV4dEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCwgcElkICkge1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVTYXZlQW5kQ29weUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCwgcElkICkge1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVTYXZlQW5kQ29udGludWVJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBJZCApIHtcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0fVxuXG5cdHNldERlZmF1bHRNZW51U2F2ZUFuZEFkZEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCwgcElkICkge1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVDb3B5QXNOZXdJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBJZCApIHtcblx0XHRpZiAoICggIXRoaXMuY29weUFzTmV3UGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSApIHx8IHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCBncmlkX3NlbGVjdGVkX2xlbmd0aCA9PT0gMSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUxvZ2luSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoLCBwSWQgKSB7XG5cdFx0aWYgKCAhUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoICdjb21wYW55JywgJ2xvZ2luX290aGVyX3VzZXInICkgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmdldEdyaWRTZWxlY3RJZEFycmF5KCkubGVuZ3RoICE9PSAxICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudUNhbmNlbEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCwgcElkICkge1xuXHRcdGlmICggIXRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldERlZmF1bHRNZW51RXhwb3J0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoLCBwSWQgKSB7XG5cdFx0aWYgKCB0aGlzLmVkaXRfb25seV9tb2RlIHx8IHRoaXMuaXNfdmlld2luZyB8fCB0aGlzLmlzX2VkaXQgfHwgdGhpcy5pc19hZGQgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH0gZWxzZSBpZiAoIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID09IDAgfHwgdGhpcy5ncmlkID09IHVuZGVmaW5lZCApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RGVmYXVsdE1lbnVJbXBvcnRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGgsIHBJZCApIHtcblx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcElkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXREZWZhdWx0TWVudVBlcm1pc3Npb25XaXphcmRJY29uKCBjb250ZXh0X2J0biwgcElkICkge1xuXHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdH1cblxuXHRzZXRFZGl0TWVudVBlcm1pc3Npb25XaXphcmRJY29uKCBjb250ZXh0X2J0biwgcElkICkge1xuXHR9XG5cblx0c2V0RWRpdE1lbnVJbXBvcnRJY29uKCBjb250ZXh0X2J0biApIHtcblx0XHRpZiAoIHRoaXMuZWRpdF9vbmx5X21vZGUgfHwgdGhpcy5pc192aWV3aW5nIHx8IHRoaXMuaXNfZWRpdCB8fCB0aGlzLmlzX2FkZCApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51QWRkSWNvbiggY29udGV4dF9idG4sIHBJZCApIHtcblx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcElkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuaXNfYWRkID09IHRydWUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51RWRpdEljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlIHx8IHRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0Ly9Ob3Qgc2hvd24gaW4gZWRpdCBvbmx5IG1vZGUgb3IgbWFzcyBlZGl0LiBNYXNzIGVkaXQgc2hvdWxkIG9ubHkgc2hvdyBtYXNzIGVkaXQgKG5lZWQgdG8gc2V0IHRoYXQgcGFydCBpbiBtYXNzIGVkaXQgaWNvbikuXG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuaXNfdmlld2luZyB8fCAhdGhpcy5lZGl0T3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RWRpdE1lbnVOYXZFZGl0SWNvbiggY29udGV4dF9idG4sIHBfaWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudU5hdlZpZXdJY29uKCBjb250ZXh0X2J0biwgcF9pZCApIHtcblx0XHRpZiAoICF0aGlzLnZpZXdQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51Vmlld0ljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RWRpdE1lbnVNYXNzRWRpdEljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlIHx8ICF0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHR9XG5cblx0c2V0RWRpdE1lbnVEZWxldGVJY29uKCBjb250ZXh0X2J0biwgcElkICkge1xuXHRcdGlmICggIXRoaXMuZGVsZXRlUGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB8fCAhdGhpcy5kZWxldGVPd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBJZCApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudURlbGV0ZUFuZE5leHRJY29uKCBjb250ZXh0X2J0biwgcElkICkge1xuXHRcdGlmICggIXRoaXMuZGVsZXRlUGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB8fCAhdGhpcy5kZWxldGVPd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBJZCApICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudUNvcHlJY29uKCBjb250ZXh0X2J0biwgcElkICkge1xuXHRcdGlmICggIXRoaXMuY29weVBlcm1pc3Npb25WYWxpZGF0ZSggcElkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RWRpdE1lbnVDb3B5QW5kQWRkSWNvbiggY29udGV4dF9idG4sIHBJZCApIHtcblx0XHRpZiAoICF0aGlzLmNvcHlBc05ld1Blcm1pc3Npb25WYWxpZGF0ZSggcElkICkgfHwgdGhpcy5lZGl0X29ubHlfbW9kZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHRpZiAoICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkgfHwgdGhpcy5pc192aWV3aW5nICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVJY29uKCBjb250ZXh0X2J0biwgcElkICkge1xuXG5cdFx0dGhpcy5zYXZlVmFsaWRhdGUoIGNvbnRleHRfYnRuLCBwSWQgKTtcblxuXHRcdGlmICggdGhpcy5pc192aWV3aW5nICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudVNhdmVBbmRDb250aW51ZUljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0dGhpcy5zYXZlQW5kQ29udGludWVWYWxpZGF0ZSggY29udGV4dF9idG4sIHBJZCApO1xuXG5cdFx0aWYgKCB0aGlzLmlzX21hc3NfYWRkaW5nIHx8IHRoaXMuaXNfbWFzc19lZGl0aW5nIHx8IHRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RWRpdE1lbnVTYXZlQW5kQ29weUljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0dGhpcy5zYXZlQW5kQ29weVZhbGlkYXRlKCBjb250ZXh0X2J0biwgcElkICk7XG5cblx0XHRpZiAoIHRoaXMuaXNfbWFzc19lZGl0aW5nIHx8IHRoaXMuaXNfdmlld2luZyApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0fVxuXHR9XG5cblx0c2V0RWRpdE1lbnVTYXZlQW5kTmV4dEljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwSWQgKSB8fCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblxuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB8fCB0aGlzLmlzX3ZpZXdpbmcgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51U2F2ZUFuZEFkZEljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdFx0dGhpcy5zYXZlQW5kTmV3VmFsaWRhdGUoIGNvbnRleHRfYnRuLCBwSWQgKTtcblxuXHRcdGlmICggdGhpcy5pc192aWV3aW5nIHx8IHRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHR9XG5cdH1cblxuXHRzZXRFZGl0TWVudUNhbmNlbEljb24oIGNvbnRleHRfYnRuLCBwSWQgKSB7XG5cdH1cblxuXHRpZkNvbnRleHRCdXR0b25FeGlzdCggdmFsdWUgKSB7XG5cdFx0dmFyIGNvbnRleHRfbWVudV9hcnJheSA9IENvbnRleHRNZW51TWFuYWdlci5nZXRNZW51TW9kZWxCeU1lbnVJZCggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkICk7XG5cdFx0dmFyIGxlbiA9IGNvbnRleHRfbWVudV9hcnJheS5sZW5ndGg7XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRsZXQgY29udGV4dF9idG4gPSBjb250ZXh0X21lbnVfYXJyYXlbaV07XG5cdFx0XHRsZXQgaWQgPSBjb250ZXh0X21lbnVfYXJyYXlbaV0uaWQ7XG5cdFx0XHRpZiAoIGlkID09PSB2YWx1ZSAmJiBjb250ZXh0X2J0bi52aXNpYmxlICkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0b25TdWJWaWV3TW9kZURpc2FibGVQYXJlbnRDb250ZXh0TWVudUJ1dHRvbnMoKSB7XG5cdFx0Ly9XaGVuIG9uIGEgc3ViIHZpZXcgbW9kZSB0YWIgd2Ugd2FudCB0byBkaXNhYmxlIGNlcnRhaW4gY29udGV4dCBtZW51IGJ1dHRvbnMgb2YgdGhlIHBhcmVudCB2aWV3LlxuXHRcdC8vVGhpcyBpcyB0byBoZWxwIHByZXZlbnQgdXNlcnMgZnJvbSB1c2luZyBjb250ZXh0IG1lbnUgYnV0dG9ucyBmb3IgdGhlIHdyb25nIHZpZXcgYW5kIGRlbGV0aW5nL2NvcHlpbmcgcmVjb3JkcyB0aGV5IGRpZCBub3QgaW50ZW5kIHRvIHVzZS5cblx0XHRpZiAoIHRoaXMuc3ViX3ZpZXdfbW9kZSAmJiB0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIgKSB7XG5cdFx0XHR2YXIgcGFyZW50X2NvbnRleHRfbWVudV9hcnJheSA9IENvbnRleHRNZW51TWFuYWdlci5nZXRNZW51TW9kZWxCeU1lbnVJZCggdGhpcy5wYXJlbnRfdmlld19jb250cm9sbGVyLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKTtcblx0XHRcdHZhciBsZW4gPSBwYXJlbnRfY29udGV4dF9tZW51X2FycmF5Lmxlbmd0aDtcblxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdGxldCBjb250ZXh0X2J0biA9IHBhcmVudF9jb250ZXh0X21lbnVfYXJyYXlbaV07XG5cdFx0XHRcdGxldCBpZCA9IHBhcmVudF9jb250ZXh0X21lbnVfYXJyYXlbaV0uaWQ7XG5cblx0XHRcdFx0Ly9Td2l0Y2ggaW5zdGVhZCBvZiBpZi9lbHNlIGluY2FzZSB3ZSB3YW50IGRpZmZlcmVuY2VzIGJldHdlZW4gYnV0dG9ucyBpbiBmdXR1cmUsIGVhc2llciB0byByZWFkIHRoYW4gbG9uZyBjb25kaXRpb25hbC5cblx0XHRcdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRcdFx0Y2FzZSAnYWRkJzpcblx0XHRcdFx0XHRjYXNlICdkZWxldGVfaWNvbic6XG5cdFx0XHRcdFx0Y2FzZSAnZGVsZXRlX2FuZF9uZXh0Jzpcblx0XHRcdFx0XHRjYXNlICdjb3B5Jzpcblx0XHRcdFx0XHRjYXNlICdjb3B5X2FzX25ldyc6XG5cdFx0XHRcdFx0Y2FzZSAnc2F2ZV9hbmRfY29weSc6XG5cdFx0XHRcdFx0Y2FzZSAnc2F2ZV9hbmRfbmV3Jzpcblx0XHRcdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMucGFyZW50X3ZpZXdfY29udHJvbGxlci5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGhpZGVKdW1wVG9NZW51KCkge1xuXHRcdC8vSnVtcCB0byBzaG91bGQgYmUgaGlkZGVuIG9uIGFsbCBcIm5ld1wiIHJlY29yZCB2aWV3cyBhbmQgb25seSBhdmFpbGFibGUgd2hlbiBlZGl0aW5nIGEgcmVjb3JkLlxuXHRcdC8vVGhpcyBpcyB0byBwcmV2ZW50IHVzZXJzIGZyb20gdXNpbmcgdGhlIGp1bXAgdG8gYnV0dG9uIHRvIG5hdmlnYXRpbmcgdG8gYnJva2VuIG9yIGJsYW5rIHBhZ2VzLlxuXHRcdGlmICggdGhpcy5pc19hZGQgfHwgdGhpcy5pc19tYXNzX2FkZGluZyApIHtcblx0XHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBjb250ZXh0X21lbnVfYXJyYXkubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdGlmICggY29udGV4dF9tZW51X2FycmF5W2ldLmFjdGlvbl9ncm91cCA9PT0gJ2p1bXBfdG8nICkge1xuXHRcdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9tZW51X2FycmF5W2ldLmlkLCBmYWxzZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly9DYWxsIHRoaXMgd2hlbiBzZWxlY3QgZ3JpZCByb3dcblx0Ly9DYWxsIHRoaXMgd2hlbiBzZXRMYXlvdXRcblx0c2V0RGVmYXVsdE1lbnUoIGRvTm90U2V0Rm9jdXMsIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdC8vQ2hlY2sgaWYgdGhlcmUgaXMgYSBjdXJyZW50X2NvbXBhbnkgb2JqZWN0IGF0IGFsbC5cblx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmlzTG9jYWxDYWNoZUV4aXN0cyggJ2N1cnJlbnRfY29tcGFueScgKSA9PSBmYWxzZSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHR0aGlzLnNldFRvdGFsRGlzcGxheVNwYW4oKTtcblxuXHRcdHZhciBjb250ZXh0X21lbnVfYXJyYXkgPSBDb250ZXh0TWVudU1hbmFnZXIuZ2V0TWVudU1vZGVsQnlNZW51SWQoIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCApO1xuXHRcdHZhciBsZW4gPSBjb250ZXh0X21lbnVfYXJyYXkubGVuZ3RoO1xuXHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhciBncmlkX3NlbGVjdGVkX2lkX2FycmF5ID0gdGhpcy5nZXRHcmlkU2VsZWN0SWRBcnJheSgpO1xuXHRcdFx0Z3JpZF9zZWxlY3RlZF9sZW5ndGggPSBncmlkX3NlbGVjdGVkX2lkX2FycmF5Lmxlbmd0aDtcblx0XHR9XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGxldCBjb250ZXh0X2J0biA9IGNvbnRleHRfbWVudV9hcnJheVtpXTtcblx0XHRcdGxldCBpZCA9IGNvbnRleHRfbWVudV9hcnJheVtpXS5pZDtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIHRydWUgKTtcblxuXHRcdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRcdGNhc2UgJ2FkZCc6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUFkZEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdlZGl0Jzpcblx0XHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51RWRpdEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICd2aWV3Jzpcblx0XHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51Vmlld0ljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdtYXNzX2VkaXQnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVNYXNzRWRpdEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdjb3B5Jzpcblx0XHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51Q29weUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdkZWxldGVfaWNvbic6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudURlbGV0ZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdkZWxldGVfYW5kX25leHQnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVEZWxldGVBbmROZXh0SWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3NhdmUnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVTYXZlSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3NhdmVfYW5kX25leHQnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVTYXZlQW5kTmV4dEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdzYXZlX2FuZF9jb250aW51ZSc6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudVNhdmVBbmRDb250aW51ZUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdzYXZlX2FuZF9uZXcnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVTYXZlQW5kQWRkSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3NhdmVfYW5kX2NvcHknOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVTYXZlQW5kQ29weUljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdjb3B5X2FzX25ldyc6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUNvcHlBc05ld0ljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdsb2dpbic6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUxvZ2luSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2NhbmNlbCc6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUNhbmNlbEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdpbXBvcnRfaWNvbic6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUltcG9ydEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdwZXJtaXNzaW9uX3dpemFyZCc6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudVBlcm1pc3Npb25XaXphcmRJY29uKCBjb250ZXh0X2J0biwgZ3JpZF9zZWxlY3RlZF9sZW5ndGggKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnbWFwJzpcblx0XHRcdFx0XHR0aGlzLnNldERlZmF1bHRNZW51TWFwSWNvbiggY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2V4cG9ydF9leGNlbCc6XG5cdFx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudUV4cG9ydEljb24oIGNvbnRleHRfYnRuLCBncmlkX3NlbGVjdGVkX2xlbmd0aCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdHRoaXMuc2V0Q3VzdG9tRGVmYXVsdE1lbnVJY29uKCBpZCwgY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHR9XG5cblx0XHR0aGlzLmluaXRSaWdodENsaWNrTWVudSgpO1xuXHR9XG5cblx0c2V0Q3VzdG9tRGVmYXVsdE1lbnVJY29uKCBpZCwgY29udGV4dF9idG4sIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoICkge1xuXHRcdHJldHVybiBmYWxzZTsgLy9GQUxTRSB0ZWxscyBzZXRDdXN0b21EZWZhdWx0TWVudUljb24oKSB0byBrZWVwIHByb2Nlc3NpbmcuXG5cdH1cblxuXHRzZXRFZGl0TWVudSgpIHtcblx0XHR2YXIgY29udGV4dF9tZW51X2FycmF5ID0gQ29udGV4dE1lbnVNYW5hZ2VyLmdldE1lbnVNb2RlbEJ5TWVudUlkKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKTtcblxuXHRcdHZhciBsZW4gPSBjb250ZXh0X21lbnVfYXJyYXkubGVuZ3RoO1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0bGV0IGNvbnRleHRfYnRuID0gY29udGV4dF9tZW51X2FycmF5W2ldO1xuXHRcdFx0bGV0IGlkID0gY29udGV4dF9tZW51X2FycmF5W2ldLmlkO1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXG5cdFx0XHRpZiAoIHRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdFx0XHRjYXNlICdzYXZlJzpcblx0XHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVTYXZlSWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ2VkaXQnOlxuXHRcdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUVkaXRJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnY2FuY2VsJzpcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoICggaWQgKSB7XG5cdFx0XHRcdGNhc2UgJ2FkZCc6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUFkZEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2VkaXQnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVFZGl0SWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAndmlldyc6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudVZpZXdJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdtYXNzX2VkaXQnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVNYXNzRWRpdEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2NvcHknOlxuXHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVDb3B5SWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnZGVsZXRlX2ljb24nOlxuXHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVEZWxldGVJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdkZWxldGVfYW5kX25leHQnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVEZWxldGVBbmROZXh0SWNvbiggY29udGV4dF9idG4gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnc2F2ZSc6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudVNhdmVJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdzYXZlX2FuZF9jb250aW51ZSc6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudVNhdmVBbmRDb250aW51ZUljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3NhdmVfYW5kX25ldyc6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudVNhdmVBbmRBZGRJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdzYXZlX2FuZF9uZXh0Jzpcblx0XHRcdFx0XHR0aGlzLnNldEVkaXRNZW51U2F2ZUFuZE5leHRJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdzYXZlX2FuZF9jb3B5Jzpcblx0XHRcdFx0XHR0aGlzLnNldEVkaXRNZW51U2F2ZUFuZENvcHlJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdjb3B5X2FzX25ldyc6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUNvcHlBbmRBZGRJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdjYW5jZWwnOlxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdpbXBvcnRfaWNvbic6XG5cdFx0XHRcdFx0dGhpcy5zZXRFZGl0TWVudUltcG9ydEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ3Blcm1pc3Npb25fd2l6YXJkJzpcblx0XHRcdFx0XHR0aGlzLnNldEVkaXRNZW51UGVybWlzc2lvbldpemFyZEljb24oIGNvbnRleHRfYnRuICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ2xvZ2luJzpcblx0XHRcdFx0XHR0aGlzLnNldEVkaXRNZW51TG9naW5JY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdtYXAnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RWRpdE1lbnVNYXBJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdleHBvcnRfZXhjZWwnOlxuXHRcdFx0XHRcdHRoaXMuc2V0RGVmYXVsdE1lbnVFeHBvcnRJY29uKCBjb250ZXh0X2J0biApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdHRoaXMuc2V0Q3VzdG9tRWRpdE1lbnVJY29uKCBpZCwgY29udGV4dF9idG4gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmhpZGVKdW1wVG9NZW51KCk7XG5cdFx0dGhpcy5pbml0UmlnaHRDbGlja01lbnUoIFJpZ2h0Q2xpY2tNZW51VHlwZS5FRElUVklFVyApO1xuXHR9XG5cblx0c2V0Q3VzdG9tRWRpdE1lbnVJY29uKCBpZCwgY29udGV4dF9idG4gKSB7XG5cdFx0cmV0dXJuIGZhbHNlOyAvL0ZBTFNFIHRlbGxzIHNldEN1c3RvbUVkaXRNZW51SWNvbigpIHRvIGtlZXAgcHJvY2Vzc2luZy5cblx0fVxuXG5cdHNldERlZmF1bHRNZW51TWFwSWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0aWYgKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA8PSAxMCApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cblx0XHR2YXIgc2hvdyA9IGZhbHNlO1xuXHRcdGlmICggdGhpcy5ncmlkICkge1xuXHRcdFx0dmFyIHNlbGVjdGVkX2l0ZW1zID0gdGhpcy5nZXRTZWxlY3RlZEl0ZW1zKCk7XG5cdFx0XHREZWJ1Zy5BcnIoIHNlbGVjdGVkX2l0ZW1zLCAnc2VsZWN0ZWQgaXRlbXMnLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdzZXREZWZhdWx0TWVudU1hcEljb24nLCAxMCApO1xuXHRcdFx0aWYgKCBzZWxlY3RlZF9pdGVtcy5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRmb3IgKCB2YXIgeCA9IDA7IHggPCBzZWxlY3RlZF9pdGVtcy5sZW5ndGg7IHgrKyApIHtcblx0XHRcdFx0XHRpZiAoIHNlbGVjdGVkX2l0ZW1zW3hdICYmIHNlbGVjdGVkX2l0ZW1zW3hdLmxhdGl0dWRlICYmIHNlbGVjdGVkX2l0ZW1zW3hdLmxvbmdpdHVkZSApIHtcblx0XHRcdFx0XHRcdHNob3cgPSB0cnVlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCBzaG93ICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgdHJ1ZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApO1xuXHRcdH1cblx0fVxuXG5cdHNldEVkaXRNZW51TWFwSWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0dGhpcy5zZXREZWZhdWx0TWVudU1hcEljb24oIGNvbnRleHRfYnRuICk7XG5cdH1cblxuXHRzZXRFZGl0TWVudUxvZ2luSWNvbiggY29udGV4dF9idG4gKSB7XG5cdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmRpc2FibGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKTtcblx0fVxuXG5cdHNldEVycm9yTWVudSgpIHtcblx0XHR2YXIgY29udGV4dF9tZW51X2FycmF5ID0gQ29udGV4dE1lbnVNYW5hZ2VyLmdldE1lbnVNb2RlbEJ5TWVudUlkKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQgKTtcblx0XHR2YXIgbGVuID0gY29udGV4dF9tZW51X2FycmF5Lmxlbmd0aDtcblxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0bGV0IGNvbnRleHRfYnRuID0gY29udGV4dF9tZW51X2FycmF5W2ldO1xuXHRcdFx0bGV0IGlkID0gY29udGV4dF9tZW51X2FycmF5W2ldLmlkO1xuXG5cdFx0XHRpZiAoIGNvbnRleHRfbWVudV9hcnJheVtpXS5zcGxpdF9idXR0b25fYWN0aXZlX2l0ZW0gKSB7XG5cdFx0XHRcdC8vVGVtcG9yYXJpbHkgc2V0cyBzcGxpdCBidXR0b24gdG8gaWdub3JlIHJlc2V0dGluZyBvZiB0aGUgYWN0aXZlIGl0ZW0uIFRoaXMgc3RvcHMgYWN0aXZlIHNwbGl0IGJ1dHRvbiBpdGVtIGZyb20gcmVzZXR0aW5nLlxuXHRcdFx0XHQvL0V4YW1wbGUgaWYgZG9pbmcgXCJTYXZlICYgQ29udGludWVcIiB3ZSBkbyBub3Qgd2FudCB0aGUgYnV0dG9uIHRvIHN3aXRjaCBiYWNrIHRvIFwiU2F2ZVwiIGp1c3QgYmVjYXVzZSB2YWxpZGF0aW9uIGZhaWxlZC5cblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmZyZWV6ZVNwbGl0QnV0dG9uQWN0aXZlSXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCApO1xuXHRcdFx0fVxuXG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuZGlzYWJsZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCB0cnVlICk7XG5cblx0XHRcdHN3aXRjaCAoIGlkICkge1xuXHRcdFx0XHRjYXNlICdjYW5jZWwnOlxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5kaXNhYmxlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHR9XG5cdH1cblxuXHRyZW5kZXIoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdCQoIHdpbmRvdyApLm9mZiggJ3Jlc2l6ZS5lZGl0X3RhYnMnICkub24oICdyZXNpemUuZWRpdF90YWJzJywgR2xvYmFsLmRlYm91bmNlKCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggJHRoaXMuZWRpdF92aWV3ICkge1xuXHRcdFx0XHQkdGhpcy5zZXRFZGl0Vmlld1RhYlNpemUoKTtcblx0XHRcdH1cblx0XHR9LCAyMDAgKSApO1xuXG5cdFx0VFRQcm9taXNlLmFkZCggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXRDdXN0b21GaWVsZHMnICk7XG5cblx0XHR0aGlzLmdldEN1c3RvbUZpZWxkc0ZvclZpZXcoKTtcblxuXHRcdC8vQ3JlYXRlIHNlYXJjaCBwYW5lbCBvbmx5IHdoZW4gc2hvdyBhcyBhIG1haW4gdmlld1xuXG5cdFx0aWYgKCAhdGhpcy5zdWJfdmlld19tb2RlICYmICF0aGlzLmVkaXRfb25seV9tb2RlICYmICF0aGlzLnRyZWVfbW9kZSApIHtcblx0XHRcdHZhciBzZWFyY2hfcGFuZWxfdyA9ICQoICQuZm4uU2VhcmNoUGFuZWwuaHRtbC5zZWFyY2hfcGFuZWwgKTtcblxuXHRcdFx0JCggdGhpcy5lbCApLnByZXBlbmQoIHNlYXJjaF9wYW5lbF93ICk7XG5cblx0XHRcdGlmICggIXRoaXMuc2hvd19zZWFyY2hfdGFiICkge1xuXHRcdFx0XHRzZWFyY2hfcGFuZWxfdy5oaWRlKCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuc2VhcmNoX3BhbmVsID0gc2VhcmNoX3BhbmVsX3cuU2VhcmNoUGFuZWwoIHsgdmlld0NvbnRyb2xsZXI6IHRoaXMgfSApO1xuXG5cdFx0XHR0aGlzLnNlYXJjaF9wYW5lbC5vbiggJ3NlYXJjaFRhYlNlbGVjdCcsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQkdGhpcy5vblNlYXJjaFRhYlNlbGVjdDtcblx0XHRcdH0gKTtcblxuXHRcdFx0VFRQcm9taXNlLndhaXQoICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZ2V0Q3VzdG9tRmllbGRzJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHRoaXMuYnVpbGRTZWFyY2hGaWVsZHMoKTtcblx0XHRcdFx0dGhpcy5idWlsZEN1c3RvbUZpZWxkU2VhcmNoRmllbGRzKClcblx0XHRcdFx0dGhpcy5idWlsZEJhc2ljU2VhcmNoVUkoKTtcblx0XHRcdFx0dGhpcy5idWlsZEFkdmFuY2VkU2VhcmNoVUkoKTtcblx0XHRcdFx0dGhpcy5idWlsZFNlYXJjaEFuZExheW91dFVJKCk7XG5cblx0XHRcdFx0Ly9Xb3JrIGFyb3VuZCB0aGF0IHRoZSBsaSBvZmZzZXQgaXMgZW1wdHkgaW4gY2hyb21lXG5cdFx0XHRcdHNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCR0aGlzLnNldEN1cnJlbnRWaWV3UG9zaXRpb24oKTtcblx0XHRcdFx0fSwgNTAwICk7XG5cdFx0XHR9LmJpbmQoIHRoaXMgKSApO1xuXG5cdFx0fVxuXHR9XG5cblx0c2V0Q3VycmVudFZpZXdQb3NpdGlvbigpIHtcblx0XHR2YXIgY3VycmVudF92aWV3X2RpdiA9IHRoaXMuc2VhcmNoX3BhbmVsLmZpbmQoICcubGF5b3V0LXNlbGVjdG9yLWRpdicgKTtcblx0XHR2YXIgc2F2ZWRfbGF5b3V0X2xpID0gdGhpcy5zZWFyY2hfcGFuZWwuZmluZCggJ2FbcmVmPVxcJ3NhdmVkX2xheW91dFxcJ10nICkucGFyZW50KCk7XG5cdFx0Ly8gRXJyb3I6IFVuYWJsZSB0byBnZXQgcHJvcGVydHkgJ2xlZnQnIG9mIHVuZGVmaW5lZCBvciBudWxsIHJlZmVyZW5jZSBpbiAvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTguMC42LTIwMTUwNDE3LTA4Mzg0OSBsaW5lIDM2OTFcblx0XHRpZiAoICFjdXJyZW50X3ZpZXdfZGl2IHx8ICFzYXZlZF9sYXlvdXRfbGkgfHwgIXNhdmVkX2xheW91dF9saS5vZmZzZXQoKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8gTm93IGNvbnRyb2xsZWQgZnJvbSBDU1MgaW4gU2VhcmNoUGFuZWwuY3NzIERvbnQgdW5kZXJzdGFuZCB3aHkgdGhlcmUgaXMgYSBjb21wbGV4IGxlZnQ6IHggSlMgY2FsYywgcmlnaHQgcG9zaXRpb24gc2VlbXMgYmV0dGVyIGFuZCBtb3JlIGNvbnNpc3RlbnQuXG5cdFx0Ly8gY3VycmVudF92aWV3X2Rpdi5jc3MoICdsZWZ0Jywgc2F2ZWRfbGF5b3V0X2xpLm9mZnNldCgpLmxlZnQgKyBzYXZlZF9sYXlvdXRfbGkud2lkdGgoKSAtIDYwICk7IC8vIENoYW5nZSB0byA2MCBpcyB0cmlhbCBhbmQgZXJyb3IgdHJ5aW5nIHRvIHByZXZlbnQgY3VycmVudCB2aWV3IGRyb3Bkb3duIGZyb20gb3ZlcmxhcHBpbmcgaW4gbmV3IGxheW91dCBkZXNpZ25cblx0fVxuXG5cdC8vQnVpbGQgZmllbGRzIHdoZW4gc2VhcmNoIHRhYiBjaGFuZ2Vcblx0b25TZWFyY2hUYWJTZWxlY3QoIGUsIGUxLCB1aSApIHtcblx0XHR2YXIgdGFiX2lkID0gJCggdWkgKS5wcm9wKCAnaWQnICk7XG5cblx0XHRzd2l0Y2ggKCB0YWJfaWQgKSB7XG5cdFx0XHRjYXNlICdiYXNpY19zZWFyY2gnOlxuXG5cdFx0XHRcdGlmICggdGhpcy5zZWFyY2hfcGFuZWwuZ2V0TGFzdFNlbGVjdFRhYklkKCkgIT09ICdzYXZlZF9sYXlvdXQnICkge1xuXHRcdFx0XHRcdHRoaXMuZ2V0U2VhcmNoUGFuZWxGaWx0ZXIoIDEsIHRydWUgKTtcblx0XHRcdFx0XHR0aGlzLmJ1aWxkQmFzaWNTZWFyY2hVSSgpO1xuXHRcdFx0XHRcdHRoaXMuc2V0U2VhcmNoUGFuZWxGaWx0ZXIoIGZhbHNlLCAwICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ2Fkdl9zZWFyY2gnOlxuXHRcdFx0XHRpZiAoIHRoaXMuc2VhcmNoX3BhbmVsLmdldExhc3RTZWxlY3RUYWJJZCgpICE9PSAnc2F2ZWRfbGF5b3V0JyApIHtcblx0XHRcdFx0XHR0aGlzLmdldFNlYXJjaFBhbmVsRmlsdGVyKCAwLCB0cnVlICk7XG5cdFx0XHRcdFx0dGhpcy5idWlsZEFkdmFuY2VkU2VhcmNoVUkoKTtcblx0XHRcdFx0XHR0aGlzLnNldFNlYXJjaFBhbmVsRmlsdGVyKCBmYWxzZSwgMSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdzYXZlZF9sYXlvdXQnOlxuXHRcdFx0XHR0aGlzLmdldFNlYXJjaFBhbmVsRmlsdGVyKCB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXN0U2VsZWN0VGFiSW5kZXgoKSApO1xuXHRcdH1cblx0fVxuXG5cdGluaXREcm9wRG93bk9wdGlvbnMoIG9wdGlvbnMsIGNhbGxCYWNrICkge1xuXHRcdGxldCAkdGhpcyA9IHRoaXM7XG5cdFx0bGV0IGFwaV9ncm91cHMgPSB7fTtcblxuXHRcdC8vRmlsbCBhbnkgdmFsdWVzIHRoYXQgYXJlIG5vdCBzZXQgYW5kIGdyb3VwIG9wdGlvbiBjYWxscyBieSB0aGVpciBBUEkgZW5kcG9pbnQuXG5cdFx0Zm9yICggbGV0IGkgPSAwOyBpIDwgb3B0aW9ucy5sZW5ndGg7IGkrKyApIHtcblx0XHRcdGxldCBvcHRpb24gPSBvcHRpb25zW2ldO1xuXHRcdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBvcHRpb24uYXBpICkgKSB7XG5cdFx0XHRcdG9wdGlvbi5hcGkgPSB0aGlzLmFwaTtcblx0XHRcdH1cblx0XHRcdGlmICggIUdsb2JhbC5pc1NldCggb3B0aW9uLmZpZWxkX25hbWUgKSB8fCAhb3B0aW9uLmZpZWxkX25hbWUgKSB7XG5cdFx0XHRcdG9wdGlvbi5maWVsZF9uYW1lID0gb3B0aW9uLm9wdGlvbl9uYW1lICsgJ19pZCc7XG5cdFx0XHR9XG5cdFx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIG9wdGlvbi5wYXJlbnQgKSB8fCAhb3B0aW9uLnBhcmVudCApIHtcblx0XHRcdFx0b3B0aW9uLnBhcmVudCA9IG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdC8vR3JvdXAgZ2V0T3B0aW9uIGNhbGxzIGJ5IHRoZWlyIEFQSSBlbmRwb2ludC5cblx0XHRcdGlmICggIWFwaV9ncm91cHNbb3B0aW9uLmFwaS5jbGFzc05hbWVdICkge1xuXHRcdFx0XHRhcGlfZ3JvdXBzW29wdGlvbi5hcGkuY2xhc3NOYW1lXSA9IFtdO1xuXHRcdFx0fVxuXHRcdFx0YXBpX2dyb3Vwc1tvcHRpb24uYXBpLmNsYXNzTmFtZV0ucHVzaCggb3B0aW9uICk7XG5cdFx0fVxuXG5cdFx0Ly9DYWxsIGdldE9wdGlvbnNCYXRjaCBvbiBlYWNoIHJlcXVlc3RlZCBBUElcblx0XHRsZXQgY29tcGxldGVkX2FwaV9jYWxscyA9IDA7XG5cdFx0Zm9yICggbGV0IGFwaV9jbGFzcyBpbiBhcGlfZ3JvdXBzICkge1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBhcGlfZ3JvdXBzW2FwaV9jbGFzc10gKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdC8vSXNzdWUgIzMyMjMgLSBFcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBhcGlfZ3JvdXBzW2FwaV9jbGFzc10ucmVkdWNlIGlzIG5vdCBhIGZ1bmN0aW9uXG5cdFx0XHRcdC8vVGhlIGNhdXNlIGZvciB0aGlzIGV4Y2VwdGlvbiBpcyB1bmtub3duIGFzIHRoZSBhYm92ZSBjb2RlIGlzIHN5bmNyb25vdXMgYW5kIHNob3VsZCBhbHdheXMgcHJvZHVjZVxuXHRcdFx0XHQvL3RoZSBzYW1lIHJlc3VsdHMgZ2l2ZW4gdGhlIHNhbWUgaW5wdXQuIEhvd2V2ZXIsIGZvciBzb21lIHJlYXNvbiBhcGlfZ3JvdXBzW2FwaV9jbGFzc10gaXMgbm90IGFuIGFsd2F5cyBhbiBhcnJheS5cblx0XHRcdFx0Ly9UaGlzIGNoYW5nZSBpcyBzaW1wbHkgbWVhbnQgdG8gcHJldmVudCB0aGUgZXJyb3IgZnJvbSBiZWluZyB0aHJvd24uXG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBjYWxsQmFjayApICkge1xuXHRcdFx0XHRcdGNhbGxCYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0RGVidWcuVGV4dCggJ1VuZXhwZWN0ZWQgZXJyb3IgYXBpX2dyb3Vwc1thcGlfY2xhc3NdIGlzIG5vdCBhbiBhcnJheS4nLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdpbml0RHJvcERvd25PcHRpb25zJywgOSApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHQvL1JlZHVjZSBkYXRhIHNlbnQgdG8gQVBJIHdpdGggb25seSBkYXRhIHJlcXVpcmVkIGZvciB0aGUgQVBJLlxuXHRcdFx0bGV0IGRhdGEgPSBhcGlfZ3JvdXBzW2FwaV9jbGFzc10ucmVkdWNlKCAoIG5ld19vYmosIG9wdGlvbiApID0+ICggbmV3X29ialtvcHRpb24ub3B0aW9uX25hbWVdID0gb3B0aW9uLnBhcmVudCwgbmV3X29iaiApLCB7fSApO1xuXHRcdFx0VFRBUElbYXBpX2NsYXNzXS5nZXRPcHRpb25zQmF0Y2goIGRhdGEsIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXNwb25zZSApIHtcblx0XHRcdFx0XHRsZXQgcmVzdWx0cyA9IHJlc3BvbnNlLmdldFJlc3VsdCgpO1xuXHRcdFx0XHRcdGlmICggcmVzdWx0cyAmJiBPYmplY3Qua2V5cyggcmVzdWx0cyApLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0XHRmb3IgKCBsZXQgb3B0aW9uIGluIHJlc3VsdHMgKSB7XG5cdFx0XHRcdFx0XHRcdGxldCBvcHRpb25fZGF0YSA9IHJlc3VsdHNbb3B0aW9uXTtcblx0XHRcdFx0XHRcdFx0bGV0IG9wdGlvbl9maWVsZF9pbmZvID0gYXBpX2dyb3Vwc1thcGlfY2xhc3NdLmZpbmQoIGljb24gPT4gaWNvbi5vcHRpb25fbmFtZSA9PT0gb3B0aW9uICk7XG5cdFx0XHRcdFx0XHRcdC8vU2V0IHZpZXcgY29udHJvbGxlciB2YXJpYWJsZXMgYW5kIGZpZWxkIGRhdGFcblx0XHRcdFx0XHRcdFx0JHRoaXNbb3B0aW9uICsgJ19hcnJheSddID0gR2xvYmFsLmJ1aWxkUmVjb3JkQXJyYXkoIG9wdGlvbl9kYXRhICk7XG5cdFx0XHRcdFx0XHRcdGlmICggISR0aGlzLnN1Yl92aWV3X21vZGUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWNbb3B0aW9uX2ZpZWxkX2luZm8uZmllbGRfbmFtZV0gKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdCR0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWNbb3B0aW9uX2ZpZWxkX2luZm8uZmllbGRfbmFtZV0uc2V0U291cmNlRGF0YSggR2xvYmFsLmJ1aWxkUmVjb3JkQXJyYXkoIG9wdGlvbl9kYXRhICkgKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmFkdl9zZWFyY2hfZmllbGRfdWlfZGljW29wdGlvbl9maWVsZF9pbmZvLmZpZWxkX25hbWVdICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQkdGhpcy5hZHZfc2VhcmNoX2ZpZWxkX3VpX2RpY1tvcHRpb25fZmllbGRfaW5mby5maWVsZF9uYW1lXS5zZXRTb3VyY2VEYXRhKCBHbG9iYWwuYnVpbGRSZWNvcmRBcnJheSggb3B0aW9uX2RhdGEgKSApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGNvbXBsZXRlZF9hcGlfY2FsbHMrKztcblxuXHRcdFx0XHRcdGlmICggT2JqZWN0LmtleXMoIGFwaV9ncm91cHMgKS5sZW5ndGggPT09IGNvbXBsZXRlZF9hcGlfY2FsbHMgJiYgR2xvYmFsLmlzU2V0KCBjYWxsQmFjayApICkge1xuXHRcdFx0XHRcdFx0Ly9Pbmx5IGNhbGwgdGhlIGNhbGxiYWNrIHdoZW4gYWxsIEFQSSBjYWxscyBoYXZlIGNvbXBsZXRlZC5cblx0XHRcdFx0XHRcdGNhbGxCYWNrKCByZXNwb25zZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblx0fVxuXG5cdGJ1aWxkV2lkZ2V0Q29udGFpbmVyV2l0aFRleHRUaXAoIHdpZGdldCwgdGlwICkge1xuXHRcdHZhciBoX2JveCA9ICQoICc8ZGl2IGNsYXNzPVxcJ2gtYm94XFwnPjwvZGl2PicgKTtcblxuXHRcdHZhciB0ZXh0X2JveCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuVEVYVCApO1xuXHRcdHRleHRfYm94LmNzcyggJ21hcmdpbi1sZWZ0JywgJzEwcHgnICk7XG5cdFx0dGV4dF9ib3guVFRleHQoKTtcblx0XHR0ZXh0X2JveC5zZXRWYWx1ZSggdGlwICk7XG5cblx0XHRoX2JveC5hcHBlbmQoIHdpZGdldCApO1xuXHRcdGhfYm94LmFwcGVuZCggdGV4dF9ib3ggKTtcblxuXHRcdHJldHVybiBoX2JveDtcblx0fVxuXG5cdC8vU2V0IG9wdGlvbiBsaXN0IGZvciBzZWFyY2ggcGFuZWwgYW5kIGVkaXQgdmlld1xuXHRpbml0RHJvcERvd25PcHRpb24oIG9wdGlvbl9uYW1lLCBmaWVsZF9uYW1lLCBhcGksIGNhbGxCYWNrLCBhcnJheV9uYW1lICkge1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBhcGkgKSApIHtcblx0XHRcdGFwaSA9IHRoaXMuYXBpO1xuXHRcdH1cblxuXHRcdGlmICggIUdsb2JhbC5pc1NldCggZmllbGRfbmFtZSApIHx8ICFmaWVsZF9uYW1lICkge1xuXHRcdFx0ZmllbGRfbmFtZSA9IG9wdGlvbl9uYW1lICsgJ19pZCc7XG5cdFx0fVxuXHRcdGFwaS5nZXRPcHRpb25zKCBvcHRpb25fbmFtZSwge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXMgKSB7XG5cdFx0XHRcdHZhciByZXN1bHQgPSByZXMuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0aWYgKCBhcnJheV9uYW1lICkge1xuXHRcdFx0XHRcdCR0aGlzW2FycmF5X25hbWVdID0gR2xvYmFsLmJ1aWxkUmVjb3JkQXJyYXkoIHJlc3VsdCApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0JHRoaXNbb3B0aW9uX25hbWUgKyAnX2FycmF5J10gPSBHbG9iYWwuYnVpbGRSZWNvcmRBcnJheSggcmVzdWx0ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoICEkdGhpcy5zdWJfdmlld19tb2RlICkge1xuXG5cdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWNbZmllbGRfbmFtZV0gKSApIHtcblx0XHRcdFx0XHRcdCR0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWNbZmllbGRfbmFtZV0uc2V0U291cmNlRGF0YSggR2xvYmFsLmJ1aWxkUmVjb3JkQXJyYXkoIHJlc3VsdCApICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmFkdl9zZWFyY2hfZmllbGRfdWlfZGljW2ZpZWxkX25hbWVdICkgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5hZHZfc2VhcmNoX2ZpZWxkX3VpX2RpY1tmaWVsZF9uYW1lXS5zZXRTb3VyY2VEYXRhKCBHbG9iYWwuYnVpbGRSZWNvcmRBcnJheSggcmVzdWx0ICkgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGNhbGxCYWNrICkgKSB7XG5cdFx0XHRcdFx0Y2FsbEJhY2soIHJlcyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRjbGVhclNlYXJjaFBhbmVsKCkge1xuXG5cdFx0Zm9yICggdmFyIGtleSBpbiB0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWMgKSB7XG5cdFx0XHR2YXIgc2VhcmNoX2lucHV0ID0gdGhpcy5iYXNpY19zZWFyY2hfZmllbGRfdWlfZGljW2tleV07XG5cdFx0XHRzZWFyY2hfaW5wdXQuc2V0VmFsdWUoIG51bGwgKTtcblx0XHR9XG5cblx0XHRmb3IgKCB2YXIga2V5IGluIHRoaXMuYWR2X3NlYXJjaF9maWVsZF91aV9kaWMgKSB7XG5cdFx0XHRzZWFyY2hfaW5wdXQgPSB0aGlzLmFkdl9zZWFyY2hfZmllbGRfdWlfZGljW2tleV07XG5cdFx0XHRzZWFyY2hfaW5wdXQuc2V0VmFsdWUoIG51bGwgKTtcblx0XHR9XG5cdH1cblxuXHRvblNlYXJjaCgpIHtcblx0XHRUVFByb21pc2UuYWRkKCAnaW5pdCcsICdpbml0JyApO1xuXHRcdFRUUHJvbWlzZS53YWl0KCk7XG5cblx0XHR2YXIgZG9fdXBkYXRlID0gZmFsc2U7XG5cblx0XHQvL2Rvbid0IGtlZXAgdGVtcCBmaWx0ZXIgYW55IG1vcmUsIHNldCB0aGVtIHdoZW4gY2hhbmdlIHRhYlxuXHRcdHRoaXMudGVtcF9hZHZfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0dGhpcy5nZXRTZWFyY2hQYW5lbEZpbHRlcigpO1xuXHRcdGlmICggdGhpcy5zZWFyY2hfcGFuZWwuZ2V0TGF5b3V0c0FycmF5KCkgJiYgdGhpcy5zZWFyY2hfcGFuZWwuZ2V0TGF5b3V0c0FycmF5KCkubGVuZ3RoID4gMCApIHtcblx0XHRcdHZhciBkZWZhdWx0X2xheW91dF9pZCA9ICQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X3NlbGVjdG9yICkuY2hpbGRyZW4oICdvcHRpb246Y29udGFpbnMoXFwnJyArIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICsgJ1xcJyknICkuYXR0ciggJ3ZhbHVlJyApO1xuXG5cdFx0XHRpZiAoICFkZWZhdWx0X2xheW91dF9pZCApIHtcblx0XHRcdFx0dGhpcy5vblNhdmVOZXdMYXlvdXQoIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciBsYXlvdXRfbmFtZSA9IEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lO1xuXG5cdFx0fSBlbHNlIGlmICggdGhpcy5zaG93X3NlYXJjaF90YWIgKSB7XG5cdFx0XHR0aGlzLm9uU2F2ZU5ld0xheW91dCggQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKTtcblx0XHRcdHJldHVybjtcblx0XHR9IGVsc2UgaWYgKCAhdGhpcy5zaG93X3NlYXJjaF90YWIgKSB7XG5cdFx0XHR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0dGhpcy5zZXRHcmlkSGVhZGVyU3R5bGUoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc29ydF9maWx0ZXIgPSB0aGlzLmdldFNlYXJjaFBhbmVsU29ydEZpbHRlcigpO1xuXHRcdHZhciBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnMgPSB0aGlzLmdldFNlYXJjaFBhbmVsRGlzcGxheUNvbHVtbnMoKTtcblxuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5pZCA9IGRlZmF1bHRfbGF5b3V0X2lkO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5kaXNwbGF5X2NvbHVtbnMgPSBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9zb3J0ID0gc29ydF9maWx0ZXI7XG5cblx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5jbGVhckF3ZXNvbWVib3hMYXlvdXRDYWNoZSgpO1xuXHRcdFx0XHRcdCR0aGlzLm5lZWRfc2VsZWN0X2xheW91dF9uYW1lID0gbGF5b3V0X25hbWU7XG5cdFx0XHRcdFx0JHRoaXMuaW5pdExheW91dCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0b25DbGVhclNlYXJjaCgpIHtcblx0XHR2YXIgZG9fdXBkYXRlID0gZmFsc2U7XG5cdFx0aWYgKCB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKSAmJiB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKS5sZW5ndGggPiAwICkge1xuXHRcdFx0dmFyIGRlZmF1bHRfbGF5b3V0X2lkID0gJCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKS5jaGlsZHJlbiggJ29wdGlvbjpjb250YWlucyhcXCcnICsgQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKyAnXFwnKScgKS5hdHRyKCAndmFsdWUnICk7XG5cblx0XHRcdGlmICggIWRlZmF1bHRfbGF5b3V0X2lkICkge1xuXHRcdFx0XHR0aGlzLmNsZWFyU2VhcmNoUGFuZWwoKTtcblx0XHRcdFx0dGhpcy5maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHRcdHRoaXMudGVtcF9hZHZfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdFx0XHR0aGlzLnRlbXBfYmFzaWNfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdFx0XHR0aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRTZWxlY3RHcmlkRGF0YSggdGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucyApO1xuXHRcdFx0XHR0aGlzLnNvcnRfYnlfc2VsZWN0b3Iuc2V0VmFsdWUoIG51bGwgKTtcblxuXHRcdFx0XHR0aGlzLm9uU2F2ZU5ld0xheW91dCggQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgbGF5b3V0X25hbWUgPSBCYXNlVmlld0NvbnRyb2xsZXIuZGVmYXVsdF9sYXlvdXRfbmFtZTtcblx0XHRcdHRoaXMuY2xlYXJTZWFyY2hQYW5lbCgpO1xuXHRcdFx0dGhpcy5maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHR0aGlzLnRlbXBfYWR2X2ZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHRcdHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSA9IG51bGw7XG5cdFx0XHRkb191cGRhdGUgPSB0cnVlO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0dGhpcy5jbGVhclNlYXJjaFBhbmVsKCk7XG5cdFx0XHR0aGlzLmZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHRcdHRoaXMudGVtcF9hZHZfZmlsdGVyX2RhdGEgPSBudWxsO1xuXHRcdFx0dGhpcy50ZW1wX2Jhc2ljX2ZpbHRlcl9kYXRhID0gbnVsbDtcblx0XHRcdHRoaXMuY29sdW1uX3NlbGVjdG9yLnNldFNlbGVjdEdyaWREYXRhKCB0aGlzLmRlZmF1bHRfZGlzcGxheV9jb2x1bW5zICk7XG5cdFx0XHR0aGlzLnNvcnRfYnlfc2VsZWN0b3Iuc2V0VmFsdWUoIG51bGwgKTtcblxuXHRcdFx0dGhpcy5vblNhdmVOZXdMYXlvdXQoIEJhc2VWaWV3Q29udHJvbGxlci5kZWZhdWx0X2xheW91dF9uYW1lICk7XG5cdFx0XHRyZXR1cm47XG5cblx0XHR9XG5cbi8vXHRcdHRoaXMuY29sdW1uX3NlbGVjdG9yLnNldFNlbGVjdEdyaWREYXRhKCB0aGlzLmRlZmF1bHRfZGlzcGxheV9jb2x1bW5zICk7XG5cblx0XHR0aGlzLnNvcnRfYnlfc2VsZWN0b3Iuc2V0VmFsdWUoIG51bGwgKTtcblxuXHRcdHZhciBzb3J0X2ZpbHRlciA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxTb3J0RmlsdGVyKCk7XG5cdFx0dmFyIHNlbGVjdGVkX2Rpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxEaXNwbGF5Q29sdW1ucygpO1xuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdGlmICggZG9fdXBkYXRlICkge1xuXHRcdFx0dmFyIGFyZ3MgPSB7fTtcblx0XHRcdGFyZ3MuaWQgPSBkZWZhdWx0X2xheW91dF9pZDtcblx0XHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdFx0YXJncy5kYXRhLmRpc3BsYXlfY29sdW1ucyA9IHNlbGVjdGVkX2Rpc3BsYXlfY29sdW1ucztcblx0XHRcdGFyZ3MuZGF0YS5maWx0ZXJfZGF0YSA9IGZpbHRlcl9kYXRhO1xuXHRcdFx0YXJncy5kYXRhLmZpbHRlcl9zb3J0ID0gc29ydF9maWx0ZXI7XG5cblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMudXNlcl9nZW5lcmljX2RhdGFfYXBpLnNldFVzZXJHZW5lcmljRGF0YSggYXJncywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXMgKSB7XG5cblx0XHRcdFx0aWYgKCByZXMuaXNWYWxpZCgpICkge1xuXHRcdFx0XHRcdCR0aGlzLmNsZWFyVmlld0xheW91dENhY2hlKCk7XG5cdFx0XHRcdFx0JHRoaXMubmVlZF9zZWxlY3RfbGF5b3V0X25hbWUgPSBsYXlvdXRfbmFtZTtcblx0XHRcdFx0XHQkdGhpcy5pbml0TGF5b3V0KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uU2F2ZU5ld0xheW91dCggZGVmYXVsdF9sYXlvdXRfbmFtZSApIHtcblxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBkZWZhdWx0X2xheW91dF9uYW1lICkgKSB7XG5cdFx0XHR2YXIgbGF5b3V0X25hbWUgPSBkZWZhdWx0X2xheW91dF9uYW1lO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsYXlvdXRfbmFtZSA9IHRoaXMuc2F2ZV9zZWFyY2hfYXNfaW5wdXQuZ2V0VmFsdWUoKTtcblx0XHR9XG5cblx0XHRpZiAoICFsYXlvdXRfbmFtZSB8fCBsYXlvdXRfbmFtZS5sZW5ndGggPCAxICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBzb3J0X2ZpbHRlciA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxTb3J0RmlsdGVyKCk7XG5cdFx0dmFyIHNlbGVjdGVkX2Rpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ2V0U2VhcmNoUGFuZWxEaXNwbGF5Q29sdW1ucygpO1xuXHRcdHZhciBmaWx0ZXJfZGF0YSA9IHRoaXMuZ2V0VmFsaWRTZWFyY2hGaWx0ZXIoKTtcblxuXHRcdHZhciBhcmdzID0ge307XG5cdFx0YXJncy5zY3JpcHQgPSB0aGlzLnNjcmlwdF9uYW1lO1xuXHRcdGFyZ3MubmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdGFyZ3MuaXNfZGVmYXVsdCA9IGZhbHNlO1xuXHRcdGFyZ3MuZGF0YSA9IHt9O1xuXHRcdGFyZ3MuZGF0YS5kaXNwbGF5X2NvbHVtbnMgPSBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9kYXRhID0gZmlsdGVyX2RhdGE7XG5cdFx0YXJncy5kYXRhLmZpbHRlcl9zb3J0ID0gc29ydF9maWx0ZXI7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGFfbGF5b3V0X25hbWUgPSBBTGF5b3V0Q2FjaGUubGF5b3V0X2RpY1t0aGlzLnNjcmlwdF9uYW1lXTtcblx0XHRpZiAoIGFfbGF5b3V0X25hbWUgJiYgQUxheW91dENhY2hlLmxheW91dF9kaWNbYV9sYXlvdXRfbmFtZV0gKSB7XG5cdFx0XHRBTGF5b3V0Q2FjaGUubGF5b3V0X2RpY1thX2xheW91dF9uYW1lXSA9IG51bGw7XG5cdFx0fVxuXG5cdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuc2V0VXNlckdlbmVyaWNEYXRhKCBhcmdzLCB7XG5cdFx0XHRvblJlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJBd2Vzb21lYm94TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5jbGVhclZpZXdMYXlvdXRDYWNoZSgpO1xuXHRcdFx0XHRcdCR0aGlzLm5lZWRfc2VsZWN0X2xheW91dF9uYW1lID0gbGF5b3V0X25hbWU7XG5cdFx0XHRcdFx0JHRoaXMuaW5pdExheW91dCgpO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0VEFsZXJ0TWFuYWdlci5zaG93RXJyb3JBbGVydCggcmVzICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uVXBkYXRlTGF5b3V0KCkge1xuXG5cdFx0dmFyIHNlbGVjdElkID0gJCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKS5jaGlsZHJlbiggJ29wdGlvbjpzZWxlY3RlZCcgKS5hdHRyKCAndmFsdWUnICk7XG5cdFx0dmFyIGxheW91dF9uYW1lID0gJCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKS5jaGlsZHJlbiggJ29wdGlvbjpzZWxlY3RlZCcgKS50ZXh0KCk7XG5cblx0XHR2YXIgc29ydF9maWx0ZXIgPSB0aGlzLmdldFNlYXJjaFBhbmVsU29ydEZpbHRlcigpO1xuXHRcdHZhciBzZWxlY3RlZF9kaXNwbGF5X2NvbHVtbnMgPSB0aGlzLmdldFNlYXJjaFBhbmVsRGlzcGxheUNvbHVtbnMoKTtcblx0XHR2YXIgZmlsdGVyX2RhdGEgPSB0aGlzLmdldFZhbGlkU2VhcmNoRmlsdGVyKCk7XG5cblx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdGFyZ3MuaWQgPSBzZWxlY3RJZDtcblx0XHRhcmdzLmRhdGEgPSB7fTtcblx0XHRhcmdzLmRhdGEuZGlzcGxheV9jb2x1bW5zID0gc2VsZWN0ZWRfZGlzcGxheV9jb2x1bW5zO1xuXHRcdGFyZ3MuZGF0YS5maWx0ZXJfZGF0YSA9IGZpbHRlcl9kYXRhO1xuXHRcdGFyZ3MuZGF0YS5maWx0ZXJfc29ydCA9IHNvcnRfZmlsdGVyO1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBhX2xheW91dF9uYW1lID0gQUxheW91dENhY2hlLmxheW91dF9kaWNbdGhpcy5zY3JpcHRfbmFtZV07XG5cdFx0aWYgKCBhX2xheW91dF9uYW1lICYmIEFMYXlvdXRDYWNoZS5sYXlvdXRfZGljW2FfbGF5b3V0X25hbWVdICkge1xuXHRcdFx0QUxheW91dENhY2hlLmxheW91dF9kaWNbYV9sYXlvdXRfbmFtZV0gPSBudWxsO1xuXHRcdH1cblxuXHRcdHRoaXMudXNlcl9nZW5lcmljX2RhdGFfYXBpLnNldFVzZXJHZW5lcmljRGF0YSggYXJncywge1xuXHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXMgKSB7XG5cblx0XHRcdFx0aWYgKCByZXMuaXNWYWxpZCgpICkge1xuXHRcdFx0XHRcdCR0aGlzLmNsZWFyQXdlc29tZWJveExheW91dENhY2hlKCk7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJWaWV3TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSA9IGxheW91dF9uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0Y2xlYXJWaWV3TGF5b3V0Q2FjaGUoKSB7XG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS52aWV3X2xheW91dF9jYWNoZSAmJiBMb2NhbENhY2hlRGF0YS52aWV3X2xheW91dF9jYWNoZVt0aGlzLnNjcmlwdF9uYW1lXSApIHtcblx0XHRcdExvY2FsQ2FjaGVEYXRhLnZpZXdfbGF5b3V0X2NhY2hlW3RoaXMuc2NyaXB0X25hbWVdID0gbnVsbDtcblx0XHR9XG5cdH1cblxuXHRjbGVhckF3ZXNvbWVib3hMYXlvdXRDYWNoZSgpIHtcblx0XHQvLyBSZW1vdmVkIHNhdmVkIHZpZXcgbGF5b3V0IGZvciBhd2Vzb21lYm94IGlmIGl0IGV4aXN0ZWQuXG5cdFx0aWYgKCBBTGF5b3V0Q2FjaGUubGF5b3V0X2RpYyAmJiBBTGF5b3V0Q2FjaGUubGF5b3V0X2RpY1t0aGlzLnNjcmlwdF9uYW1lXSApIHtcblx0XHRcdEFMYXlvdXRDYWNoZS5sYXlvdXRfZGljW0FMYXlvdXRDYWNoZS5sYXlvdXRfZGljW3RoaXMuc2NyaXB0X25hbWVdXSA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0b25EZWxldGVMYXlvdXQoKSB7XG5cdFx0dmFyIHNlbGVjdElkID0gJCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKS5jaGlsZHJlbiggJ29wdGlvbjpzZWxlY3RlZCcgKS5hdHRyKCAndmFsdWUnICk7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMudXNlcl9nZW5lcmljX2RhdGFfYXBpLmRlbGV0ZVVzZXJHZW5lcmljRGF0YSggc2VsZWN0SWQsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzICkge1xuXHRcdFx0XHRpZiAoIHJlcy5pc1ZhbGlkKCkgKSB7XG5cdFx0XHRcdFx0JHRoaXMuY2xlYXJBd2Vzb21lYm94TGF5b3V0Q2FjaGUoKTtcblx0XHRcdFx0XHQkdGhpcy5jbGVhclZpZXdMYXlvdXRDYWNoZSgpO1xuXHRcdFx0XHRcdCR0aGlzLm5lZWRfc2VsZWN0X2xheW91dF9uYW1lID0gJHRoaXMuc2VsZWN0X2xheW91dC5uYW1lO1xuXHRcdFx0XHRcdCR0aGlzLmluaXRMYXlvdXQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0YnVpbGRTZWFyY2hGaWVsZHMoKSB7XG5cdFx0Ly9PdmVycmlkZSBpbiBhbGwgc3Vidmlld1xuXHR9XG5cblx0YnVpbGRDdXN0b21GaWVsZFNlYXJjaEZpZWxkcygpIHtcblx0XHRpZiAoICF0aGlzLnNlYXJjaF9maWVsZHMgKSB7XG5cdFx0XHR0aGlzLnNlYXJjaF9maWVsZHMgPSBbXTtcblx0XHR9XG5cblx0XHR0aGlzLmN1c3RvbV9maWVsZHMuZm9yRWFjaCggKCBmaWVsZCApID0+IHtcblx0XHRcdGlmICggZmllbGQuZW5hYmxlX3NlYXJjaCApIHtcblxuXHRcdFx0XHRsZXQgZmllbGRfc2V0dGluZ3MgPSB7XG5cdFx0XHRcdFx0bGFiZWw6IGZpZWxkLm5hbWUsXG5cdFx0XHRcdFx0aW5fY29sdW1uOiAxLFxuXHRcdFx0XHRcdGZpZWxkOiB0aGlzLmdldFByZWZpeGVkQ3VzdG9tRmllbGRJRCggZmllbGQuaWQgKSxcblx0XHRcdFx0XHRiYXNpY19zZWFyY2g6IGZhbHNlLFxuXHRcdFx0XHRcdGFkdl9zZWFyY2g6IHRydWUsXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0bGV0IHR5cGVfaWQgPSBwYXJzZUludCggZmllbGQudHlwZV9pZCApO1xuXG5cdFx0XHRcdHN3aXRjaCAoIHR5cGVfaWQgKSB7XG5cdFx0XHRcdFx0Y2FzZSA1MDA6IC8vQ2hlY2tib3hcblx0XHRcdFx0XHRcdGZpZWxkX3NldHRpbmdzLmZvcm1faXRlbV90eXBlID0gRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YO1xuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MubXVsdGlwbGUgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGZpZWxkX3NldHRpbmdzLmxheW91dF9uYW1lID0gJ2dsb2JhbF9vcHRpb25fY29sdW1uJztcblx0XHRcdFx0XHRcdGZpZWxkX3NldHRpbmdzLmFkZGl0aW9uX3NvdXJjZV9mdW5jdGlvbiA9ICggdGFyZ2V0LCBzb3VyY2VfZGF0YSApID0+IHtcblx0XHRcdFx0XHRcdFx0c291cmNlX2RhdGEgPSBbXG5cdFx0XHRcdFx0XHRcdFx0eyB2YWx1ZTogVFRVVUlELnplcm9faWQsIGxhYmVsOiAnLS0gJyArICQuaTE4bi5fKCAnQU5ZJyApICsgJyAtLScgfSxcblx0XHRcdFx0XHRcdFx0XHR7IHZhbHVlOiB0cnVlLCBsYWJlbDogJC5pMThuLl8oICdZZXMnICkgfSxcblx0XHRcdFx0XHRcdFx0XHR7IHZhbHVlOiBmYWxzZSwgbGFiZWw6ICQuaTE4bi5fKCAnTm8nICkgfVxuXHRcdFx0XHRcdFx0XHRdO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gc291cmNlX2RhdGE7XG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAxMDAwOiAvL0RhdGVcblx0XHRcdFx0XHRcdGZpZWxkX3NldHRpbmdzLmZvcm1faXRlbV90eXBlID0gRm9ybUl0ZW1UeXBlLkRBVEVfUElDS0VSO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Ly8gY2FzZSAxMDEwOiAvL0RhdGUgUmFuZ2UgU2VhcmNoIERpc2FibGVkXG5cdFx0XHRcdFx0Ly8gXHRmaWVsZF9zZXR0aW5ncy5mb3JtX2l0ZW1fdHlwZSA9IEZvcm1JdGVtVHlwZS5EQVRFX1BJQ0tFUjtcblx0XHRcdFx0XHQvLyBcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgMTEwMDogLy9UaW1lXG5cdFx0XHRcdFx0XHRmaWVsZF9zZXR0aW5ncy5mb3JtX2l0ZW1fdHlwZSA9IEZvcm1JdGVtVHlwZS5USU1FX1BJQ0tFUjtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgMTIwMDogLy9EYXRldGltZVxuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MuZm9ybV9pdGVtX3R5cGUgPSBGb3JtSXRlbVR5cGUuREFURV9QSUNLRVI7XG5cdFx0XHRcdFx0XHRmaWVsZF9zZXR0aW5ncy5tb2RlID0gJ2RhdGVfdGltZSc7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIDEzMDA6IC8vVGltZSBVbml0XG5cdFx0XHRcdFx0XHRmaWVsZF9zZXR0aW5ncy5mb3JtX2l0ZW1fdHlwZSA9IEZvcm1JdGVtVHlwZS5URVhUX0lOUFVUO1xuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MubW9kZSA9ICd0aW1lX3VuaXQnO1xuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MubmVlZF9wYXJzZXJfc2VjID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgMjEwMDogLy9TaW5nbGUtc2VsZWN0IGRyb3Bkb3duXG5cdFx0XHRcdFx0Y2FzZSAyMTEwOiAvL011bHRpLXNlbGVjdCBkcm9wZG93blxuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MuZm9ybV9pdGVtX3R5cGUgPSBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1g7XG5cdFx0XHRcdFx0XHRmaWVsZF9zZXR0aW5ncy5tdWx0aXBsZSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MubGF5b3V0X25hbWUgPSAnZ2xvYmFsX29wdGlvbl9jb2x1bW4nO1xuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MuYWRkaXRpb25fc291cmNlX2Z1bmN0aW9uID0gKCB0YXJnZXQsIHNvdXJjZV9kYXRhICkgPT4ge1xuXHRcdFx0XHRcdFx0XHRzb3VyY2VfZGF0YSA9IFtdOyAvL092ZXJ3cml0aW5nIHNvdXJjZSBkYXRhIHRvIGVtcHR5IGFycmF5LlxuXHRcdFx0XHRcdFx0XHRpZiAoIGZpZWxkLm1ldGFfZGF0YS52YWxpZGF0aW9uLm11bHRpX3NlbGVjdF9pdGVtcyApIHtcblx0XHRcdFx0XHRcdFx0XHRmaWVsZC5tZXRhX2RhdGEudmFsaWRhdGlvbi5tdWx0aV9zZWxlY3RfaXRlbXMuZm9yRWFjaCggKCBpdGVtICkgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdFx0c291cmNlX2RhdGEucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZDogaXRlbS5pZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFsdWU6IGl0ZW0uaWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGxhYmVsOiBpdGVtLmxhYmVsXG5cdFx0XHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJldHVybiBzb3VyY2VfZGF0YTtcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0ZmllbGRfc2V0dGluZ3MuZm9ybV9pdGVtX3R5cGUgPSBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVDtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLnNlYXJjaF9maWVsZHMucHVzaCggbmV3IFNlYXJjaEZpZWxkKCBmaWVsZF9zZXR0aW5ncyApICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cblx0YnVpbGRCYXNpY1NlYXJjaFVJKCkge1xuXHRcdGlmICggIXRoaXMuc2VhcmNoX2ZpZWxkcyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgYmFzaWNfc2VhcmNoX2RpdiA9IHRoaXMuc2VhcmNoX3BhbmVsLmZpbmQoICdkaXYgI2Jhc2ljX3NlYXJjaF9jb250ZW50X2RpdicgKTtcblxuXHRcdHZhciBsZW4gPSB0aGlzLnNlYXJjaF9maWVsZHMubGVuZ3RoO1xuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHR2YXIgY29sdW1uMSA9IGJhc2ljX3NlYXJjaF9kaXYuZmluZCggJy5maXJzdC1jb2x1bW4nICk7XG5cdFx0dmFyIGNvbHVtbjIgPSBiYXNpY19zZWFyY2hfZGl2LmZpbmQoICcuc2Vjb25kLWNvbHVtbicgKTtcblx0XHR2YXIgY29sdW1uMyA9IGJhc2ljX3NlYXJjaF9kaXYuZmluZCggJy50aGlyZC1jb2x1bW4nICk7XG5cblx0XHR2YXIgYWxyZWFkeV9jcmVhdGVkX3VpID0gZmFsc2U7XG5cdFx0JC5lYWNoKCB0aGlzLnNlYXJjaF9maWVsZHMsIGZ1bmN0aW9uKCBpbmRleCwgc2VhcmNoX2ZpZWxkICkge1xuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWNbc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApXSApICkge1xuXHRcdFx0XHRhbHJlYWR5X2NyZWF0ZWRfdWkgPSB0cnVlO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggIXNlYXJjaF9maWVsZC5nZXQoICdiYXNpY19zZWFyY2gnICkgKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB2YXIgZm9ybV9pdGVtID0gJCggR2xvYmFsLmxvYWRXaWRnZXQoICdnbG9iYWwvd2lkZ2V0cy9zZWFyY2hfcGFuZWwvRm9ybUl0ZW0uaHRtbCcgKSApOyAvLyBUT0RPOiAjMzAyMzogRGVsZXRlIHRoaXMgbGluZSBvbmNlIHdpZGdldCBodG1sIGNvbnZlcnRlZCBhbmQgbm8gbG9uZ2VyIG5lZWQgdGhpcyBxdWljayByZWZlcmVuY2UgZm9yIHRoZSBvbGQgZm9ybWF0LlxuXHRcdFx0dmFyIGZvcm1faXRlbSA9ICQoICQuZm4uU2VhcmNoUGFuZWwuaHRtbC5mb3JtX2l0ZW0gKTtcblx0XHRcdHZhciBmb3JtX2l0ZW1fbGFiZWwgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0tbGFiZWwnICk7XG5cdFx0XHR2YXIgZm9ybV9pdGVtX2lucHV0X2RpdiA9IGZvcm1faXRlbS5maW5kKCAnLmZvcm0taXRlbS1pbnB1dC1kaXYnICk7XG5cdFx0XHR2YXIgZm9ybV9pdGVtX2lucHV0ID0gJHRoaXMuZ2V0Rm9ybUl0ZW1JbnB1dCggc2VhcmNoX2ZpZWxkICk7XG5cdFx0XHRmb3JtX2l0ZW1fbGFiZWwudGV4dCggc2VhcmNoX2ZpZWxkLmdldCggJ2xhYmVsJyApICk7XG5cdFx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggZm9ybV9pdGVtX2lucHV0ICk7XG5cblx0XHRcdHN3aXRjaCAoIHNlYXJjaF9maWVsZC5nZXQoICdpbl9jb2x1bW4nICkgKSB7XG5cdFx0XHRcdGNhc2UgMTpcblx0XHRcdFx0XHRjb2x1bW4xLmFwcGVuZCggZm9ybV9pdGVtICk7XG5cdFx0XHRcdFx0Y29sdW1uMS5hcHBlbmQoICc8ZGl2IGNsYXNzPVxcJ2NsZWFyLWJvdGgtZGl2XFwnPjwvZGl2PicgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHRcdGNvbHVtbjIuYXBwZW5kKCBmb3JtX2l0ZW0gKTtcblx0XHRcdFx0XHRjb2x1bW4yLmFwcGVuZCggJzxkaXYgY2xhc3M9XFwnY2xlYXItYm90aC1kaXZcXCc+PC9kaXY+JyApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDM6XG5cdFx0XHRcdFx0Y29sdW1uMy5hcHBlbmQoIGZvcm1faXRlbSApO1xuXHRcdFx0XHRcdGNvbHVtbjMuYXBwZW5kKCAnPGRpdiBjbGFzcz1cXCdjbGVhci1ib3RoLWRpdlxcJz48L2Rpdj4nICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHRcdCR0aGlzLmJhc2ljX3NlYXJjaF9maWVsZF91aV9kaWNbc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApXSA9IGZvcm1faXRlbV9pbnB1dDtcblx0XHR9ICk7XG5cblx0XHRpZiAoICFhbHJlYWR5X2NyZWF0ZWRfdWkgKSB7XG5cdFx0XHR0aGlzLm9uQnVpbGRCYXNpY1VJRmluaXNoZWQoKTtcblx0XHR9XG5cdH1cblxuXHRidWlsZEFkdmFuY2VkU2VhcmNoVUkoKSB7XG5cdFx0aWYgKCAhdGhpcy5zZWFyY2hfZmllbGRzICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBhZHZTZWFyY2hEaXYgPSB0aGlzLnNlYXJjaF9wYW5lbC5maW5kKCAnZGl2ICNhZHZfc2VhcmNoX2NvbnRlbnRfZGl2JyApO1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBjb2x1bW4xID0gYWR2U2VhcmNoRGl2LmZpbmQoICcuZmlyc3QtY29sdW1uJyApO1xuXHRcdHZhciBjb2x1bW4yID0gYWR2U2VhcmNoRGl2LmZpbmQoICcuc2Vjb25kLWNvbHVtbicgKTtcblx0XHR2YXIgY29sdW1uMyA9IGFkdlNlYXJjaERpdi5maW5kKCAnLnRoaXJkLWNvbHVtbicgKTtcblxuXHRcdHZhciBhbHJlYWR5X2NyZWF0ZWRfdWkgPSBmYWxzZTtcblx0XHR2YXIgbm9fYWR2X3VpID0gdHJ1ZTtcblxuXHRcdCQuZWFjaCggdGhpcy5zZWFyY2hfZmllbGRzLCBmdW5jdGlvbiggaW5kZXgsIHNlYXJjaF9maWVsZCApIHtcblxuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLmFkdl9zZWFyY2hfZmllbGRfdWlfZGljW3NlYXJjaF9maWVsZC5nZXQoICdmaWVsZCcgKV0gKSApIHtcblx0XHRcdFx0YWxyZWFkeV9jcmVhdGVkX3VpID0gdHJ1ZTtcblx0XHRcdFx0bm9fYWR2X3VpID0gZmFsc2U7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhc2VhcmNoX2ZpZWxkLmdldCggJ2Fkdl9zZWFyY2gnICkgKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgZm9ybV9pdGVtID0gJCggJC5mbi5TZWFyY2hQYW5lbC5odG1sLmZvcm1faXRlbSApO1xuXHRcdFx0dmFyIGZvcm1faXRlbV9sYWJlbCA9IGZvcm1faXRlbS5maW5kKCAnLmZvcm0taXRlbS1sYWJlbCcgKTtcblx0XHRcdHZhciBmb3JtX2l0ZW1faW5wdXRfZGl2ID0gZm9ybV9pdGVtLmZpbmQoICcuZm9ybS1pdGVtLWlucHV0LWRpdicgKTtcblx0XHRcdHZhciBmb3JtX2l0ZW1faW5wdXQgPSAkdGhpcy5nZXRGb3JtSXRlbUlucHV0KCBzZWFyY2hfZmllbGQgKTtcblx0XHRcdGZvcm1faXRlbV9sYWJlbC50ZXh0KCBzZWFyY2hfZmllbGQuZ2V0KCAnbGFiZWwnICkgKTtcblx0XHRcdGZvcm1faXRlbV9pbnB1dF9kaXYuYXBwZW5kKCBmb3JtX2l0ZW1faW5wdXQgKTtcblxuXHRcdFx0c3dpdGNoICggc2VhcmNoX2ZpZWxkLmdldCggJ2luX2NvbHVtbicgKSApIHtcblx0XHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHRcdGNvbHVtbjEuYXBwZW5kKCBmb3JtX2l0ZW0gKTtcblx0XHRcdFx0XHRjb2x1bW4xLmFwcGVuZCggJzxkaXYgY2xhc3M9XFwnY2xlYXItYm90aC1kaXZcXCc+PC9kaXY+JyApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDI6XG5cdFx0XHRcdFx0Y29sdW1uMi5hcHBlbmQoIGZvcm1faXRlbSApO1xuXHRcdFx0XHRcdGNvbHVtbjIuYXBwZW5kKCAnPGRpdiBjbGFzcz1cXCdjbGVhci1ib3RoLWRpdlxcJz48L2Rpdj4nICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMzpcblx0XHRcdFx0XHRjb2x1bW4zLmFwcGVuZCggZm9ybV9pdGVtICk7XG5cdFx0XHRcdFx0Y29sdW1uMy5hcHBlbmQoICc8ZGl2IGNsYXNzPVxcJ2NsZWFyLWJvdGgtZGl2XFwnPjwvZGl2PicgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0JHRoaXMuYWR2X3NlYXJjaF9maWVsZF91aV9kaWNbc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApXSA9IGZvcm1faXRlbV9pbnB1dDtcblx0XHRcdG5vX2Fkdl91aSA9IGZhbHNlO1xuXHRcdH0gKTtcblxuXHRcdGlmICggbm9fYWR2X3VpICkge1xuXG5cdFx0XHR0aGlzLnNlYXJjaF9wYW5lbC5oaWRlQWR2U2VhcmNoUGFuZWwoKTtcblx0XHR9XG5cblx0XHRpZiAoICFhbHJlYWR5X2NyZWF0ZWRfdWkgKSB7XG5cdFx0XHR0aGlzLm9uQnVpbGRBZHZVSUZpbmlzaGVkKCk7XG5cdFx0fVxuXHR9XG5cblx0b25TZXRTZWFyY2hGaWx0ZXJGaW5pc2hlZCgpIHtcblx0fVxuXG5cdG9uQnVpbGRBZHZVSUZpbmlzaGVkKCkge1xuXHRcdC8vQWx3YXlzIG92ZXJyaWRlIGluIHN1YiBjbGFzc1xuXHR9XG5cblx0b25CdWlsZEJhc2ljVUlGaW5pc2hlZCgpIHtcblx0XHQvL0Fsd2F5cyBvdmVycmlkZSBpbiBzdWIgY2xhc3Ncblx0fVxuXG5cdGdldEZvcm1JdGVtSW5wdXQoIHNlYXJjaF9maWVsZCApIHtcblx0XHR2YXIgaW5wdXQ7XG5cdFx0dmFyIGZvcm1fdHlwZSA9IHNlYXJjaF9maWVsZC5nZXQoICdmb3JtX2l0ZW1fdHlwZScgKTtcblxuXHRcdHN3aXRjaCAoIGZvcm1fdHlwZSApIHtcblx0XHRcdGNhc2UgRm9ybUl0ZW1UeXBlLkFXRVNPTUVfQk9YOlxuXHRcdFx0XHRpbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblx0XHRcdFx0dmFyIHNob3dfc2VhcmNoID0gZmFsc2U7XG5cdFx0XHRcdHZhciBrZXk7XG5cblx0XHRcdFx0aWYgKCBzZWFyY2hfZmllbGQuZ2V0KCAnbGF5b3V0X25hbWUnICkgIT09ICdnbG9iYWxfb3B0aW9uX2NvbHVtbicgJiYgc2VhcmNoX2ZpZWxkLmdldCggJ2xheW91dF9uYW1lJyApICE9PSAnZ2xvYmFsX3RyZWVfY29sdW1uJyApIHtcblx0XHRcdFx0XHRzaG93X3NlYXJjaCA9IHRydWU7XG5cdFx0XHRcdFx0a2V5ID0gJ2lkJztcblx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdGlmICggc2VhcmNoX2ZpZWxkLmdldCggJ2xheW91dF9uYW1lJyApID09PSAnZ2xvYmFsX3RyZWVfY29sdW1uJyApIHtcblx0XHRcdFx0XHRcdGtleSA9ICdpZCc7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGtleSA9ICd2YWx1ZSc7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpbnB1dC5BQ29tYm9Cb3goIHtcblx0XHRcdFx0XHRhcGlfY2xhc3M6IHNlYXJjaF9maWVsZC5nZXQoICdhcGlfY2xhc3MnICksXG5cdFx0XHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiBzZWFyY2hfZmllbGQuZ2V0KCAnbXVsdGlwbGUnICksXG5cdFx0XHRcdFx0bGF5b3V0X25hbWU6IHNlYXJjaF9maWVsZC5nZXQoICdsYXlvdXRfbmFtZScgKSxcblx0XHRcdFx0XHR0cmVlX21vZGU6IHNlYXJjaF9maWVsZC5nZXQoICd0cmVlX21vZGUnICksXG5cdFx0XHRcdFx0ZGVmYXVsdF9hcmdzOiBzZWFyY2hfZmllbGQuZ2V0KCAnZGVmYXVsdF9hcmdzJyApLFxuXHRcdFx0XHRcdHNob3dfc2VhcmNoX2lucHV0czogc2hvd19zZWFyY2gsXG5cdFx0XHRcdFx0c2V0X2FueTogc2VhcmNoX2ZpZWxkLmdldCggJ3NldF9hbnknICksXG5cdFx0XHRcdFx0YWRkaXRpb25fc291cmNlX2Z1bmN0aW9uOiBzZWFyY2hfZmllbGQuZ2V0KCAnYWRkaXRpb25fc291cmNlX2Z1bmN0aW9uJyApLFxuXHRcdFx0XHRcdHNjcmlwdF9uYW1lOiBzZWFyY2hfZmllbGQuZ2V0KCAnc2NyaXB0X25hbWUnICksXG5cdFx0XHRcdFx0Y3VzdG9tX2ZpcnN0X2xhYmVsOiBzZWFyY2hfZmllbGQuZ2V0KCAnY3VzdG9tX2ZpcnN0X2xhYmVsJyApLFxuXHRcdFx0XHRcdGtleToga2V5LFxuXHRcdFx0XHRcdHNlYXJjaF9wYW5lbF9tb2RlbDogdHJ1ZSxcblx0XHRcdFx0XHRmaWVsZDogc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRpZiAoIHNlYXJjaF9maWVsZC5nZXQoICdjdXN0b21TZWFyY2hGaWx0ZXInICkgKSB7XG5cdFx0XHRcdFx0aW5wdXQuY3VzdG9tU2VhcmNoRmlsdGVyID0gc2VhcmNoX2ZpZWxkLmdldCggJ2N1c3RvbVNlYXJjaEZpbHRlcicgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBGb3JtSXRlbVR5cGUuVEVYVF9JTlBVVDpcblx0XHRcdFx0aW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHRcdFx0aW5wdXQuVFRleHRJbnB1dCgge1xuXHRcdFx0XHRcdGZpZWxkOiBzZWFyY2hfZmllbGQuZ2V0KCAnZmllbGQnICksXG5cdFx0XHRcdFx0bmVlZF9wYXJzZXJfc2VjOiBzZWFyY2hfZmllbGQuZ2V0KCAnbmVlZF9wYXJzZXJfc2VjJyApLFxuXHRcdFx0XHRcdG1vZGU6IHNlYXJjaF9maWVsZC5nZXQoICdtb2RlJyApLFxuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBGb3JtSXRlbVR5cGUuVElNRV9QSUNLRVI6XG5cdFx0XHRcdGlucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5USU1FX1BJQ0tFUiApO1xuXHRcdFx0XHRpbnB1dC5UVGltZVBpY2tlcigge1xuXHRcdFx0XHRcdGZpZWxkOiBzZWFyY2hfZmllbGQuZ2V0KCAnZmllbGQnIClcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgRm9ybUl0ZW1UeXBlLlBBU1NXT1JEX0lOUFVUOlxuXHRcdFx0XHRpbnB1dCA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuUEFTU1dPUkRfSU5QVVQgKTtcblx0XHRcdFx0aW5wdXQuVFRleHRJbnB1dCgge1xuXHRcdFx0XHRcdGZpZWxkOiBzZWFyY2hfZmllbGQuZ2V0KCAnZmllbGQnIClcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgRm9ybUl0ZW1UeXBlLkNPTUJPX0JPWDpcblx0XHRcdFx0aW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLkNPTUJPX0JPWCApO1xuXHRcdFx0XHRpbnB1dC5UQ29tYm9Cb3goIHtcblx0XHRcdFx0XHRmaWVsZDogc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApLFxuXHRcdFx0XHRcdHNldF9hbnk6IHRydWVcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgRm9ybUl0ZW1UeXBlLlRBR19JTlBVVDpcblx0XHRcdFx0aW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRBR19JTlBVVCApO1xuXHRcdFx0XHRpbnB1dC5UVGFnSW5wdXQoIHtcblx0XHRcdFx0XHRmaWVsZDogc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApLFxuXHRcdFx0XHRcdG9iamVjdF90eXBlX2lkOiBzZWFyY2hfZmllbGQuZ2V0KCAnb2JqZWN0X3R5cGVfaWQnIClcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBGb3JtSXRlbVR5cGUuREFURV9QSUNLRVI6XG5cdFx0XHRcdGlucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIGZvcm1fdHlwZSApO1xuXHRcdFx0XHRpbnB1dCA9ICQoIGlucHV0ICk7XG5cdFx0XHRcdGlucHV0LlREYXRlUGlja2VyKCB7XG5cdFx0XHRcdFx0ZmllbGQ6IHNlYXJjaF9maWVsZC5nZXQoICdmaWVsZCcgKSxcblx0XHRcdFx0XHRtb2RlOiBzZWFyY2hfZmllbGQuZ2V0KCAnbW9kZScgKSxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBGb3JtSXRlbVR5cGUuQ0hFQ0tCT1g6XG5cdFx0XHRcdGlucHV0ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIEZvcm1JdGVtVHlwZS5DSEVDS0JPWCApO1xuXHRcdFx0XHRpbnB1dC5UQ2hlY2tib3goIHtcblx0XHRcdFx0XHRmaWVsZDogc2VhcmNoX2ZpZWxkLmdldCggJ2ZpZWxkJyApXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdERlYnVnLkVycm9yKCAnRVJST1I6IEZvcm0gdHlwZSBkb2VzIG5vdCBleGlzdDogJysgZm9ybV90eXBlLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXRGb3JtSXRlbUlucHV0JywgMiApO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHRyZXR1cm4gaW5wdXQ7XG5cdH1cblxuXHRidWlsZFNlYXJjaEFuZExheW91dFVJKCkge1xuXHRcdHZhciBsYXlvdXRfZGl2ID0gdGhpcy5zZWFyY2hfcGFuZWwuZmluZCggJ2RpdiAjc2F2ZWRfbGF5b3V0X2NvbnRlbnRfZGl2JyApO1xuXG5cdFx0Ly9EaXNwbGF5IENvbHVtbnNcblxuXHRcdHZhciBmb3JtX2l0ZW0gPSAkKCAkLmZuLlNlYXJjaFBhbmVsLmh0bWwuZm9ybV9pdGVtICk7XG5cdFx0dmFyIGZvcm1faXRlbV9sYWJlbCA9IGZvcm1faXRlbS5maW5kKCAnLmZvcm0taXRlbS1sYWJlbCcgKTtcblx0XHR2YXIgZm9ybV9pdGVtX2lucHV0X2RpdiA9IGZvcm1faXRlbS5maW5kKCAnLmZvcm0taXRlbS1pbnB1dC1kaXYnICk7XG5cblx0XHR0aGlzLmNvbHVtbl9zZWxlY3RvciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9EUk9QRE9XTiApO1xuXG5cdFx0dGhpcy5jb2x1bW5fc2VsZWN0b3IgPSB0aGlzLmNvbHVtbl9zZWxlY3Rvci5BRHJvcERvd24oIHtcblx0XHRcdGRpc3BsYXlfc2hvd19hbGw6IGZhbHNlLFxuXHRcdFx0aWQ6IHRoaXMudWlfaWQgKyAnX2NvbHVtbl9zZWxlY3RvcicsXG5cdFx0XHRrZXk6ICd2YWx1ZScsXG5cdFx0XHRhbGxvd19kcmFnX3RvX29yZGVyOiB0cnVlLFxuXHRcdFx0ZGlzcGxheV9jbG9zZV9idG46IGZhbHNlLFxuXHRcdFx0ZGlzcGxheV9jb2x1bW5fc2V0dGluZ3M6IGZhbHNlLFxuXHRcdFx0bWF4X2hlaWdodDogMTUwXG5cdFx0fSApO1xuXHRcdHRoaXMuY29sdW1uX3NlbGVjdG9yLm9uKCAnZm9ybUl0ZW1DaGFuZ2UnLCBmdW5jdGlvbigpIHtcblx0XHRcdCR0aGlzLmxheW91dF9jaGFuZ2VkID0gdHJ1ZTtcblx0XHR9ICk7XG5cblx0XHRmb3JtX2l0ZW1fbGFiZWwudGV4dCggJC5pMThuLl8oICdEaXNwbGF5IENvbHVtbnMnICkgKTtcblx0XHRmb3JtX2l0ZW1fbGFiZWwuYWRkQ2xhc3MoICdTZWFyY2hQYW5lbC1kaXNwbGF5Q29sdW1ucy1sYWJlbCcgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggdGhpcy5jb2x1bW5fc2VsZWN0b3IgKTtcblxuXHRcdGxheW91dF9kaXYuYXBwZW5kKCBmb3JtX2l0ZW0gKTtcblxuXHRcdGxheW91dF9kaXYuYXBwZW5kKCAnPGRpdiBjbGFzcz1cXCdjbGVhci1ib3RoLWRpdlxcJz48L2Rpdj4nICk7XG5cblx0XHR0aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRDb2x1bW5zKCBbXG5cdFx0XHR7IG5hbWU6ICdsYWJlbCcsIGluZGV4OiAnbGFiZWwnLCBsYWJlbDogJC5pMThuLl8oICdDb2x1bW4gTmFtZScgKSwgd2lkdGg6IDEwMCwgc29ydGFibGU6IGZhbHNlIH1cblx0XHRdICk7XG5cblx0XHQvL1NvcnQgQnlcblx0XHRmb3JtX2l0ZW0gPSAkKCAkLmZuLlNlYXJjaFBhbmVsLmh0bWwuZm9ybV9pdGVtICk7XG5cdFx0Zm9ybV9pdGVtX2xhYmVsID0gZm9ybV9pdGVtLmZpbmQoICcuZm9ybS1pdGVtLWxhYmVsJyApO1xuXHRcdGZvcm1faXRlbV9pbnB1dF9kaXYgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0taW5wdXQtZGl2JyApO1xuXHRcdHRoaXMuc29ydF9ieV9zZWxlY3RvciA9IEdsb2JhbC5sb2FkV2lkZ2V0QnlOYW1lKCBGb3JtSXRlbVR5cGUuQVdFU09NRV9CT1ggKTtcblx0XHR0aGlzLnNvcnRfYnlfc2VsZWN0b3IgPSB0aGlzLnNvcnRfYnlfc2VsZWN0b3IuQUNvbWJvQm94KCB7XG5cdFx0XHRhbGxvd19kcmFnX3RvX29yZGVyOiB0cnVlLFxuXHRcdFx0YWxsb3dfbXVsdGlwbGVfc2VsZWN0aW9uOiB0cnVlLFxuXHRcdFx0c2V0X2VtcHR5OiB0cnVlLFxuXHRcdFx0bGF5b3V0X25hbWU6ICdnbG9iYWxfc29ydF9jb2x1bW5zJ1xuXHRcdH0gKTtcblxuXHRcdGZvcm1faXRlbV9sYWJlbC50ZXh0KCAkLmkxOG4uXyggJ1NvcnQgQnknICkgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggdGhpcy5zb3J0X2J5X3NlbGVjdG9yICk7XG5cblx0XHRsYXlvdXRfZGl2LmFwcGVuZCggZm9ybV9pdGVtICk7XG5cblx0XHRsYXlvdXRfZGl2LmFwcGVuZCggJzxkaXYgY2xhc3M9XFwnY2xlYXItYm90aC1kaXZcXCc+PC9kaXY+JyApO1xuXG5cdFx0Ly9TYXZlIGFuZCB1cGRhdGUgbGF5b3V0XG5cblx0XHRmb3JtX2l0ZW0gPSAkKCAkLmZuLlNlYXJjaFBhbmVsLmh0bWwuZm9ybV9pdGVtICk7XG5cdFx0Zm9ybV9pdGVtX2xhYmVsID0gZm9ybV9pdGVtLmZpbmQoICcuZm9ybS1pdGVtLWxhYmVsJyApO1xuXHRcdGZvcm1faXRlbV9pbnB1dF9kaXYgPSBmb3JtX2l0ZW0uZmluZCggJy5mb3JtLWl0ZW0taW5wdXQtZGl2JyApO1xuXG5cdFx0Zm9ybV9pdGVtX2xhYmVsLnRleHQoICQuaTE4bi5fKCAnU2F2ZSBTZWFyY2ggQXMnICkgKTtcblxuXHRcdHRoaXMuc2F2ZV9zZWFyY2hfYXNfaW5wdXQgPSBHbG9iYWwubG9hZFdpZGdldEJ5TmFtZSggRm9ybUl0ZW1UeXBlLlRFWFRfSU5QVVQgKTtcblx0XHR0aGlzLnNhdmVfc2VhcmNoX2FzX2lucHV0LlRUZXh0SW5wdXQoKTtcblxuXHRcdHZhciBzYXZlX2J0biA9ICQoICc8YnV0dG9uIGNsYXNzPVwidHQtYnV0dG9uIHAtYnV0dG9uIHAtY29tcG9uZW50IHNtYWxsLXNlYXJjaC1wYW5lbC1idXR0b25cIiB0eXBlPVwiYnV0dG9uXCI+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJ0dGljb24gdHRpY29uLXNhdmVfYmxhY2tfMjRkcFwiPjwvc3Bhbj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInAtYnV0dG9uLWxhYmVsXCI+JyArICQuaTE4bi5fKCAnU2F2ZScgKSArICc8L3NwYW4+XFxuJyArXG5cdFx0XHQnPC9idXR0b24+JyApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0X2Rpdi5hcHBlbmQoIHRoaXMuc2F2ZV9zZWFyY2hfYXNfaW5wdXQgKTtcblx0XHRmb3JtX2l0ZW1faW5wdXRfZGl2LmFwcGVuZCggc2F2ZV9idG4gKTtcblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cdFx0c2F2ZV9idG4uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMuc2F2aW5nX2xheW91dF9pbl9sYXlvdXRfdGFiID0gdHJ1ZTtcblx0XHRcdCR0aGlzLm9uU2F2ZU5ld0xheW91dCgpO1xuXHRcdFx0JHRoaXMuc2VhcmNoKCk7XG5cdFx0fSApO1xuXG5cdFx0Ly9QcmV2aW91cyBTYXZlZCBMYXlvdXRcblxuXHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2RpdiA9ICQoICc8ZGl2IGNsYXNzPVxcJ3ByZXZpb3VzLXNhdmVkLWxheW91dC1kaXZcXCc+PC9kaXY+JyApO1xuXG5cdFx0Zm9ybV9pdGVtX2lucHV0X2Rpdi5hcHBlbmQoIHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2RpdiApO1xuXG5cdFx0Zm9ybV9pdGVtX2xhYmVsID0gJCggJzxzcGFuIHN0eWxlPVxcJ21hcmdpbi1sZWZ0OiA1cHhcXCcgPicgKyAkLmkxOG4uXyggJ1ByZXZpb3VzIFNhdmVkIFNlYXJjaGVzJyApICsgJzo8L3NwYW4+JyApO1xuXHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2Rpdi5hcHBlbmQoIGZvcm1faXRlbV9sYWJlbCApO1xuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgPSAkKCAnPHNlbGVjdCBzdHlsZT1cXCdtYXJnaW4tbGVmdDogNXB4XFwnIGNsYXNzPVxcJ3Qtc2VsZWN0XFwnPicgKTtcblx0XHR2YXIgdXBkYXRlX2J0biA9ICQoICc8YnV0dG9uIGNsYXNzPVwidHQtYnV0dG9uIHAtYnV0dG9uIHAtY29tcG9uZW50IHNtYWxsLXNlYXJjaC1wYW5lbC1idXR0b25cIiB0eXBlPVwiYnV0dG9uXCI+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJ0dGljb24gdHRpY29uLXNhdmVfYmxhY2tfMjRkcFwiPjwvc3Bhbj5cXG4nICtcblx0XHRcdCc8c3BhbiBjbGFzcz1cInAtYnV0dG9uLWxhYmVsXCI+JyArICQuaTE4bi5fKCAnVXBkYXRlJyApICsgJzwvc3Bhbj5cXG4nICtcblx0XHRcdCc8L2J1dHRvbj4nICk7XG5cblx0XHR2YXIgZGVsX2J0biA9ICQoICc8YnV0dG9uIGNsYXNzPVwidHQtYnV0dG9uIHAtYnV0dG9uIHAtY29tcG9uZW50IHNtYWxsLXNlYXJjaC1wYW5lbC1idXR0b25cIiB0eXBlPVwiYnV0dG9uXCI+XFxuJyArXG5cdFx0XHQnPHNwYW4gY2xhc3M9XCJ0dGljb24gdHRpY29uLWRlbGV0ZV9ibGFja18yNGRwXCI+PC9zcGFuPlxcbicgK1xuXHRcdFx0JzxzcGFuIGNsYXNzPVwicC1idXR0b24tbGFiZWxcIj4nICsgJC5pMThuLl8oICdEZWxldGUnICkgKyAnPC9zcGFuPlxcbicgK1xuXHRcdFx0JzwvYnV0dG9uPicgKTtcblxuXHRcdHVwZGF0ZV9idG4uY2xpY2soIGZ1bmN0aW9uKCkge1xuXHRcdFx0JHRoaXMub25VcGRhdGVMYXlvdXQoKTtcblx0XHR9ICk7XG5cblx0XHRkZWxfYnRuLmNsaWNrKCBmdW5jdGlvbigpIHtcblx0XHRcdCR0aGlzLm9uRGVsZXRlTGF5b3V0KCk7XG5cdFx0fSApO1xuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmFwcGVuZCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKTtcblx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuYXBwZW5kKCB1cGRhdGVfYnRuICk7XG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmFwcGVuZCggZGVsX2J0biApO1xuXG5cdFx0bGF5b3V0X2Rpdi5hcHBlbmQoIGZvcm1faXRlbSApO1xuXG5cdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfZGl2LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0fVxuXG5cdG9uR3JpZFNlbGVjdFJvdygpIHtcblx0XHQkKCAnI3JpYmJvbl92aWV3X2NvbnRhaW5lciAuY29udGV4dC1tZW51OnZpc2libGUgYScgKS5jbGljaygpO1xuXHRcdHRoaXMuc2V0RGVmYXVsdE1lbnUoKTtcblx0fVxuXG5cdHNldFByZXZpb3VzU2F2ZWRTZWFyY2hTb3VyY2VzQW5kVmFsdWUoIGxheW91dHNfYXJyYXkgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdGlmICggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IgKSB7XG5cdFx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9zZWxlY3Rvci5lbXB0eSgpO1xuXG5cdFx0XHRpZiAoIGxheW91dHNfYXJyYXkgJiYgbGF5b3V0c19hcnJheS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHR0aGlzLnByZXZpb3VzX3NhdmVkX2xheW91dF9kaXYuY3NzKCAnZGlzcGxheScsICdpbmxpbmUnICk7XG5cblx0XHRcdFx0dmFyIGxlbiA9IGxheW91dHNfYXJyYXkubGVuZ3RoO1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHR2YXIgaXRlbSA9IGxheW91dHNfYXJyYXlbaV07XG5cdFx0XHRcdFx0dGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IuYXBwZW5kKCAkKCAnPG9wdGlvbiB2YWx1ZT1cIicgKyBpdGVtLmlkICsgJ1wiPjwvb3B0aW9uPicgKS50ZXh0KCBpdGVtLm5hbWUgKSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JCggdGhpcy5wcmV2aW91c19zYXZlZF9sYXlvdXRfc2VsZWN0b3IuZmluZCggJ29wdGlvbicgKSApLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuICQoIHRoaXMgKS5hdHRyKCAndmFsdWUnICkgPT0gJHRoaXMuc2VsZWN0X2xheW91dC5pZDtcblx0XHRcdFx0fSApLnByb3AoICdzZWxlY3RlZCcsIHRydWUgKS5hdHRyKCAnc2VsZWN0ZWQnLCB0cnVlICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMucHJldmlvdXNfc2F2ZWRfbGF5b3V0X2Rpdi5jc3MoICdkaXNwbGF5JywgJ25vbmUnICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0c2V0U2VsZWN0TGF5b3V0KCBleGNsdWRlX2NvbHVtbiApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBncmlkO1xuXG5cdFx0dmFyIGdyaWRfaWQgPSAnZ3JpZCc7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCB0aGlzLmdyaWQgKSApIHtcblx0XHRcdGdyaWQgPSAkKCB0aGlzLmVsICkuZmluZCggJyNncmlkJyApO1xuXG5cdFx0XHRncmlkLmF0dHIoICdpZCcsIHRoaXMudWlfaWQgKyAnX2dyaWQnICk7ICAvL0dyaWQncyBpZCBpcyBTY3JpcHROYW1lICsgX2dyaWRcblxuXHRcdFx0Z3JpZF9pZCA9IHRoaXMudWlfaWQgKyAnX2dyaWQnO1xuXHRcdH1cblxuXHRcdHZhciBjb2x1bW5faW5mb19hcnJheSA9IFtdO1xuXG5cdFx0aWYgKCAhdGhpcy5zZWxlY3RfbGF5b3V0ICkgeyAvL1NldCB0byBkZWZhdWx0IGxheW91dCBpZiBubyBsYXlvdXQgYXQgYWxsXG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQgPSB7IGlkOiAnJyB9O1xuXHRcdFx0dGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEgPSB7IGZpbHRlcl9kYXRhOiB7fSwgZmlsdGVyX3NvcnQ6IHt9IH07XG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5kaXNwbGF5X2NvbHVtbnMgPSB0aGlzLmRlZmF1bHRfZGlzcGxheV9jb2x1bW5zO1xuXHRcdH1cblxuXHRcdHZhciBsYXlvdXRfZGF0YSA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhO1xuXG5cdFx0aWYgKCAhbGF5b3V0X2RhdGEuZGlzcGxheV9jb2x1bW5zIHx8IGxheW91dF9kYXRhLmRpc3BsYXlfY29sdW1ucy5sZW5ndGggPT0gMCApIHtcblx0XHRcdGxheW91dF9kYXRhLmRpc3BsYXlfY29sdW1ucyA9IHRoaXMuZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0fVxuXG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuYnVpbGREaXNwbGF5Q29sdW1ucyggbGF5b3V0X2RhdGEuZGlzcGxheV9jb2x1bW5zICk7XG5cblx0XHRpZiAoICF0aGlzLnN1Yl92aWV3X21vZGUgJiYgdGhpcy5zZWFyY2hfcGFuZWwgKSB7XG5cblx0XHRcdC8vU2V0IERpc3BsYXkgQ29sdW1uIGluIGxheW91dCBwYW5lbFxuXHRcdFx0Ly9FcnJvcjogVHlwZUVycm9yOiBudWxsIGlzIG5vdCBhbiBvYmplY3QgKGV2YWx1YXRpbmcgJ3RoaXMuY29sdW1uX3NlbGVjdG9yLnNldFNlbGVjdEdyaWREYXRhJylcblx0XHRcdGlmICggdGhpcy5jb2x1bW5fc2VsZWN0b3IgKSB7XG5cdFx0XHRcdHRoaXMuY29sdW1uX3NlbGVjdG9yLnNldFNlbGVjdEdyaWREYXRhKCBkaXNwbGF5X2NvbHVtbnMgKTtcblx0XHRcdFx0Ly90aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRHcmlkQ29sdW1uc1dpZHRocygpOyAvL1RoaXMgaXMgY2FsbGVkIGluIFNlYXJjaFBhbmVsLnNldEdyaWRTaXplKCkgb24gZXhwYW5kIGluc3RlYWQsIGFzIGJyb3dzZXJzIHNlZW0gdG8gb3B0aW1pemUgb3V0IHNjcm9sbGJhciBjYWxjdWxhdGlvbnMgdW50aWwgdGhlIERPTSBlbGVtZW50IGlzIHZpc2libGUuXG5cdFx0XHR9XG5cblx0XHRcdC8vU2V0IFNvcnQgYnkgYXdlc29tZWJveCBpbiBsYXlvdXQgcGFuZWxcblx0XHRcdC8vRXJyb3I6IFR5cGVFcnJvcjogbnVsbCBpcyBub3QgYW4gb2JqZWN0IChldmFsdWF0aW5nICd0aGlzLnNvcnRfYnlfc2VsZWN0b3Iuc2V0U291cmNlRGF0YScpXG5cdFx0XHRpZiAoIHRoaXMuc29ydF9ieV9zZWxlY3RvciApIHtcblx0XHRcdFx0dGhpcy5zb3J0X2J5X3NlbGVjdG9yLnNldFNvdXJjZURhdGEoIHRoaXMuYnVpbGRTb3J0U2VsZWN0b3JVblNlbGVjdENvbHVtbnMoIGRpc3BsYXlfY29sdW1ucyApICk7XG5cdFx0XHRcdHRoaXMuc29ydF9ieV9zZWxlY3Rvci5zZXRWYWx1ZSggdGhpcy5idWlsZFNvcnRCeVNlbGVjdENvbHVtbnMoKSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvL1NldCBQcmV2aW9vdXMgU2F2ZWQgbGF5b3V0IGNvbWJvYm94IGluIGxheW91dCBwYW5lbFxuXHRcdFx0dmFyIGxheW91dHNfYXJyYXkgPSB0aGlzLnNlYXJjaF9wYW5lbC5nZXRMYXlvdXRzQXJyYXkoKTtcblxuXHRcdFx0dGhpcy5zZXRQcmV2aW91c1NhdmVkU2VhcmNoU291cmNlc0FuZFZhbHVlKCBsYXlvdXRzX2FycmF5ICk7XG5cblx0XHR9XG5cblx0XHQvL1NldCBEYXRhIEdyaWQgb24gTGlzdCB2aWV3XG5cdFx0dmFyIGxlbiA9IGRpc3BsYXlfY29sdW1ucy5sZW5ndGg7XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciB2aWV3X2NvbHVtbl9kYXRhID0gZGlzcGxheV9jb2x1bW5zW2ldO1xuXG5cdFx0XHRpZiAoICQuaW5BcnJheSggdmlld19jb2x1bW5fZGF0YS52YWx1ZSwgZXhjbHVkZV9jb2x1bW4gKSAhPT0gLTEgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgY29sdW1uX2luZm8gPSB7XG5cdFx0XHRcdG5hbWU6IHZpZXdfY29sdW1uX2RhdGEudmFsdWUsXG5cdFx0XHRcdGluZGV4OiB2aWV3X2NvbHVtbl9kYXRhLnZhbHVlLFxuXHRcdFx0XHRsYWJlbDogdmlld19jb2x1bW5fZGF0YS5sYWJlbCxcblx0XHRcdFx0d2lkdGg6IDEwMCxcblx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHR0aXRsZTogZmFsc2Vcblx0XHRcdH07XG5cdFx0XHRjb2x1bW5faW5mb19hcnJheS5wdXNoKCBjb2x1bW5faW5mbyApO1xuXHRcdH1cblxuXHRcdHZhciBncmlkX25lZWRzX3JlbG9hZCA9IGZhbHNlO1xuXHRcdGlmICggdGhpcy5ncmlkICkge1xuXHRcdFx0Z3JpZF9pZCA9IHRoaXMudWlfaWQgKyAnX2dyaWQnO1xuXG5cdFx0XHRpZiAoIHRoaXMubGF5b3V0X2NoYW5nZWQgPT0gdHJ1ZSApIHtcblx0XHRcdFx0JHRoaXMubGF5b3V0X2NoYW5nZWQgPSBmYWxzZTtcblx0XHRcdFx0dGhpcy5ncmlkLmdyaWQuanFHcmlkKCAnR3JpZFVubG9hZCcgKTtcblx0XHRcdFx0dGhpcy5ncmlkID0gbnVsbDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vVGhpcyBpcyBkb25lIGluIEJhc2VWaWV3Q29udHJvbGVyLT5zZWFyY2goKSByaWdodCBiZWZvcmUgdGhlIGRhdGEgaXMgc2V0LCB3aGljaCBwcmV2ZW50cyBcImZsYXNoaW5nXCIuXG5cdFx0XHRcdC8vICBIb3dldmVyIHNvbWUgdmlld3Mgb3ZlcnJpZGUgdGhpcyBmdW5jdGlvbiBhbmQgbmVlZCB0byBiZSBmaXhlZCBtYW51YWxseS5cblx0XHRcdFx0Ly90aGlzLmdyaWQuY2xlYXJHcmlkRGF0YSgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuc2hvd0dyaWRCb3JkZXJzKCk7XG5cblx0XHRpZiAoICF0aGlzLmdyaWQgKSB7XG5cdFx0XHR2YXIgZ3JpZF9zZXR1cCA9IHRoaXMuZ2V0R3JpZFNldHVwKCk7XG5cdFx0XHRpZiAoIHRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdFx0Z3JpZF9zZXR1cC5oZWlnaHQgPSAxO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5ncmlkID0gbmV3IFRUR3JpZCggZ3JpZF9pZCwgZ3JpZF9zZXR1cCwgY29sdW1uX2luZm9fYXJyYXkgKTtcblxuXHRcdFx0aWYgKCB0aGlzLnN1Yl92aWV3X21vZGUgKSB7XG5cdFx0XHRcdHRoaXMuZ3JpZC5ncmlkLmhpZGUoKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5zZXRHcmlkQ29sdW1uc1dpZHRoKCk7IC8vSGVscHMgbWFrZXMgY2hhbmdpbmcgbGF5b3V0cyBcImZsYXNoXCIgbGVzcywgZXNwZWNpYWxseSB3aGVuIGdvaW5nIGZyb20gb25seSBhIGZldyBjb2x1bW5zIHRvIG1hbnkuXG5cdFx0XHR0aGlzLnNldEdyaWRTaXplKCB0aGlzLnVpX2lkLCB0aGlzLnN1Yl92aWV3X21vZGUsIHRoaXMuc3ViX3ZpZXdfZ3JpZF9hdXRvc2l6ZSwgdGhpcy5wYWdlcl9kYXRhICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmdyaWQgJiYgZ3JpZF9uZWVkc19yZWxvYWQgKSB7XG5cdFx0XHR0aGlzLmdyaWQucmVsb2FkR3JpZCgpO1xuXHRcdH1cblxuXHRcdC8vQWRkIHdpZGdldCBvbiBVSSBhbmQgYmluZCBldmVudHMuIE5leHQgc2V0IGRhdGEgaW4gaXQgaW4gc2VhcmNoIHJlc3VsdFxuXHRcdGlmICggTG9jYWxDYWNoZURhdGEucGFnaW5nX3R5cGUgPT09IDAgKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFnaW5nX3dpZGdldC5wYXJlbnQoKS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHR0aGlzLnBhZ2luZ193aWRnZXQucmVtb3ZlKCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMucGFnaW5nX3dpZGdldC5jc3MoICd3aWR0aCcsIHRoaXMuZ3JpZC5ncmlkLndpZHRoKCkgKTtcblx0XHRcdHRoaXMuZ3JpZC5ncmlkLmFwcGVuZCggdGhpcy5wYWdpbmdfd2lkZ2V0ICk7XG5cblx0XHRcdHRoaXMucGFnaW5nX3dpZGdldC5jbGljayggJHRoaXMub25QYWdpbmcoKSApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoIHRoaXMuZWwgKS5maW5kKCAnLnRvdGFsLW51bWJlci1kaXYnICkuYXBwZW5kKCB0aGlzLnBhZ2luZ193aWRnZXQgKTtcblx0XHRcdCQoIHRoaXMuZWwgKS5maW5kKCAnLmJvdHRvbS1kaXYnICkuYXBwZW5kKCB0aGlzLnBhZ2luZ193aWRnZXRfMiApO1xuXG5cdFx0XHR0aGlzLnBhZ2luZ193aWRnZXQub24oICdwYWdpbmcnLCBmdW5jdGlvbiggZSwgYWN0aW9uLCBwYWdlX251bWJlciApIHtcblx0XHRcdFx0JHRoaXMub25QYWdpbmcyKCBlLCBhY3Rpb24sIHBhZ2VfbnVtYmVyICk7XG5cdFx0XHR9ICk7XG5cdFx0XHR0aGlzLnBhZ2luZ193aWRnZXRfMi5iaW5kKCAncGFnaW5nJywgZnVuY3Rpb24oIGUsIGFjdGlvbiwgcGFnZV9udW1iZXIgKSB7XG5cdFx0XHRcdCR0aGlzLm9uUGFnaW5nMiggZSwgYWN0aW9uLCBwYWdlX251bWJlciApO1xuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdHRoaXMuYmluZEdyaWRDb2x1bW5FdmVudHMoKTtcblxuXHRcdHRoaXMuc2V0R3JpZEhlYWRlclN0eWxlKCk7IC8vU2V0IFNvcnQgU3R5bGVcblx0XHQvL3JlcGxhY2Ugc2VsZWN0IGxheW91dCBmaWx0ZXJfZGF0YSB0byBmaWx0ZXIgc2V0IGluIG9uTmF2aWdhdGlvbiBmdW5jdGlvbiB3aGVuIGdvdG8gdmlldyBmcm9tIG5hdmlnYXRpb24gY29udGV4dCBncm91cFxuXHRcdGlmICggTG9jYWxDYWNoZURhdGEuZGVmYXVsdF9maWx0ZXJfZm9yX25leHRfb3Blbl92aWV3ICkge1xuXHRcdFx0dGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX2RhdGEgPSBMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcuZmlsdGVyX2RhdGE7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5kZWZhdWx0X2ZpbHRlcl9mb3JfbmV4dF9vcGVuX3ZpZXcgPSBudWxsO1xuXHRcdH1cblxuXHRcdHRoaXMuZmlsdGVyX2RhdGEgPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfZGF0YTtcblxuXHRcdGlmICggIXRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdHRoaXMuc2V0U2VhcmNoUGFuZWxGaWx0ZXIoIHRydWUgKTsgLy9BdXRvIGNoYW5nZSB0byBwcm9wZXJ0eSB0YWIgd2hlbiBzZXQgdmFsdWUgdG8gc2VhcmNoIGZpZWxkcy5cblx0XHR9XG5cdH1cblxuXHRnZXRHcmlkU2V0dXAoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBjb250YWluZXIgPSB0aGlzLmdyaWRfcGFyZW50ID8gdGhpcy5ncmlkX3BhcmVudCA6ICcuZ3JpZC1kaXYnO1xuXHRcdGlmICggIXRoaXMuZ3JpZF9wYXJlbnQgJiYgdGhpcy5zdWJfdmlld19tb2RlICkge1xuXHRcdFx0aWYgKCAkKCAnIycgKyB0aGlzLnVpX2lkICsgJ19ncmlkJyApLnBhcmVudHMoICcuc3ViLXZpZXcnICkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0Y29udGFpbmVyID0gJy5zdWItZ3JpZC12aWV3LWRpdic7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb250YWluZXIgPSAnLmVkaXQtdmlldy10YWItYmFyJztcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29udGFpbmVyX3NlbGVjdG9yOiBjb250YWluZXIsXG5cdFx0XHRzdWJfZ3JpZF9tb2RlOiB0aGlzLnN1Yl92aWV3X21vZGUsXG5cdFx0XHRvblJlc2l6ZUdyaWQ6IHRydWUsXG5cdFx0XHRvblNlbGVjdFJvdzogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLm9uR3JpZFNlbGVjdFJvdygpO1xuXHRcdFx0fSxcblx0XHRcdG9uQ2VsbFNlbGVjdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCR0aGlzLm9uR3JpZFNlbGVjdFJvdygpO1xuXHRcdFx0fSxcblx0XHRcdG9uU2VsZWN0QWxsOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0JHRoaXMub25HcmlkU2VsZWN0QWxsKCk7XG5cdFx0XHR9LFxuXHRcdFx0b25kYmxDbGlja1JvdzogZnVuY3Rpb24oIGUgKSB7XG5cdFx0XHRcdCR0aGlzLm9uR3JpZERibENsaWNrUm93KCBlICk7XG5cdFx0XHR9LFxuXHRcdFx0b25SaWdodENsaWNrUm93OiBmdW5jdGlvbiggcm93SWQgKSB7XG5cdFx0XHRcdHZhciBpZF9hcnJheSA9ICR0aGlzLmdldEdyaWRTZWxlY3RJZEFycmF5KCk7XG5cdFx0XHRcdGlmICggaWRfYXJyYXkuaW5kZXhPZiggcm93SWQgKSA8IDAgKSB7XG5cdFx0XHRcdFx0JHRoaXMuZ3JpZC5ncmlkLnJlc2V0U2VsZWN0aW9uKCk7XG5cdFx0XHRcdFx0JHRoaXMuZ3JpZC5ncmlkLnNldFNlbGVjdGlvbiggcm93SWQgKTtcblx0XHRcdFx0XHQkdGhpcy5vbkdyaWRTZWxlY3RSb3coKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGhlaWdodDogMSwgLy9TdGFydCByZWFsbHkgc21hbGwgdG8gcmVkdWNlIGZsYXNoaW5nLCBhcyBoZWlnaHQgaXMgY2hhbmdlZCB3aXRoIHNldEdyaWRTaXplKCkgc2hvcnRseSBhZnRlciBhbnl3YXlzLlxuXHRcdH07XG5cdH1cblxuXHRvbkdyaWRTZWxlY3RBbGwoKSB7XG5cdFx0dGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHR9XG5cblx0dW5TZWxlY3RBbGwoKSB7XG5cdFx0dGhpcy5ncmlkLmdyaWQucmVzZXRTZWxlY3Rpb24oKTtcblx0fVxuXG5cdG9uR3JpZERibENsaWNrUm93KCBlICkge1xuXHRcdHRoaXMuZ3JpZC5ncmlkLnJlc2V0U2VsZWN0aW9uKCk7XG5cdFx0dGhpcy5ncmlkLnNldFNlbGVjdGlvbiggZSwgZmFsc2UgKTtcblx0XHR0aGlzLnNldERlZmF1bHRNZW51KCB0cnVlICk7XG5cdFx0dmFyIGNvbnRleHRfbWVudV9hcnJheSA9IENvbnRleHRNZW51TWFuYWdlci5nZXRNZW51TW9kZWxCeU1lbnVJZCggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkICk7XG5cdFx0dmFyIGxlbiA9IGNvbnRleHRfbWVudV9hcnJheS5sZW5ndGg7XG5cdFx0dmFyIG5lZWRfYnJlYWsgPSBmYWxzZTtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGlmICggbmVlZF9icmVhayApIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHR2YXIgaWQgPSBjb250ZXh0X21lbnVfYXJyYXlbaV0uaWQ7XG5cdFx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdFx0Y2FzZSAnZWRpdCc6XG5cdFx0XHRcdFx0aWYgKCAhY29udGV4dF9tZW51X2FycmF5W2ldLmRpc2FibGVkICYmIGNvbnRleHRfbWVudV9hcnJheVtpXS52aXNpYmxlICkge1xuXHRcdFx0XHRcdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHRcdFx0XHRcdHRoaXMub25FZGl0Q2xpY2soKTtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0aWYgKCBuZWVkX2JyZWFrICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdHZhciBpZCA9IGNvbnRleHRfbWVudV9hcnJheVtpXS5pZDtcblx0XHRcdHN3aXRjaCAoIGlkICkge1xuXHRcdFx0XHRjYXNlICd2aWV3Jzpcblx0XHRcdFx0XHRuZWVkX2JyZWFrID0gdHJ1ZTtcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0X21lbnVfYXJyYXlbaV0uZGlzYWJsZWQgJiYgY29udGV4dF9tZW51X2FycmF5W2ldLnZpc2libGUgKSB7XG5cdFx0XHRcdFx0XHRQcm9ncmVzc0Jhci5zaG93T3ZlcmxheSgpO1xuXHRcdFx0XHRcdFx0dGhpcy5vblZpZXdDbGljaygpO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgaWQgPSBjb250ZXh0X21lbnVfYXJyYXlbaV0uaWQ7XG5cdFx0XHRzd2l0Y2ggKCBpZCApIHtcblx0XHRcdFx0Y2FzZSAnYWRkJzpcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0X21lbnVfYXJyYXlbaV0uZGlzYWJsZWQgJiYgY29udGV4dF9tZW51X2FycmF5W2ldLnZpc2libGUgKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm9uQWRkQ2xpY2soKTtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0b25QYWdpbmcoKSB7XG5cdFx0dGhpcy5zZWFyY2goIHRydWUsICduZXh0JyApO1xuXHR9XG5cblx0b25QYWdpbmcyKCBlLCBhY3Rpb24sIHBhZ2VfbnVtYmVyICkge1xuXHRcdHRoaXMuc2VhcmNoKCB0cnVlLCBhY3Rpb24sIHBhZ2VfbnVtYmVyICk7XG5cdH1cblxuXHQvL0JpbmQgY29sdW1uIGNsaWNrIGV2ZW50IHRvIGNoYW5nZSBzb3J0IHR5cGUgYW5kIHNhdmUgY29sdW1ucyB0byB0X2dyaWRfaGVhZGVyX2FycmF5IHRvIHVzZSB0byBzZXQgY29sdW1uIHN0eWxlIChhc2Mgb3IgZGVzYylcblx0YmluZEdyaWRDb2x1bW5FdmVudHMoKSB7XG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuZ3JpZC5nZXRDb2x1bW5Nb2RlbCgpO1xuXG5cdFx0aWYgKCAhZGlzcGxheV9jb2x1bW5zICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBsZW4gPSBkaXNwbGF5X2NvbHVtbnMubGVuZ3RoO1xuXG5cdFx0dGhpcy50X2dyaWRfaGVhZGVyX2FycmF5ID0gW107XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBjb2x1bW5faW5mbyA9IGRpc3BsYXlfY29sdW1uc1tpXTtcblx0XHRcdHZhciBjb2x1bW5faGVhZGVyID0gJCggJCggdGhpcy5lbCApLmZpbmQoICcjZ2JveF8nICsgdGhpcy51aV9pZCArICdfZ3JpZCcgKS5maW5kKCAnZGl2ICNqcWdoXycgKyB0aGlzLnVpX2lkICsgJ19ncmlkXycgKyBjb2x1bW5faW5mby5uYW1lICkgKTtcblxuXHRcdFx0dGhpcy50X2dyaWRfaGVhZGVyX2FycmF5LnB1c2goIGNvbHVtbl9oZWFkZXIuVEdyaWRIZWFkZXIoKSApO1xuXHRcdFx0aWYgKCB0aGlzLnNlYXJjaF9wYW5lbCApIHtcblx0XHRcdFx0Y29sdW1uX2hlYWRlci5vbiggJ2NsaWNrJywgb25Db2x1bW5IZWFkZXJDbGljayApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHZhciAkdGhpcyA9IHRoaXM7XG5cblx0XHRmdW5jdGlvbiBvbkNvbHVtbkhlYWRlckNsaWNrKCBlICkge1xuXHRcdFx0dmFyIGZpZWxkID0gJCggdGhpcyApLmF0dHIoICdpZCcgKTtcblx0XHRcdGZpZWxkID0gZmllbGQuc3Vic3RyaW5nKCAxMCArICR0aGlzLnVpX2lkLmxlbmd0aCArIDEsIGZpZWxkLmxlbmd0aCApO1xuXG5cdFx0XHRpZiAoIGZpZWxkID09PSAnY2InICkgeyAvL2ZpcnN0IGNvbHVtbiwgY2hlY2sgYm94IGNvbHVtbi5cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7IC8vY2FuJ3QgYmUgY2FuY2VsbGVkIGJlZm9yZSBjYiBpcyBkZXRlY3RlZCBhcyB3ZSBuZWVkIHRoZSBkZWZhdWx0IGV2ZW50IGluIHRoYXQgY2FzZS5cblxuXHRcdFx0aWYgKCAhJHRoaXMuc29ydGluZ19yb3dzICkge1xuXHRcdFx0XHQkdGhpcy5zb3J0aW5nX3Jvd3MgPSB0cnVlO1xuXHRcdFx0XHRUVFByb21pc2UuYWRkKCAnaW5pdCcsICdpbml0JyApO1xuXHRcdFx0XHRUVFByb21pc2Uud2FpdCggbnVsbCwgbnVsbCwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JHRoaXMuc29ydGluZ19yb3dzID0gZmFsc2U7IC8vcHJldmVudCBkb3VibGluZyB1cCBldmVudHMgKCB3aGljaCBsb29wcyBmb3JldmVyIClcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdGlmICggZS5tZXRhS2V5IHx8IGUuY3RybEtleSApIHtcblx0XHRcdFx0XHQkdGhpcy5idWlsZFNvcnRDb25kaXRpb24oIGZhbHNlLCBmaWVsZCApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCR0aGlzLmJ1aWxkU29ydENvbmRpdGlvbiggdHJ1ZSwgZmllbGQgKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICkge1xuXHRcdFx0XHRcdCR0aGlzLnNlYXJjaCgpO1xuXHRcdFx0XHRcdCR0aGlzLnNldEdyaWRIZWFkZXJTdHlsZSgpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmICggJHRoaXMuc29ydF9ieV9zZWxlY3RvciApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNvcnRfYnlfc2VsZWN0b3Iuc2V0VmFsdWUoICR0aGlzLmJ1aWxkU29ydEJ5U2VsZWN0Q29sdW1ucygpICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCR0aGlzLm9uU2VhcmNoKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdERlYnVnLlRleHQoICdTa2lwcGluZyBjb2x1bW4gc29ydCBjYWxsICcsICcnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ29uQ29sdW1uSGVhZGVyQ2xpY2snLCAxMCApO1xuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0Z2V0VmFsaWRTZWFyY2hGaWx0ZXIoKSB7XG5cdFx0dmFyIHZhbGlkRmlsdGVyRGF0YSA9IHt9O1xuXHRcdGZvciAoIHZhciBrZXkgaW4gdGhpcy5maWx0ZXJfZGF0YSApIHtcblx0XHRcdC8vIEVycm9yOiBVbmFibGUgdG8gZ2V0IHByb3BlcnR5ICd2YWx1ZScgb2YgdW5kZWZpbmVkIG9yIG51bGwgcmVmZXJlbmNlIGluIC9pbnRlcmZhY2UvaHRtbDUvdmlld3MvQmFzZVZpZXdDb250cm9sbGVyLmpzP3Y9OC4wLjYtMjAxNTA0MTctMTQzNzM0IGxpbmUgNDcyN1xuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHRoaXMuZmlsdGVyX2RhdGFba2V5XSApICYmIEdsb2JhbC5pc1NldCggdGhpcy5maWx0ZXJfZGF0YVtrZXldLnZhbHVlICkgJiYgdGhpcy5maWx0ZXJfZGF0YVtrZXldLnZhbHVlICE9PSAnJyApIHtcblx0XHRcdFx0dmFsaWRGaWx0ZXJEYXRhW2tleV0gPSB0aGlzLmZpbHRlcl9kYXRhW2tleV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZhbGlkRmlsdGVyRGF0YTtcblx0fVxuXG5cdGdldFNlYXJjaFBhbmVsRGlzcGxheUNvbHVtbnMoKSB7XG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IFtdO1xuXG5cdFx0dmFyIHNlbGVjdF9pdGVtcyA9IHRoaXMuY29sdW1uX3NlbGVjdG9yLmdldFNlbGVjdEl0ZW1zKCk7XG5cblx0XHRpZiAoIHNlbGVjdF9pdGVtcyAmJiBzZWxlY3RfaXRlbXMubGVuZ3RoID4gMCApIHtcblx0XHRcdCQuZWFjaCggc2VsZWN0X2l0ZW1zLCBmdW5jdGlvbiggaW5kZXgsIGNvbnRlbnQgKSB7XG5cdFx0XHRcdGRpc3BsYXlfY29sdW1ucy5wdXNoKCBjb250ZW50LnZhbHVlICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhZGlzcGxheV9jb2x1bW5zIHx8IGRpc3BsYXlfY29sdW1ucy5sZW5ndGggPT0gMCApIHtcblx0XHRcdGRpc3BsYXlfY29sdW1ucyA9IHRoaXMuZGVmYXVsdF9kaXNwbGF5X2NvbHVtbnM7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGRpc3BsYXlfY29sdW1ucztcblx0fVxuXG5cdGdldFNlYXJjaFBhbmVsU29ydEZpbHRlcigpIHtcblx0XHR2YXIgc29ydF9maWx0ZXIgPSBbXTtcblx0XHRpZiAoIHRoaXMuc29ydF9ieV9zZWxlY3RvciApIHtcblx0XHRcdHZhciBzZWxlY3RfaXRlbXMgPSB0aGlzLnNvcnRfYnlfc2VsZWN0b3IuZ2V0VmFsdWUoIHRydWUgKTtcblxuXHRcdFx0aWYgKCBzZWxlY3RfaXRlbXMgJiYgc2VsZWN0X2l0ZW1zLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdCQuZWFjaCggc2VsZWN0X2l0ZW1zLCBmdW5jdGlvbiggaW5kZXgsIGNvbnRlbnQgKSB7XG5cdFx0XHRcdFx0dmFyIHNvcnQgPSB7fTtcblx0XHRcdFx0XHRzb3J0W2NvbnRlbnQudmFsdWVdID0gY29udGVudC5zb3J0O1xuXHRcdFx0XHRcdHNvcnRfZmlsdGVyLnB1c2goIHNvcnQgKTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBzb3J0X2ZpbHRlcjtcblx0fVxuXG5cdGdldFNlYXJjaFBhbmVsRmlsdGVyKCBnZXRGcm9tVGFiSW5kZXgsIHNhdmVfdGVtcF9maWx0ZXIgKSB7XG5cdFx0aWYgKCAhdGhpcy5zZWFyY2hfcGFuZWwgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBnZXRGcm9tVGFiSW5kZXggKSApIHtcblx0XHRcdHZhciBzZWFyY2hfdGFiX3NlbGVjdF9pbmRleCA9IGdldEZyb21UYWJJbmRleDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0c2VhcmNoX3RhYl9zZWxlY3RfaW5kZXggPSB0aGlzLnNlYXJjaF9wYW5lbC5nZXRTZWxlY3RUYWJJbmRleCgpO1xuXHRcdH1cblxuLy9cdFx0dmFyIGJhc2ljX2ZpZWxkc19sZW4gPSB0aGlzLnNlYXJjaF9maWVsZHMubGVuZ3RoO1xuXHRcdHZhciB0YXJnZXRfdWlfZGljID0gbnVsbDtcblxuXHRcdGlmICggc2VhcmNoX3RhYl9zZWxlY3RfaW5kZXggPT09IDAgKSB7XG5cdFx0XHR0aGlzLmZpbHRlcl9kYXRhID0gW107XG5cdFx0XHR0YXJnZXRfdWlfZGljID0gdGhpcy5iYXNpY19zZWFyY2hfZmllbGRfdWlfZGljO1xuXHRcdH0gZWxzZSBpZiAoIHNlYXJjaF90YWJfc2VsZWN0X2luZGV4ID09PSAxICYmIHRoaXMuc2VhcmNoX3BhbmVsLmlzQWR2VGFiVmlzaWJsZSgpICkge1xuXHRcdFx0dGhpcy5maWx0ZXJfZGF0YSA9IFtdO1xuXHRcdFx0dGFyZ2V0X3VpX2RpYyA9IHRoaXMuYWR2X3NlYXJjaF9maWVsZF91aV9kaWM7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdCQuZWFjaCggdGFyZ2V0X3VpX2RpYywgZnVuY3Rpb24oIGtleSwgY29udGVudCApIHtcblx0XHRcdCR0aGlzLmZpbHRlcl9kYXRhW2tleV0gPSB7IGZpZWxkOiBrZXksIGlkOiAnJywgdmFsdWU6IHRhcmdldF91aV9kaWNba2V5XS5nZXRWYWx1ZSggdHJ1ZSApIH07XG5cblx0XHRcdGlmICggJHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSApIHtcblx0XHRcdFx0JHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YVtrZXldID0gJHRoaXMuZmlsdGVyX2RhdGFba2V5XTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAkdGhpcy50ZW1wX2Fkdl9maWx0ZXJfZGF0YSApIHtcblx0XHRcdFx0JHRoaXMudGVtcF9hZHZfZmlsdGVyX2RhdGFba2V5XSA9ICR0aGlzLmZpbHRlcl9kYXRhW2tleV07XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdFx0aWYgKCBzYXZlX3RlbXBfZmlsdGVyICkge1xuXHRcdFx0aWYgKCBzZWFyY2hfdGFiX3NlbGVjdF9pbmRleCA9PT0gMCApIHtcblx0XHRcdFx0JHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YSA9IEdsb2JhbC5jbG9uZSggJHRoaXMuZmlsdGVyX2RhdGEgKTtcblx0XHRcdH0gZWxzZSBpZiAoIHNlYXJjaF90YWJfc2VsZWN0X2luZGV4ID09PSAxICkge1xuXHRcdFx0XHQkdGhpcy50ZW1wX2Fkdl9maWx0ZXJfZGF0YSA9IEdsb2JhbC5jbG9uZSggJHRoaXMuZmlsdGVyX2RhdGEgKTtcblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdC8vU2V0IHZhbHVlIHRvIGZpZWxkIFVJIGluIHNlYXJjaCB0YWJcblx0c2V0U2VhcmNoUGFuZWxGaWx0ZXIoIGF1dG9DaGFuZ2VUYWIsIHRhYl9pbmRleCApIHtcblxuXHRcdHRoaXMuY2xlYXJTZWFyY2hQYW5lbCgpO1xuXG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBhdXRvQ2hhbmdlVGFiICkgKSB7XG5cdFx0XHRhdXRvQ2hhbmdlVGFiID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0dmFyIGZpbHRlciA9IHRoaXMuZmlsdGVyX2RhdGE7XG5cblx0XHRpZiAoIEdsb2JhbC5pc1NldCggdGFiX2luZGV4ICkgKSB7XG5cdFx0XHRpZiAoIHRhYl9pbmRleCA9PT0gMCAmJiB0aGlzLnRlbXBfYmFzaWNfZmlsdGVyX2RhdGEgKSB7XG5cdFx0XHRcdGZpbHRlciA9IHRoaXMudGVtcF9iYXNpY19maWx0ZXJfZGF0YTtcblx0XHRcdH0gZWxzZSBpZiAoIHRhYl9pbmRleCA9PT0gMSAmJiB0aGlzLnRlbXBfYWR2X2ZpbHRlcl9kYXRhICkge1xuXHRcdFx0XHRmaWx0ZXIgPSB0aGlzLnRlbXBfYWR2X2ZpbHRlcl9kYXRhO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIUdsb2JhbC5pc1NldCggZmlsdGVyICkgfHwgIXRoaXMuc2VhcmNoX2ZpZWxkcyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgYmFzaWNfZmllbGRzX2xlbiA9IHRoaXMuc2VhcmNoX2ZpZWxkcy5sZW5ndGg7XG5cblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBiYXNpY19maWVsZHNfbGVuOyBpKysgKSB7XG5cdFx0XHR2YXIgZmllbGQgPSB0aGlzLnNlYXJjaF9maWVsZHNbaV07XG5cdFx0XHR2YXIgZmllbGRfbmFtZSA9IGZpZWxkLmdldCggJ2ZpZWxkJyApO1xuXG5cdFx0XHR2YXIgc2VhcmNoX2lucHV0ID0gdGhpcy5iYXNpY19zZWFyY2hfZmllbGRfdWlfZGljW2ZpZWxkX25hbWVdO1xuXHRcdFx0dmFyIHNlYXJjaF9pbnB1dF8xID0gdGhpcy5hZHZfc2VhcmNoX2ZpZWxkX3VpX2RpY1tmaWVsZF9uYW1lXTtcblxuXHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIGZpbHRlcltmaWVsZF9uYW1lXSApICkge1xuXG5cdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCBzZWFyY2hfaW5wdXQgKSApIHtcblxuXHRcdFx0XHRcdGlmICggJC50eXBlKCBmaWx0ZXJbZmllbGRfbmFtZV0gKSA9PT0gJ3N0cmluZycgfHwgJC50eXBlKCBmaWx0ZXJbZmllbGRfbmFtZV0gKSA9PT0gJ251bWJlcicgKSB7XG5cdFx0XHRcdFx0XHRzZWFyY2hfaW5wdXQuc2V0VmFsdWUoIGZpbHRlcltmaWVsZF9uYW1lXSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdGlmICggZmlsdGVyW2ZpZWxkX25hbWVdLmhhc093blByb3BlcnR5KCAndmFsdWUnICkgKSB7IC8vIHdoZW4gc2V0IGRlZmF1bHQgZmlsdGVyIGRvbid0IGhhdmUgJ3ZhbHVlJyBpbiBpdCwgRm9yIGV4YW1wbGUgSW52b2ljZSBlZGl0IHZpZXdcblx0XHRcdFx0XHRcdFx0c2VhcmNoX2lucHV0LnNldFZhbHVlKCBmaWx0ZXJbZmllbGRfbmFtZV0udmFsdWUgKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHNlYXJjaF9pbnB1dC5zZXRWYWx1ZSggZmlsdGVyW2ZpZWxkX25hbWVdICk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fSBlbHNlIGlmICggYXV0b0NoYW5nZVRhYiAmJiAhdGhpcy5zYXZpbmdfbGF5b3V0X2luX2xheW91dF90YWIgKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLnNlYXJjaF9wYW5lbC5nZXRTZWxlY3RUYWJJbmRleCgpICE9PSAxICkge1xuXHRcdFx0XHRcdFx0dGhpcy5zZWFyY2hfcGFuZWwuc2V0U2VsZWN0VGFiSW5kZXgoIDEsIGZhbHNlICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoIHNlYXJjaF9pbnB1dF8xICkgKSB7XG5cblx0XHRcdFx0XHRpZiAoICQudHlwZSggZmlsdGVyW2ZpZWxkX25hbWVdICkgPT09ICdzdHJpbmcnIHx8ICQudHlwZSggZmlsdGVyW2ZpZWxkX25hbWVdICkgPT09ICdudW1iZXInICkge1xuXHRcdFx0XHRcdFx0c2VhcmNoX2lucHV0XzEuc2V0VmFsdWUoIGZpbHRlcltmaWVsZF9uYW1lXSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiAoIGZpbHRlcltmaWVsZF9uYW1lXS5oYXNPd25Qcm9wZXJ0eSggJ3ZhbHVlJyApICkgeyAvLyB3aGVuIHNldCBkZWZhdWx0IGZpbHRlciBkb24ndCBoYXZlICd2YWx1ZScgaW4gaXQsIEZvciBleGFtcGxlIEludm9pY2UgZWRpdCB2aWV3XG5cdFx0XHRcdFx0XHRcdHNlYXJjaF9pbnB1dF8xLnNldFZhbHVlKCBmaWx0ZXJbZmllbGRfbmFtZV0udmFsdWUgKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHNlYXJjaF9pbnB1dF8xLnNldFZhbHVlKCBmaWx0ZXJbZmllbGRfbmFtZV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG4vL1x0XHRcdFx0XHRzZWFyY2hfaW5wdXRfMS5zZXRWYWx1ZSggZmlsdGVyW2ZpZWxkX25hbWVdLnZhbHVlICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0fVxuXG5cdFx0dGhpcy5nZXRTZWFyY2hQYW5lbEZpbHRlcigpOyAvL01ha2Ugc3VyZSBmaWx0ZXIgb25seSBoYXMgZmllbGRzIG9uIGN1cnJlbnQgZGlzcGxheSBhYlxuXG5cdFx0dGhpcy5zZWFyY2hfcGFuZWwuc2V0U2VhcmNoRmxhZyggdGhpcy5nZXRWYWxpZFNlYXJjaEZpbHRlcigpICk7IC8vIEFkZCAhIHRvIHRhYiB3aGljaCBoYXMgc2VhcmNoIGNvbmRpdGlvbiBpbiBpdFxuXG5cdFx0dGhpcy5vblNldFNlYXJjaEZpbHRlckZpbmlzaGVkKCk7XG5cdH1cblxuXHQvL1NldCBHcmlkIGhlYWRlciBzdHlsZSBmb3IgYXNjIG9yIGRlc2Ncblx0c2V0R3JpZEhlYWRlclN0eWxlKCkge1xuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHRoaXMudF9ncmlkX2hlYWRlcl9hcnJheS5sZW5ndGg7IGkrKyApIHtcblx0XHRcdHZhciB0X2dyaWRfaGVhZGVyID0gdGhpcy50X2dyaWRfaGVhZGVyX2FycmF5W2ldO1xuXG5cdFx0XHR2YXIgZmllbGQgPSB0X2dyaWRfaGVhZGVyLmF0dHIoICdpZCcgKTtcblx0XHRcdGlmICggdHlwZW9mIGZpZWxkID09PSAnc3RyaW5nJyB8fCBmaWVsZCBpbnN0YW5jZW9mIFN0cmluZyApIHtcblx0XHRcdFx0ZmllbGQgPSBmaWVsZC5zdWJzdHJpbmcoIDEwICsgdGhpcy51aV9pZC5sZW5ndGggKyAxLCBmaWVsZC5sZW5ndGggKTtcblxuXHRcdFx0XHR0X2dyaWRfaGVhZGVyLmNsZWFuU29ydFN0eWxlKCk7XG5cblx0XHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydCApIHtcblx0XHRcdFx0XHR2YXIgc29ydF9hcnJheV9sZW4gPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydC5sZW5ndGg7XG5cblx0XHRcdFx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCBzb3J0X2FycmF5X2xlbjsgaisrICkge1xuXHRcdFx0XHRcdFx0dmFyIHNvcnRfaXRlbSA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmZpbHRlcl9zb3J0W2pdO1xuXHRcdFx0XHRcdFx0dmFyIHNvcnRGaWVsZCA9IEdsb2JhbC5nZXRGaXJzdEtleUZyb21PYmplY3QoIHNvcnRfaXRlbSApO1xuXHRcdFx0XHRcdFx0aWYgKCBzb3J0RmllbGQgPT09IGZpZWxkICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoIHNvcnRfYXJyYXlfbGVuID4gMSApIHtcblx0XHRcdFx0XHRcdFx0XHR0X2dyaWRfaGVhZGVyLnNldFNvcnRTdHlsZSggc29ydF9pdGVtW3NvcnRGaWVsZF0sIGogKyAxICk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0dF9ncmlkX2hlYWRlci5zZXRTb3J0U3R5bGUoIHNvcnRfaXRlbVtzb3J0RmllbGRdLCAwICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRidWlsZFNvcnRDb25kaXRpb24oIHJlc2V0LCBmaWVsZCApIHtcblx0XHR2YXIgbmV4dF9zb3J0ID0gJ2Rlc2MnO1xuXG5cdFx0aWYgKCByZXNldCApIHtcblxuXHRcdFx0aWYgKCB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydCAmJiB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydC5sZW5ndGggPiAwICkge1xuXHRcdFx0XHR2YXIgbGVuID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX3NvcnQubGVuZ3RoO1xuXHRcdFx0XHR2YXIgZm91bmQgPSBmYWxzZTtcblxuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHR2YXIgc29ydF9pdGVtID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX3NvcnRbaV07XG5cdFx0XHRcdFx0Zm9yICggdmFyIGtleSBpbiBzb3J0X2l0ZW0gKSB7XG5cblx0XHRcdFx0XHRcdGlmICggIXNvcnRfaXRlbS5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAoIGtleSA9PT0gZmllbGQgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggc29ydF9pdGVtW2tleV0gPT09ICdhc2MnICkge1xuXHRcdFx0XHRcdFx0XHRcdG5leHRfc29ydCA9ICdkZXNjJztcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRuZXh0X3NvcnQgPSAnYXNjJztcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGZvdW5kICkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydCA9IFtcblx0XHRcdFx0e31cblx0XHRcdF07XG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydFswXVtmaWVsZF0gPSBuZXh0X3NvcnQ7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCAhdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX3NvcnQgKSB7XG5cdFx0XHRcdHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmZpbHRlcl9zb3J0ID0gW1xuXHRcdFx0XHRcdHt9XG5cdFx0XHRcdF07XG5cdFx0XHRcdHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmZpbHRlcl9zb3J0WzBdW2ZpZWxkXSA9ICdhc2MnO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bGVuID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX3NvcnQubGVuZ3RoO1xuXHRcdFx0XHRmb3VuZCA9IGZhbHNlO1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHRzb3J0X2l0ZW0gPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydFtpXTtcblx0XHRcdFx0XHRmb3IgKCB2YXIga2V5IGluIHNvcnRfaXRlbSApIHtcblxuXHRcdFx0XHRcdFx0aWYgKCAhc29ydF9pdGVtLmhhc093blByb3BlcnR5KCBrZXkgKSApIHtcblx0XHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGlmICgga2V5ID09PSBmaWVsZCApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBzb3J0X2l0ZW1ba2V5XSA9PT0gJ2FzYycgKSB7XG5cdFx0XHRcdFx0XHRcdFx0c29ydF9pdGVtW2tleV0gPSAnZGVzYyc7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0c29ydF9pdGVtW2tleV0gPSAnYXNjJztcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIGZvdW5kICkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoICFmb3VuZCApIHtcblx0XHRcdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydC5wdXNoKCB7fSApO1xuXHRcdFx0XHRcdHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmZpbHRlcl9zb3J0W2xlbl1bZmllbGRdID0gJ2FzYyc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH1cblx0fVxuXG5cdHNlYXJjaCggc2V0X2RlZmF1bHRfbWVudSwgcGFnZV9hY3Rpb24sIHBhZ2VfbnVtYmVyLCBjYWxsQmFjayApIHtcblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHNldF9kZWZhdWx0X21lbnUgKSApIHtcblx0XHRcdHNldF9kZWZhdWx0X21lbnUgPSB0cnVlO1xuXHRcdH1cblxuXHRcdHZhciBmaWx0ZXIgPSB7fTtcblx0XHRmaWx0ZXIuZmlsdGVyX2RhdGEgPSB7fTtcblx0XHRmaWx0ZXIuZmlsdGVyX3NvcnQgPSB7fTtcblx0XHRmaWx0ZXIuZmlsdGVyX2NvbHVtbnMgPSB0aGlzLmdldEZpbHRlckNvbHVtbnNGcm9tRGlzcGxheUNvbHVtbnMoKTtcblx0XHRmaWx0ZXIuZmlsdGVyX2l0ZW1zX3Blcl9wYWdlID0gMDsgLy8gRGVmYXVsdCB0byAwIHRvIGxvYWQgdXNlciBwcmVmZXJlbmNlIGRlZmluZWRcblx0XHRpZiAoIHRoaXMucGFnZXJfZGF0YSApIHtcblxuXHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5wYWdpbmdfdHlwZSA9PT0gMCApIHtcblx0XHRcdFx0aWYgKCBwYWdlX2FjdGlvbiA9PT0gJ25leHQnICkge1xuXHRcdFx0XHRcdGZpbHRlci5maWx0ZXJfcGFnZSA9IHRoaXMucGFnZXJfZGF0YS5uZXh0X3BhZ2U7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZmlsdGVyLmZpbHRlcl9wYWdlID0gMTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c3dpdGNoICggcGFnZV9hY3Rpb24gKSB7XG5cdFx0XHRcdFx0Y2FzZSAnbmV4dCc6XG5cdFx0XHRcdFx0XHRmaWx0ZXIuZmlsdGVyX3BhZ2UgPSB0aGlzLnBhZ2VyX2RhdGEubmV4dF9wYWdlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSAnbGFzdCc6XG5cdFx0XHRcdFx0XHRmaWx0ZXIuZmlsdGVyX3BhZ2UgPSB0aGlzLnBhZ2VyX2RhdGEucHJldmlvdXNfcGFnZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgJ3N0YXJ0Jzpcblx0XHRcdFx0XHRcdGZpbHRlci5maWx0ZXJfcGFnZSA9IDE7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdlbmQnOlxuXHRcdFx0XHRcdFx0ZmlsdGVyLmZpbHRlcl9wYWdlID0gdGhpcy5wYWdlcl9kYXRhLmxhc3RfcGFnZV9udW1iZXI7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlICdnb190byc6XG5cdFx0XHRcdFx0XHRmaWx0ZXIuZmlsdGVyX3BhZ2UgPSBwYWdlX251bWJlcjtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0XHRmaWx0ZXIuZmlsdGVyX3BhZ2UgPSB0aGlzLnBhZ2VyX2RhdGEuY3VycmVudF9wYWdlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0ZmlsdGVyLmZpbHRlcl9wYWdlID0gMTtcblx0XHR9XG5cdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnZGF0YScgb2YgbnVsbFxuXHRcdGlmICggdHlwZW9mIHRoaXMuc2VsZWN0X2xheW91dCAhPSAndW5kZWZpbmVkJyAmJiB0aGlzLnN1Yl92aWV3X21vZGUgJiYgdGhpcy5wYXJlbnRfa2V5ICkge1xuXHRcdFx0dGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX2RhdGFbdGhpcy5wYXJlbnRfa2V5XSA9IHRoaXMucGFyZW50X3ZhbHVlO1xuXHRcdH1cblx0XHQvL0Vycm9yOiBVbmNhdWdodCBUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnR5ICdkYXRhJyBvZiBudWxsXG5cdFx0Ly9JZiBzdWIgdmlldyBjb250cm9sbGVyIHNldCBjdXN0b20gZmlsdGVycywgZ2V0IGl0XG5cdFx0aWYgKCB0eXBlb2YgdGhpcy5zZWxlY3RfbGF5b3V0ICE9ICd1bmRlZmluZWQnICYmIEdsb2JhbC5pc1NldCggdGhpcy5nZXRTdWJWaWV3RmlsdGVyICkgKSB7XG5cdFx0XHR0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfZGF0YSA9IHRoaXMuZ2V0U3ViVmlld0ZpbHRlciggdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX2RhdGEgKTtcblx0XHR9XG5cblx0XHQvL3NlbGVjdF9sYXlvdXQgd2lsbCBub3QgYmUgbnVsbCwgaXQncyBzZXQgaW4gc2V0U2VsZWN0TGF5b3V0IGZ1bmN0aW9uXG5cdFx0ZmlsdGVyLmZpbHRlcl9kYXRhID0gR2xvYmFsLmNvbnZlcnRMYXlvdXRGaWx0ZXJUb0FQSUZpbHRlciggdGhpcy5zZWxlY3RfbGF5b3V0ICk7XG5cdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnZGF0YScgb2YgbnVsbFxuXHRcdGlmICggdGhpcy5zZWxlY3RfbGF5b3V0ICYmIHRoaXMuc2VsZWN0X2xheW91dC5kYXRhICkge1xuXHRcdFx0ZmlsdGVyLmZpbHRlcl9zb3J0ID0gdGhpcy5zZWxlY3RfbGF5b3V0LmRhdGEuZmlsdGVyX3NvcnQ7XG5cdFx0fVxuXG5cdFx0aWYgKCBUVFVVSUQuaXNVVUlEKCB0aGlzLnJlZnJlc2hfaWQgKSApIHtcblx0XHRcdGZpbHRlci5maWx0ZXJfZGF0YSA9IHt9O1xuXHRcdFx0ZmlsdGVyLmZpbHRlcl9kYXRhLmlkID0gW3RoaXMucmVmcmVzaF9pZF07XG5cblx0XHRcdHRoaXMubGFzdF9zZWxlY3RfaWRzID0gZmlsdGVyLmZpbHRlcl9kYXRhLmlkO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMubGFzdF9zZWxlY3RfaWRzID0gW107XG5cdFx0XHR2YXIgaWRzID0gdGhpcy5nZXRHcmlkU2VsZWN0SWRBcnJheSgpO1xuXHRcdFx0Ly9lbnN1cmUgZGV0YWNoZWQgcmVmZXJlbmNlIHRvIHZhbHVlIHNvdXJjZSBvciBsb3NlIHRoaXMubGFzdF9zZWxlY3RfaWRzIHdoZW4gZ3JpZCBpcyBjbGVhcmVkLlxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgaWRzLmxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHR0aGlzLmxhc3Rfc2VsZWN0X2lkcy5wdXNoKCBpZHNbaV0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuYXBpWydnZXQnICsgdGhpcy5hcGkua2V5X25hbWVdKCBmaWx0ZXIsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHR2YXIgcmVzdWx0X2RhdGEgPSByZXN1bHQuZ2V0UmVzdWx0KCk7XG5cdFx0XHRcdHZhciBsZW47XG5cdFx0XHRcdGlmICggc2V0X2RlZmF1bHRfbWVudSApIHtcblx0XHRcdFx0XHQkdGhpcy5zZXREZWZhdWx0TWVudSggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggIUdsb2JhbC5pc0FycmF5KCByZXN1bHRfZGF0YSApICYmICggIVRUVVVJRC5pc1VVSUQoICR0aGlzLnJlZnJlc2hfaWQgKSB8fCAkdGhpcy5yZWZyZXNoX2lkID09IFRUVVVJRC56ZXJvX2lkIHx8ICR0aGlzLnJlZnJlc2hfaWQgPT0gVFRVVUlELm5vdF9leGlzdF9pZCApICkge1xuXHRcdFx0XHRcdCR0aGlzLnJlZnJlc2hfaWQgPSBudWxsO1xuXHRcdFx0XHRcdCR0aGlzLnNob3dOb1Jlc3VsdENvdmVyKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0JHRoaXMucmVtb3ZlTm9SZXN1bHRDb3ZlcigpO1xuXHRcdFx0XHRcdGlmICggR2xvYmFsLmlzU2V0KCAkdGhpcy5fX2NyZWF0ZVJvd0lkICkgKSB7XG5cdFx0XHRcdFx0XHRyZXN1bHRfZGF0YSA9ICR0aGlzLl9fY3JlYXRlUm93SWQoIHJlc3VsdF9kYXRhICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKCBHbG9iYWwuaXNTZXQoICR0aGlzLnNob3dHcmlkT3B0aW9uRmllbGRzICkgKSB7XG5cdFx0XHRcdFx0XHRyZXN1bHRfZGF0YSA9ICR0aGlzLnNob3dHcmlkT3B0aW9uRmllbGRzKCByZXN1bHRfZGF0YSApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHJlc3VsdF9kYXRhID0gR2xvYmFsLmZvcm1hdEdyaWREYXRhKCByZXN1bHRfZGF0YSwgJHRoaXMuYXBpLmtleV9uYW1lICk7XG5cdFx0XHRcdFx0bGVuID0gcmVzdWx0X2RhdGEubGVuZ3RoO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBUVFVVSUQuaXNVVUlEKCAkdGhpcy5yZWZyZXNoX2lkICkgKSB7XG5cdFx0XHRcdFx0JHRoaXMucmVmcmVzaF9pZCA9IG51bGw7XG5cdFx0XHRcdFx0dmFyIGdyaWRfc291cmNlX2RhdGEgPSAkdGhpcy5ncmlkLmdldERhdGEoKTtcblx0XHRcdFx0XHRsZW4gPSBncmlkX3NvdXJjZV9kYXRhLmxlbmd0aDtcblx0XHRcdFx0XHRpZiAoICQudHlwZSggZ3JpZF9zb3VyY2VfZGF0YSApICE9PSAnYXJyYXknICkge1xuXHRcdFx0XHRcdFx0Z3JpZF9zb3VyY2VfZGF0YSA9IFtdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR2YXIgZm91bmQgPSBmYWxzZTtcblx0XHRcdFx0XHR2YXIgbmV3X3JlY29yZCA9IHJlc3VsdF9kYXRhWzBdO1xuXHRcdFx0XHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2lkJyBvZiB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj03LjQuMy0yMDE0MDkyNC0wODQ2MDUgbGluZSA0ODUxXG5cdFx0XHRcdFx0aWYgKCBuZXdfcmVjb3JkICkge1xuXHRcdFx0XHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRcdHZhciByZWNvcmQgPSBncmlkX3NvdXJjZV9kYXRhW2ldO1xuXHRcdFx0XHRcdFx0XHQvL0ZpeGVkID09PSBpc3N1ZS4gVGhlIGlkIHNldCBieSBqUUdyaWQgaXMgc3RyaW5nIHR5cGUuXG5cdFx0XHRcdFx0XHRcdC8vQ29tbWVudGVkIG91dCBhcyB3ZSBub3cgZXhwZWN0IHRoZSB2YXJpYWJsZSB0eXBlIG9mIHRoZSBpZHMgdG8gYmUgVVVJRCAoc3RyaW5nIGluIGphdmFzY3JpcHQpXG5cdFx0XHRcdFx0XHRcdC8vaWYgKCAhaXNOYU4oIHBhcnNlSW50KCByZWNvcmQuaWQgKSApICkge1xuXHRcdFx0XHRcdFx0XHQvL1x0cmVjb3JkLmlkID0gcGFyc2VJbnQoIHJlY29yZC5pZCApO1xuXHRcdFx0XHRcdFx0XHQvL31cblx0XHRcdFx0XHRcdFx0aWYgKCByZWNvcmQuaWQgPT0gbmV3X3JlY29yZC5pZCApIHtcblx0XHRcdFx0XHRcdFx0XHQkdGhpcy5ncmlkLnNldFJvd0RhdGEoIG5ld19yZWNvcmQuaWQsIG5ld19yZWNvcmQgKTtcblx0XHRcdFx0XHRcdFx0XHRncmlkX3NvdXJjZV9kYXRhW2ldID0gbmV3X3JlY29yZDtcblx0XHRcdFx0XHRcdFx0XHRmb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmICggIWZvdW5kICkge1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5ncmlkLnNldERhdGEoIGdyaWRfc291cmNlX2RhdGEuY29uY2F0KCBuZXdfcmVjb3JkICkgKTtcblx0XHRcdFx0XHRcdFx0Ly8gJHRoaXMuc2V0R3JpZENvbHVtbnNXaWR0aCgpO1xuXHRcdFx0XHRcdFx0XHQvLyBpZiAoICR0aGlzLnN1Yl92aWV3X21vZGUgJiYgR2xvYmFsLmlzU2V0KCAkdGhpcy5yZXNpemVTdWJHcmlkICkgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFx0bGVuID0gR2xvYmFsLmlzU2V0KCBsZW4gKSA/IGxlbiA6IDA7XG5cdFx0XHRcdFx0XHRcdC8vIFx0JHRoaXMucmVzaXplU3ViR3JpZCggbGVuICsgMSApO1xuXHRcdFx0XHRcdFx0XHQvLyB9XG5cdFx0XHRcdFx0XHRcdCR0aGlzLmhpZ2hMaWdodEdyaWRSb3dCeUlkKCBuZXdfcmVjb3JkLmlkICk7XG5cdFx0XHRcdFx0XHRcdCR0aGlzLnJlU2VsZWN0TGFzdFNlbGVjdEl0ZW1zKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vU2V0IFBhZ2UgZGF0YSB0byB3aWRnZXQsIG5leHQgc2hvdyBkaXNwbGF5IGluZm8gd2hlbiBzZXREZWZhdWx0IE1lbnVcblx0XHRcdFx0XHQkdGhpcy5wYWdlcl9kYXRhID0gcmVzdWx0LmdldFBhZ2VyRGF0YSgpO1xuXHRcdFx0XHRcdC8vQ0xpY2sgdG8gc2hvdyBtb3JlIG1vZGUgbm8gbmVlZCB0aGlzIHN0ZXBcblx0XHRcdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLnBhZ2luZ190eXBlICE9PSAwICYmICR0aGlzLnBhZ2luZ193aWRnZXQgJiYgJHRoaXMucGFnaW5nX3dpZGdldF8yICkge1xuXHRcdFx0XHRcdFx0JHRoaXMucGFnaW5nX3dpZGdldC5zZXRQYWdlckRhdGEoICR0aGlzLnBhZ2VyX2RhdGEgKTtcblx0XHRcdFx0XHRcdCR0aGlzLnBhZ2luZ193aWRnZXRfMi5zZXRQYWdlckRhdGEoICR0aGlzLnBhZ2VyX2RhdGEgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5wYWdpbmdfdHlwZSA9PT0gMCAmJiBwYWdlX2FjdGlvbiA9PT0gJ25leHQnICkge1xuXHRcdFx0XHRcdFx0dmFyIGN1cnJlbnRfZGF0YSA9ICR0aGlzLmdyaWQuZ2V0RGF0YSgpO1xuXHRcdFx0XHRcdFx0cmVzdWx0X2RhdGEgPSBjdXJyZW50X2RhdGEuY29uY2F0KCByZXN1bHRfZGF0YSApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByb2Nlc3MgcmVzdWx0X2RhdGEgaWYgbmVjZXNzYXJ5LCB0aGlzIGFsd2F5cyBuZWVkcyBvdmVycmlkZS5cblx0XHRcdFx0XHRyZXN1bHRfZGF0YSA9ICR0aGlzLnByb2Nlc3NSZXN1bHREYXRhKCByZXN1bHRfZGF0YSApO1xuXG5cdFx0XHRcdFx0aWYgKCAkdGhpcy5ncmlkICkge1xuXHRcdFx0XHRcdFx0JHRoaXMuZ3JpZC5zZXREYXRhKCByZXN1bHRfZGF0YSApOyAvL1RoaXMgY2FsbHMgY2xlYXJHcmlkRGF0YSBhbmQgcmVsb2FkR3JpZC5cblxuXHRcdFx0XHRcdFx0Ly8kdGhpcy5zZXRHcmlkQ29sdW1uc1dpZHRoKCk7IC8vSGFuZGxlIGluIHNlYXJjaERvbmUoKSBpbnN0ZWFkLlxuXHRcdFx0XHRcdFx0Ly8gaWYgKCAkdGhpcy5zdWJfdmlld19tb2RlICYmIEdsb2JhbC5pc1NldCggJHRoaXMucmVzaXplU3ViR3JpZCApICkge1xuXHRcdFx0XHRcdFx0Ly8gXHQkdGhpcy5yZXNpemVTdWJHcmlkKCBsZW4gKTtcblx0XHRcdFx0XHRcdC8vIH1cblx0XHRcdFx0XHRcdCR0aGlzLnJlU2VsZWN0TGFzdFNlbGVjdEl0ZW1zKCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblx0XHRcdFx0JHRoaXMuc2V0R3JpZENlbGxCYWNrR3JvdW5kKCk7IC8vU2V0IGNlbGwgYmFja2dyb3VuZCBmb3Igc29tZSB2aWV3c1xuXHRcdFx0XHRQcm9ncmVzc0Jhci5jbG9zZU92ZXJsYXkoKTsgLy9BZGQgdGhpcyBpbiBpbml0RGF0YVxuXHRcdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLnBhZ2luZ190eXBlID09PSAwICkge1xuXHRcdFx0XHRcdGlmICggISR0aGlzLnBhZ2VyX2RhdGEgfHwgJHRoaXMucGFnZXJfZGF0YS5pc19sYXN0X3BhZ2UgKSB7XG5cdFx0XHRcdFx0XHQkdGhpcy5wYWdpbmdfd2lkZ2V0LmNzcyggJ2Rpc3BsYXknLCAnbm9uZScgKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JHRoaXMucGFnaW5nX3dpZGdldC5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIGNhbGxCYWNrICkge1xuXHRcdFx0XHRcdGNhbGxCYWNrKCByZXN1bHQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyB3aGVuIGNhbGwgdGhpcyBmcm9tIHNhdmUgYW5kIG5ldyByZXN1bHQsIHdlIGRvbid0IGNhbGwgYXV0byBvcGVuLCBiZWNhdXNlIHRoaXMgd2lsbCBjYWxsIG9uQWRkQ2xpY2sgdHdpY2Vcblx0XHRcdFx0aWYgKCBzZXRfZGVmYXVsdF9tZW51ICkge1xuXHRcdFx0XHRcdCR0aGlzLmF1dG9PcGVuRWRpdFZpZXdJZk5lY2Vzc2FyeSgpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdCR0aGlzLnNlYXJjaERvbmUoKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHQvL1RoaXMgc2hvdWxkbid0IGJlIGNhbGxlZCBhbnltb3JlLCBpbiBmYXZvciBvZjogYmFzZVZpZXdTdWJUYWJHcmlkUmVzaXplKClcblx0cmVzaXplU3ViR3JpZCggbGVuZ3RoICkge1xuXHRcdHZhciBoZWlnaHQgPSAoIGxlbmd0aCAqIDI2ID49IDIwMCApID8gMjAwIDogbGVuZ3RoICogMjY7XG5cdFx0aWYgKCAkKCAnLmVkaXQtdmlldy10YWI6dmlzaWJsZSAuZ3JpZC1kaXYnICkubGVuZ3RoID4gMSApIHtcblx0XHRcdGlmICggaGVpZ2h0IDwgMTAwICkge1xuXHRcdFx0XHRoZWlnaHQgPSAxMDA7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGhlaWdodCA9ICggJCggJy5lZGl0LXZpZXctdGFiOnZpc2libGUnICkucGFyZW50KCkuaGVpZ2h0KCkgLSA4NSApO1xuXHRcdH1cblx0XHR0aGlzLnNldEdyaWRDb2x1bW5zV2lkdGgoKTtcblx0XHR0aGlzLnNldEdyaWRIZWlnaHQoIGhlaWdodCApO1xuXHR9XG5cblx0c2V0R3JpZENvbHVtbnNXaWR0aCgpIHtcblx0XHRpZiAoIHRoaXMuZ3JpZCApIHtcblx0XHRcdHRoaXMuZ3JpZC5zZXRHcmlkQ29sdW1uc1dpZHRoKCk7XG5cdFx0fVxuXHR9XG5cblx0c2V0R3JpZEhlaWdodCggaGVpZ2h0ICkge1xuXHRcdGlmICggdGhpcy5ncmlkICkge1xuXHRcdFx0dGhpcy5ncmlkLnNldEdyaWRIZWlnaHQoIGhlaWdodCApO1xuXHRcdH1cblx0fVxuXG5cdHNldEdyaWRXaWR0aCggd2lkdGggKSB7XG5cdFx0aWYgKCB0aGlzLmdyaWQgKSB7XG5cdFx0XHR0aGlzLmdyaWQuc2V0R3JpZFdpZHRoKCB3aWR0aCApO1xuXHRcdH1cblx0fVxuXG5cdHByb2Nlc3NSZXN1bHREYXRhKCByZXN1bHRfZGF0YSApIHtcblx0XHQvL0Fsd2F5cyBuZWVkcyBvdmVycmlkZVxuXHRcdHJldHVybiByZXN1bHRfZGF0YTtcblx0fVxuXG5cdHNlYXJjaERvbmUoKSB7XG5cdFx0Ly90aGUgcm90YXRlIGljb24gZnJvbSBzZWFyY2ggcGFuZWxcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdCQoICcuYnV0dG9uLXJvdGF0ZScgKS5yZW1vdmVDbGFzcyggJ2J1dHRvbi1yb3RhdGUnICk7XG5cblx0XHR0aGlzLnNldFRvdGFsRGlzcGxheVNwYW4oKTtcblxuXHRcdHRoaXMuc2V0R3JpZENvbHVtbnNXaWR0aCgpO1xuXHRcdHRoaXMuc2V0R3JpZFNpemUoIHRoaXMudWlfaWQsIHRoaXMuc3ViX3ZpZXdfbW9kZSwgdGhpcy5zdWJfdmlld19ncmlkX2F1dG9zaXplLCB0aGlzLnBhZ2VyX2RhdGEgKTtcblxuXHRcdGlmICggdGhpcy5zdWJfdmlld19tb2RlICYmIHRoaXMuZ3JpZCApIHtcblx0XHRcdHRoaXMuZ3JpZC5ncmlkLnNob3coKTtcblx0XHR9XG5cblx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvblRhYlNob3cnICk7XG5cdFx0VFRQcm9taXNlLnJlc29sdmUoICdpbml0JywgJ2luaXQnICk7XG5cdH1cblxuXHRyZVNlbGVjdExhc3RTZWxlY3RJdGVtcygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdGlmICggdGhpcy5sYXN0X3NlbGVjdF9pZHMgJiYgdGhpcy5sYXN0X3NlbGVjdF9pZHMubGVuZ3RoID4gMCApIHtcblx0XHRcdCQuZWFjaCggdGhpcy5sYXN0X3NlbGVjdF9pZHMsIGZ1bmN0aW9uKCBpbmRleCwgY29udGVudCApIHtcblx0XHRcdFx0JHRoaXMuZ3JpZC5ncmlkLnNldFNlbGVjdGlvbiggY29udGVudCwgZmFsc2UgKTtcblxuXHRcdFx0XHRpZiAoICR0aGlzLmdyaWRfc2VsZWN0X2lkX2FycmF5ICkge1xuXHRcdFx0XHRcdCR0aGlzLmdyaWRfc2VsZWN0X2lkX2FycmF5LnB1c2goIGNvbnRlbnQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMubGFzdF9zZWxlY3RfaWRzID0gW107XG5cdFx0XHRpZiAoICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdFx0dGhpcy5zZXREZWZhdWx0TWVudSgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGF1dG9PcGVuRWRpdFZpZXdJZk5lY2Vzc2FyeSgpIHtcblx0XHQvL0F1dG8gb3BlbiBlZGl0IHZpZXcuIFNob3VsZCBzZXQgaW4gSW5kZXhDb250cm9sbGVyXG5cblx0XHQvL1RoZXJlIGFyZSB2YXJpb3VzIGJ1Z3MgdGhhdCBoYXBwZW4gd2hlbiBhdXRvIG9wZW5pbmcgZWRpdCB2aWV3cyBkdXJpbmcgc3ViX3ZpZXdfbW9kZSBmcm9tIGEgXCJKdW1wIFRvXCIgYWN0aW9uLiAoTWFzdGVyIGJyYW5jaCBhbHNvIGFuZCBub3Qgb25sdSBWdWUpXG5cdFx0Ly9UaGlzIGlzIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSB2aWV3IGluaGVyaXRzIHRoZSBcIkxvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb25cIiBvZiB0aGUgbGFzdCB2aWV3LiBFeGFtcGxlczpcblx0XHQvLyAtIFRpbWVTaGVldCAtPiBBZGQgUHVuY2ggLT4gSnVtcCBUbyAtPiBFZGl0IEVtcGxveWVlIGFuZCBzd2l0Y2hpbmcgdGFicyB3b3VsZCBhdXRvIG9wZW4gYSBuZXcgZW50cnkgaW5zdGVhZCBvZiBsaXN0IHZpZXcuXG5cdFx0Ly8gLSBUaW1lU2hlZXQgLT4gQWRkIFB1bmNoIC0+IEp1bXAgVG8gLT4gQWRkIFJlcXVlc3Qgd291bGQgY2F1c2UgdGhlIHVzZXIgc3R1Y2sgdG8gYmUgc3R1Y2sgaW4gdGhlIHZpZXcuXG5cdFx0aWYgKCB0aGlzLnN1Yl92aWV3X21vZGUgJiYgIUxvY2FsQ2FjaGVEYXRhLmVkaXRfaWRfZm9yX25leHRfb3Blbl92aWV3ICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHN3aXRjaCAoIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gKSB7XG5cdFx0XHRjYXNlICdlZGl0Jzpcblx0XHRcdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5lZGl0X2lkX2Zvcl9uZXh0X29wZW5fdmlldyApIHtcblx0XHRcdFx0XHR0aGlzLm9uRWRpdENsaWNrKCBMb2NhbENhY2hlRGF0YS5lZGl0X2lkX2Zvcl9uZXh0X29wZW5fdmlldyApO1xuXHRcdFx0XHRcdExvY2FsQ2FjaGVEYXRhLmVkaXRfaWRfZm9yX25leHRfb3Blbl92aWV3ID0gbnVsbDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAndmlldyc6XG5cdFx0XHRcdGlmICggTG9jYWxDYWNoZURhdGEuZWRpdF9pZF9mb3JfbmV4dF9vcGVuX3ZpZXcgKSB7XG5cdFx0XHRcdFx0dGhpcy5vblZpZXdDbGljayggTG9jYWxDYWNoZURhdGEuZWRpdF9pZF9mb3JfbmV4dF9vcGVuX3ZpZXcgKTtcblx0XHRcdFx0XHRMb2NhbENhY2hlRGF0YS5lZGl0X2lkX2Zvcl9uZXh0X29wZW5fdmlldyA9IG51bGw7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICduZXcnOlxuXHRcdFx0XHRpZiAoICF0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdFx0XHR0aGlzLm9uQWRkQ2xpY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHR0aGlzLmF1dG9PcGVuRWRpdE9ubHlWaWV3SWZOZWNlc3NhcnkoKTtcblx0fVxuXG5cdGF1dG9PcGVuRWRpdE9ubHlWaWV3SWZOZWNlc3NhcnkoKSB7XG5cblx0XHQvL0Rvbid0IHRyeSB0byBvcGVuIGFueXRoaW5nIGlmIGN1cnJlbnQgbG9hZGluZyBhIHN1YiB2aWV3XG5cdFx0aWYgKCB0aGlzLnN1Yl92aWV3X21vZGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmICggTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpICYmIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5zbSAmJiAhTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX2VkaXRfb25seV9jb250cm9sbGVyICkge1xuXG5cdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5zbS5pbmRleE9mKCAnUmVwb3J0JyApIDwgMCApIHtcblx0XHRcdFx0SW5kZXhWaWV3Q29udHJvbGxlci5vcGVuRWRpdFZpZXcoIHRoaXMsIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5zbSwgTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnNpZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0SW5kZXhWaWV3Q29udHJvbGxlci5vcGVuUmVwb3J0KCB0aGlzLCBMb2NhbENhY2hlRGF0YS5nZXRBbGxVUkxBcmdzKCkuc20gKTtcblxuXHRcdFx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmdldEFsbFVSTEFyZ3MoKS5zaWQgKSB7XG5cdFx0XHRcdFx0TG9jYWxDYWNoZURhdGEuZGVmYXVsdF9lZGl0X2lkX2Zvcl9uZXh0X29wZW5fZWRpdF92aWV3ID0gTG9jYWxDYWNoZURhdGEuZ2V0QWxsVVJMQXJncygpLnNpZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0c2V0R3JpZENlbGxCYWNrR3JvdW5kKCkge1xuXHRcdC8vU2V0IGJhY2tncm91bmQgY29sb3IgZm9yIGluX3VzZT1mYWxzZSByb3dzIGZvciBhbGwgcG9saWN5IHZpZXcgYW5kIFJlY3VycmluZ1NjaGVkdWxlVGVtcGxhdGVDb250cm9sVmlld1xuXHRcdGlmICggdGhpcy5ncmlkXG5cdFx0XHQmJlxuXHRcdFx0KFxuXHRcdFx0XHR0aGlzLnNjcmlwdF9uYW1lLmluZGV4T2YoICdQb2xpY3knICkgPj0gMCB8fFxuXHRcdFx0XHR0aGlzLnNjcmlwdF9uYW1lID09PSAnUmVjdXJyaW5nU2NoZWR1bGVUZW1wbGF0ZUNvbnRyb2xWaWV3JyB8fFxuXHRcdFx0XHR0aGlzLnNjcmlwdF9uYW1lID09PSAnUGF5Q29kZVZpZXcnIHx8XG5cdFx0XHRcdHRoaXMuc2NyaXB0X25hbWUgPT09ICdSZWN1cnJpbmdIb2xpZGF5VmlldycgfHxcblx0XHRcdFx0dGhpcy5zY3JpcHRfbmFtZSA9PT0gJ0xlZ2FsRW50aXR5VmlldycgfHxcblx0XHRcdFx0dGhpcy5zY3JpcHRfbmFtZSA9PT0gJ1JlbWl0dGFuY2VTb3VyY2VBY2NvdW50VmlldycgfHxcblx0XHRcdFx0dGhpcy5zY3JpcHRfbmFtZSA9PT0gJ1BheXJvbGxSZW1pdHRhbmNlQWdlbmN5VmlldycgfHxcblx0XHRcdFx0dGhpcy5zY3JpcHRfbmFtZSA9PT0gJ1JlbWl0dGFuY2VEZXN0aW5hdGlvbkFjY291bnRWaWV3J1xuXHRcdFx0KVxuXHRcdCkge1xuXHRcdFx0dmFyIGRhdGEgPSB0aGlzLmdyaWQuZ2V0RGF0YSgpO1xuXG5cdFx0XHQvL0Vycm9yOiBUeXBlRXJyb3I6IGRhdGEgaXMgdW5kZWZpbmVkIGluIC9pbnRlcmZhY2UvaHRtbDUvZnJhbWV3b3JrL2pxdWVyeS5taW4uanM/dj03LjQuNi0yMDE0MTAyNy0wNzQxMjcgbGluZSAyID4gZXZhbCBsaW5lIDcwXG5cdFx0XHRpZiAoICFkYXRhICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciBsZW4gPSBkYXRhLmxlbmd0aDtcblxuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdHZhciBpdGVtID0gZGF0YVtpXTtcblxuXHRcdFx0XHRpZiAoIGl0ZW0uaXNfaW5fdXNlID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHQkKCAndHJbaWQ9XFwnJyArIGl0ZW0uaWQgKyAnXFwnXScgKS5hZGRDbGFzcyggJ3BvbGljeS1ub3QtaW4tdXNlJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0c2hvd0dyaWRCb3JkZXJzKCkge1xuXHRcdHZhciB0b3BfYm9yZGVyID0gJCggdGhpcy5lbCApLmZpbmQoICcuZ3JpZC10b3AtYm9yZGVyJyApO1xuXHRcdHZhciBib3R0b21fYm9yZGVyID0gJCggdGhpcy5lbCApLmZpbmQoICcuZ3JpZC1ib3R0b20tYm9yZGVyJyApO1xuXG5cdFx0dG9wX2JvcmRlci5jc3MoICdkaXNwbGF5JywgJ2Jsb2NrJyApO1xuXHRcdGJvdHRvbV9ib3JkZXIuY3NzKCAnZGlzcGxheScsICdibG9jaycgKTtcblx0fVxuXG5cdF9zZXRHcmlkU2l6ZUdyb3VwaGVpZ2h0KCBoZWFkZXJfc2l6ZSApIHtcblx0XHR0aGlzLmdyaWQuZ3JpZC5zZXRHcmlkSGVpZ2h0KCAoICQoIHRoaXMuZWwgKS5oZWlnaHQoKSAtICggdGhpcy5zZWFyY2hfcGFuZWwgJiYgdGhpcy5zZWFyY2hfcGFuZWwuaXMoICc6dmlzaWJsZScgKSA/IHRoaXMuc2VhcmNoX3BhbmVsLmhlaWdodCgpIDogMCApIC0gNDMgLSBoZWFkZXJfc2l6ZSApICk7XG5cdH1cblxuXHRzZXRFZGl0Vmlld1RhYlNpemUoKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR2YXIgdGFiX2Jhcl9sYWJlbCA9IHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnLmVkaXQtdmlldy10YWItYmFyLWxhYmVsJyApO1xuXHRcdHZhciB0YWJfd2lkdGggPSB0aGlzLmVkaXRfdmlld190YWIud2lkdGgoKSAtIDgwOyAvLyAtODAgaXMgdG8gaG9wZWZ1bGx5IGFjY291bnQgZm9yIHRoZSAyMHB4IHBhZGRpbmcgYW5kIG1hcmdpbiBmb3IgdGhlIGNvbnRleHQtYm9yZGVyXG5cdFx0dmFyIG5hdl93aWR0aCA9IHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnLm5hdmlnYXRpb24tZGl2JyApLndpZHRoKCk7XG5cdFx0dmFyIHdyYXBfZGl2ID0gdGhpcy5lZGl0X3ZpZXcuZmluZCggJy50YWItbGFiZWwtd3JhcCcgKTtcblxuXHRcdHZhciB0b3RhbF90YWJfd2lkdGggPSAwO1xuXHRcdHRhYl9iYXJfbGFiZWwuY2hpbGRyZW4oKS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHRvdGFsX3RhYl93aWR0aCArPSAkKCB0aGlzICkud2lkdGgoKTtcblx0XHR9ICk7XG5cblx0XHRpZiAoIHRvdGFsX3RhYl93aWR0aCA+ICggdGFiX3dpZHRoIC0gbmF2X3dpZHRoIC0gMjUgKSApIHtcblxuXHRcdFx0dGFiX2Jhcl9sYWJlbC53aWR0aCggdG90YWxfdGFiX3dpZHRoICsgMjAgKTtcblxuXHRcdFx0aWYgKCB3cmFwX2Rpdi5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHRcdHZhciByaWdodF9hcnJvdyA9ICQoICc8aW1nIGNsYXNzPVwidGFiLWFycm93IHRhYi1yaWdodC1hcnJvd1wiIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiIHNyYz1cInRoZW1lL2RlZmF1bHQvaW1hZ2VzL3JpZ2h0X2JpZ19hcnJvdy5wbmdcIiA+JyApO1xuXHRcdFx0XHR2YXIgbGVmdF9hcnJvdyA9ICQoICc8aW1nIGNsYXNzPVwidGFiLWFycm93IHRhYi1sZWZ0LWFycm93XCIgc3R5bGU9XCJkaXNwbGF5OiBub25lXCIgc3JjPVwidGhlbWUvZGVmYXVsdC9pbWFnZXMvbGVmdF9iaWdfYXJyb3cucG5nXCIgPicgKTtcblx0XHRcdFx0d3JhcF9kaXYgPSAkKCAnPGRpdiBjbGFzcz1cInRhYi1sYWJlbC13cmFwXCI+PGRpdiBjbGFzcz1cImxhYmVsLXdyYXBcIj48L2Rpdj48ZGl2IGNsYXNzPVwiYnRuLXdyYXBcIj48L2Rpdj48L2Rpdj4nICk7XG5cdFx0XHRcdHdyYXBfZGl2Lmluc2VydEJlZm9yZSggdGFiX2Jhcl9sYWJlbCApO1xuXHRcdFx0XHR3cmFwX2Rpdi53aWR0aCggdGFiX3dpZHRoIC0gbmF2X3dpZHRoIC0gMjUgKTtcblx0XHRcdFx0d3JhcF9kaXYuY2hpbGRyZW4oKS5lcSggMCApLndpZHRoKCB0YWJfd2lkdGggLSBuYXZfd2lkdGggLSAxMDAgKTtcblx0XHRcdFx0d3JhcF9kaXYuY2hpbGRyZW4oKS5lcSggMCApLmFwcGVuZCggdGFiX2Jhcl9sYWJlbCApO1xuXHRcdFx0XHR3cmFwX2Rpdi5jaGlsZHJlbigpLmVxKCAxICkuYXBwZW5kKCBsZWZ0X2Fycm93ICk7XG5cdFx0XHRcdHdyYXBfZGl2LmNoaWxkcmVuKCkuZXEoIDEgKS5hcHBlbmQoIHJpZ2h0X2Fycm93ICk7XG5cblx0XHRcdFx0cmlnaHRfYXJyb3cuYmluZCggJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0d3JhcF9kaXYuY2hpbGRyZW4oKS5lcSggMCApLnNjcm9sbExlZnQoIHdyYXBfZGl2LmNoaWxkcmVuKCkuZXEoIDAgKS5zY3JvbGxMZWZ0KCkgKyA1MDAgKTtcblx0XHRcdFx0XHRzZXRBcnJvd1N0YXR1cygpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdGxlZnRfYXJyb3cuYmluZCggJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0d3JhcF9kaXYuY2hpbGRyZW4oKS5lcSggMCApLnNjcm9sbExlZnQoIHdyYXBfZGl2LmNoaWxkcmVuKCkuZXEoIDAgKS5zY3JvbGxMZWZ0KCkgLSA1MDAgKTtcblx0XHRcdFx0XHRzZXRBcnJvd1N0YXR1cygpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3cmFwX2Rpdi53aWR0aCggdGFiX3dpZHRoIC0gbmF2X3dpZHRoIC0gMjUgKTtcblx0XHRcdFx0d3JhcF9kaXYuY2hpbGRyZW4oKS5lcSggMCApLndpZHRoKCB0YWJfd2lkdGggLSBuYXZfd2lkdGggLSAxMDAgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0YWJfYmFyX2xhYmVsLmNoaWxkcmVuKCkuZXEoIDAgKS5pcyggJzp2aXNpYmxlJyApICYmICF0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdFx0dGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcudGFiLWFycm93JyApLnNob3coKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnLnRhYi1hcnJvdycgKS5oaWRlKCk7XG5cdFx0XHR9XG5cblx0XHRcdHNldEFycm93U3RhdHVzKCk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0dGFiX2Jhcl9sYWJlbC53aWR0aCggJ2F1dG8nICk7XG5cdFx0XHRpZiAoIHdyYXBfZGl2Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdHRhYl9iYXJfbGFiZWwuaW5zZXJ0QmVmb3JlKCB3cmFwX2RpdiApO1xuXHRcdFx0XHR3cmFwX2Rpdi5yZW1vdmUoKTtcblxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHNldEFycm93U3RhdHVzKCkge1xuXHRcdFx0dmFyIGxlZnRfYXJyb3cgPSAkdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcudGFiLWxlZnQtYXJyb3cnICk7XG5cdFx0XHR2YXIgcmlnaHRfYXJyb3cgPSAkdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcudGFiLXJpZ2h0LWFycm93JyApO1xuXHRcdFx0dmFyIGxhYmVsX3dyYXAgPSB3cmFwX2Rpdi5jaGlsZHJlbigpLmVxKCAwICk7XG5cblx0XHRcdGxlZnRfYXJyb3cucmVtb3ZlQ2xhc3MoICdkaXNhYmxlLWltYWdlJyApO1xuXHRcdFx0cmlnaHRfYXJyb3cucmVtb3ZlQ2xhc3MoICdkaXNhYmxlLWltYWdlJyApO1xuXG5cdFx0XHRpZiAoIGxhYmVsX3dyYXAuc2Nyb2xsTGVmdCgpID09PSAwICkge1xuXHRcdFx0XHRsZWZ0X2Fycm93LmFkZENsYXNzKCAnZGlzYWJsZS1pbWFnZScgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly9DZWlsIGFuZCBhYnMgcmVxdWlyZWQgYXMgdmFsdWUgY2FuIGJlIG9mZiBieSBhIHRpbnkgcGl4ZWwgYW1vdW50IHN1Y2ggYXMgMS4yLlxuXHRcdFx0aWYgKCBNYXRoLmFicyggbGFiZWxfd3JhcC5zY3JvbGxMZWZ0KCkgLSBNYXRoLmNlaWwoIGxhYmVsX3dyYXBbMF0uc2Nyb2xsV2lkdGggLSBsYWJlbF93cmFwLndpZHRoKCkgKSApIDwgMiApIHtcblx0XHRcdFx0cmlnaHRfYXJyb3cuYWRkQ2xhc3MoICdkaXNhYmxlLWltYWdlJyApO1xuXHRcdFx0fVxuXG5cdFx0fVxuXHR9XG5cblx0Z2V0RmlsdGVyQ29sdW1uc0Zyb21EaXNwbGF5Q29sdW1ucyggY29sdW1uX2ZpbHRlciwgZW5hYmxlX3N5c3RlbV9jb2x1bW5zICkge1xuXHRcdHJldHVybiB0aGlzLl9nZXRGaWx0ZXJDb2x1bW5zRnJvbURpc3BsYXlDb2x1bW5zKCBjb2x1bW5fZmlsdGVyLCBlbmFibGVfc3lzdGVtX2NvbHVtbnMgKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBzdXBlciBmb3IgZ2V0RmlsdGVyQ29sdW1uc0Zyb21EaXNwbGF5Q29sdW1uc1xuXHQgKiB1c2VkIHdoZW4gZnVuY3Rpb24gaXMgb3ZlcnJpZGRlbiBieSBjaGlsZCBjbGFzcy5cblx0ICpcblx0ICogQHBhcmFtIGNvbHVtbl9maWx0ZXJcblx0ICogQHBhcmFtIGVuYWJsZV9zeXN0ZW1fY29sdW1ucyBUUlVFXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0X2dldEZpbHRlckNvbHVtbnNGcm9tRGlzcGxheUNvbHVtbnMoIGNvbHVtbl9maWx0ZXIsIGVuYWJsZV9zeXN0ZW1fY29sdW1ucyApIHtcblx0XHRpZiAoICFjb2x1bW5fZmlsdGVyICkge1xuXHRcdFx0Y29sdW1uX2ZpbHRlciA9IHt9O1xuXHRcdH1cblxuXHRcdGlmICggZW5hYmxlX3N5c3RlbV9jb2x1bW5zID09IHVuZGVmaW5lZCB8fCBlbmFibGVfc3lzdGVtX2NvbHVtbnMgPT0gdHJ1ZSApIHtcblx0XHRcdGNvbHVtbl9maWx0ZXIuaXNfb3duZXIgPSB0cnVlO1xuXHRcdFx0Y29sdW1uX2ZpbHRlci5pZCA9IHRydWU7XG5cdFx0XHRjb2x1bW5fZmlsdGVyLmlzX2NoaWxkID0gdHJ1ZTtcblx0XHRcdGNvbHVtbl9maWx0ZXIuaW5fdXNlID0gdHJ1ZTtcblx0XHRcdGNvbHVtbl9maWx0ZXIuZmlyc3RfbmFtZSA9IHRydWU7XG5cdFx0XHRjb2x1bW5fZmlsdGVyLmxhc3RfbmFtZSA9IHRydWU7XG5cdFx0fVxuXG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IHt9O1xuXG5cdFx0aWYgKCBHbG9iYWwuaXNTZXQoIExvY2FsQ2FjaGVEYXRhLnZpZXdfbGF5b3V0X2NhY2hlW3RoaXMuc2NyaXB0X25hbWVdICkgKSB7XG5cdFx0XHR2YXIgcmVzdWx0ID0gTG9jYWxDYWNoZURhdGEudmlld19sYXlvdXRfY2FjaGVbdGhpcy5zY3JpcHRfbmFtZV0uZ2V0UmVzdWx0KCk7XG5cdFx0XHRpZiAoIHJlc3VsdCAhPSB1bmRlZmluZWQgJiYgcmVzdWx0Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdGRpc3BsYXlfY29sdW1ucyA9IHJlc3VsdFswXS5kYXRhLmRpc3BsYXlfY29sdW1ucztcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc2VsZWN0X2xheW91dCAmJiB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YSAmJiB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5kaXNwbGF5X2NvbHVtbnMgKSB7XG5cdFx0XHRmb3IgKCB2YXIgbiBpbiB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5kaXNwbGF5X2NvbHVtbnMgKSB7XG5cdFx0XHRcdGRpc3BsYXlfY29sdW1uc1tuXSA9IHRoaXMuc2VsZWN0X2xheW91dC5kYXRhLmRpc3BsYXlfY29sdW1uc1tuXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvL2dldCB0aGUgZGVmYXVsdCBkaXNwbGF5IGNvbHVtbnMgaWYgbm8gY29sdW1ucyBoYXZlIGJlZW4gZGVmaW5lZC5cblx0XHRpZiAoIGRpc3BsYXlfY29sdW1ucy5sZW5ndGggPT0gdW5kZWZpbmVkIHx8ICggZGlzcGxheV9jb2x1bW5zLmxlbmd0aCA9PSAwICYmIEdsb2JhbC5pc1NldCggdGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucyApICkgKSB7XG5cdFx0XHRkaXNwbGF5X2NvbHVtbnMgPSB0aGlzLmRlZmF1bHRfZGlzcGxheV9jb2x1bW5zO1xuXHRcdH1cblxuXHRcdC8vRml4ZWQgcG9zc2libGUgZXhjZXB0aW9uIC0tIEVycm9yOiBVbmFibGUgdG8gZ2V0IHByb3BlcnR5ICdsZW5ndGgnIG9mIHVuZGVmaW5lZCBvciBudWxsIHJlZmVyZW5jZSBpbiAvaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTcuNC4zLTIwMTQwOTI0LTA5MDEyOSBsaW5lIDUwMzFcblx0XHRpZiAoIGRpc3BsYXlfY29sdW1ucy5sZW5ndGggIT0gdW5kZWZpbmVkICYmIGRpc3BsYXlfY29sdW1ucy5sZW5ndGggPiAwICkge1xuXHRcdFx0dmFyIGxlbiA9IGRpc3BsYXlfY29sdW1ucy5sZW5ndGg7XG5cdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0Y29sdW1uX2ZpbHRlcltkaXNwbGF5X2NvbHVtbnNbaV1dID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gY29sdW1uX2ZpbHRlcjtcblx0fVxuXG5cdGdldEFsbExheW91dHMoIGNhbGxCYWNrICkge1xuXG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdHZhciBjdXJyZW50X3NlbGVjdF9sYXlvdXRfbmFtZTtcblxuXHRcdGlmICggdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZSApIHtcblx0XHRcdGN1cnJlbnRfc2VsZWN0X2xheW91dF9uYW1lID0gdGhpcy5uZWVkX3NlbGVjdF9sYXlvdXRfbmFtZTtcblx0XHRcdHRoaXMubmVlZF9zZWxlY3RfbGF5b3V0X25hbWUgPSAnJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3VycmVudF9zZWxlY3RfbGF5b3V0X25hbWUgPSBCYXNlVmlld0NvbnRyb2xsZXIuZGVmYXVsdF9sYXlvdXRfbmFtZTtcblx0XHR9XG5cblx0XHQvL0lzc3VlICMzMjg2IC0gVXNlcnMgd2l0aG91dCBwZXJtaXNzaW9uIHRvIGRpc3BsYXkgXCJDdXJyZW50IFZpZXdcIiBkcm9wZG93biBvbiBUaW1lU2hlZXQgc3RpbGwgbmVlZCB0byBsb2FkIHNlbGVjdCBsYXlvdXQgZnJvbSB1c2VyIGdlbmVyaWMgZGF0YVxuXHRcdC8vVGhpcyBpcyB0byBlbnN1cmUgdGhlIEFQSSBhdHRlbXB0cyB0byB1cGRhdGUgdGhlIGN1cnJlbnQgbGF5b3V0IGFuZCBub3QgY3JlYXRlIGEgbmV3IG9uZSBjYXVzaW5nIGEgdmFsaWRhdGlvbiBlcnJvci5cblx0XHQvL2ZvcmNlX2dldF9zZWxlY3RfbGF5b3V0IHN0aWxsIGdldHMgdGhlIGxheW91dCBkYXRhLCBidXQgZG9lcyBub3QgZGlzcGxheSBpdC5cblx0XHRpZiAoICF0aGlzLmZvcmNlX2dldF9zZWxlY3RfbGF5b3V0ICYmICggdGhpcy5zdWJfdmlld19tb2RlIHx8ICF0aGlzLnNob3dfc2VhcmNoX3RhYiApICkge1xuXHRcdFx0JHRoaXMuc2VsZWN0X2xheW91dCA9IG51bGw7XG5cdFx0XHRpZiAoIGNhbGxCYWNrICkge1xuXHRcdFx0XHRjYWxsQmFjaygpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gQ2hlY2sgdmlldyBsYXlvdXQgY2FjaGUuXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS52aWV3X2xheW91dF9jYWNoZVt0aGlzLnNjcmlwdF9uYW1lXSApIHtcblx0XHRcdC8vTWFrZSB0aGlzIGFzeW5jIHdheVxuXHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdG9uR2V0VXNlckdlbmVyaWNEYXRhUmVzdWx0KCBMb2NhbENhY2hlRGF0YS52aWV3X2xheW91dF9jYWNoZVskdGhpcy5zY3JpcHRfbmFtZV0gKTtcblx0XHRcdH0sIDAgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCAhdGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkgKSB7XG5cdFx0XHRcdHRoaXMudXNlcl9nZW5lcmljX2RhdGFfYXBpID0gVFRBUEkuQVBJVXNlckdlbmVyaWNEYXRhO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy51c2VyX2dlbmVyaWNfZGF0YV9hcGkuZ2V0VXNlckdlbmVyaWNEYXRhKCB7XG5cdFx0XHRcdGZpbHRlcl9kYXRhOiB7XG5cdFx0XHRcdFx0c2NyaXB0OiB0aGlzLnNjcmlwdF9uYW1lLFxuXHRcdFx0XHRcdGRlbGV0ZWQ6IGZhbHNlXG5cdFx0XHRcdH1cblx0XHRcdH0sIHtcblx0XHRcdFx0b25SZXN1bHQ6IGZ1bmN0aW9uKCByZXN1bHRzICkge1xuXHRcdFx0XHRcdG9uR2V0VXNlckdlbmVyaWNEYXRhUmVzdWx0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBvbkdldFVzZXJHZW5lcmljRGF0YVJlc3VsdCggcmVzdWx0cyApIHtcblx0XHRcdGlmICggcmVzdWx0cyApIHtcblx0XHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0cy5nZXRSZXN1bHQoKTtcblx0XHRcdFx0JHRoaXMuc2VsZWN0X2xheW91dCA9IG51bGw7IC8vUmVzZXQgc2VsZWN0IGxheW91dDtcblx0XHRcdFx0TG9jYWxDYWNoZURhdGEudmlld19sYXlvdXRfY2FjaGVbJHRoaXMuc2NyaXB0X25hbWVdID0gcmVzdWx0cztcblx0XHRcdFx0aWYgKCByZXN1bHRfZGF0YSAmJiByZXN1bHRfZGF0YS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRcdHJlc3VsdF9kYXRhLnNvcnQoIGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gR2xvYmFsLmNvbXBhcmUoIGEsIGIsICduYW1lJyApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0dmFyIGxlbiA9IHJlc3VsdF9kYXRhLmxlbmd0aDtcblx0XHRcdFx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHRcdHZhciBsYXlvdXQgPSByZXN1bHRfZGF0YVtpXTtcblx0XHRcdFx0XHRcdGlmICggbGF5b3V0Lm5hbWUgPT09IGN1cnJlbnRfc2VsZWN0X2xheW91dF9uYW1lICkge1xuXHRcdFx0XHRcdFx0XHQkdGhpcy5zZWxlY3RfbGF5b3V0ID0gbGF5b3V0O1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKCAhJHRoaXMuc2VsZWN0X2xheW91dCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNlbGVjdF9sYXlvdXQgPSByZXN1bHRfZGF0YVswXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JHRoaXMuc2VhcmNoX3BhbmVsLnNldExheW91dHNBcnJheSggcmVzdWx0X2RhdGEgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQkdGhpcy5zZWxlY3RfbGF5b3V0ID0gbnVsbDtcblx0XHRcdFx0XHRpZiAoICR0aGlzLnNlYXJjaF9wYW5lbCApIHtcblx0XHRcdFx0XHRcdCR0aGlzLnNlYXJjaF9wYW5lbC5zZXRMYXlvdXRzQXJyYXkoIG51bGwgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBjYWxsQmFjayApIHtcblx0XHRcdFx0XHRjYWxsQmFjaygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Z2V0QWxsQ29sdW1ucyggY2FsbEJhY2sgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHR0aGlzLmFwaS5nZXRPcHRpb25zKCAnY29sdW1ucycsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggY29sdW1uc19yZXN1bHQgKSB7XG5cdFx0XHRcdHZhciBjb2x1bW5zX3Jlc3VsdF9kYXRhID0gY29sdW1uc19yZXN1bHQuZ2V0UmVzdWx0KCk7XG5cblx0XHRcdFx0JHRoaXMuYWxsX2NvbHVtbnMgPSBHbG9iYWwuYnVpbGRDb2x1bW5BcnJheSggY29sdW1uc19yZXN1bHRfZGF0YSApO1xuXHRcdFx0XHRpZiAoICEkdGhpcy5zdWJfdmlld19tb2RlICYmICR0aGlzLmNvbHVtbl9zZWxlY3RvciApIHtcblx0XHRcdFx0XHQkdGhpcy5jb2x1bW5fc2VsZWN0b3Iuc2V0VW5zZWxlY3RlZEdyaWREYXRhKCAkdGhpcy5hbGxfY29sdW1ucyApO1xuXHRcdFx0XHRcdCR0aGlzLmNvbHVtbl9zZWxlY3Rvci5zZXRIZWlnaHQoICR0aGlzLmFsbF9jb2x1bW5zLmxlbmd0aCAqIDMyICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGNhbGxCYWNrICkge1xuXHRcdFx0XHRcdGNhbGxCYWNrKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdGdldERlZmF1bHREaXNwbGF5Q29sdW1ucyggY2FsbEJhY2sgKSB7XG5cblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuYXBpLmdldE9wdGlvbnMoICdkZWZhdWx0X2Rpc3BsYXlfY29sdW1ucycsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggY29sdW1uc19yZXN1bHQgKSB7XG5cblx0XHRcdFx0dmFyIGNvbHVtbnNfcmVzdWx0X2RhdGEgPSBjb2x1bW5zX3Jlc3VsdC5nZXRSZXN1bHQoKTtcblxuXHRcdFx0XHQkdGhpcy5kZWZhdWx0X2Rpc3BsYXlfY29sdW1ucyA9IGNvbHVtbnNfcmVzdWx0X2RhdGE7XG5cblx0XHRcdFx0aWYgKCBjYWxsQmFjayApIHtcblx0XHRcdFx0XHRjYWxsQmFjaygpO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cblxuXHRidWlsZFNvcnRCeVNlbGVjdENvbHVtbnMoKSB7XG5cdFx0dmFyIHNvcnRfYnlfYXJyYXkgPSB0aGlzLnNlbGVjdF9sYXlvdXQuZGF0YS5maWx0ZXJfc29ydDtcblx0XHR2YXIgc29ydF9ieV9zZWxlY3RfY29sdW1ucyA9IFtdO1xuXHRcdHZhciBzb3J0X2J5X3Vuc2VsZWN0X2NvbHVtbnMgPSB0aGlzLnNvcnRfYnlfc2VsZWN0b3IuZ2V0U291cmNlRGF0YSgpO1xuXG5cdFx0aWYgKCBzb3J0X2J5X2FycmF5ICkge1xuXHRcdFx0JC5lYWNoKCBzb3J0X2J5X2FycmF5LCBmdW5jdGlvbiggaW5kZXgsIGNvbnRlbnQgKSB7XG5cblx0XHRcdFx0Zm9yICggdmFyIGtleSBpbiBjb250ZW50ICkge1xuXG5cdFx0XHRcdFx0JC5lYWNoKCBzb3J0X2J5X3Vuc2VsZWN0X2NvbHVtbnMsIGZ1bmN0aW9uKCBpbmRleDEsIGNvbnRlbnQxICkge1xuXHRcdFx0XHRcdFx0aWYgKCBjb250ZW50MS52YWx1ZSA9PT0ga2V5ICkge1xuXHRcdFx0XHRcdFx0XHRjb250ZW50MS5zb3J0ID0gY29udGVudFtrZXldO1xuXHRcdFx0XHRcdFx0XHRzb3J0X2J5X3NlbGVjdF9jb2x1bW5zLnB1c2goIGNvbnRlbnQxICk7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBzb3J0X2J5X3NlbGVjdF9jb2x1bW5zO1xuXHR9XG5cblx0YnVpbGRTb3J0U2VsZWN0b3JVblNlbGVjdENvbHVtbnMoIGRpc3BsYXlfY29sdW1ucyApIHtcblx0XHR2YXIgZmluYV9hcnJheSA9IFtdO1xuXHRcdHZhciBpID0gMTAwO1xuXHRcdCQuZWFjaCggZGlzcGxheV9jb2x1bW5zLCBmdW5jdGlvbiggaW5kZXgsIGNvbnRlbnQgKSB7XG5cdFx0XHR2YXIgbmV3X2NvbnRlbnQgPSAkLmV4dGVuZCgge30sIGNvbnRlbnQgKTtcblx0XHRcdG5ld19jb250ZW50LmlkID0gaTsgLy9OZWVkXG5cdFx0XHRuZXdfY29udGVudC5zb3J0ID0gJ2FzYyc7XG5cdFx0XHRmaW5hX2FycmF5LnB1c2goIG5ld19jb250ZW50ICk7XG5cdFx0XHRpID0gaSArIDE7XG5cdFx0fSApO1xuXG5cdFx0cmV0dXJuIGZpbmFfYXJyYXk7XG5cdH1cblxuXHRidWlsZERpc3BsYXlDb2x1bW5zKCBhcGlEaXNwbGF5Q29sdW1uc0FycmF5ICkge1xuXG5cdFx0dmFyIGxlbiA9IHRoaXMuYWxsX2NvbHVtbnMubGVuZ3RoO1xuXHRcdHZhciBsZW4xID0gYXBpRGlzcGxheUNvbHVtbnNBcnJheS5sZW5ndGg7XG5cdFx0dmFyIGRpc3BsYXlfY29sdW1ucyA9IFtdO1xuXG5cdFx0Zm9yICggdmFyIGogPSAwOyBqIDwgbGVuMTsgaisrICkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdGlmICggYXBpRGlzcGxheUNvbHVtbnNBcnJheVtqXSA9PT0gdGhpcy5hbGxfY29sdW1uc1tpXS52YWx1ZSApIHtcblx0XHRcdFx0XHRkaXNwbGF5X2NvbHVtbnMucHVzaCggdGhpcy5hbGxfY29sdW1uc1tpXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBkaXNwbGF5X2NvbHVtbnM7XG5cdH1cblxuXHRidWlsZERpc3BsYXlDb2x1bW5zQnlDb2x1bW5Nb2RlbCggY29sTW9kZWwgKSB7XG5cblx0XHRpZiAoICFjb2xNb2RlbCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgbGVuID0gY29sTW9kZWwubGVuZ3RoO1xuXHRcdHZhciBkaXNwbGF5X2NvbHVtbnMgPSBbXTtcblx0XHR2YXIgaWQgPSAyMDAwOyAvLyBNYWtzZSBzdXJlIHRoZSBpZCBub3QgZHVwbGljYXRlIHdpdGggYWxsX2NvbHVtbnMsIHRoaXMgd2lpbCBiZSB1c2VkIGluIGFjb21ib3gsIHNldCBwb3NzaWJsZSBjb2x1bW5zIGluIG5hdmlnYXRpb24gbW9kZVxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0dmFyIGNvbHVtbiA9IGNvbE1vZGVsW2ldO1xuXHRcdFx0aWYgKCBjb2x1bW4ubmFtZSA9PT0gJ2NiJyApIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRkaXNwbGF5X2NvbHVtbnMucHVzaCggeyBsYWJlbDogY29sdW1uLmxhYmVsLCB2YWx1ZTogY29sdW1uLm5hbWUsIGlkOiBpZCB9ICk7XG5cdFx0XHRpZCA9IGlkICsgMTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZGlzcGxheV9jb2x1bW5zO1xuXHR9XG5cblx0cmVtb3ZlQ29udGVudE1lbnVCeU5hbWUoIG5hbWUgKSB7XG5cdFx0Ly8gVlVFIE5PVEU6IFRoaXMgZnVuY3Rpb24gaXMgZm9yIHRoZSBsZWdhY3kgY29udGV4dCBtZW51LCB0aGlzIGlzIG5vdCBmb3IgdGhlIFZ1ZSBjb250ZXh0IG1lbnUsIGFzIGxlZ2FjeSBvbmx5IGhhcyB0byBkZWxldGUgYSBjb250ZXh0bWVudSBmcm9tIGEgdmlldywgVnVlIGhhcyBtZW51cyBpbiBtdWx0aXBsZSBwbGFjZXMgaW5zdGVhZC4gU2VlIEJhc2VWaWV3Q29udHJvbGxlci51bm1vdW50Q29udGV4dE1lbnUgYW5kIHJlbGF0ZWQgZnVuY3Rpb25zLlxuXG5cdFx0aWYgKCAhTG9jYWxDYWNoZURhdGEuY3VycmVudF9vcGVuX3ByaW1hcnlfY29udHJvbGxlciApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dmFyIHByaW1hcnlfdmlld19pZCA9IExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl9wcmltYXJ5X2NvbnRyb2xsZXIudmlld0lkO1xuXG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBuYW1lICkgKSB7XG5cdFx0XHRuYW1lID0gdGhpcy5jb250ZXh0X21lbnVfbmFtZTtcblx0XHR9XG5cblx0XHR2YXIgdGFiID0gJCggJyNyaWJib24gdWwgYScgKS5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuICQoIHRoaXMgKS5hdHRyKCAncmVmJyApID09PSBuYW1lO1xuXHRcdH0gKS5wYXJlbnQoKTtcblxuXHRcdHZhciBpbmRleCA9ICQoICdsaScsICQoICcjcmliYm9uJyApICkuaW5kZXgoIHRhYiApO1xuXHRcdGlmICggaW5kZXggPj0gMCApIHtcblx0XHRcdC8vICQoICcjcmliYm9uX3ZpZXdfY29udGFpbmVyJyApLnRhYnMoIHsncmVtb3ZlJzogaW5kZXh9ICk7XG5cdFx0XHQkKCAnI3JpYmJvbl92aWV3X2NvbnRhaW5lcicgKS50YWJzKCAncmVmcmVzaCcgKTtcblx0XHR9XG5cdH1cblxuXHRtb3ZlUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkge1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggcF9pZCApICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoIHBfaWQgPT09ICdyZXBvcnQnICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICYmIHRoaXMuZGVsZXRlUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRzdWJBdWRpdFZhbGlkYXRlKCkge1xuXHRcdGlmICggdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRzdWJEb2N1bWVudFZhbGlkYXRlKCkge1xuXHRcdGlmICggKCBHbG9iYWwuZ2V0UHJvZHVjdEVkaXRpb24oKSA+PSAyMCApICYmIFBlcm1pc3Npb25NYW5hZ2VyLmNoZWNrVG9wTGV2ZWxQZXJtaXNzaW9uKCAnRG9jdW1lbnQnICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRhZGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSB7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBwX2lkICkgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnYWRkJyApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Z2V0UmVjb3JkRnJvbUdyaWRCeUlkKCBpZCApIHtcblxuXHRcdHZhciBkYXRhID0gdGhpcy5ncmlkLmdldERhdGEoKTtcblx0XHR2YXIgcmVzdWx0ID0gbnVsbDtcblx0XHQvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG5cdFx0Ly9pZCBjb3VsZCBiZSBzdHJpbmcgb3IgbnVtYmVyLlxuXHRcdCQuZWFjaCggZGF0YSwgZnVuY3Rpb24oIGluZGV4LCB2YWx1ZSApIHtcblxuXHRcdFx0aWYgKCB2YWx1ZS5pZCA9PSBpZCApIHtcblx0XHRcdFx0cmVzdWx0ID0gR2xvYmFsLmNsb25lKCB2YWx1ZSApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHR9ICk7XG5cdFx0LyoganNoaW50IGlnbm9yZTplbmQgKi9cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0Z2V0U2VsZWN0ZWRJdGVtcygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBzZWxlY3RlZF9pdGVtcyA9IFtdO1xuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXcgKSB7XG5cdFx0XHRzZWxlY3RlZF9pdGVtcyA9IFt0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmRdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSA9IHRoaXMuZ2V0R3JpZFNlbGVjdElkQXJyYXkoKTtcblx0XHRcdHZhciBncmlkX3NlbGVjdGVkX2xlbmd0aCA9IGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXkubGVuZ3RoO1xuXHRcdFx0c2VsZWN0ZWRfaXRlbXMgPSBfLm1hcCggZ3JpZF9zZWxlY3RlZF9pZF9hcnJheSwgZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0XHRyZXR1cm4gJHRoaXMuZ2V0UmVjb3JkRnJvbUdyaWRCeUlkKCBpZCApO1xuXHRcdFx0fSApO1xuXHRcdH1cblx0XHRyZXR1cm4gc2VsZWN0ZWRfaXRlbXM7XG5cdH1cblxuXHRnZXRTZWxlY3RlZEl0ZW0oKSB7XG5cblx0XHR2YXIgc2VsZWN0ZWRfaXRlbSA9IG51bGw7XG5cdFx0aWYgKCB0aGlzLmVkaXRfdmlldyApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBncmlkX3NlbGVjdGVkX2lkX2FycmF5ID0gdGhpcy5nZXRHcmlkU2VsZWN0SWRBcnJheSgpO1xuXHRcdFx0dmFyIGdyaWRfc2VsZWN0ZWRfbGVuZ3RoID0gZ3JpZF9zZWxlY3RlZF9pZF9hcnJheS5sZW5ndGg7XG5cblx0XHRcdGlmICggZ3JpZF9zZWxlY3RlZF9sZW5ndGggPiAwICkge1xuXHRcdFx0XHRzZWxlY3RlZF9pdGVtID0gdGhpcy5nZXRSZWNvcmRGcm9tR3JpZEJ5SWQoIGdyaWRfc2VsZWN0ZWRfaWRfYXJyYXlbMF0gKTtcblx0XHRcdH1cblxuXHRcdH1cblxuXHRcdGlmICggc2VsZWN0ZWRfaXRlbSApIHtcblx0XHRcdHJldHVybiBHbG9iYWwuY2xvbmUoIHNlbGVjdGVkX2l0ZW0gKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHR9XG5cblx0ZGVsZXRlT3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkge1xuXG5cdFx0aWYgKCAhcF9pZCApIHtcblx0XHRcdHBfaWQgPSB0aGlzLnBlcm1pc3Npb25faWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCAhc2VsZWN0ZWRfaXRlbSApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmdldFNlbGVjdGVkSXRlbSgpO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoXG5cdFx0XHRQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2RlbGV0ZScgKSB8fFxuXHRcdFx0KCBzZWxlY3RlZF9pdGVtICYmIHNlbGVjdGVkX2l0ZW0uaXNfb3duZXIgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdkZWxldGVfb3duJyApICkgfHxcblx0XHRcdCggc2VsZWN0ZWRfaXRlbSAmJiBzZWxlY3RlZF9pdGVtLmlzX2NoaWxkICYmIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZGVsZXRlX2NoaWxkJyApICkgKSB7XG5cblx0XHRcdHJldHVybiB0cnVlO1xuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0dmlld093bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgc2VsZWN0ZWRfaXRlbSApIHtcblxuXHRcdGlmICggIXBfaWQgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoICFzZWxlY3RlZF9pdGVtICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuZ2V0U2VsZWN0ZWRJdGVtKCk7XG5cdFx0fVxuXG5cdFx0aWYgKFxuXHRcdFx0UGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICd2aWV3JyApIHx8XG5cdFx0XHQoIHNlbGVjdGVkX2l0ZW0gJiYgc2VsZWN0ZWRfaXRlbS5pc19vd25lciAmJiBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ3ZpZXdfb3duJyApICkgfHxcblx0XHRcdCggc2VsZWN0ZWRfaXRlbSAmJiBzZWxlY3RlZF9pdGVtLmlzX2NoaWxkICYmIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAndmlld19jaGlsZCcgKSApICkge1xuXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblxuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGVkaXRPd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsIHNlbGVjdGVkX2l0ZW0gKSB7XG5cblx0XHRpZiAoICFwX2lkICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoICFzZWxlY3RlZF9pdGVtICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuZ2V0U2VsZWN0ZWRJdGVtKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCBwX2lkID09PSAncmVwb3J0JyApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChcblx0XHRcdFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdCcgKSB8fFxuXHRcdFx0KCBzZWxlY3RlZF9pdGVtICYmIHNlbGVjdGVkX2l0ZW0uaXNfb3duZXIgJiYgUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICdlZGl0X293bicgKSApIHx8XG5cdFx0XHQoIHNlbGVjdGVkX2l0ZW0gJiYgc2VsZWN0ZWRfaXRlbS5pc19jaGlsZCAmJiBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgJ2VkaXRfY2hpbGQnICkgKSApIHtcblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRvd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsIHBlcm1pc3Npb25fbmFtZSwgc2VsZWN0ZWRfaXRlbSApIHtcblxuXHRcdHZhciBmaWVsZDtcblx0XHRpZiAoIHBlcm1pc3Npb25fbmFtZS5pbmRleE9mKCAnY2hpbGQnICkgPiAtMSApIHtcblx0XHRcdGZpZWxkID0gJ2lzX2NoaWxkJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZmllbGQgPSAnaXNfb3duZXInO1xuXHRcdH1cbi8vXG4vL1x0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCBwZXJtaXNzaW9uX25hbWUgKSAmJlxuLy9cdFx0XHQoIXNlbGVjdGVkX2l0ZW0gfHxcbi8vXHRcdFx0XHQoIHNlbGVjdGVkX2l0ZW0gJiYgKHNlbGVjdGVkX2l0ZW1bZmllbGRdIHx8ICghc2VsZWN0ZWRfaXRlbS5pZCAmJiAhc2VsZWN0ZWRfaXRlbS5oYXNPd25Qcm9wZXJ0eSggZmllbGQgKSkgKSApICkgKSB7XG4vL1x0XHRcdHJldHVybiB0cnVlO1xuLy9cdFx0fVxuXG5cdFx0aWYgKCBQZXJtaXNzaW9uTWFuYWdlci52YWxpZGF0ZSggcF9pZCwgcGVybWlzc2lvbl9uYW1lICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRlZGl0Q2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsIHNlbGVjdGVkX2l0ZW0gKSB7XG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBwX2lkICkgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggIUdsb2JhbC5pc1NldCggc2VsZWN0ZWRfaXRlbSApICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuZ2V0U2VsZWN0ZWRJdGVtKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCBwX2lkID09PSAncmVwb3J0JyApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICggIVBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZW5hYmxlZCcgKSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdCcgKSB8fFxuXHRcdFx0dGhpcy5vd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsICdlZGl0X2NoaWxkJywgc2VsZWN0ZWRfaXRlbSApICkge1xuXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRlZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkge1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggcF9pZCApICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHNlbGVjdGVkX2l0ZW0gKSApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmdldFNlbGVjdGVkSXRlbSgpO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZWRpdCcgKSB8fCB0aGlzLm93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgJ2VkaXRfY2hpbGQnLCBzZWxlY3RlZF9pdGVtICkgfHwgdGhpcy5vd25lck9yQ2hpbGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsICdlZGl0X293bicsIHNlbGVjdGVkX2l0ZW0gKSApIHtcblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Y29weVBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgc2VsZWN0ZWRfaXRlbSApIHtcblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHBfaWQgKSApIHtcblx0XHRcdHBfaWQgPSB0aGlzLnBlcm1pc3Npb25faWQ7XG5cdFx0fVxuXG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBzZWxlY3RlZF9pdGVtICkgKSB7XG5cdFx0XHRzZWxlY3RlZF9pdGVtID0gdGhpcy5nZXRTZWxlY3RlZEl0ZW0oKTtcblx0XHR9XG5cblx0XHRpZiAoIHBfaWQgPT09ICdyZXBvcnQnICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLnZpZXdQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQsIHNlbGVjdGVkX2l0ZW0gKSAmJiB0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgc2VsZWN0ZWRfaXRlbSApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Y29weUFzTmV3UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkge1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggcF9pZCApICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHNlbGVjdGVkX2l0ZW0gKSApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmdldFNlbGVjdGVkSXRlbSgpO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMudmlld1Blcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgc2VsZWN0ZWRfaXRlbSApICYmIHRoaXMuYWRkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHR2aWV3UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkge1xuXG5cdFx0aWYgKCAhR2xvYmFsLmlzU2V0KCBwX2lkICkgKSB7XG5cdFx0XHRwX2lkID0gdGhpcy5wZXJtaXNzaW9uX2lkO1xuXHRcdH1cblxuXHRcdGlmICggIUdsb2JhbC5pc1NldCggc2VsZWN0ZWRfaXRlbSApICkge1xuXHRcdFx0c2VsZWN0ZWRfaXRlbSA9IHRoaXMuZ2V0U2VsZWN0ZWRJdGVtKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCBwX2lkID09PSAncmVwb3J0JyApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICggUGVybWlzc2lvbk1hbmFnZXIudmFsaWRhdGUoIHBfaWQsICd2aWV3JyApIHx8IHRoaXMub3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCAndmlld19jaGlsZCcsIHNlbGVjdGVkX2l0ZW0gKSB8fCB0aGlzLm93bmVyT3JDaGlsZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCwgJ3ZpZXdfb3duJywgc2VsZWN0ZWRfaXRlbSApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0ZGVsZXRlUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCBzZWxlY3RlZF9pdGVtICkge1xuXHRcdGlmICggIUdsb2JhbC5pc1NldCggcF9pZCApICkge1xuXHRcdFx0cF9pZCA9IHRoaXMucGVybWlzc2lvbl9pZDtcblx0XHR9XG5cblx0XHRpZiAoICFHbG9iYWwuaXNTZXQoIHNlbGVjdGVkX2l0ZW0gKSApIHtcblx0XHRcdHNlbGVjdGVkX2l0ZW0gPSB0aGlzLmdldFNlbGVjdGVkSXRlbSgpO1xuXHRcdH1cblxuXHRcdGlmICggcF9pZCA9PT0gJ3JlcG9ydCcgKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIFBlcm1pc3Npb25NYW5hZ2VyLnZhbGlkYXRlKCBwX2lkLCAnZGVsZXRlJyApIHx8IHRoaXMub3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCAnZGVsZXRlX2NoaWxkJywgc2VsZWN0ZWRfaXRlbSApIHx8IHRoaXMub3duZXJPckNoaWxkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkLCAnZGVsZXRlX293bicsIHNlbGVjdGVkX2l0ZW0gKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHNhdmVWYWxpZGF0ZSggY29udGV4dF9idG4sIHBfaWQgKSB7XG5cdFx0aWYgKCAoICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgfHwgIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApICYmICF0aGlzLmlzX21hc3NfZWRpdGluZyApIHtcblx0XHRcdGlmICggIXRoaXMuYWRkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgKSB7XG5cdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKCAoICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkgJiYgdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB8fCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSB7XG5cblx0XHRcdGlmICggIXRoaXMuZWRpdFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0c2F2ZUFuZENvcHlWYWxpZGF0ZSggY29udGV4dF9idG4sIHBfaWQgKSB7XG5cblx0XHRpZiAoICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZCB8fCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkgJiYgIXRoaXMuaXNfbWFzc19lZGl0aW5nICkge1xuXHRcdFx0aWYgKCAhdGhpcy5hZGRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSApIHtcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSAmJiB0aGlzLmlzX21hc3NfZWRpdGluZyApIHx8IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblxuXHRcdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgfHwgIXRoaXMuYWRkUGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgKSB7XG5cdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuZWRpdF9vbmx5X21vZGUgKSB7XG5cdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0fVxuXHR9XG5cblx0c2F2ZUFuZENvbnRpbnVlVmFsaWRhdGUoIGNvbnRleHRfYnRuLCBwX2lkICkge1xuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSAmJiAhdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApIHx8ICF0aGlzLmVkaXRQZXJtaXNzaW9uVmFsaWRhdGUoIHBfaWQgKSApIHtcblx0XHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSAmJiB0aGlzLmlzX21hc3NfZWRpdGluZyApIHx8IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCApIHtcblxuXHRcdFx0aWYgKCAhdGhpcy5lZGl0UGVybWlzc2lvblZhbGlkYXRlKCBwX2lkICkgKSB7XG5cdFx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc2hvd1NhdmVBbmRDb250aW51ZU9uRWRpdE9ubHkoKSA9PSBmYWxzZSApIHtcblx0XHRcdENvbnRleHRNZW51TWFuYWdlci5oaWRlTWVudUl0ZW0oIHRoaXMuZGV0ZXJtaW5lQ29udGV4dE1lbnVNb3VudEF0dHJpYnV0ZXMoKS5pZCwgY29udGV4dF9idG4uaWQsIGZhbHNlIClcblx0XHR9XG5cdH1cblxuXHRzaG93U2F2ZUFuZENvbnRpbnVlT25FZGl0T25seSgpIHtcblx0XHQvL0J5IGRlZmF1bHQsIHZpZXdzIG1hcmtlZCBhcyBlZGl0X29ubHlfbW9kZSBkbyBub3Qgc2hvdyBzYXZlIGFuZCBjb250aW51ZS5cblx0XHQvL0hvd2V2ZXIsIGluIGNlcnRhaW4gY2FzZXMgd2UgZG8gd2FudCB0byBzaG93IGl0LCBzdWNoIGFzIHdoZW4gY2xpY2tpbmcgXCJIaXJlIEFwcGxpY2FudFwiIG9uIEpvYkFwcGxpY2F0aW9uIHZpZXdcblx0XHRpZiAoIHRoaXMuZWRpdF9vbmx5X21vZGUgPT0gdHJ1ZSAmJiAoIHRoaXMucGFyZW50X3ZpZXdfY29udHJvbGxlciAmJiB0aGlzLnZpZXdJZCA9PT0gJ0VtcGxveWVlJyAmJiB0aGlzLnBhcmVudF92aWV3X2NvbnRyb2xsZXIudmlld0lkID09PSAnSm9iQXBwbGljYXRpb24nICkgPT0gZmFsc2UgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRzYXZlQW5kTmV3VmFsaWRhdGUoIGNvbnRleHRfYnRuLCBwX2lkICkge1xuXHRcdGlmICggKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkIHx8ICF0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSAmJiAhdGhpcy5pc19tYXNzX2VkaXRpbmcgKSB7XG5cdFx0XHRpZiAoICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmICggKCAhR2xvYmFsLmlzU2V0KCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgKSAmJiB0aGlzLmlzX21hc3NfZWRpdGluZyApIHx8IEdsb2JhbC5pc1NldCggdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkgKSB7XG5cblx0XHRcdGlmICggIXRoaXMuZWRpdFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApIHx8ICF0aGlzLmFkZFBlcm1pc3Npb25WYWxpZGF0ZSggcF9pZCApICkge1xuXHRcdFx0XHRDb250ZXh0TWVudU1hbmFnZXIuaGlkZU1lbnVJdGVtKCB0aGlzLmRldGVybWluZUNvbnRleHRNZW51TW91bnRBdHRyaWJ1dGVzKCkuaWQsIGNvbnRleHRfYnRuLmlkLCBmYWxzZSApXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmVkaXRfb25seV9tb2RlICkge1xuXHRcdFx0Q29udGV4dE1lbnVNYW5hZ2VyLmhpZGVNZW51SXRlbSggdGhpcy5kZXRlcm1pbmVDb250ZXh0TWVudU1vdW50QXR0cmlidXRlcygpLmlkLCBjb250ZXh0X2J0bi5pZCwgZmFsc2UgKVxuXHRcdH1cblx0fVxuXG5cdHNldFN1YkxvZ1ZpZXdGaWx0ZXIoKSB7XG5cdFx0Ly8gIzI3NjEgUmVmYWN0b3Igb2Ygc2V0U3ViTG9nVmlld0NvbnRyb2xsZXIgYW5kIHNldFN1YlZpZXdGaWx0ZXJGdW5jdGlvbiBpbnRvIHNldFN1YkxvZ1ZpZXdGaWx0ZXJcblx0XHQvLyBUaGlzIHJlZmFjdG9yIGlzIGJlY2F1c2UgdGhlIGtleSB2YWx1ZSBhdHRyaWJ1dGVzIGFyZSBsaW5rZWQgd2l0aCB0aGUgZmlsdGVyLlxuXHRcdC8vIEluIGdlbmVyYWwsIGl0IHdhcyBmb3VuZCB0aGF0IGVpdGhlciB0aGUga2V5IHZhbHVlIGFyZSBzZXQsIG9yIHRoZSBmaWx0ZXJzLCBidXQgbm90IGJvdGguIFNvIG1ha2VzIHNlbnNlIHRvIGJlIGluIHRoZSBzYW1lIGZ1bmN0aW9uLiBOb3QgY29uZmlybWVkIHRoYXQgdGhpcyBpcyB0aGUgY2FzZSBpbiBhbGwgdmlld3MsIHNvIGl0cyBub3QgYmVlbiBtYWRlIGludG8gYW4gJ2VpdGhlciBvcicgZnVuY3Rpb24uXG5cblx0XHRpZiAoICF0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIE9wdGlvbiAjMTogZmlsdGVyIG9uIHNpbmdsZSBjcml0ZXJpYSAoZGVmYXVsdClcblx0XHR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnBhcmVudF9rZXkgPSAnb2JqZWN0X2lkJztcblx0XHR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnBhcmVudF92YWx1ZSA9IHRoaXMudW5pZm9ybVZhcmlhYmxlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQgKS5pZDtcblx0XHR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnRhYmxlX25hbWVfa2V5ID0gdGhpcy50YWJsZV9uYW1lX2tleTtcblxuXHRcdC8vIE9wdGlvbiAjMjogZmlsdGVyIG9uIG11bHRpcGxlIGNyaXRlcmlhLlxuXG5cdFx0Ly8gIzI3NjE6IEZpbHRlciBmdW5jdGlvbiBhcHBlYXJzIHRvIG9ubHkgd29yayBpZiBwYXJlbnRfa2V5LCB2YWx1ZSBhbmQgdGFibGUgYXJlIG51bGwgb3Igbm90IHNldC5cblx0XHQvLyBGaWx0ZXIgc3RydWN0dXJlIHdvcmtzIHNpbWlsYXIgdG8gcHNldWRvIGNvZGU6IFdIRVJFICggdGFibGVfbmFtZSA9ICdwdW5jaCcgQU5EIG9iamVjdF9pZCA9ICckcHVuY2hfaWQnKSBPUiAoIHRhYmxlX25hbWUgPSAncHVuY2hfY29udHJvbCcgQU5EIG9iamVjdF9pZCA9ICckcHVuY2hfY29udHJvbF9pZCcgKVxuXHRcdC8vIGtleSwgdmFsdWUsIHRhYmxlIGxpbmVzIGNhbiBqdXN0IGJlIG9tbWl0dGVkLCBhcyBkZWZhdWx0IHN0YXRlIGlzIG51bGwuIEluY2x1ZGVkIGhlcmUgZm9yIGVtcGhhc2lzIGluIGV4YW1wbGUuXG5cdFx0Ly8gdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5wYXJlbnRfa2V5ID0gbnVsbDtcblx0XHQvLyB0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnBhcmVudF92YWx1ZSA9IG51bGw7XG5cdFx0Ly8gdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci50YWJsZV9uYW1lX2tleSA9IG51bGw7XG5cdFx0Ly8gdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5nZXRTdWJWaWV3RmlsdGVyID0gZnVuY3Rpb24gKCBmaWx0ZXIgKSB7XG5cdFx0Ly8gXHRmaWx0ZXJbJ3RhYmxlX25hbWVfb2JqZWN0X2lkJ10gPSB7XG5cdFx0Ly8gXHRcdCdwdW5jaCc6IFt0aGlzLnBhcmVudF9lZGl0X3JlY29yZC5pZF0sXG5cdFx0Ly8gXHRcdCdwdW5jaF9jb250cm9sJzogW3RoaXMucGFyZW50X2VkaXRfcmVjb3JkLnB1bmNoX2NvbnRyb2xfaWRdXG5cdFx0Ly8gXHR9O1xuXHRcdC8vXG5cdFx0Ly8gXHRyZXR1cm4gZmlsdGVyO1xuXHRcdC8vIH07XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGluaXRTdWJMb2dWaWV3KCB0YWJfaWQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblxuXHRcdGlmICggIXRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCB8fCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQgPT0gVFRVVUlELnplcm9faWQgKSB7XG5cdFx0XHRUVFByb21pc2UucmVzb2x2ZSggJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdvblRhYlNob3cnICk7IC8vU2luY2Ugc2VhcmNoKCkgaXNuJ3QgY2FsbGVkIGluIHRoaXMgY2FzZSwgYW5kIHdlIGp1c3QgZGlzcGxheSB0aGUgXCJQbGVhc2UgU2F2ZSBUaGlzIFJlY29yZCAuLi5cIiBtZXNzYWdlLCByZXNvbHZlIHRoZSBwcm9taXNlLlxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlciApIHtcblx0XHRcdC8vIElmIHRoZSBBdWRpdCB0YWIgaGFzIGFscmVhZHkgYmVlbiBvcGVuZWQgYmVmb3JlIGluIHRoaXMgZWRpdCB2aWV3LlxuXHRcdFx0dGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5idWlsZENvbnRleHRNZW51KCB0cnVlICk7XG5cdFx0XHR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnNldERlZmF1bHRNZW51KCk7XG5cdFx0XHR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnBhcmVudF9lZGl0X3JlY29yZCA9IHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHRcdHRoaXMuc2V0U3ViTG9nVmlld0ZpbHRlcigpOyAvLyB0cmlnZ2VycyB0aGUgc2V0dGluZyBvZiB0aGUgZmlsdGVyIGZ1bmN0aW9uIGZvciB2aWV3cyB0aGF0IG5lZWQgaXQuXG5cdFx0XHQvLyAkdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5wYXJlbnRfa2V5ID0gJ29iamVjdF9pZCc7XG5cdFx0XHQvLyAkdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5wYXJlbnRfdmFsdWUgPSAkdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkO1xuXHRcdFx0Ly8gJHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIudGFibGVfbmFtZV9rZXkgPSAkdGhpcy50YWJsZV9uYW1lX2tleTtcblxuXHRcdFx0dGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlci5zZWFyY2goKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gSWYgdGhlIEF1ZGl0IHRhYiBoYXMgTk9UIHlldCBiZWVuIG9wZW5lZCBiZWZvcmUgaW4gdGhpcyBlZGl0IHZpZXcuXG5cdFx0XHRHbG9iYWwubG9hZFNjcmlwdCggJ3ZpZXdzL2NvcmUvbG9nL0xvZ1ZpZXdDb250cm9sbGVyLmpzJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggISR0aGlzLmVkaXRfdmlld190YWIgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHZhciB0YWIgPSAkdGhpcy5lZGl0X3ZpZXdfdGFiLmZpbmQoICcjJyArIHRhYl9pZCApO1xuXHRcdFx0XHR2YXIgZmlyc3RDb2x1bW4gPSB0YWIuZmluZCggJy5maXJzdC1jb2x1bW4tc3ViLXZpZXcnICk7XG5cblx0XHRcdFx0VFRQcm9taXNlLmFkZCggJ2luaXRTdWJBdWRpdCcsICdpbml0JyApO1xuXHRcdFx0XHRUVFByb21pc2Uud2FpdCggJ2luaXRTdWJBdWRpdCcsICdpbml0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0Zmlyc3RDb2x1bW4uY3NzKCAnb3BhY2l0eScsICcxJyApO1xuXHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0Zmlyc3RDb2x1bW4uY3NzKCAnb3BhY2l0eScsICcwJyApOyAvL0hpZGUgdGhlIGdyaWQgd2hpbGUgaXRzIGxvYWRpbmcvc2l6aW5nLlxuXG5cdFx0XHRcdEdsb2JhbC50cmFja1ZpZXcoICdTdWInICsgJ0xvZycgKyAnVmlldycsIExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfZG9pbmdfY29udGV4dF9hY3Rpb24gKTtcblx0XHRcdFx0TG9nVmlld0NvbnRyb2xsZXIubG9hZFN1YlZpZXcoIGZpcnN0Q29sdW1uLCBiZWZvcmVMb2FkVmlldywgYWZ0ZXJMb2FkVmlldyApO1xuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGJlZm9yZUxvYWRWaWV3KCkge1xuXG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gYWZ0ZXJMb2FkVmlldyggc3ViVmlld0NvbnRyb2xsZXIgKSB7XG5cdFx0XHQkdGhpcy5zdWJfbG9nX3ZpZXdfY29udHJvbGxlciA9IHN1YlZpZXdDb250cm9sbGVyO1xuXHRcdFx0JHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIucGFyZW50X3ZpZXdfY29udHJvbGxlciA9ICR0aGlzO1xuXHRcdFx0JHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIucGFyZW50X2VkaXRfcmVjb3JkID0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHRcdCR0aGlzLnNldFN1YkxvZ1ZpZXdGaWx0ZXIoKTsgLy8gdHJpZ2dlcnMgdGhlIHNldHRpbmcgb2YgdGhlIGZpbHRlciBmdW5jdGlvbiBmb3Igdmlld3MgdGhhdCBuZWVkIGl0LlxuXHRcdFx0Ly8gJHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIucGFyZW50X2tleSA9ICdvYmplY3RfaWQnO1xuXHRcdFx0Ly8gJHRoaXMuc3ViX2xvZ192aWV3X2NvbnRyb2xsZXIucGFyZW50X3ZhbHVlID0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZDtcblx0XHRcdC8vICR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnRhYmxlX25hbWVfa2V5ID0gJHRoaXMudGFibGVfbmFtZV9rZXk7XG5cblx0XHRcdCR0aGlzLnN1Yl9sb2dfdmlld19jb250cm9sbGVyLnBvc3RJbml0ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHRoaXMuaW5pdERhdGEoKTtcblx0XHRcdH07XG5cblx0XHR9XG5cdH1cblxuXHRzaG93Tm9SZXN1bHRDb3Zlciggc2hvd19uZXdfYnRuICkge1xuXHRcdGlmICggIXNob3dfbmV3X2J0biApIHtcblx0XHRcdHNob3dfbmV3X2J0biA9IHRoaXMuaWZDb250ZXh0QnV0dG9uRXhpc3QoICdhZGQnICk7XG5cdFx0fVxuXG5cdFx0dGhpcy5yZW1vdmVOb1Jlc3VsdENvdmVyKCk7XG5cdFx0dGhpcy5ub19yZXN1bHRfYm94ID0gR2xvYmFsLmxvYWRXaWRnZXRCeU5hbWUoIFdpZGdldE5hbWVzRGljLk5PX1JFU1VMVF9CT1ggKTtcblx0XHR0aGlzLm5vX3Jlc3VsdF9ib3guTm9SZXN1bHRCb3goIHsgcmVsYXRlZF92aWV3X2NvbnRyb2xsZXI6IHRoaXMsIGlzX25ldzogc2hvd19uZXdfYnRuIH0gKTtcblx0XHR0aGlzLm5vX3Jlc3VsdF9ib3guYXR0ciggJ2lkJywgdGhpcy51aV9pZCArICdfbm9fcmVzdWx0X2JveCcgKTtcblxuXHRcdHZhciBncmlkX2RpdiA9ICQoIHRoaXMuZWwgKS5maW5kKCAnLmdyaWQtZGl2JyApO1xuXG5cdFx0Z3JpZF9kaXYuYXBwZW5kKCB0aGlzLm5vX3Jlc3VsdF9ib3ggKTtcblxuXHRcdHRoaXMuaW5pdFJpZ2h0Q2xpY2tNZW51KCBSaWdodENsaWNrTWVudVR5cGUuTk9SRVNVTFRCT1ggKTtcblx0fVxuXG5cdHJlbW92ZU5vUmVzdWx0Q292ZXIoKSB7XG5cblx0XHRpZiAoIHRoaXMubm9fcmVzdWx0X2JveCAmJiB0aGlzLm5vX3Jlc3VsdF9ib3gubGVuZ3RoID4gMCApIHtcblx0XHRcdHRoaXMubm9fcmVzdWx0X2JveC5yZW1vdmUoKTtcblx0XHR9XG5cdFx0dGhpcy5ub19yZXN1bHRfYm94ID0gbnVsbDtcblx0fVxuXG5cdGNsZWFuV2hlblVubG9hZFZpZXcoIGNhbGxCYWNrICkge1xuXHRcdHRoaXMudW5tb3VudENvbnRleHRNZW51KCk7IC8vIFRoaXMgaXMganVzdCBpbiBjYXNlLCBjb250ZXh0bWVudSBzaG91bGQgYWxyZWFkeSBiZSB1bm1vdW50ZWQgaW4gSW5kZXhDb250cm9sbGVyLnJlbW92ZUN1cnJlbnRWaWV3XG5cdFx0dGhpcy5yZW1vdmVDb250ZW50TWVudUJ5TmFtZSgpO1xuXHRcdGlmICggR2xvYmFsLmlzU2V0KCBjYWxsQmFjayApICkge1xuXHRcdFx0Y2FsbEJhY2soKTtcblx0XHR9XG5cdH1cblxuXHRncmlkU2Nyb2xsVG9wKCkge1xuXG5cdFx0aWYgKCB0aGlzLnZpZXdJZCA9PT0gJ1RpbWVTaGVldCcgfHwgdGhpcy52aWV3SWQgPT09ICdTY2hlZHVsZScgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCAhdGhpcy5ncmlkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuZ3JpZC5ncmlkLnBhcmVudCgpLnBhcmVudCgpLnNjcm9sbFRvcCggMCApO1xuXHR9XG5cblx0Z3JpZFNjcm9sbERvd24oKSB7XG5cblx0XHRpZiAoIHRoaXMudmlld0lkID09PSAnVGltZVNoZWV0JyB8fCB0aGlzLnZpZXdJZCA9PT0gJ1NjaGVkdWxlJyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmdyaWQgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5ncmlkLmdyaWQucGFyZW50KCkucGFyZW50KCkuc2Nyb2xsVG9wKCAxMDAwMCApO1xuXHR9XG5cblx0c2VsZWN0QWxsKCkge1xuXHRcdGlmICggdGhpcy52aWV3SWQgPT09ICdUaW1lU2hlZXQnIHx8IHRoaXMudmlld0lkID09PSAnU2NoZWR1bGUnICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuZ3JpZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLmdyaWQuZ3JpZC5yZXNldFNlbGVjdGlvbigpO1xuXHRcdHZhciBzb3VyY2VfZGF0YSA9IHRoaXMuZ3JpZC5nZXREYXRhKCk7XG5cdFx0dmFyIGxlbiA9IHNvdXJjZV9kYXRhLmxlbmd0aDtcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdHZhciBpdGVtID0gc291cmNlX2RhdGFbaV07XG5cdFx0XHRpZiAoIEdsb2JhbC5pc1NldCggaXRlbS5pZCApICkge1xuXHRcdFx0XHR0aGlzLmdyaWQuZ3JpZC5zZXRTZWxlY3Rpb24oIGl0ZW0uaWQsIGZhbHNlICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmdyaWQuZ3JpZC5zZXRTZWxlY3Rpb24oIGkgKyAxLCBmYWxzZSApO1xuXHRcdFx0fVxuXG5cdFx0fVxuXG5cdFx0dGhpcy5ncmlkLmdyaWQucGFyZW50KCkucGFyZW50KCkucGFyZW50KCkuZmluZCggJy5jYm94LWhlYWRlcicgKS5wcm9wKCAnY2hlY2tlZCcsIHRydWUgKTtcblx0XHR0aGlzLnNldERlZmF1bHRNZW51KCk7XG5cdH1cblxuXHRkZXRhY2hFbGVtZW50KCBrZXkgKSB7XG5cdFx0Ly9FcnJvcjogVW5jYXVnaHQgVHlwZUVycm9yOiBDYW5ub3QgcmVhZCBwcm9wZXJ0eSAnZGV0YWNoJyBvZiB1bmRlZmluZWQgaW4gaW50ZXJmYWNlL2h0bWw1L3ZpZXdzL0Jhc2VWaWV3Q29udHJvbGxlci5qcz92PTkuMC4wLTIwMTUwODI0LTExMDMwMCBsaW5lIDY0NDFcblx0XHRpZiAoICF0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljIHx8ICF0aGlzLmVkaXRfdmlld19mb3JtX2l0ZW1fZGljW2tleV0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHBsYWNlX2hvbGRlciA9ICQoICc8cCBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIj4nICk7XG5cdFx0cGxhY2VfaG9sZGVyLmFkZENsYXNzKCAnLmVkaXQtdmlldzp2aXNpYmxlIHBsYWNlX2hvbGRlcl8nICsga2V5ICk7XG5cdFx0cGxhY2VfaG9sZGVyLmluc2VydEJlZm9yZSggdGhpcy5lZGl0X3ZpZXdfZm9ybV9pdGVtX2RpY1trZXldICk7XG5cdFx0dGhpcy5lZGl0X3ZpZXdfZm9ybV9pdGVtX2RpY1trZXldLmRldGFjaCgpO1xuXHR9XG5cblx0YXR0YWNoRWxlbWVudCgga2V5ICkge1xuXHRcdC8vRXJyb3I6IFVuY2F1Z2h0IFR5cGVFcnJvcjogQ2Fubm90IHJlYWQgcHJvcGVydHkgJ2luc2VydEJlZm9yZScgb2YgdW5kZWZpbmVkIGluIGludGVyZmFjZS9odG1sNS92aWV3cy9CYXNlVmlld0NvbnRyb2xsZXIuanM/dj05LjAuMC0yMDE1MDgyMi0yMTA1NDQgbGluZSA2NDM5XG5cdFx0aWYgKCAhdGhpcy5lZGl0X3ZpZXdfZm9ybV9pdGVtX2RpYyB8fCAhdGhpcy5lZGl0X3ZpZXdfZm9ybV9pdGVtX2RpY1trZXldICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vdmFyIHBsYWNlX2hvbGRlciA9ICQoICcuZWRpdC12aWV3OnZpc2libGUgLmVkaXQtdmlldy10YWI6dmlzaWJsZSAucGxhY2VfaG9sZGVyXycgKyBrZXkpO1xuXHRcdHZhciBwbGFjZV9ob2xkZXIgPSAkKCAnLmVkaXQtdmlldzp2aXNpYmxlIC5wbGFjZV9ob2xkZXJfJyArIGtleSApO1xuXHRcdHRoaXMuZWRpdF92aWV3X2Zvcm1faXRlbV9kaWNba2V5XS5pbnNlcnRCZWZvcmUoIHBsYWNlX2hvbGRlciApO1xuXHRcdHBsYWNlX2hvbGRlci5yZW1vdmUoKTtcblx0fVxuXG5cdGdldEJhbGFuY2VIYW5kbGVyKCByZXN1bHQsIGxhc3RfZGF0ZV9zdGFtcCApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHZhciBhdmFpbGFibGVfYmFsYW5jZV92YWx1ZSwgY3VycmVudF90aW1lX3ZhbHVlLCByZW1haW5pbmdfYmFsYW5jZV92YWx1ZSwgc3VtbWFyeV9hdmFpbGFibGVfdmFsdWU7XG5cblx0XHQvL0Vycm9yOiBUeXBlRXJyb3I6IHRoaXMuZWRpdF92aWV3X3VpX2RpYy5hdmFpbGFibGVfYmFsYW5jZSBpcyB1bmRlZmluZWQgaW4gL2ludGVyZmFjZS9odG1sNS9mcmFtZXdvcmsvanF1ZXJ5Lm1pbi5qcz92PTguMC4wLTIwMTQxMTE3LTA5MTQzMyBsaW5lIDIgPiBldmFsIGxpbmUgNjU3MFxuXHRcdGlmICggISR0aGlzLmVkaXRfdmlld191aV9kaWMgfHwgISR0aGlzLmVkaXRfdmlld191aV9kaWNbJ2F2YWlsYWJsZV9iYWxhbmNlJ10gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCBHbG9iYWwuaXNPYmplY3QoIHJlc3VsdCApICkge1xuXHRcdFx0dmFyIHJlc3VsdF9kYXRhID0gcmVzdWx0LmdldFJlc3VsdCgpO1xuXHRcdFx0aWYgKCAhcmVzdWx0X2RhdGEgKSB7XG5cdFx0XHRcdCR0aGlzLmRldGFjaEVsZW1lbnQoICdhdmFpbGFibGVfYmFsYW5jZScgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkdGhpcy5kZXRhY2hFbGVtZW50KCAnYXZhaWxhYmxlX2JhbGFuY2UnICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdCR0aGlzLmF0dGFjaEVsZW1lbnQoICdhdmFpbGFibGVfYmFsYW5jZScgKTtcblxuXHRcdGF2YWlsYWJsZV9iYWxhbmNlX3ZhbHVlID0gR2xvYmFsLmdldFRpbWVVbml0KCByZXN1bHRfZGF0YS5hdmFpbGFibGVfYmFsYW5jZSApO1xuXHRcdGN1cnJlbnRfdGltZV92YWx1ZSA9IEdsb2JhbC5nZXRUaW1lVW5pdCggcmVzdWx0X2RhdGEuY3VycmVudF90aW1lICk7XG5cdFx0cmVtYWluaW5nX2JhbGFuY2VfdmFsdWUgPSBHbG9iYWwuZ2V0VGltZVVuaXQoIHJlc3VsdF9kYXRhLnJlbWFpbmluZ19iYWxhbmNlICk7XG5cdFx0c3VtbWFyeV9hdmFpbGFibGVfdmFsdWUgPSBHbG9iYWwuZ2V0VGltZVVuaXQoIHJlc3VsdF9kYXRhLnByb2plY3RlZF9yZW1haW5pbmdfYmFsYW5jZSApO1xuXHRcdGlmICggcmVzdWx0X2RhdGEuaGFzT3duUHJvcGVydHkoICdyZW1haW5pbmdfZG9sbGFyX2JhbGFuY2UnICkgKSB7XG5cdFx0XHRhdmFpbGFibGVfYmFsYW5jZV92YWx1ZSA9IGF2YWlsYWJsZV9iYWxhbmNlX3ZhbHVlICsgJyAvICcgKyBMb2NhbENhY2hlRGF0YS5nZXRDdXJyZW50Q3VycmVuY3lTeW1ib2woKSArIHJlc3VsdF9kYXRhLmF2YWlsYWJsZV9kb2xsYXJfYmFsYW5jZTtcblx0XHRcdGN1cnJlbnRfdGltZV92YWx1ZSA9IGN1cnJlbnRfdGltZV92YWx1ZSArICcgLyAnICsgTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudEN1cnJlbmN5U3ltYm9sKCkgKyByZXN1bHRfZGF0YS5jdXJyZW50X2RvbGxhcl9hbW91bnQ7XG5cdFx0XHRyZW1haW5pbmdfYmFsYW5jZV92YWx1ZSA9IHJlbWFpbmluZ19iYWxhbmNlX3ZhbHVlICsgJyAvICcgKyBMb2NhbENhY2hlRGF0YS5nZXRDdXJyZW50Q3VycmVuY3lTeW1ib2woKSArIHJlc3VsdF9kYXRhLnJlbWFpbmluZ19kb2xsYXJfYmFsYW5jZTtcblx0XHRcdHN1bW1hcnlfYXZhaWxhYmxlX3ZhbHVlID0gc3VtbWFyeV9hdmFpbGFibGVfdmFsdWUgKyAnIC8gJyArIExvY2FsQ2FjaGVEYXRhLmdldEN1cnJlbnRDdXJyZW5jeVN5bWJvbCgpICsgcmVzdWx0X2RhdGEucmVtYWluaW5nX2RvbGxhcl9iYWxhbmNlO1xuXHRcdH1cblx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydhdmFpbGFibGVfYmFsYW5jZSddLnNldFZhbHVlKCBzdW1tYXJ5X2F2YWlsYWJsZV92YWx1ZSApO1xuXG5cdFx0Ly9JZiBhdmFpbGFibGUgYmFsYW5jZSBpcyBuZWdhdGl2ZSwgY2hhbmdlIGZvbnQgY29sb3IgdG8gcmVkIHNvIGl0cyBtb3JlIG5vdGljYWJsZS5cblx0XHRpZiAoIHJlc3VsdF9kYXRhLnByb2plY3RlZF9yZW1haW5pbmdfYmFsYW5jZSA8IDAgKSB7XG5cdFx0XHQkdGhpcy5lZGl0X3ZpZXdfdWlfZGljWydhdmFpbGFibGVfYmFsYW5jZSddLmNzcyggJ2NvbG9yJywgJ3JlZCcgKTsgLy9Gb250IGNvbG9yIHRvIHJlZC5cblx0XHR9IGVsc2Uge1xuXHRcdFx0JHRoaXMuZWRpdF92aWV3X3VpX2RpY1snYXZhaWxhYmxlX2JhbGFuY2UnXS5jc3MoICdjb2xvcicsICdibGFjaycgKTtcblx0XHR9XG5cblx0XHRpZiAoICR0aGlzLmF2YWlsYWJsZV9iYWxhbmNlX2luZm8gKSB7XG5cdFx0XHQkdGhpcy5hdmFpbGFibGVfYmFsYW5jZV9pbmZvLnF0aXAoXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRzaG93OiB7XG5cdFx0XHRcdFx0XHRldmVudDogJ2NsaWNrJyxcblx0XHRcdFx0XHRcdGRlbGF5OiAxMCxcblx0XHRcdFx0XHRcdGVmZmVjdDogdHJ1ZVxuXHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHRoaWRlOiB7XG5cdFx0XHRcdFx0XHRldmVudDogWyd1bmZvY3VzIGNsaWNrJ10sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRzdHlsZToge1xuXHRcdFx0XHRcdFx0Ly9jbGFzc2VzOiAnY3JlYW0nLFxuXHRcdFx0XHRcdFx0d2lkdGg6IDM0MCAvL0R5bmFtaWNhbGx5IGNoYW5naW5nIHRoZSB3aWR0aCBjYXVzZXMgZGlzcGxheSBidWdzIHdoZW4gc3dpdGNoaW5nIGJldHdlZW4gQWJzZW5jZSBQb2xpY2llcyBhbmQgdGhlcmVieSB3aWR0aHMuXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRjb250ZW50OiAnPGRpdiBzdHlsZT1cIndpZHRoOjEwMCU7XCI+JyArXG5cdFx0XHRcdFx0XHQnPGRpdiBzdHlsZT1cIndpZHRoOjEwMCU7IGNsZWFyOiBib3RoO1wiPjxzcGFuIHN0eWxlPVwiZmxvYXQ6bGVmdDtcIj4nICsgJC5pMThuLl8oICdBdmFpbGFibGUgQmFsYW5jZScgKSArICc6IDwvc3Bhbj48c3BhbiBzdHlsZT1cImZsb2F0OnJpZ2h0O1wiPicgKyBhdmFpbGFibGVfYmFsYW5jZV92YWx1ZSArICc8L3NwYW4+PC9kaXY+JyArXG5cdFx0XHRcdFx0XHQnPGRpdiBzdHlsZT1cIndpZHRoOjEwMCU7IGNsZWFyOiBib3RoO1wiPjxzcGFuIHN0eWxlPVwiZmxvYXQ6bGVmdDtcIj4nICsgJC5pMThuLl8oICdDdXJyZW50IFRpbWUnICkgKyAnOiA8L3NwYW4+PHNwYW4gc3R5bGU9XCJmbG9hdDpyaWdodDtcIj4nICsgY3VycmVudF90aW1lX3ZhbHVlICsgJzwvc3Bhbj48L2Rpdj4nICtcblx0XHRcdFx0XHRcdCc8ZGl2IHN0eWxlPVwid2lkdGg6MTAwJTsgY2xlYXI6IGJvdGg7XCI+PHNwYW4gc3R5bGU9XCJmbG9hdDpsZWZ0O1wiPicgKyAkLmkxOG4uXyggJ1JlbWFpbmluZyBCYWxhbmNlJyApICsgJzogPC9zcGFuPjxzcGFuIHN0eWxlPVwiZmxvYXQ6cmlnaHQ7XCI+JyArIHJlbWFpbmluZ19iYWxhbmNlX3ZhbHVlICsgJzwvc3Bhbj48L2Rpdj4nICtcblx0XHRcdFx0XHRcdCc8ZGl2IHN0eWxlPVwid2lkdGg6MTAwJTsgaGVpZ2h0OiAyMHB4OyBjbGVhcjogYm90aDtcIj48L2Rpdj4nICtcblx0XHRcdFx0XHRcdCc8ZGl2IHN0eWxlPVwid2lkdGg6MTAwJTsgY2xlYXI6IGJvdGg7XCI+PHNwYW4gc3R5bGU9XCJmbG9hdDpsZWZ0O1wiPicgKyAkLmkxOG4uXyggJ1Byb2plY3RlZCBCYWxhbmNlIGJ5JyApICsgJyAnICsgbGFzdF9kYXRlX3N0YW1wICsgJzogPC9zcGFuPjxzcGFuIHN0eWxlPVwiZmxvYXQ6cmlnaHQ7XCI+JyArIEdsb2JhbC5nZXRUaW1lVW5pdCggcmVzdWx0X2RhdGEucHJvamVjdGVkX2JhbGFuY2UgKSArICc8L3NwYW4+PC9kaXY+JyArXG5cdFx0XHRcdFx0XHQnPGRpdiBzdHlsZT1cIndpZHRoOjEwMCU7IGNsZWFyOiBib3RoO1wiPjxzcGFuIHN0eWxlPVwiZmxvYXQ6bGVmdDtcIj4nICsgJC5pMThuLl8oICdQcm9qZWN0ZWQgUmVtYWluaW5nIEJhbGFuY2UnICkgKyAnOjwvc3Bhbj48c3BhbiBzdHlsZT1cImZsb2F0OnJpZ2h0O1wiPicgKyBHbG9iYWwuZ2V0VGltZVVuaXQoIHJlc3VsdF9kYXRhLnByb2plY3RlZF9yZW1haW5pbmdfYmFsYW5jZSApICsgJzwvc3Bhbj48L2Rpdj4nICtcblx0XHRcdFx0XHRcdCc8L2Rpdj4nXG5cdFx0XHRcdH0gKTtcblx0XHR9XG5cdH1cblxuXHRvbkV4cG9ydENsaWNrKCBtZXRob2QgKSB7XG5cdFx0UHJvZ3Jlc3NCYXIuc2hvd092ZXJsYXkoKTtcblx0XHRpZiAoIG1ldGhvZCA9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRtZXRob2QgPSB0aGlzLmFwaVsnZXhwb3J0JyArIHRoaXMuYXBpLmtleV9uYW1lXTtcblx0XHR9XG5cblx0XHQvL0RlYnVnLlRleHQoJ0V4cG9ydGluZyBHcmlkIFRvIENTVjogJyttZXRob2QsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ29uRXhwb3J0Q2xpY2snLCAxMCk7XG5cblx0XHR2YXIgYXJncyA9IHt9O1xuXHRcdGFyZ3MuZmlsdGVyX2NvbHVtbnMgPSB0aGlzLl9nZXRGaWx0ZXJDb2x1bW5zRnJvbURpc3BsYXlDb2x1bW5zKCBudWxsLCBmYWxzZSApO1xuXHRcdGFyZ3MuZmlsdGVyX2RhdGEgPSBHbG9iYWwuY29udmVydExheW91dEZpbHRlclRvQVBJRmlsdGVyKCB0aGlzLnNlbGVjdF9sYXlvdXQgKTtcblx0XHRpZiAoIEdsb2JhbC5pc1NldCggdGhpcy5zb3J0X2J5X3NlbGVjdG9yICkgKSB7XG5cdFx0XHRhcmdzLmZpbHRlcl9zb3J0ID0gdGhpcy5nZXRTZWFyY2hQYW5lbFNvcnRGaWx0ZXIoKTtcblx0XHR9XG5cdFx0dmFyIHBvc3RfZGF0YSA9IHsgMDogJ2NzdicsIDE6IGFyZ3MsIDI6IHRydWUgfTtcblxuXHRcdEdsb2JhbC5BUElGaWxlRG93bmxvYWQoIHRoaXMuYXBpLmNsYXNzTmFtZSwgbWV0aG9kLCBwb3N0X2RhdGEgKTtcblx0fVxuXG5cdGhpZ2hMaWdodEdyaWRSb3dCeUlkKCBpZCApIHtcblx0XHRpZiAoIHRoaXMuZ3JpZCAmJiB0aGlzLmdyaWQuZ3JpZCApIHtcblx0XHRcdHRoaXMuZ3JpZC5ncmlkLmZpbmQoICd0ciMnICsgaWQgKS5hZGRDbGFzcyggJ2ZsYXNoQmFja2dyb3VuZCcgKTtcblx0XHRcdHRoaXMuZ3JpZFNjcm9sbERvd24oKTtcblx0XHR9XG5cdH1cblxuXHRzZXRDb252ZXJzaW9uUmF0ZUV4YW1wbGVUZXh0KCBjb252ZXJzaW9uX3JhdGUsIGlzb19jb2RlLCBjdXJyZW5jeV9pZCApIHtcblx0XHR2YXIgZGF0YSA9IHt9O1xuXHRcdGRhdGEuZmlsdGVyX2RhdGEgPSBHbG9iYWwuY29udmVydExheW91dEZpbHRlclRvQVBJRmlsdGVyKCB0aGlzLnNlbGVjdF9sYXlvdXQgKTtcblx0XHR2YXIgYXBpID0gVFRBUEkuQVBJQ3VycmVuY3k7XG5cdFx0dmFyIG15X2N1cnJlbmNpZXMgPSBhcGkuZ2V0Q3VycmVuY3koIGRhdGEsIHsgYXN5bmM6IGZhbHNlIH0gKS5nZXRSZXN1bHQoKTtcblx0XHR2YXIgYmFzZV9jdXJyZW5jeV9pc29fY29kZSA9ICcnO1xuXHRcdGlmICggdGhpcy5lZGl0X3ZpZXdfdWlfZGljLnJvdW5kX2RlY2ltYWxfcGxhY2VzICkge1xuXHRcdFx0dmFyIGRlY2ltYWxfcGxhY2VzID0gdGhpcy5lZGl0X3ZpZXdfdWlfZGljLnJvdW5kX2RlY2ltYWxfcGxhY2VzLmdldFZhbHVlKCk7XG5cdFx0fVxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IG15X2N1cnJlbmNpZXMubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRpZiAoIG15X2N1cnJlbmNpZXNbaV0uaXNfYmFzZSApIHtcblx0XHRcdFx0YmFzZV9jdXJyZW5jeV9pc29fY29kZSA9IG15X2N1cnJlbmNpZXNbaV0uaXNvX2NvZGU7XG5cblx0XHRcdH1cblx0XHRcdGlmICggY3VycmVuY3lfaWQgJiYgIWlzb19jb2RlICYmIG15X2N1cnJlbmNpZXNbaV0uaWQgPT0gY3VycmVuY3lfaWQgKSB7XG5cdFx0XHRcdGlzb19jb2RlID0gbXlfY3VycmVuY2llc1tpXS5pc29fY29kZTtcblx0XHRcdFx0aWYgKCAhZGVjaW1hbF9wbGFjZXMgKSB7XG5cdFx0XHRcdFx0ZGVjaW1hbF9wbGFjZXMgPSBteV9jdXJyZW5jaWVzW2ldLnJvdW5kX2RlY2ltYWxfcGxhY2VzO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9uZWVkIGRpZmZlcmVudCBpZCBvbiB0aGUgc3VidmlldyBmb3IgcmF0ZS5cblx0XHRpZiAoIGlzb19jb2RlICE9IGJhc2VfY3VycmVuY3lfaXNvX2NvZGUgKSB7XG5cdFx0XHRpZiAoIHRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdFx0JCggJyNyYXRlX2NvbnZlcnNpb25fcmF0ZV9jbGFyaWZpY2F0aW9uX2JveCcgKS5odG1sKCAnJm5ic3A7Jm5ic3A7MS4wMCAnICsgYmFzZV9jdXJyZW5jeV9pc29fY29kZSArICcgPSAnICsgR2xvYmFsLnJlbW92ZVRyYWlsaW5nWmVyb3MoIGNvbnZlcnNpb25fcmF0ZSwgZGVjaW1hbF9wbGFjZXMgKSArICcgJyArIGlzb19jb2RlICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkKCAnI2NvbnZlcnNpb25fcmF0ZV9jbGFyaWZpY2F0aW9uX2JveCcgKS5odG1sKCAnJm5ic3A7Jm5ic3A7MS4wMCAnICsgYmFzZV9jdXJyZW5jeV9pc29fY29kZSArICcgPSAnICsgR2xvYmFsLnJlbW92ZVRyYWlsaW5nWmVyb3MoIGNvbnZlcnNpb25fcmF0ZSwgZGVjaW1hbF9wbGFjZXMgKSArICcgJyArIGlzb19jb2RlICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdCQoICcjY29udmVyc2lvbl9yYXRlX2NsYXJpZmljYXRpb25fYm94JyApLmhpZGUoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogZ2V0cyBkZWZhdWx0IGNvb3JkaW5hdGVzIG9iamVjdCBmb3IgbWFwcy5cblx0ICovXG5cdHN0YXJ0TWFwQ29vcmRpbmF0ZXMoKSB7XG5cdFx0dmFyIGxhdCA9IDM5LjUwO1xuXHRcdHZhciBsbmcgPSAtOTguMzU7XG5cblx0XHRpZiAoIExvY2FsQ2FjaGVEYXRhLmdldEN1cnJlbnRDb21wYW55KCkubGF0aXR1ZGUgIT0gMCAmJiBMb2NhbENhY2hlRGF0YS5nZXRDdXJyZW50Q29tcGFueSgpLmxvbmdpdHVkZSAhPSAwICkge1xuXHRcdFx0bGF0ID0gTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudENvbXBhbnkoKS5sYXRpdHVkZTtcblx0XHRcdGxuZyA9IExvY2FsQ2FjaGVEYXRhLmdldEN1cnJlbnRDb21wYW55KCkubG9uZ2l0dWRlO1xuXHRcdFx0RGVidWcuVGV4dCggJ1VzaW5nIGNvbXBhbnkgY29vcmRpbmF0ZXMuJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnc3RhcnRNYXBDb29yZGluYXRlcycsIDEwICk7XG5cdFx0fSBlbHNlIGlmICggTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyKCkubGF0aXR1ZGUgIT0gMCAmJiBMb2NhbENhY2hlRGF0YS5nZXRMb2dpblVzZXIoKS5sb25naXR1ZGUgIT0gMCApIHtcblx0XHRcdGxhdCA9IExvY2FsQ2FjaGVEYXRhLmdldExvZ2luVXNlcigpLmxhdGl0dWRlO1xuXHRcdFx0bG5nID0gTG9jYWxDYWNoZURhdGEuZ2V0TG9naW5Vc2VyKCkubG9uZ2l0dWRlO1xuXHRcdFx0RGVidWcuVGV4dCggJ1VzaW5nIHVzZXIgY29vcmRpbmF0ZXMuJywgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnc3RhcnRNYXBDb29yZGluYXRlcycsIDEwICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBjb21wYW55X2FwaSA9IFRUQVBJLkFQSUNvbXBhbnk7XG5cdFx0XHR2YXIgY291bnRyeV9hcnIgPSBjb21wYW55X2FwaS5nZXRPcHRpb25zKCAnY291bnRyeScsIHsgYXN5bmM6IGZhbHNlIH0gKS5nZXRSZXN1bHQoKTtcblx0XHRcdHZhciBwcm92aW5jZV9hcnIgPSBjb21wYW55X2FwaS5nZXRPcHRpb25zKCAncHJvdmluY2UnLCBMb2NhbENhY2hlRGF0YS5nZXRDdXJyZW50Q29tcGFueSgpLmNvdW50cnksIHsgYXN5bmM6IGZhbHNlIH0gKS5nZXRSZXN1bHQoKTtcblxuXHRcdFx0aWYgKCBBUElHbG9iYWwucHJlX2xvZ2luX2RhdGEubWFwX2dlb2NvZGVfdXJsICYmIHByb3ZpbmNlX2FyciAmJiBjb3VudHJ5X2FyciAmJiBwcm92aW5jZV9hcnJbTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudENvbXBhbnkoKS5wcm92aW5jZV0gJiYgY291bnRyeV9hcnJbTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudENvbXBhbnkoKS5jb3VudHJ5XSApIHtcblx0XHRcdFx0dmFyIHF1ZXJ5ID0gTG9jYWxDYWNoZURhdGEuZ2V0Q3VycmVudENvbXBhbnkoKS5jaXR5ICsgJyAnICsgcHJvdmluY2VfYXJyW0xvY2FsQ2FjaGVEYXRhLmdldEN1cnJlbnRDb21wYW55KCkucHJvdmluY2VdICsgJywgJyArIGNvdW50cnlfYXJyW0xvY2FsQ2FjaGVEYXRhLmdldEN1cnJlbnRDb21wYW55KCkuY291bnRyeV07XG5cdFx0XHRcdHZhciB1cmwgPSBBUElHbG9iYWwucHJlX2xvZ2luX2RhdGEubWFwX2dlb2NvZGVfdXJsICsgJz9xPScgKyBxdWVyeSArICcmZm9ybWF0PWpzb24mdHRfa2V5PScgKyBBUElHbG9iYWwucHJlX2xvZ2luX2RhdGEucmVnaXN0cmF0aW9uX2tleTtcblx0XHRcdFx0dmFyIHJlc3VsdCA9IGpRdWVyeS5hamF4KCB7IHVybDogdXJsLCBhc3luYzogZmFsc2UgfSApO1xuXHRcdFx0XHREZWJ1Zy5BcnIoICdHZW9jb2RpbmcgYWRkcmVzczogJyArIHF1ZXJ5LCByZXN1bHQsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ3N0YXJ0TWFwQ29vcmRpbmF0ZXMnLCAxMCApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHJlc3VsdCAmJiByZXN1bHQucmVzcG9uc2VKU09OICYmIHJlc3VsdC5yZXNwb25zZUpTT05bMF0gJiYgcmVzdWx0LnJlc3BvbnNlSlNPTlswXS5sYXQgJiYgcmVzdWx0LnJlc3BvbnNlSlNPTlswXS5sb24gKSB7XG5cdFx0XHRcdGxhdCA9IHJlc3VsdC5yZXNwb25zZUpTT05bMF0ubGF0O1xuXHRcdFx0XHRsbmcgPSByZXN1bHQucmVzcG9uc2VKU09OWzBdLmxvbjtcblx0XHRcdFx0RGVidWcuVGV4dCggJ1VzaW5nIGNvbXBhbnkgYWRkcmVzcyBjb29yZGluYXRlcy4nLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdzdGFydE1hcENvb3JkaW5hdGVzJywgMTAgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdERlYnVnLlRleHQoICdVc2luZyBkZWZhdWx0IGNvb3JkaW5hdGVzLicsICdCYXNlVmlld0NvbnRyb2xsZXIuanMnLCAnQmFzZVZpZXdDb250cm9sbGVyJywgJ3N0YXJ0TWFwQ29vcmRpbmF0ZXMnLCAxMCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdERlYnVnLlRleHQoICdDb29yZGluYXRlcyAobGF0LGxvbmcpOiAnICsgbGF0ICsgJywnICsgbG5nLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdzdGFydE1hcENvb3JkaW5hdGVzJywgMTAgKTtcblx0XHRyZXR1cm4gbmV3IEwuTGF0TG5nKCBsYXQsIGxuZyApO1xuXHR9XG5cblx0aW5pdFN1YkRvY3VtZW50VmlldygpIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXG5cdFx0aWYgKCAhdGhpcy5jdXJyZW50X2VkaXRfcmVjb3JkLmlkICkge1xuXHRcdFx0VFRQcm9taXNlLnJlc29sdmUoICdCYXNlVmlld0NvbnRyb2xsZXInLCAnb25UYWJTaG93JyApOyAvL1NpbmNlIHNlYXJjaCgpIGlzbid0IGNhbGxlZCBpbiB0aGlzIGNhc2UsIGFuZCB3ZSBqdXN0IGRpc3BsYXkgdGhlIFwiUGxlYXNlIFNhdmUgVGhpcyBSZWNvcmQgLi4uXCIgbWVzc2FnZSwgcmVzb2x2ZSB0aGUgcHJvbWlzZS5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc3ViX2RvY3VtZW50X3ZpZXdfY29udHJvbGxlciApIHtcblx0XHRcdHRoaXMuc3ViX2RvY3VtZW50X3ZpZXdfY29udHJvbGxlci5idWlsZENvbnRleHRNZW51KCB0cnVlICk7XG5cdFx0XHR0aGlzLnN1Yl9kb2N1bWVudF92aWV3X2NvbnRyb2xsZXIuc2V0RGVmYXVsdE1lbnUoKTtcblx0XHRcdCR0aGlzLnN1Yl9kb2N1bWVudF92aWV3X2NvbnRyb2xsZXIucGFyZW50X3ZhbHVlID0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZDtcblx0XHRcdCR0aGlzLnN1Yl9kb2N1bWVudF92aWV3X2NvbnRyb2xsZXIucGFyZW50X2VkaXRfcmVjb3JkID0gJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZDtcblx0XHRcdCR0aGlzLnN1Yl9kb2N1bWVudF92aWV3X2NvbnRyb2xsZXIuaW5pdERhdGEoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRHbG9iYWwubG9hZFNjcmlwdCggJ3ZpZXdzL2RvY3VtZW50L0RvY3VtZW50Vmlld0NvbnRyb2xsZXIuanMnLCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggISR0aGlzLmVkaXRfdmlld190YWIgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciB0YWJfY29udGFjdF9pbmZvID0gJHRoaXMuZWRpdF92aWV3X3RhYi5maW5kKCAnI3RhYl9hdHRhY2htZW50JyApO1xuXHRcdFx0dmFyIGZpcnN0Q29sdW1uID0gdGFiX2NvbnRhY3RfaW5mby5maW5kKCAnLmZpcnN0LWNvbHVtbi1zdWItdmlldycgKTtcblxuXHRcdFx0VFRQcm9taXNlLmFkZCggJ2luaXRTdWJEb2N1bWVudFZpZXcnLCAnaW5pdCcgKTtcblx0XHRcdFRUUHJvbWlzZS53YWl0KCAnaW5pdFN1YkRvY3VtZW50VmlldycsICdpbml0JywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGZpcnN0Q29sdW1uLmNzcyggJ29wYWNpdHknLCAnMScgKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0Zmlyc3RDb2x1bW4uY3NzKCAnb3BhY2l0eScsICcwJyApOyAvL0hpZGUgdGhlIGdyaWQgd2hpbGUgaXRzIGxvYWRpbmcvc2l6aW5nLlxuXG5cdFx0XHRHbG9iYWwudHJhY2tWaWV3KCAnU3ViRG9jdW1lbnRWaWV3JyApO1xuXHRcdFx0RG9jdW1lbnRWaWV3Q29udHJvbGxlci5sb2FkU3ViVmlldyggZmlyc3RDb2x1bW4sIGJlZm9yZUxvYWRWaWV3LCBhZnRlckxvYWRWaWV3ICk7XG5cblx0XHR9ICk7XG5cblx0XHRmdW5jdGlvbiBiZWZvcmVMb2FkVmlldygpIHtcblxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGFmdGVyTG9hZFZpZXcoIHN1YlZpZXdDb250cm9sbGVyICkge1xuXHRcdFx0JHRoaXMuc3ViX2RvY3VtZW50X3ZpZXdfY29udHJvbGxlciA9IHN1YlZpZXdDb250cm9sbGVyO1xuXHRcdFx0JHRoaXMuc3ViX2RvY3VtZW50X3ZpZXdfY29udHJvbGxlci5wYXJlbnRfa2V5ID0gJ29iamVjdF9pZCc7XG5cdFx0XHQkdGhpcy5zdWJfZG9jdW1lbnRfdmlld19jb250cm9sbGVyLnBhcmVudF92YWx1ZSA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQ7XG5cdFx0XHQkdGhpcy5zdWJfZG9jdW1lbnRfdmlld19jb250cm9sbGVyLmRvY3VtZW50X29iamVjdF90eXBlX2lkID0gJHRoaXMuZG9jdW1lbnRfb2JqZWN0X3R5cGVfaWQ7XG5cdFx0XHQkdGhpcy5zdWJfZG9jdW1lbnRfdmlld19jb250cm9sbGVyLnBhcmVudF9lZGl0X3JlY29yZCA9ICR0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQ7XG5cdFx0XHQkdGhpcy5zdWJfZG9jdW1lbnRfdmlld19jb250cm9sbGVyLnBhcmVudF92aWV3X2NvbnRyb2xsZXIgPSAkdGhpcztcblx0XHRcdCR0aGlzLnN1Yl9kb2N1bWVudF92aWV3X2NvbnRyb2xsZXIuaW5pdERhdGEoKTtcblx0XHR9XG5cdH1cblxuXHRvbkRlbGV0ZUltYWdlKCBjYWxsYmFjayApIHtcblx0XHR2YXIgJHRoaXMgPSB0aGlzO1xuXHRcdHRoaXMuYXBpLmRlbGV0ZUltYWdlKCB0aGlzLmN1cnJlbnRfZWRpdF9yZWNvcmQuaWQsIHtcblx0XHRcdG9uUmVzdWx0OiBmdW5jdGlvbiggcmVzdWx0ICkge1xuXHRcdFx0XHQkdGhpcy5vbkVkaXRDbGljayggJHRoaXMuY3VycmVudF9lZGl0X3JlY29yZC5pZCwgdHJ1ZSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fVxuXG5cdG9uVHJlZUdyaWROYXZpZ2F0aW9uUm93U2VsZWN0KCBpZCApIHtcblx0XHRpZiAoICFpZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvL2Rvbid0IGNsb3NlIG9uIGNvbGxhcHNlIG9mIHRyZWUgbW9kZSBlbGVtZW50XG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5jdXJyZW50bHlfY29sbGFwc2luZ19uYXZpZ2F0aW9uX3RyZWVfZWxlbWVudCAhPSB0cnVlICkge1xuXHRcdFx0dGhpcy5vbkVkaXRDbGljayggaWQgKTtcblx0XHRcdCQoICcuYS1kcm9wZG93bi1kaXYnICkucmVtb3ZlKCk7XG5cdFx0XHRMb2NhbENhY2hlRGF0YS5vcGVuQXdlc29tZUJveCA9IG51bGw7XG5cdFx0fSBlbHNlIHtcblx0XHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRseV9jb2xsYXBzaW5nX25hdmlnYXRpb25fdHJlZV9lbGVtZW50ID0gZmFsc2U7XG5cdFx0XHR0aGlzLm9uRWRpdENsaWNrKCBpZCwgdHJ1ZSApO1xuXHRcdFx0dGhpcy5zZXROYXZpZ2F0aW9uKCk7XG5cdFx0fVxuXHR9XG5cblx0cGFyc2VyRGF0ZXNSYW5nZSggZGF0ZSApIHtcblx0XHR2YXIgZGF0ZXMgPSBkYXRlLnNwbGl0KCBcIiAtIFwiICk7XG5cdFx0dmFyIHJlc3VsdEFycmF5ID0gW107XG5cdFx0dmFyIGJlZ2luRGF0ZSA9IEdsb2JhbC5zdHJUb0RhdGUoIGRhdGVzWzBdICk7XG5cdFx0dmFyIGVuZERhdGUgPSBHbG9iYWwuc3RyVG9EYXRlKCBkYXRlc1sxXSApO1xuXG5cdFx0dmFyIG5leHREYXRlID0gYmVnaW5EYXRlO1xuXG5cdFx0d2hpbGUgKCBuZXh0RGF0ZS5nZXRUaW1lKCkgPCBlbmREYXRlLmdldFRpbWUoKSApIHtcblx0XHRcdHJlc3VsdEFycmF5LnB1c2goIG5leHREYXRlLmZvcm1hdCgpICk7XG5cdFx0XHRuZXh0RGF0ZSA9IG5ldyBEYXRlKCBuZXcgRGF0ZSggbmV4dERhdGUuZ2V0VGltZSgpICkuc2V0RGF0ZSggbmV4dERhdGUuZ2V0RGF0ZSgpICsgMSApICk7XG5cdFx0fVxuXG5cdFx0cmVzdWx0QXJyYXkucHVzaCggZGF0ZXNbMV0gKTtcblxuXHRcdHJldHVybiByZXN1bHRBcnJheTtcblx0fVxuXG5cdGJhc2VWaWV3U3ViVGFiR3JpZFJlc2l6ZSggaWQgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpczs7XG5cblx0XHRpZiAoICFpZCApIHtcblx0XHRcdGlkID0gJy5lZGl0LXZpZXctdGFiLW91dHNpZGUtc3ViLXZpZXcnO1xuXHRcdH0gZWxzZSBpZiAoIGlkLmluZGV4T2YoICcjJyApID09PSAtMSAmJiBpZC5pbmRleE9mKCAnLicgKSAhPSAwICkge1xuXHRcdFx0aWQgPSAnIycgKyBpZDtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuZ3JpZC5ncmlkLnBhcmVudHMoIGlkICkubGVuZ3RoID4gMCApIHtcblxuXHRcdFx0dmFyIGhlaWdodCA9IE1hdGguZmxvb3IoIHRoaXMuZ2V0QXZhaWxhYmxlSGVpZ2h0Rm9yR3JpZCggaWQgKSApO1xuXG5cdFx0XHR0aGlzLmdyaWQuc2V0dXAuY29udGFpbmVyX3NlbGVjdG9yID0gaWQ7XG5cblx0XHRcdERlYnVnLlRleHQoICdTcGVjaWFsIFN1YlZpZXcgSUQ6ICcgKyBpZCArICcgSGVpZ2h0OiAnICsgaGVpZ2h0ICsgJyBPZmZzZXQ6ICcgKyBvZmZzZXQsICdUVEdyaWQuanMnLCAnVFRHcmlkJywgJ2Jhc2VWaWV3U3ViVGFiR3JpZFJlc2l6ZScsIDEwICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBvZmZzZXQgPSB0aGlzLmdldERlZmF1bHRIZWlnaHRPZmZzZXQoKTtcblx0XHRcdHZhciBoZWlnaHQgPSAoIHRoaXMuZ3JpZC5ncmlkLnBhcmVudHMoICcuZWRpdC12aWV3LXRhYicgKS5pbm5lckhlaWdodCgpIC0gb2Zmc2V0ICk7XG5cblx0XHRcdERlYnVnLlRleHQoICdOb3JtYWwgU3ViVmlldyBJRDogJyArIGlkICsgJyBIZWlnaHQ6ICcgKyBoZWlnaHQgKyAnIE9mZnNldDogJyArIG9mZnNldCwgJ1RUR3JpZC5qcycsICdUVEdyaWQnLCAnYmFzZVZpZXdTdWJUYWJHcmlkUmVzaXplJywgMTAgKTtcblx0XHR9XG5cblx0XHRpZiAoIGhlaWdodCA8IDI1MCApIHtcblx0XHRcdGhlaWdodCA9IDI1MDtcblx0XHR9XG5cblx0XHR0aGlzLnNldEdyaWRIZWlnaHQoIGhlaWdodCApO1xuXHRcdHRoaXMuc2V0R3JpZFdpZHRoKCk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgZ3JpZCdzIGhlaWdodC5cblx0ICogQHBhcmFtIHVpX2lkXG5cdCAqIEBwYXJhbSBzdWJfdmlld19tb2RlXG5cdCAqIEBwYXJhbSBzdWJfdmlld19ncmlkX2F1dG9zaXplXG5cdCAqIEBwYXJhbSBwYWdlcl9kYXRhXG5cdCAqL1xuXHRzZXRHcmlkU2l6ZSggdWlfaWQsIHN1Yl92aWV3X21vZGUsIHN1Yl92aWV3X2dyaWRfYXV0b3NpemUsIHBhZ2VyX2RhdGEgKSB7XG5cdFx0dmFyICR0aGlzID0gdGhpcztcblx0XHRpZiAoIHRoaXMuZ3JpZCAmJiB0aGlzLmdyaWQuc2V0dXAgJiYgdGhpcy5ncmlkLnNldHVwLnNldEdyaWRTaXplICYmIHR5cGVvZiB0aGlzLmdyaWQuc2V0dXAuc2V0R3JpZFNpemUgPT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdHRoaXMuZ3JpZC5zZXR1cC5zZXRHcmlkU2l6ZSgpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggKCAhdWlfaWQgJiYgIXRoaXMudWlfaWQgKSB8fCAhdGhpcy5ncmlkICkge1xuXHRcdFx0RGVidWcuVGV4dCggJ0VSUk9SOiBZb3UgbXVzdCBwcm92aWRlIGF0IGxlYXN0IGEgdWlfaWQgZm9yIHNldEdyaWRTaXplKCknLCAnVFRHcmlkLmpzJywgJ1RUR3JpZCcsICdzZXRHcmlkU2l6ZScsIDEwICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCAhdWlfaWQgJiYgdGhpcy51aV9pZCApIHtcblx0XHRcdHVpX2lkID0gdGhpcy51aV9pZDtcblx0XHR9XG5cblx0XHRpZiAoICFzdWJfdmlld19tb2RlICYmIHRoaXMuc3ViX3ZpZXdfbW9kZSApIHtcblx0XHRcdHN1Yl92aWV3X21vZGUgPSB0aGlzLnN1Yl92aWV3X21vZGU7XG5cdFx0fVxuXG5cdFx0aWYgKCAhc3ViX3ZpZXdfZ3JpZF9hdXRvc2l6ZSAmJiB0aGlzLnN1Yl92aWV3X2dyaWRfYXV0b3NpemUgKSB7XG5cdFx0XHRzdWJfdmlld19ncmlkX2F1dG9zaXplID0gdGhpcy5zdWJfdmlld19ncmlkX2F1dG9zaXplO1xuXHRcdH1cblxuXHRcdC8vdGhpcy5zZXRHcmlkV2lkdGggKCB0aGlzLnNldEdyaWRDb2x1bW5zV2lkdGgoKSApO1xuXG5cdFx0dmFyIGhlaWdodCA9IDEwMDtcblxuXHRcdGlmICggc3ViX3ZpZXdfbW9kZSAmJlxuXHRcdFx0dGhpcy5ncmlkLmdyaWQucGFyZW50cyggJy5ncmlkLWRpdicgKS5maW5kKCAnLm5vLXJlc3VsdC1kaXY6dmlzaWJsZScgKS5sZW5ndGggPiAwICYmXG5cdFx0XHR0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnI3RhYl9oaXN0b3J5LCAjdGFiX3F1YWxpZmljYXRpb25zJyApLmxlbmd0aCA+IDBcblx0XHQpIHtcblx0XHRcdGhlaWdodCA9IDEwMDtcblx0XHR9IGVsc2UgaWYgKCB0aGlzLmdyaWQuc2V0dXAuc3RhdGljX2hlaWdodCApIHtcblx0XHRcdGhlaWdodCA9IHRoaXMuZ3JpZC5zZXR1cC5zdGF0aWNfaGVpZ2h0O1xuXHRcdH0gZWxzZSBpZiAoIHRoaXMuZ3JpZC5zZXR1cC52ZXJ0aWNhbFJlc2l6ZSAmJiB0aGlzLmdyaWQuc2V0dXAudmVydGljYWxSZXNpemUgPT09IHRydWUgKSB7XG5cdFx0XHRpZiAoIHN1Yl92aWV3X21vZGUgKSB7XG5cdFx0XHRcdGlmICggdGhpcy5ncmlkLmdyaWQucGFyZW50cyggJy5lZGl0LXZpZXctdGFiLW91dHNpZGUtc3ViLXZpZXcnICkuZmluZCggJy5jb250ZXh0LWJvcmRlcicgKS5sZW5ndGggPiAxIHx8IHRoaXMuZ3JpZC5ncmlkLnBhcmVudHMoICcuZWRpdC12aWV3LXRhYi1vdXRzaWRlLXN1Yi12aWV3JyApLmZpbmQoICcudWktanFncmlkLWh0YWJsZScgKS5sZW5ndGggPiAxICkge1xuXHRcdFx0XHRcdC8vVGhpcyB0YWIgaGFzIG11bHRpcGxlIGdyaWRzIG9yIHN1YiB2aWV3cy5cblx0XHRcdFx0XHQvL1RhYnMgbGlrZSB0aGlzIGFyZSBcIkVtcGxveWVlIC0+IEVkaXQgRW1wbG95ZWUgLT4gUXVhbGlmaWNhdGlvbnNcIiBvciBSZWNydWl0bWVudCAtPiBKb2IgQXBwbGljYW50IEhpc3RvcnkgYW5kIFF1YWxpZmljYXRpb24gdGFiIHdpdGggbXVsdGlwbGUgZ3JpZHMuXG5cblx0XHRcdFx0XHRsZXQgbGVuZ3RoID0gdGhpcy5ncmlkLmdldFJlY29yZENvdW50KCk7XG5cdFx0XHRcdFx0bGV0IGNlbGxfaGVpZ2h0ID0gdGhpcy5ncmlkLmdyaWQuZmluZCggJ3RyOmxhc3QgdGQ6Zmlyc3QnICkuaGVpZ2h0KCk7XG5cblx0XHRcdFx0XHRpZiAoIGNlbGxfaGVpZ2h0IDwgMTggKSB7IC8vSWYgY2Fubm90IGRldGVybWluZSBjZWxsIGhlaWdodCwgdXNlIGRlZmF1bHQgb2YgMjIuXG5cdFx0XHRcdFx0XHRjZWxsX2hlaWdodCA9IDIyO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vR3JpZCBoZWlnaHQgaXMgYmV0d2VlbiAzIGFuZCA2IHJvd3MuIE5vdGhpbmcgdG9vIHNtYWxsIG9yIHRhbGwgc28gdGhhdCBhbGwgZ3JpZHMgY2FuIGJlIHZpZXdlZCBlYXNpbHlcblx0XHRcdFx0XHRsZXQgcm93c190b19zaG93ID0gMztcblx0XHRcdFx0XHRpZiAoIGxlbmd0aCA+IDYgKSB7XG5cdFx0XHRcdFx0XHRyb3dzX3RvX3Nob3cgPSA2O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCBsZW5ndGggPiAzICkge1xuXHRcdFx0XHRcdFx0cm93c190b19zaG93ID0gbGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB9XG5cblx0XHRcdFx0XHRoZWlnaHQgPSAoIHJvd3NfdG9fc2hvdyAqIGNlbGxfaGVpZ2h0ICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly9Ob3JtYWwgc2luZ2xlIGdyaWQgc3ViIHZpZXcuXG5cdFx0XHRcdFx0aWYgKCB0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnLmVkaXQtdmlldy10YWItb3V0c2lkZS1zdWItdmlldycgKSAmJiB0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnLmVkaXQtdmlldy10YWItb3V0c2lkZS1zdWItdmlldycgKS5sZW5ndGggPiAwICYmIHRoaXMuZ3JpZC5ncmlkLnBhcmVudHMoICcuZWRpdC12aWV3LXRhYi1vdXRzaWRlLXN1Yi12aWV3JyApWzBdICkge1xuXHRcdFx0XHRcdFx0aGVpZ2h0ID0gdGhpcy5nZXRBdmFpbGFibGVIZWlnaHRGb3JHcmlkKCB0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnLmVkaXQtdmlldy10YWItb3V0c2lkZS1zdWItdmlldycgKVswXS5pZCApO1xuXG5cdFx0XHRcdFx0XHRsZXQgY2hpbGRfY29udGV4dF9ib3JkZXIgPSB0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnLmVkaXQtdmlldy10YWItb3V0c2lkZS1zdWItdmlldycgKS5maW5kKCAnLmNvbnRleHQtYm9yZGVyJyApO1xuXHRcdFx0XHRcdFx0aWYgKCBjaGlsZF9jb250ZXh0X2JvcmRlci5sZW5ndGggIT09IDAgKSB7XG5cdFx0XHRcdFx0XHRcdC8vQWRqdXN0IGhlaWdodCBieSBtYXJnaW5zIG9mIHRoZSBjb250ZXh0IGJvcmRlci5cblx0XHRcdFx0XHRcdFx0aGVpZ2h0IC09ICggY2hpbGRfY29udGV4dF9ib3JkZXIub3V0ZXJIZWlnaHQoIHRydWUgKSAtIGNoaWxkX2NvbnRleHRfYm9yZGVyLmlubmVySGVpZ2h0KCkgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGhlaWdodCA9IHRoaXMuZ2V0QXZhaWxhYmxlSGVpZ2h0Rm9yR3JpZCggdWlfaWQgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvL0Vuc3VyZSBncmlkIGhhcyBhIG1pbmltdW0gaGVpZ2h0LlxuXHRcdGlmICggaGVpZ2h0IDwgMTAwICkge1xuXHRcdFx0aGVpZ2h0ID0gMTAwO1xuXHRcdH1cblxuXHRcdHRoaXMuZ3JpZC5ncmlkLnNldEdyaWRIZWlnaHQoIGhlaWdodCApO1xuXG5cdFx0Ly90aGlzIGxvb2tzIG9kZCwgYnV0IGNzcyBkb2VzIG5vdCBoYXZlIGEgaGFzIHNlbGVjdG9yLlxuXHRcdCQoICcuc3ViLXZpZXcgLmJvdHRvbS1kaXY6aGFzKC5wYWdpbmctMi1kaXY6dmlzaWJsZSknICkuY3NzKCAnaGVpZ2h0JywgJzIwcHgnICk7XG5cdFx0JCggJy5zdWItdmlldyAuYm90dG9tLWRpdjpoYXMoLnBhZ2luZy0yLWRpdjpoaWRkZW4pJyApLmNzcyggJ2hlaWdodCcsICdhdXRvJyApO1xuXHRcdC8vdGhpcy5yZWxvYWRHcmlkKCk7IC8vc2xvd3MgZG93biBhd2Vzb21lYm94ZXNcblx0fVxuXG5cdGdldEF2YWlsYWJsZUhlaWdodEZvckdyaWQoIGVsZW1lbnRfaWQsIG9mZnNldCApIHtcblx0XHQvL1RoZSBhdmFpbGFibGUgaGVpZ2h0IGZvciB0aGUgdGFibGUgaXMgdGhlIHZpZXcgaGVpZ2h0IG1pbnVzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdG9wIG9mIHZpZXcgYW5kIGJvdHRvbSBvZiB0YWJsZSBoZWFkZXIuXG5cdFx0aWYgKCBlbGVtZW50X2lkLmluZGV4T2YoICcjJyApID09PSAtMSAmJiBlbGVtZW50X2lkLmluZGV4T2YoICcuJyApICE9IDAgKSB7XG5cdFx0XHRlbGVtZW50X2lkID0gJyMnICsgZWxlbWVudF9pZDtcblx0XHR9XG5cdFx0bGV0IHRhYmxlX2hlYWRlciA9ICQoIGVsZW1lbnRfaWQgKS5maW5kKCAnI2dib3hfJyArIHRoaXMuZ3JpZC5nZXRHcmlkSWQoKSArICcgLnVpLWpxZ3JpZC1sYWJlbHMnICk7XG5cdFx0aWYgKCB0YWJsZV9oZWFkZXIubGVuZ3RoID09PSAwICkge1xuXHRcdFx0Ly9Jc3N1ZSAjMzEyMCAtIENlcnRhaW4gc3ViIHZpZXdzIGhhdmUgZ3JpZCBpbiBhIGRpZmZlcmVudCBwYXJ0IG9mIHRoZSBET00uXG5cdFx0XHQvL05lZWQgdG8gbWFrZSBzdXJlIHRvIGNoZWNrIGZvciB0aGF0IGVsc2UgdGhlIGdyaWQgd2lsbCBiZSBnaXZlbiBhbiBpbmNvcnJlY3Qgb3IgMCBoZWlnaHQ7XG5cdFx0XHR0YWJsZV9oZWFkZXIgPSAkKCAnI2dib3hfJyArIHRoaXMuZ3JpZC5nZXRHcmlkSWQoKSArICcgLnVpLWpxZ3JpZC1sYWJlbHMnICk7XG5cdFx0XHRpZiAoIHRhYmxlX2hlYWRlci5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHRcdHJldHVybiAxMDA7IC8vRGVmYXVsdCBoZWlnaHQuXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0bGV0IGNvbnRhaW5lcl9oZWlnaHQgPSAgJCggZWxlbWVudF9pZCApLmNoaWxkcmVuKCcuY29udGV4dC1ib3JkZXInKS5sZW5ndGggIT09IDAgPyAkKCBlbGVtZW50X2lkICkuY2hpbGRyZW4oJy5jb250ZXh0LWJvcmRlcicpLmlubmVySGVpZ2h0KCkgOiAkKCBlbGVtZW50X2lkICkuaGVpZ2h0KCk7XG5cdFx0bGV0IGhlaWdodCA9IGNvbnRhaW5lcl9oZWlnaHQgLSAoICggdGFibGVfaGVhZGVyLm9mZnNldCgpLnRvcCArIHRhYmxlX2hlYWRlci5oZWlnaHQoKSApIC0gJCggZWxlbWVudF9pZCApLm9mZnNldCgpLnRvcCApO1xuXG5cdFx0Ly9DaGVjayBpZiB2aWV3IGhhcyBhIHBhZ2luZyAvIGJvdHRvbSBkaXYgYW5kIGFkanVzdCBncmlkIGhlaWdodCBhY2NvcmRpbmdseS5cblx0XHRsZXQgYm90dG9tX2RpdiA9ICQoIGVsZW1lbnRfaWQgKS5maW5kKCAnLmJvdHRvbS1kaXYnICk7XG5cdFx0aWYgKCBib3R0b21fZGl2Lmxlbmd0aCA+IDAgJiYgYm90dG9tX2Rpdi5pcyhcIjp2aXNpYmxlXCIpICkge1xuICAgICAgICAgICAgaGVpZ2h0IC09IDUwO1xuICAgICAgICB9XG5cblx0XHRpZiAoIEdsb2JhbC5pc0hvcml6b250YWxTY3JvbGxCYXJSZXF1aXJlZCggJCggJyNnYm94XycgKyB0aGlzLmdyaWQuZ2V0R3JpZElkKCkgKVswXSApICkgeyAvL3Bhc3MgZG9tIGVsZW1lbnQgbm90IGpxdWVyeSBvYmplY3Rcblx0XHRcdGhlaWdodCAtPSBHbG9iYWwuZ2V0U2Nyb2xsYmFySGVpZ2h0KCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGhlaWdodDtcblx0fVxuXG5cdGdldERlZmF1bHRIZWlnaHRPZmZzZXQoKSB7XG5cdFx0Ly9wcm90ZWN0IGFnYWluc3QgTmFOc1xuXG5cdFx0dmFyIG9mZnNldCA9IHRoaXMuZ3JpZC5ncmlkLnBhcmVudHMoICcudWktanFncmlkLWpxdWVyeS11aScgKS5maW5kKCAnLnVpLWpxZ3JpZC1oYm94JyApLmhlaWdodCgpIC0gMjI7IC8vIDIyIGlzIGRlZmF1bHQgY2VsbCBoZWlnaHQuIHdlIGp1c3Qgd2FudCB0aGUgb3ZlcmFnZSBoZXJlLlxuXHRcdERlYnVnLlRleHQoICdJbml0aWFsIG9mZnNldDogJyArIG9mZnNldCwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZ2V0RGVmYXVsdEhlaWdodE9mZnNldCcsIDEwICk7XG5cblx0XHQvL2dldHRpbmcgdGhlc2Ugc2VsZWN0b3JzIHJpZ2h0IGZvciBldmVyeSBncmlkIHdhcyBhIGxvdCBvZiB0cmlhbCBhbmQgZXJyb3IuXG5cdFx0aWYgKCB0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnLnVpLWpxZ3JpZC1iZGl2JyApLndpZHRoKCkgPiB0aGlzLmdyaWQuZ3JpZC5wYXJlbnRzKCAnLnVpLWpxZ3JpZC1qcXVlcnktdWknICkud2lkdGgoKSApIHtcblx0XHRcdG9mZnNldCArPSAxNTsgLy9zY3JvbGxiYXIgb2Zmc2V0XG5cdFx0XHREZWJ1Zy5UZXh0KCAnU2Nyb2xsYmFyIG9mZnNldCBkZXRlY3RlZDogMTUnLCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXREZWZhdWx0SGVpZ2h0T2Zmc2V0JywgMTAgKTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMuc2VhcmNoX3BhbmVsICYmIHRoaXMuc2VhcmNoX3BhbmVsLmlzKCAnOnZpc2libGUnICkgPT0gdHJ1ZSApIHtcblx0XHRcdG9mZnNldCArPSB0aGlzLnNlYXJjaF9wYW5lbC5oZWlnaHQoKTtcblx0XHRcdERlYnVnLlRleHQoICdTZWFyY2ggcGFuZWwgZGV0ZWN0ZWQ6ICcgKyB0aGlzLnNlYXJjaF9wYW5lbC5oZWlnaHQoKSwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZ2V0RGVmYXVsdEhlaWdodE9mZnNldCcsIDEwICk7XG5cdFx0fVxuXG5cdFx0dmFyIHRvdGFsX251bWJlcl9kaXZfaGVpZ2h0ID0gKCAkKCAnLnRvdGFsLW51bWJlci1kaXY6dmlzaWJsZScgKS5sZW5ndGggPiAwICkgPyAkKCAnLnRvdGFsLW51bWJlci1kaXY6dmlzaWJsZScgKS5oZWlnaHQoKSA6IDA7XG5cdFx0aWYgKCB0b3RhbF9udW1iZXJfZGl2X2hlaWdodCB8fCB0b3RhbF9udW1iZXJfZGl2X2hlaWdodCA9PT0gMCApIHtcblx0XHRcdG9mZnNldCArPSB0b3RhbF9udW1iZXJfZGl2X2hlaWdodDtcblx0XHRcdERlYnVnLlRleHQoICdUb3RhbCBudW1iZXIgRElWIGhlaWdodCBvZmZzZXQgZGV0ZWN0ZWQ6ICcgKyAkKCAnLnRvdGFsLW51bWJlci1kaXY6dmlzaWJsZScgKS5oZWlnaHQoKSwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZ2V0RGVmYXVsdEhlaWdodE9mZnNldCcsIDEwICk7XG5cdFx0fVxuXG5cdFx0dmFyIGZvb3Rlcl9oZWlnaHQgPSAkKCAnLmJvdHRvbS1kaXYnICkuaGVpZ2h0KCkgKyA1O1xuXHRcdGlmICggZm9vdGVyX2hlaWdodCB8fCBmb290ZXJfaGVpZ2h0ID09PSAwICkge1xuXHRcdFx0b2Zmc2V0ICs9IGZvb3Rlcl9oZWlnaHQ7XG5cdFx0XHREZWJ1Zy5UZXh0KCAnRm9vdGVyIGhlaWdodCBvZmZzZXQgZGV0ZWN0ZWQ6ICcgKyBmb290ZXJfaGVpZ2h0LCAnQmFzZVZpZXdDb250cm9sbGVyLmpzJywgJ0Jhc2VWaWV3Q29udHJvbGxlcicsICdnZXREZWZhdWx0SGVpZ2h0T2Zmc2V0JywgMTAgKTtcblx0XHR9XG5cblx0XHR2YXIgcmVkX2JvcmRlcl9oZWlnaHQgPSAkKCAnLmdyaWQtdG9wLWJvcmRlcicgKS5oZWlnaHQoKSAqIDI7XG5cdFx0aWYgKCByZWRfYm9yZGVyX2hlaWdodCB8fCByZWRfYm9yZGVyX2hlaWdodCA9PT0gMCApIHtcblx0XHRcdG9mZnNldCArPSByZWRfYm9yZGVyX2hlaWdodDtcblx0XHRcdERlYnVnLlRleHQoICdSZWQgYm9yZGVyIGhlaWdodCBvZmZzZXQgZGV0ZWN0ZWQ6ICcgKyByZWRfYm9yZGVyX2hlaWdodCwgJ0Jhc2VWaWV3Q29udHJvbGxlci5qcycsICdCYXNlVmlld0NvbnRyb2xsZXInLCAnZ2V0RGVmYXVsdEhlaWdodE9mZnNldCcsIDEwICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG9mZnNldDtcblx0fVxuXG5cdGZpbGxDdXJyZW50UmVjb3JkKCkge1xuXHRcdC8vIE92ZXJyaWRlcyBmb3JtIHdpdGggZGF0YSBmcm9tIHB1c2ggbm90aWZpY2F0aW9uIGFuZCBodHRwIGdldCB2YXJpYWJsZXMuXG5cdFx0aWYgKCBMb2NhbENhY2hlRGF0YS5nZXRBdXRvRmlsbERhdGEoKSApIHtcblx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCA9IE9iamVjdC5hc3NpZ24oIHRoaXMuY3VycmVudF9lZGl0X3JlY29yZCwgdGhpcy5maWx0ZXJBdXRvRmlsbERhdGEoIExvY2FsQ2FjaGVEYXRhLmF1dG9fZmlsbF9kYXRhICkgKTtcblx0XHRcdExvY2FsQ2FjaGVEYXRhLnNldEF1dG9GaWxsRGF0YSggbnVsbCApO1xuXHRcdH1cblxuXHRcdC8vIEZpbHRlciBodHRwIGdldCB2YXJpYWJsZXMuXG5cdFx0dmFyIGZpbHRlcmVkX2F1dG9fZmlsbF9kYXRhID0gdGhpcy5maWx0ZXJBdXRvRmlsbERhdGEoIExvY2FsQ2FjaGVEYXRhLmFsbF91cmxfYXJncyApO1xuXG5cdFx0Ly8gUmVtb3ZlIGNvbW1vbiB2YXJpYWJsZXMgZnJvbSB1cmwgdG8gcHJldmVudCB1bmludGVuZGVkIG92ZXJyaWRlcy5cblx0XHRmb3IgKCB2YXIga2V5IGluIGZpbHRlcmVkX2F1dG9fZmlsbF9kYXRhICkge1xuXHRcdFx0aWYgKCBrZXkgPT09ICdzaWQnIHx8IGtleSA9PT0gJ20nIHx8IGtleSA9PT0gJ3NtJyB8fCBrZXkgPT09ICd0YWInICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdHRoaXMuY3VycmVudF9lZGl0X3JlY29yZFtrZXldID0gZmlsdGVyZWRfYXV0b19maWxsX2RhdGFba2V5XTtcblx0XHR9XG5cdH1cblxuXHRmaWx0ZXJBdXRvRmlsbERhdGEoIGF1dG9fZmlsbF9kYXRhICkge1xuXHRcdC8vIEF1dG8gZmlsbCB2YXJpYWJsZXMgb25seSBvdmVycmlkZSBkYXRhIGlmIHRoZSBmaWVsZCBleGlzdHMgb24gVUkuXG5cdFx0Ly8gSGVscHMgcHJldmVudCBpbnZpc2libGUgY2hhbmdlcyBpbiBjdXJyZW50X2VkaXRfcmVjb3JkIGZyb20gdXNlcnMgc2hhcmluZyBsaW5rcyB3aXRoIHB1cnBvc2UgdG8gdHJpY2svZXhwbG9pdC5cblxuXHRcdHZhciBmaWx0ZXJlZF9hdXRvX2ZpbGxfZGF0YSA9IHt9O1xuXHRcdGZvciAoIHZhciBrZXkgaW4gYXV0b19maWxsX2RhdGEgKSB7XG5cblx0XHRcdC8vIElnbm9yZSBwYXNzd29yZCBmaWVsZHNcblx0XHRcdGlmICgga2V5LmluY2x1ZGVzKCAncGFzc3dvcmQnICkgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRoaXMuZWRpdF92aWV3X3VpX2RpYy5oYXNPd25Qcm9wZXJ0eSgga2V5ICkgKSB7XG5cdFx0XHRcdGZpbHRlcmVkX2F1dG9fZmlsbF9kYXRhW2tleV0gPSBhdXRvX2ZpbGxfZGF0YVtrZXldO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZmlsdGVyZWRfYXV0b19maWxsX2RhdGE7XG5cdH1cblxuXHQvL0NvbXBhcmUgdHdvIGFycmF5cyBvZiByZWNvcmRzIGFuZCByZXR1cm4gYW4gYXJyYXkgb2YgcmVjb3JkcyB0aGF0IGNoYW5nZWQuXG5cdGdldENoYW5nZWRSZWNvcmRzKCBuZXdfZGF0YSwgb2xkX2RhdGEsIGlnbm9yZWRfa2V5cyApIHtcblx0XHRsZXQgY2hhbmdlZF9kYXRhID0gbmV3X2RhdGEuZmlsdGVyKCAoIHJlY29yZCApID0+IHtcblxuXHRcdFx0bGV0IG9sZF9yZWNvcmQgPSBvbGRfZGF0YS5maW5kKCAoIG9sZF9pdGVtICkgPT4gb2xkX2l0ZW0uaWQgPT0gcmVjb3JkLmlkICk7XG5cdFx0XHQvL0lmIHJlY29yZCBpZCBkb2VzIG5vdCBleGlzdCBpbiBvbGRfZGF0YSwgaXQgaXMgYSBuZXcgcmVjb3JkIGFuZCBzaG91bGQgYmUgbWFya2VkIGFzIGNoYW5nZWQuXG5cdFx0XHRpZiAoICFvbGRfcmVjb3JkICkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly9Db21wYXJlIGVhY2gga2V5IGZvciBjaGFuZ2VkIGRhdGEuIExvb3Agb3ZlciB0aGUga2V5cyBpbiB0aGUgY3VycmVudCByZWNvcmQgYW5kIG5vdCBvbGQgaW5jYXNlIGEgbmV3IGtleSB3YXMgYWRkZWQgdGhhdCBpcyBub3QgaW4gdGhlIG9sZCByZWNvcmQuXG5cdFx0XHRmb3IgKCBsZXQga2V5cyBpbiByZWNvcmQgKSB7XG5cdFx0XHRcdC8vU29tZSB2aWV3cyBhZGQgZXh0cmEgZGF0YSB0byB0aGUgcmVjb3JkIHdoaWNoIGlzIG9ubHkgdXNlZCBsb2NhbGx5IGFuZCBzaG91bGQgbm90IGJlIHVzZWQgZm9yIGNvbXBhcmlzb24uXG5cdFx0XHRcdGlmICggaWdub3JlZF9rZXlzLmxlbmd0aCA+IDAgJiYgaWdub3JlZF9rZXlzLmluY2x1ZGVzKCBrZXlzICkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly9JZiB0aGUgdmFsdWUgaXMgYW4gYXJyYXkgY2hlY2sgZWFjaCB2YWx1ZSBleGlzdHMgaW4gdGhlIG9sZCByZWNvcmQgYXJyYXkuXG5cdFx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggcmVjb3JkW2tleXNdICkgJiYgQXJyYXkuaXNBcnJheSggb2xkX3JlY29yZFtrZXlzXSApICkge1xuXHRcdFx0XHRcdC8vSWYgdGhlIGFycmF5cyBhcmUgZGlmZmVyZW50IGxlbmd0aHMsIHdlIGtub3cgdGhleSBhcmUgZGlmZmVyZW50LCBhbmQgZG8gbm90IG5lZWQgdG8gY2hlY2sgdGhlIHZhbHVlcy5cblx0XHRcdFx0XHRpZiAoIHJlY29yZFtrZXlzXS5sZW5ndGggIT09IG9sZF9yZWNvcmRba2V5c10ubGVuZ3RoIHx8ICFyZWNvcmRba2V5c10uZXZlcnkoIHZhbHVlID0+IG9sZF9yZWNvcmRba2V5c10uaW5jbHVkZXMoIHZhbHVlICkgKSApIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHQvL0NvbXBhcmUgdmFsdWVzIG9mIGVhY2gga2V5IGluIHRoZSByZWNvcmQuXG5cdFx0XHRcdGVsc2UgaWYgKCByZWNvcmRba2V5c10gIT0gb2xkX3JlY29yZFtrZXlzXSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH0gKTtcblxuXHRcdHJldHVybiBjaGFuZ2VkX2RhdGE7XG5cdH1cblxufVxuXG4vL0Rvbid0IGNoZWNrIHRoZSBmaWxlIGZvciBub3cuIFRvbyBtYW55IGlzc3Vlc1xuLyoganNoaW50IGlnbm9yZTplbmQgKi9cblxuQmFzZVZpZXdDb250cm9sbGVyLmxvYWRWaWV3ID0gZnVuY3Rpb24oIHZpZXdfaWQgKSB7XG5cblx0R2xvYmFsLmxvYWRWaWV3U291cmNlKCB2aWV3X2lkLCB2aWV3X2lkICsgJ1ZpZXcuaHRtbCcsIGZ1bmN0aW9uKCByZXN1bHQgKSB7XG5cblx0XHQvLyAjVnVlQ29udGV4dE1lbnUjIFZ1ZSByb3V0ZSBjaGFuZ2UsIHRoaXMgdHJpZ2dlcnMgdGhlIGNvbnRleHQgbWVudS5cblx0XHQvLyBUT0RPOiBCYXNlVmlld0NvbnRyb2xsZXIubG9hZFZpZXcgaXMgb3ZlcnJpZGVuIGluIG1hbnkgcGxhY2VzLiBBbHNvIG5lZWQgdG8gaGFuZGxlIHRob3NlLlxuXHRcdC8vIFdoaWNoIGlzIGJldHRlciwgaGVyZSBvciBpbiBJbmRleENvbnRyb2xsZXIub25WaWV3Q2hhbmdlPyBoZXJlIHdpbGwgY2F0Y2ggYWxsIGNoYW5nZXMgZnJvbSBoYXNoIHRvIGxvZ2luIHRvIGZpbmFsIHZpZXdjb250cm9sbGVyLiB3aWxsIG9uVmlld0NoYW5nZSBjYXRjaCB0aGF0IHRvbz9cblx0XHQvLyBjb25zb2xlLmxvZygnYWFhYSBCYXNlVi5sb2FkVmlldycsIHZpZXdfaWQpOyAvLyBjb21wYXJpbmcgdHJpZ2dlcnMgYWdhaW5zdCBJbmRleENvbnRyb2xsZXIuXG5cblx0XHQvLyBUT0RPOiBDYW4gd2Ugc2ltcGxpZnkgdGhpcyBhbmQgcmVtb3ZlIHRoZSBuZWVkcyBmb3IgcHJvcHM6dHJ1ZSBpbiByb3V0ZXI/XG5cdFx0Ly8gTm90ZTogVGhpcyBiZWhhdmlvdXIvcm91dGVyIGNhbGwgaXMgYWxzbyBpbiBJbmRleENvbnRyb2xsZXIub3BlblJlcG9ydCgpXG5cdFx0Ly8gVnVlUm91dGVyLnB1c2goJy92aWV3LycrJHRoaXMudmlld0lkKTtcblx0XHQvLyB3aW5kb3cuY29udGV4dF9tZW51c1sgdmlld19pZCBdICA9IG5ldyBDb250ZXh0TWVudU1hbmFnZXIoKTsgLy8gSW5pdGlhbGl6ZSBWdWUgQ29udGV4dE1lbnVNYW5hZ2VyIGhlcmUgc28gdGhhdCBlYWNoIHZpZXcgaGFzIHRoZWlyIG93biB1bmlxdWUgb25lLlxuXHRcdC8vIFZ1ZVJvdXRlci5wdXNoKHtcblx0XHQvLyBcdG5hbWU6ICd2aWV3Jyxcblx0XHQvLyBcdHBhcmFtczoge1xuXHRcdC8vIFx0XHR2aWV3SWQ6IHZpZXdfaWRcblx0XHQvLyBcdH1cblx0XHQvLyB9KS50aGVuKGZ1bmN0aW9uKCkge1xuXHRcdC8vIFx0ZG9OZXh0KCByZXN1bHQgKTtcblx0XHQvLyB9KTtcblx0XHRkb05leHQoIHJlc3VsdCApOyAvLyBOb3cgdXNpbmcgb25lIGdsb2JhbCBjb250ZXh0IG1lbnUsIHNvIG5vIG5lZWQgZm9yIHJvdXRlciBjYWxscy4gSnVzdCB1c2luZyB0aGUgb25lIHNpbmdsZSBMZWdhY3lWaWV3IGZvciBub3cuXG5cdH0gKTtcblxuXG5cdGZ1bmN0aW9uIGRvTmV4dCggcmVzdWx0ICkge1xuXHRcdHZhciBhcmdzID0ge307XG5cdFx0c3dpdGNoICggdmlld19pZCApIHtcblx0XHRcdGNhc2UgJ1RpbWVTaGVldCc6XG5cdFx0XHRcdEdsb2JhbC5sb2FkVmlld1NvdXJjZSggdmlld19pZCwgdmlld19pZCArICdWaWV3LmNzcycgKTtcblx0XHRcdFx0YXJncyA9IHtcblx0XHRcdFx0XHRhY2N1bXVsYXRlZF90aW1lOiAkLmkxOG4uXyggJ0FjY3VtdWxhdGVkIFRpbWUnICksXG5cdFx0XHRcdFx0dmVyaWZ5OiAkLmkxOG4uXyggJ1ZlcmlmeScgKSxcblx0XHRcdFx0XHR0aW1lc2hlZXRfdmVyaWZpY2F0aW9uOiAkLmkxOG4uXyggJ1RpbWVTaGVldCBWZXJpZmljYXRpb24nIClcblx0XHRcdFx0fTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdMb2dpbic6XG5cdFx0XHRcdCQoICdib2R5JyApLmFkZENsYXNzKCAnbG9naW4tYmcnICk7XG5cdFx0XHRcdCQoICdib2R5JyApLnJlbW92ZUNsYXNzKCAnYXBwbGljYXRpb24tYmcnICk7XG5cdFx0XHRcdC8vIEdsb2JhbC5sb2FkVmlld1NvdXJjZSggdmlld19pZCwgdmlld19pZCArICdWaWV3LmNzcycgKTsgLy8gIzI4MzMgTG9naW4gQ1NTIHdhcyBiZWluZyBsb2FkZWQgdHdpY2UuIE5vdyBvbmx5IGxvYWRlZCBpbiB0aGUgaW5kZXgucGhwIGZpbGUgZm9yIHNwZWVkLlxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ1BvcnRhbEpvYlZhY2FuY3lEZXRhaWwnOlxuXHRcdFx0XHRhcmdzID0ge1xuXHRcdFx0XHRcdHNlYXJjaF9sYWJlbDogJC5pMThuLl8oICdTZWFyY2gnIClcblx0XHRcdFx0fTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdQb3J0YWxKb2JWYWNhbmN5Jzpcblx0XHRcdFx0YXJncyA9IHtcblx0XHRcdFx0XHRzZWFyY2hfbGFiZWw6ICQuaTE4bi5fKCAnU2VhcmNoJyApLFxuXHRcdFx0XHRcdGxvYWRfbW9yZTogJC5pMThuLl8oICdMb2FkaW5nJyApICsgJy4uLidcblx0XHRcdFx0fTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdNeUpvYkFwcGxpY2F0aW9uJzpcblx0XHRcdGNhc2UgJ015UHJvZmlsZSc6XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnU2NoZWR1bGUnOlxuXHRcdFx0XHRHbG9iYWwubG9hZFZpZXdTb3VyY2UoIHZpZXdfaWQsIHZpZXdfaWQgKyAnVmlldy5jc3MnICk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblx0XHRJbmRleFZpZXdDb250cm9sbGVyLmluc3RhbmNlLnJvdXRlci5yZW1vdmVDdXJyZW50VmlldygpO1xuXHRcdHZhciB0ZW1wbGF0ZSA9IF8udGVtcGxhdGUoIHJlc3VsdCApO1xuXHRcdEdsb2JhbC5jb250ZW50Q29udGFpbmVyKCkuaHRtbCggdGVtcGxhdGUoIGFyZ3MgKSApO1xuXHRcdExvY2FsQ2FjaGVEYXRhLmN1cnJlbnRfb3Blbl92aWV3X2lkID0gdmlld19pZDtcblx0XHRHbG9iYWwudHJhY2tWaWV3KCB2aWV3X2lkLCBMb2NhbENhY2hlRGF0YS5jdXJyZW50X2RvaW5nX2NvbnRleHRfYWN0aW9uICk7XG5cdH1cblxufTtcblxuQmFzZVZpZXdDb250cm9sbGVyLmRlZmF1bHRfbGF5b3V0X25hbWUgPSAkLmkxOG4uXyggJy0tIERlZmF1bHQgLS0nICk7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///121\n")}}]);