import*as Common from"../common/common.js";import*as i18n from"../i18n/i18n.js";import*as Persistence from"../persistence/persistence.js";import*as SourceFrame from"../source_frame/source_frame.js";import*as Workspace from"../workspace/workspace.js";import*as WorkspaceDiff from"../workspace_diff/workspace_diff.js";import{Plugin}from"./Plugin.js";const UIStrings={localModifications:"Local Modifications..."},str_=i18n.i18n.registerUIStrings("sources/GutterDiffPlugin.js",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class GutterDiffPlugin extends Plugin{constructor(e,t){super(),this._textEditor=e,this._uiSourceCode=t,this._decorations=[],this._textEditor.installGutter(DiffGutterType,!0),this._workspaceDiff=WorkspaceDiff.WorkspaceDiff.workspaceDiff(),this._workspaceDiff.subscribeToDiffChange(this._uiSourceCode,this._update,this),this._update()}static accepts(e){return e.project().type()===Workspace.Workspace.projectTypes.Network}_updateDecorations(e,t){this._textEditor.operation((function(){for(const t of e)t.remove();for(const e of t)e.install()}))}_update(){this._uiSourceCode?this._workspaceDiff.requestDiff(this._uiSourceCode).then(this._innerUpdate.bind(this)):this._innerUpdate(null)}_innerUpdate(e){if(!e)return this._updateDecorations(this._decorations,[]),void(this._decorations=[]);const t=SourceFrame.SourceCodeDiff.SourceCodeDiff.computeDiff(e),o=new Map;for(let s=0;s<t.length;++s){const e=t[s];for(let t=e.from;t<e.to;++t)o.set(t,{lineNumber:t,type:e.type})}const i=this._calculateDecorationsDiff(o),r=i.added.map((e=>new GutterDecoration(this._textEditor,e.lineNumber,e.type)));this._decorations=i.equal.concat(r),this._updateDecorations(i.removed,r),this._decorationsSetForTest(o)}_decorationsByLine(){const e=new Map;for(const t of this._decorations){const o=t.lineNumber();-1!==o&&e.set(o,t)}return e}_calculateDecorationsDiff(e){const t=this._decorationsByLine(),o=[...t.keys()],i=[...e.keys()];o.sort(((e,t)=>e-t)),i.sort(((e,t)=>e-t));const r=[],s=[],n=[];let c=0,a=0;for(;c<o.length&&a<i.length;){const f=o[c],u=i[a],d=t.get(f),p=e.get(u);if(!d)throw new Error(`No decoration with key ${f}`);if(!p)throw new Error(`No decoration with key ${u}`);f===u&&d.type===p.type?(n.push(d),++c,++a):f<=u?(r.push(d),++c):(s.push(p),++a)}for(;c<o.length;){const e=o[c++],i=t.get(e);if(!i)throw new Error(`No decoration with key ${e}`);r.push(i)}for(;a<i.length;){const t=i[a++],o=e.get(t);if(!o)throw new Error(`No decoration with key ${t}`);s.push(o)}return{added:s,removed:r,equal:n}}_decorationsSetForTest(e){}async populateLineGutterContextMenu(e,t){GutterDiffPlugin._appendRevealDiffContextMenu(e,this._uiSourceCode)}async populateTextAreaContextMenu(e,t,o){GutterDiffPlugin._appendRevealDiffContextMenu(e,this._uiSourceCode)}static _appendRevealDiffContextMenu(e,t){WorkspaceDiff.WorkspaceDiff.workspaceDiff().isUISourceCodeModified(t)&&e.revealSection().appendItem(i18nString(UIStrings.localModifications),(()=>{Common.Revealer.reveal(new WorkspaceDiff.WorkspaceDiff.DiffUILocation(t))}))}dispose(){for(const e of this._decorations)e.remove();WorkspaceDiff.WorkspaceDiff.workspaceDiff().unsubscribeFromDiffChange(this._uiSourceCode,this._update,this)}}export class GutterDecoration{constructor(e,t,o){this._textEditor=e,this._position=this._textEditor.textEditorPositionHandle(t,0),this._className="",o===SourceFrame.SourceCodeDiff.EditType.Insert?this._className="diff-entry-insert":o===SourceFrame.SourceCodeDiff.EditType.Delete?this._className="diff-entry-delete":o===SourceFrame.SourceCodeDiff.EditType.Modify&&(this._className="diff-entry-modify"),this.type=o}lineNumber(){const e=this._position.resolve();return e?e.lineNumber:-1}install(){const e=this._position.resolve();if(!e)return;const t=document.createElement("div");t.classList.add("diff-marker"),t.textContent="\xa0",this._textEditor.setGutterDecoration(e.lineNumber,DiffGutterType,t),this._textEditor.toggleLineClass(e.lineNumber,this._className,!0)}remove(){const e=this._position.resolve();e&&(this._textEditor.setGutterDecoration(e.lineNumber,DiffGutterType,null),this._textEditor.toggleLineClass(e.lineNumber,this._className,!1))}}export const DiffGutterType="CodeMirror-gutter-diff";let contextMenuProviderInstance;export class ContextMenuProvider{static instance(e={forceNew:null}){const{forceNew:t}=e;return contextMenuProviderInstance&&!t||(contextMenuProviderInstance=new ContextMenuProvider),contextMenuProviderInstance}appendApplicableItems(e,t,o){let i=o;const r=Persistence.Persistence.PersistenceImpl.instance().binding(i);r&&(i=r.network),GutterDiffPlugin._appendRevealDiffContextMenu(t,i)}}