import*as Common from"../../core/common/common.js";import*as i18n from"../../core/i18n/i18n.js";import*as Root from"../../core/root/root.js";import*as SDK from"../../core/sdk/sdk.js";import*as CodeMirror from"../../third_party/codemirror.next/codemirror.next.js";import*as TextEditor from"../../ui/components/text_editor/text_editor.js";import*as ObjectUI from"../../ui/legacy/components/object_ui/object_ui.js";import objectValueStyles from"../../ui/legacy/components/object_ui/objectValue.css.js";import*as UI from"../../ui/legacy/legacy.js";import consolePinPaneStyles from"./consolePinPane.css.js";const UIStrings={removeExpression:"Remove expression",removeAllExpressions:"Remove all expressions",removeExpressionS:"Remove expression: {PH1}",removeBlankExpression:"Remove blank expression",liveExpressionEditor:"Live expression editor",expression:"Expression",evaluateAllowingSideEffects:"Evaluate, allowing side effects",notAvailable:"not available"},str_=i18n.i18n.registerUIStrings("panels/console/ConsolePinPane.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_),elementToConsolePin=new WeakMap;export class ConsolePinPane extends UI.ThrottledWidget.ThrottledWidget{liveExpressionButton;focusOut;pins;pinsSetting;constructor(e,t){super(!0,250),this.liveExpressionButton=e,this.focusOut=t,this.contentElement.classList.add("console-pins","monospace"),this.contentElement.addEventListener("contextmenu",this.contextMenuEventFired.bind(this),!1),this.pins=new Set,this.pinsSetting=Common.Settings.Settings.instance().createLocalSetting("consolePins",[]);for(const e of this.pinsSetting.get())this.addPin(e)}wasShown(){super.wasShown(),this.registerCSSFiles([consolePinPaneStyles,objectValueStyles])}willHide(){for(const e of this.pins)e.setHovered(!1)}savePins(){const e=Array.from(this.pins).map((e=>e.expression()));this.pinsSetting.set(e)}contextMenuEventFired(e){const t=new UI.ContextMenu.ContextMenu(e),i=UI.UIUtils.deepElementFromEvent(e);if(i){const e=i.enclosingNodeOrSelfWithClass("console-pin");if(e){const i=elementToConsolePin.get(e);i&&(t.editSection().appendItem(i18nString(UIStrings.removeExpression),this.removePin.bind(this,i)),i.appendToContextMenu(t))}}t.editSection().appendItem(i18nString(UIStrings.removeAllExpressions),this.removeAllPins.bind(this)),t.show()}removeAllPins(){for(const e of this.pins)this.removePin(e)}removePin(e){e.element().remove();const t=this.focusedPinAfterDeletion(e);this.pins.delete(e),this.savePins(),t?t.focus():this.liveExpressionButton.focus()}addPin(e,t){const i=new ConsolePin(e,this,this.focusOut);this.contentElement.appendChild(i.element()),this.pins.add(i),this.savePins(),t&&i.focus(),this.update()}focusedPinAfterDeletion(e){const t=Array.from(this.pins);for(let i=0;i<t.length;i++)if(t[i]===e)return 1===t.length?null:i===t.length-1?t[i-1]:t[i+1];return null}async doUpdate(){if(!this.pins.size||!this.isShowing())return;this.isShowing()&&this.update();const e=Array.from(this.pins,(e=>e.updatePreview()));await Promise.all(e),this.updatedForTest()}updatedForTest(){}}export class ConsolePin{pinPane;focusOut;pinElement;pinPreview;lastResult;lastExecutionContext;editor;committedExpression;hovered;lastNode;deletePinIcon;constructor(e,t,i){this.pinPane=t,this.focusOut=i,this.deletePinIcon=document.createElement("div",{is:"dt-close-button"}),this.deletePinIcon.classList.add("close-button"),this.deletePinIcon.setTabbable(!0),e.length?this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeExpressionS,{PH1:e})):this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeBlankExpression)),self.onInvokeElement(this.deletePinIcon,(e=>{t.removePin(this),e.consume(!0)}));const s=UI.Fragment.Fragment.build`
  <div class='console-pin'>
  ${this.deletePinIcon}
  <div class='console-pin-name' $='name'></div>
  <div class='console-pin-preview' $='preview'></div>
  </div>`;this.pinElement=s.element(),this.pinPreview=s.$("preview");const n=s.$("name");UI.Tooltip.Tooltip.install(n,e),elementToConsolePin.set(this.pinElement,this),this.lastResult=null,this.lastExecutionContext=null,this.committedExpression=e,this.hovered=!1,this.lastNode=null,this.editor=this.createEditor(e,n),this.pinPreview.addEventListener("mouseenter",this.setHovered.bind(this,!0),!1),this.pinPreview.addEventListener("mouseleave",this.setHovered.bind(this,!1),!1),this.pinPreview.addEventListener("click",(e=>{this.lastNode&&(Common.Revealer.reveal(this.lastNode),e.consume())}),!1),n.addEventListener("keydown",(e=>{"Escape"===e.key&&e.consume()}))}createEditor(e,t){const i=[CodeMirror.EditorView.contentAttributes.of({"aria-label":i18nString(UIStrings.liveExpressionEditor)}),CodeMirror.EditorView.lineWrapping,CodeMirror.javascript.javascriptLanguage,TextEditor.Config.showCompletionHint,CodeMirror.placeholder(i18nString(UIStrings.expression)),CodeMirror.keymap.of([{key:"Escape",run:e=>(e.dispatch({changes:{from:0,to:e.state.doc.length,insert:this.committedExpression}}),this.focusOut(),!0)},{key:"Enter",run:()=>(this.focusOut(),!0)},{key:"Mod-Enter",run:()=>(this.focusOut(),!0)}]),CodeMirror.EditorView.domEventHandlers({blur:(e,t)=>this.onBlur(t)}),TextEditor.Config.baseConfiguration(e),TextEditor.Config.closeBrackets,TextEditor.Config.autocompletion.instance()];"true"!==Root.Runtime.Runtime.queryParam("noJavaScriptCompletion")&&i.push(TextEditor.JavaScript.completion());const s=new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({doc:e,extensions:i}));return t.appendChild(s),s}onBlur(e){const t=e.state.doc.toString(),i=t.trim();this.committedExpression=i,this.pinPane.savePins(),this.committedExpression.length?this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeExpressionS,{PH1:this.committedExpression})):this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeBlankExpression)),e.dispatch({selection:{anchor:i.length},changes:i!==t?{from:0,to:t.length,insert:i}:void 0})}setHovered(e){this.hovered!==e&&(this.hovered=e,!e&&this.lastNode&&SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight())}expression(){return this.committedExpression}element(){return this.pinElement}async focus(){const e=this.editor;e.editor.focus(),e.dispatch({selection:{anchor:e.state.doc.length}})}appendToContextMenu(e){this.lastResult&&!("error"in this.lastResult)&&this.lastResult.object&&(e.appendApplicableItems(this.lastResult.object),this.lastResult=null)}async updatePreview(){if(!this.editor)return;const e=TextEditor.Config.contentIncludingHint(this.editor.editor),t=this.pinElement.hasFocus(),i=t&&e!==this.committedExpression,s=i?250:void 0,n=UI.Context.Context.instance().flavor(SDK.RuntimeModel.ExecutionContext),{preview:o,result:r}=await ObjectUI.JavaScriptREPL.JavaScriptREPL.evaluateAndBuildPreview(e,i,!0,s,!t,"console",!0,!0);this.lastResult&&this.lastExecutionContext&&this.lastExecutionContext.runtimeModel.releaseEvaluationResult(this.lastResult),this.lastResult=r||null,this.lastExecutionContext=n||null;const l=o.deepTextContent();if(!l||l!==this.pinPreview.deepTextContent()){if(this.pinPreview.removeChildren(),r&&SDK.RuntimeModel.RuntimeModel.isSideEffectFailure(r)){const e=this.pinPreview.createChild("span","object-value-calculate-value-button");e.textContent="(…)",UI.Tooltip.Tooltip.install(e,i18nString(UIStrings.evaluateAllowingSideEffects))}else l?this.pinPreview.appendChild(o):t||UI.UIUtils.createTextChild(this.pinPreview,i18nString(UIStrings.notAvailable));UI.Tooltip.Tooltip.install(this.pinPreview,l)}let a=null;r&&!("error"in r)&&"object"===r.object.type&&"node"===r.object.subtype&&(a=r.object),this.hovered&&(a?SDK.OverlayModel.OverlayModel.highlightObjectAsDOMNode(a):this.lastNode&&SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight()),this.lastNode=a||null;const c=r&&!("error"in r)&&r.exceptionDetails&&!SDK.RuntimeModel.RuntimeModel.isSideEffectFailure(r);this.pinElement.classList.toggle("error-level",Boolean(c))}}