import{UIString,EventTarget,Revealer}from'../common/common.js';import{Diff}from'../diff/diff.js';import{Widget,TreeOutline,ARIAUtils,Icon,SplitWidget,EmptyWidget,Toolbar,ViewManager}from'../ui/ui.js';import{UISourceCode}from'../workspace/workspace.js';import{WorkspaceDiff}from'../workspace_diff/workspace_diff.js';import{ScriptSnippetFileSystem}from'../snippets/snippets.js';import{CodeMirrorTextEditor}from'../text_editor/text_editor.js';class ChangesSidebar extends Widget.Widget{constructor(workspaceDiff){super();this._treeoutline=new TreeOutline.TreeOutlineInShadow();this._treeoutline.setFocusable(false);this._treeoutline.registerRequiredCSS('changes/changesSidebar.css');this._treeoutline.setComparator((a,b)=>a.titleAsText().compareTo(b.titleAsText()));this._treeoutline.addEventListener(TreeOutline.Events.ElementSelected,this._selectionChanged,this);ARIAUtils.markAsTablist(this._treeoutline.contentElement);this.element.appendChild(this._treeoutline.element);this._treeElements=new Map();this._workspaceDiff=workspaceDiff;this._workspaceDiff.modifiedUISourceCodes().forEach(this._addUISourceCode.bind(this));this._workspaceDiff.addEventListener(WorkspaceDiff.Events.ModifiedStatusChanged,this._uiSourceCodeMofiedStatusChanged,this);}
selectUISourceCode(uiSourceCode,omitFocus){const treeElement=this._treeElements.get(uiSourceCode);if(!treeElement){return;}
treeElement.select(omitFocus);}
selectedUISourceCode(){return this._treeoutline.selectedTreeElement?this._treeoutline.selectedTreeElement.uiSourceCode:null;}
_selectionChanged(){this.dispatchEventToListeners(Events.SelectedUISourceCodeChanged);}
_uiSourceCodeMofiedStatusChanged(event){if(event.data.isModified){this._addUISourceCode(event.data.uiSourceCode);}else{this._removeUISourceCode(event.data.uiSourceCode);}}
_removeUISourceCode(uiSourceCode){const treeElement=this._treeElements.get(uiSourceCode);this._treeElements.delete(uiSourceCode);if(this._treeoutline.selectedTreeElement===treeElement){const nextElementToSelect=treeElement.previousSibling||treeElement.nextSibling;if(nextElementToSelect){nextElementToSelect.select(true);}else{treeElement.deselect();this._selectionChanged();}}
this._treeoutline.removeChild(treeElement);treeElement.dispose();if(this._treeoutline.rootElement().childCount()===0){this._treeoutline.setFocusable(false);}}
_addUISourceCode(uiSourceCode){const treeElement=new UISourceCodeTreeElement(uiSourceCode);this._treeElements.set(uiSourceCode,treeElement);this._treeoutline.setFocusable(true);this._treeoutline.appendChild(treeElement);if(!this._treeoutline.selectedTreeElement){treeElement.select(true);}}}
const Events={SelectedUISourceCodeChanged:Symbol('SelectedUISourceCodeChanged')};class UISourceCodeTreeElement extends TreeOutline.TreeElement{constructor(uiSourceCode){super();this.uiSourceCode=uiSourceCode;this.listItemElement.classList.add('navigator-'+uiSourceCode.contentType().name()+'-tree-item');ARIAUtils.markAsTab(this.listItemElement);let iconType='largeicon-navigator-file';if(ScriptSnippetFileSystem.isSnippetsUISourceCode(this.uiSourceCode)){iconType='largeicon-navigator-snippet';}
const defaultIcon=Icon.Icon.create(iconType,'icon');this.setLeadingIcons([defaultIcon]);this._eventListeners=[uiSourceCode.addEventListener(UISourceCode.Events.TitleChanged,this._updateTitle,this),uiSourceCode.addEventListener(UISourceCode.Events.WorkingCopyChanged,this._updateTitle,this),uiSourceCode.addEventListener(UISourceCode.Events.WorkingCopyCommitted,this._updateTitle,this)];this._updateTitle();}
_updateTitle(){let titleText=this.uiSourceCode.displayName();if(this.uiSourceCode.isDirty()){titleText='*'+titleText;}
this.title=titleText;let tooltip=this.uiSourceCode.url();if(this.uiSourceCode.contentType().isFromSourceMap()){tooltip=UIString.UIString('%s (from source map)',this.uiSourceCode.displayName());}
this.tooltip=tooltip;}
dispose(){EventTarget.EventTarget.removeEventListeners(this._eventListeners);}}
var ChangesSidebar$1=Object.freeze({__proto__:null,ChangesSidebar:ChangesSidebar,Events:Events,UISourceCodeTreeElement:UISourceCodeTreeElement});class ChangesTextEditor extends CodeMirrorTextEditor.CodeMirrorTextEditor{constructor(options){options.inputStyle='devToolsAccessibleDiffTextArea';super(options);this.codeMirror().setOption('gutters',['CodeMirror-linenumbers','changes-diff-gutter']);this.codeMirror().setOption('extraKeys',{Enter:false,Space:false,Left:function(cm){const scrollInfo=cm.getScrollInfo();if(scrollInfo.left>0){cm.scrollTo(scrollInfo.left-Math.round(scrollInfo.clientWidth/6),null);}},Right:function(cm){const scrollInfo=cm.getScrollInfo();cm.scrollTo(scrollInfo.left+Math.round(scrollInfo.clientWidth/6),null);}});}
updateDiffGutter(diffRows){this.codeMirror().eachLine(line=>{const lineNumber=this.codeMirror().getLineNumber(line);const row=diffRows[lineNumber];let gutterMarker;if(row.type===RowType.Deletion){gutterMarker=createElementWithClass('div','deletion changes-diff-gutter-marker');gutterMarker.textContent='-';}else if(row.type===RowType.Addition){gutterMarker=createElementWithClass('div','addition changes-diff-gutter-marker');gutterMarker.textContent='+';}
if(gutterMarker){this.codeMirror().setGutterMarker(line,'changes-diff-gutter',gutterMarker);}});}}
class DevToolsAccessibleDiffTextArea extends CodeMirror.inputStyles.devToolsAccessibleTextArea{reset(typing){super.reset(typing);if(this.textAreaBusy(!!typing)||!(typeof this.cm.doc.modeOption==='object')){return;}
const diffRows=this.cm.doc.modeOption.diffRows;const lineNumber=this.cm.getCursor().line;const rowType=diffRows[lineNumber].type;if(rowType===RowType.Deletion){this.textarea.value=ls`Deletion:${this.textarea.value}`;}
if(rowType===RowType.Addition){this.textarea.value=ls`Addition:${this.textarea.value}`;}
this.prevInput=this.textarea.value;}}
CodeMirror.inputStyles.devToolsAccessibleDiffTextArea=DevToolsAccessibleDiffTextArea;var ChangesTextEditor$1=Object.freeze({__proto__:null,ChangesTextEditor:ChangesTextEditor,DevToolsAccessibleDiffTextArea:DevToolsAccessibleDiffTextArea});class ChangesView extends Widget.VBox{constructor(){super(true);this.registerRequiredCSS('changes/changesView.css');const splitWidget=new SplitWidget.SplitWidget(true,false);const mainWidget=new Widget.Widget();splitWidget.setMainWidget(mainWidget);splitWidget.show(this.contentElement);this._emptyWidget=new EmptyWidget.EmptyWidget('');this._emptyWidget.show(mainWidget.element);this._workspaceDiff=WorkspaceDiff.workspaceDiff();this._changesSidebar=new ChangesSidebar(this._workspaceDiff);this._changesSidebar.addEventListener(Events.SelectedUISourceCodeChanged,this._selectedUISourceCodeChanged,this);splitWidget.setSidebarWidget(this._changesSidebar);this._selectedUISourceCode=null;this._diffRows=[];this._maxLineDigits=1;this._editor=new ChangesTextEditor({devtoolsAccessibleName:ls`Changes diff viewer`,lineNumbers:true,lineWrapping:false,maxHighlightLength:Infinity});this._editor.setReadOnly(true);const editorContainer=mainWidget.element.createChild('div','editor-container');ARIAUtils.markAsTabpanel(editorContainer);this._editor.show(editorContainer);this._editor.hideWidget();self.onInvokeElement(this._editor.element,this._click.bind(this));this._toolbar=new Toolbar.Toolbar('changes-toolbar',mainWidget.element);const revertButton=new Toolbar.ToolbarButton(ls`Revert all changes to current file`,'largeicon-undo');revertButton.addEventListener(Toolbar.ToolbarButton.Events.Click,this._revert.bind(this));this._toolbar.appendToolbarItem(revertButton);this._diffStats=new Toolbar.ToolbarText('');this._toolbar.appendToolbarItem(this._diffStats);this._toolbar.setEnabled(false);this._hideDiff(ls`No changes`);this._selectedUISourceCodeChanged();}
_selectedUISourceCodeChanged(){this._revealUISourceCode(this._changesSidebar.selectedUISourceCode());}
_revert(){const uiSourceCode=this._selectedUISourceCode;if(!uiSourceCode){return;}
this._workspaceDiff.revertToOriginal(uiSourceCode);}
_click(event){const selection=this._editor.selection();if(!selection.isEmpty()){return;}
const row=this._diffRows[selection.startLine];Revealer.reveal(this._selectedUISourceCode.uiLocation(row.currentLineNumber-1,selection.startColumn),false);event.consume(true);}
_revealUISourceCode(uiSourceCode){if(this._selectedUISourceCode===uiSourceCode){return;}
if(this._selectedUISourceCode){this._workspaceDiff.unsubscribeFromDiffChange(this._selectedUISourceCode,this._refreshDiff,this);}
if(uiSourceCode&&this.isShowing()){this._workspaceDiff.subscribeToDiffChange(uiSourceCode,this._refreshDiff,this);}
this._selectedUISourceCode=uiSourceCode;this._refreshDiff();}
wasShown(){this._refreshDiff();}
_refreshDiff(){if(!this.isShowing()){return;}
if(!this._selectedUISourceCode){this._renderDiffRows(null);return;}
const uiSourceCode=this._selectedUISourceCode;if(!uiSourceCode.contentType().isTextType()){this._hideDiff(ls`Binary data`);return;}
this._workspaceDiff.requestDiff(uiSourceCode).then(diff=>{if(this._selectedUISourceCode!==uiSourceCode){return;}
this._renderDiffRows(diff);});}
_hideDiff(message){this._diffStats.setText('');this._toolbar.setEnabled(false);this._editor.hideWidget();this._emptyWidget.text=message;this._emptyWidget.showWidget();}
_renderDiffRows(diff){this._diffRows=[];if(!diff||(diff.length===1&&diff[0][0]===Diff.Operation.Equal)){this._hideDiff(ls`No changes`);return;}
let insertions=0;let deletions=0;let currentLineNumber=0;let baselineLineNumber=0;const paddingLines=3;const originalLines=[];const currentLines=[];for(let i=0;i<diff.length;++i){const token=diff[i];switch(token[0]){case Diff.Operation.Equal:this._diffRows.push(...createEqualRows(token[1],i===0,i===diff.length-1));originalLines.push(...token[1]);currentLines.push(...token[1]);break;case Diff.Operation.Insert:for(const line of token[1]){this._diffRows.push(createRow(line,RowType.Addition));}
insertions+=token[1].length;currentLines.push(...token[1]);break;case Diff.Operation.Delete:deletions+=token[1].length;originalLines.push(...token[1]);if(diff[i+1]&&diff[i+1][0]===Diff.Operation.Insert){i++;this._diffRows.push(...createModifyRows(token[1].join('\n'),diff[i][1].join('\n')));insertions+=diff[i][1].length;currentLines.push(...diff[i][1]);}else{for(const line of token[1]){this._diffRows.push(createRow(line,RowType.Deletion));}}
break;}}
this._maxLineDigits=Math.ceil(Math.log10(Math.max(currentLineNumber,baselineLineNumber)));let insertionText='';if(insertions===1){insertionText=ls`${insertions} insertion (+),`;}else{insertionText=ls`${insertions} insertions (+),`;}
let deletionText='';if(deletions===1){deletionText=ls`${deletions} deletion (-)`;}else{deletionText=ls`${deletions} deletions (-)`;}
this._diffStats.setText(`${insertionText} ${deletionText}`);this._toolbar.setEnabled(true);this._emptyWidget.hideWidget();this._editor.operation(()=>{this._editor.showWidget();this._editor.setHighlightMode({name:'devtools-diff',diffRows:this._diffRows,mimeType:(this._selectedUISourceCode).mimeType(),baselineLines:originalLines,currentLines:currentLines});this._editor.setText(this._diffRows.map(row=>row.tokens.map(t=>t.text).join('')).join('\n'));this._editor.setLineNumberFormatter(this._lineFormatter.bind(this));this._editor.updateDiffGutter(this._diffRows);});function createEqualRows(lines,atStart,atEnd){const equalRows=[];if(!atStart){for(let i=0;i<paddingLines&&i<lines.length;i++){equalRows.push(createRow(lines[i],RowType.Equal));}
if(lines.length>paddingLines*2+1&&!atEnd){equalRows.push(createRow(UIString.UIString('( … Skipping %d matching lines … )',lines.length-paddingLines*2),RowType.Spacer));}}
if(!atEnd){const start=Math.max(lines.length-paddingLines-1,atStart?0:paddingLines);let skip=lines.length-paddingLines-1;if(!atStart){skip-=paddingLines;}
if(skip>0){baselineLineNumber+=skip;currentLineNumber+=skip;}
for(let i=start;i<lines.length;i++){equalRows.push(createRow(lines[i],RowType.Equal));}}
return equalRows;}
function createModifyRows(before,after){const internalDiff=Diff.DiffWrapper.charDiff(before,after,true);const deletionRows=[createRow('',RowType.Deletion)];const insertionRows=[createRow('',RowType.Addition)];for(const token of internalDiff){const text=token[1];const type=token[0];const className=type===Diff.Operation.Equal?'':'inner-diff';const lines=text.split('\n');for(let i=0;i<lines.length;i++){if(i>0&&type!==Diff.Operation.Insert){deletionRows.push(createRow('',RowType.Deletion));}
if(i>0&&type!==Diff.Operation.Delete){insertionRows.push(createRow('',RowType.Addition));}
if(!lines[i]){continue;}
if(type!==Diff.Operation.Insert){deletionRows[deletionRows.length-1].tokens.push({text:lines[i],className});}
if(type!==Diff.Operation.Delete){insertionRows[insertionRows.length-1].tokens.push({text:lines[i],className});}}}
return deletionRows.concat(insertionRows);}
function createRow(text,type){if(type===RowType.Addition){currentLineNumber++;}
if(type===RowType.Deletion){baselineLineNumber++;}
if(type===RowType.Equal){baselineLineNumber++;currentLineNumber++;}
return{baselineLineNumber,currentLineNumber,tokens:text?[{text,className:'inner-diff'}]:[],type};}}
_lineFormatter(lineNumber){const row=this._diffRows[lineNumber-1];let showBaseNumber=row.type===RowType.Deletion;let showCurrentNumber=row.type===RowType.Addition;if(row.type===RowType.Equal){showBaseNumber=true;showCurrentNumber=true;}
const base=showBaseNumber?numberToStringWithSpacesPadding(row.baselineLineNumber,this._maxLineDigits):spacesPadding(this._maxLineDigits);const current=showCurrentNumber?numberToStringWithSpacesPadding(row.currentLineNumber,this._maxLineDigits):spacesPadding(this._maxLineDigits);return base+spacesPadding(1)+current;}}
const RowType={Deletion:'deletion',Addition:'addition',Equal:'equal',Spacer:'spacer'};class DiffUILocationRevealer{async reveal(diffUILocation,omitFocus){if(!(diffUILocation instanceof WorkspaceDiff.DiffUILocation)){throw new Error('Internal error: not a diff ui location');}
const changesView=self.runtime.sharedInstance(ChangesView);await ViewManager.ViewManager.instance().showView('changes.changes');changesView._changesSidebar.selectUISourceCode(diffUILocation.uiSourceCode,omitFocus);}}
let Row;var ChangesView$1=Object.freeze({__proto__:null,ChangesView:ChangesView,RowType:RowType,DiffUILocationRevealer:DiffUILocationRevealer,Row:Row});function ChangesHighlighter(config,parserConfig){const diffRows=parserConfig.diffRows;const baselineLines=parserConfig.baselineLines;const currentLines=parserConfig.currentLines;const syntaxHighlightMode=CodeMirror.getMode({},parserConfig.mimeType);function fastForward(state,baselineLineNumber,currentLineNumber){if(baselineLineNumber>state.baselineLineNumber){fastForwardSyntaxHighlighter(state.baselineSyntaxState,state.baselineLineNumber,baselineLineNumber,baselineLines);state.baselineLineNumber=baselineLineNumber;}
if(currentLineNumber>state.currentLineNumber){fastForwardSyntaxHighlighter(state.currentSyntaxState,state.currentLineNumber,currentLineNumber,currentLines);state.currentLineNumber=currentLineNumber;}}
function fastForwardSyntaxHighlighter(syntaxState,from,to,lines){let lineNumber=from;while(lineNumber<to&&lineNumber<lines.length){const stream=new CodeMirror.StringStream(lines[lineNumber]);if(stream.eol()&&syntaxHighlightMode.blankLine){syntaxHighlightMode.blankLine(syntaxState);}
while(!stream.eol()){syntaxHighlightMode.token(stream,syntaxState);stream.start=stream.pos;}
lineNumber++;}}
return{startState:function(){return{rowNumber:0,diffTokenIndex:0,currentLineNumber:0,baselineLineNumber:0,currentSyntaxState:CodeMirror.startState(syntaxHighlightMode),baselineSyntaxState:CodeMirror.startState(syntaxHighlightMode),syntaxPosition:0,diffPosition:0,syntaxStyle:'',diffStyle:''};},token:function(stream,state){const diffRow=diffRows[state.rowNumber];if(!diffRow){stream.next();return'';}
fastForward(state,diffRow.baselineLineNumber-1,diffRow.currentLineNumber-1);let classes='';if(stream.pos===0){classes+=' line-background-'+diffRow.type+' line-'+diffRow.type;}
const syntaxHighlighterNeedsRefresh=state.diffPosition>=state.syntaxPosition;if(state.diffPosition<=state.syntaxPosition){state.diffPosition+=diffRow.tokens[state.diffTokenIndex].text.length;state.diffStyle=diffRow.tokens[state.diffTokenIndex].className;state.diffTokenIndex++;}
if(syntaxHighlighterNeedsRefresh){if(diffRow.type===RowType.Deletion||diffRow.type===RowType.Addition||diffRow.type===RowType.Equal){state.syntaxStyle=syntaxHighlightMode.token(stream,diffRow.type===RowType.Deletion?state.baselineSyntaxState:state.currentSyntaxState);state.syntaxPosition=stream.pos;}else{state.syntaxStyle='';state.syntaxPosition=Infinity;}}
stream.pos=Math.min(state.syntaxPosition,state.diffPosition);classes+=' '+state.syntaxStyle;classes+=' '+state.diffStyle;if(stream.eol()){state.rowNumber++;if(diffRow.type===RowType.Deletion){state.baselineLineNumber++;}else{state.currentLineNumber++;}
state.diffPosition=0;state.syntaxPosition=0;state.diffTokenIndex=0;}
return classes;},blankLine:function(state){const diffRow=diffRows[state.rowNumber];state.rowNumber++;state.syntaxPosition=0;state.diffPosition=0;state.diffTokenIndex=0;if(!diffRow){return'';}
let style='';if(syntaxHighlightMode.blankLine){if(diffRow.type===RowType.Equal||diffRow.type===RowType.Addition){style=syntaxHighlightMode.blankLine(state.currentSyntaxState);state.currentLineNumber++;}else if(diffRow.type===RowType.Deletion){style=syntaxHighlightMode.blankLine(state.baselineSyntaxState);state.baselineLineNumber++;}}
return style+' line-background-'+diffRow.type+' line-'+diffRow.type;},copyState:function(state){const newState=Object.assign({},state);newState.currentSyntaxState=CodeMirror.copyState(syntaxHighlightMode,state.currentSyntaxState);newState.baselineSyntaxState=CodeMirror.copyState(syntaxHighlightMode,state.baselineSyntaxState);return(newState);}};}
CodeMirror.defineMode('devtools-diff',ChangesHighlighter);let DiffState;var ChangesHighlighter$1=Object.freeze({__proto__:null,ChangesHighlighter:ChangesHighlighter,DiffState:DiffState});export{ChangesHighlighter$1 as ChangesHighlighter,ChangesSidebar$1 as ChangesSidebar,ChangesTextEditor$1 as ChangesTextEditor,ChangesView$1 as ChangesView};