import { __decorate, __metadata } from "tslib";
import { isFilesystemReady } from '@codeblitzjs/ide-sumi-core';
import { InlineChatHandler } from '@opensumi/ide-ai-native/lib/browser/widget/inline-chat/inline-chat.handler';
import { AppConfig, ClientAppContribution, EDITOR_COMMANDS } from '@opensumi/ide-core-browser';
import { CommandContribution, Disposable, DisposableStore, Domain, Emitter, Event, ILogger, Sequencer, URI, } from '@opensumi/ide-core-common';
import { WorkbenchEditorService } from '@opensumi/ide-editor';
import { Selection, SelectionDirection } from '@opensumi/ide-monaco';
import { InlineDiffHandler } from '@opensumi/ide-ai-native/lib/browser/widget/inline-diff/inline-diff.handler';
import { EResultKind } from '@opensumi/ide-ai-native/lib/common';
import { IEditorDocumentModelService } from '@opensumi/ide-editor/lib/browser';
import { requireModule } from '../../../api/require';
import { Autowired } from '../../../modules/opensumi__common-di';
import { MenuContribution } from '../../../modules/opensumi__ide-core-browser';
import { IDiffViewerProps } from '../common';
import { removeStart } from '../utils';
const fse = requireModule('fs-extra');
const path = requireModule('path');
let DiffViewerContribution = class DiffViewerContribution {
    constructor() {
        this._disposables = new DisposableStore();
        this._onPartialEditEvent = this._disposables.add(new Emitter());
        this.onPartialEditEvent = this._onPartialEditEvent.event;
        this._onDidTabChange = this._disposables.add(new Emitter());
        this.onDidTabChange = this._onDidTabChange.event;
    }
    getFullPath(filePath) {
        return path.join(this.appConfig.workspaceDir, filePath);
    }
    stripDirectory(filePath) {
        const result = removeStart(filePath, this.appConfig.workspaceDir);
        if (result.startsWith('/')) {
            return result.slice(1);
        }
        return result;
    }
    async initialize(app) {
        await isFilesystemReady();
        const disposable = new Disposable();
        const openFileInTab = async (filePath, content, options) => {
            const fullPath = this.getFullPath(filePath);
            if (!fse.pathExistsSync(fullPath)) {
                fse.ensureFileSync(fullPath);
                fse.writeFileSync(fullPath, content);
            }
            const uri = URI.file(fullPath);
            return {
                uri,
                result: await this.workbenchEditorService.open(uri, options),
            };
        };
        const openDiffInTab = async (filePath, oldContent, newContent, options) => {
            const { uri, result: openResourceResult } = await openFileInTab(filePath, oldContent, Object.assign(Object.assign({}, options), { preview: false }));
            if (!openResourceResult) {
                throw new Error('Failed to open file in tab: ' + filePath);
            }
            const editor = openResourceResult.group.codeEditor;
            if (oldContent === newContent) {
                this.inlineDiffHandler.hidePreviewer(editor.monacoEditor);
                return;
            }
            const model = this.editorCollectionService.getModelReference(uri);
            if (!model || !model.instance) {
                throw new Error('Failed to get model reference: ' + filePath);
            }
            const monacoModel = model.instance.getMonacoModel();
            monacoModel.setValue(oldContent);
            const fullRange = monacoModel.getFullModelRange();
            const previewer = this.inlineDiffHandler.createDiffPreviewer(editor.monacoEditor, Selection.fromRange(fullRange, SelectionDirection.LTR), {
                disposeWhenEditorClosed: false,
            });
            const whenReady = Event.toPromise(previewer.getNode().onDidEditChange);
            previewer.setValue(newContent);
            await whenReady;
            previewer.layout();
            previewer.revealFirstDiff();
        };
        const getFilePathForEditor = (editor) => {
            return this.stripDirectory(editor.currentUri.codeUri.fsPath);
        };
        const getAllTabs = () => {
            const editorGroup = this.workbenchEditorService.editorGroups[0];
            const resources = editorGroup.resources;
            return resources.map((editor, idx) => ({
                index: idx,
                filePath: this.stripDirectory(editor.uri.codeUri.fsPath),
            }));
        };
        const getFileIndex = (filePath) => {
            const aPath = this.stripDirectory(filePath);
            return getAllTabs().findIndex((tab) => tab.filePath === aPath);
        };
        disposable.addDispose(this.inlineDiffHandler.onPartialEditEvent((e) => {
            const fsPath = e.uri.fsPath;
            this._onPartialEditEvent.fire(Object.assign({ filePath: this.stripDirectory(fsPath) }, e));
        }));
        disposable.addDispose(this.workbenchEditorService.onActiveResourceChange((e) => {
            const _newPath = e === null || e === void 0 ? void 0 : e.uri.codeUri.fsPath;
            let newPath = _newPath;
            let currentIndex = -1;
            if (newPath) {
                currentIndex = getFileIndex(newPath);
                newPath = this.stripDirectory(newPath);
            }
            this._onDidTabChange.fire({
                newPath,
                currentIndex,
            });
        }));
        const sequencer = new Sequencer();
        this.diffViewerProps.onRef({
            openDiffInTab: async (filePath, oldContent, newContent, options) => {
                await sequencer.queue(() => openDiffInTab(filePath, oldContent, newContent, options));
            },
            openFileInTab: async (filePath, content, options) => {
                const { uri } = await openFileInTab(filePath, content, options);
                return uri;
            },
            openTab: async (filePath, options) => {
                const fullPath = this.getFullPath(filePath);
                const uri = URI.file(fullPath);
                await this.workbenchEditorService.open(uri, Object.assign({}, options));
            },
            closeTab: async (filePath) => {
                await this.workbenchEditorService.close(URI.file(this.getFullPath(filePath)), false);
            },
            onPartialEditEvent: (cb) => {
                return this.onPartialEditEvent(cb);
            },
            getFileContent: async (filePath) => {
                const fullPath = this.getFullPath(filePath);
                return await fse.readFile(fullPath, 'utf-8');
            },
            acceptAllPartialEdit: async () => {
                if (this.inlineDiffHandler) {
                    this.inlineDiffHandler.handleAction(this.workbenchEditorService.currentEditor.monacoEditor, EResultKind.ACCEPT);
                }
            },
            rejectAllPartialEdit: async () => {
                if (this.inlineDiffHandler) {
                    this.inlineDiffHandler.handleAction(this.workbenchEditorService.currentEditor.monacoEditor, EResultKind.DISCARD);
                }
            },
            dispose: () => {
                disposable.dispose();
            },
            getCurrentTab: () => {
                const allTabs = getAllTabs();
                const currentEditorFilePath = getFilePathForEditor(this.workbenchEditorService.currentEditor);
                const currentTabIdx = allTabs.findIndex((tab) => {
                    return tab.filePath === currentEditorFilePath;
                });
                if (currentTabIdx === -1) {
                    return;
                }
                return {
                    index: currentTabIdx,
                    filePath: currentEditorFilePath,
                };
            },
            getTabAtIndex: (index) => {
                const allTabs = getAllTabs();
                return allTabs[index];
            },
            getAllTabs: () => {
                return getAllTabs();
            },
            closeAllTab: async () => {
                return this.workbenchEditorService.closeAll();
            },
            onDidTabChange: (cb) => {
                return this.onDidTabChange(cb);
            },
        });
    }
    registerCommands() {
    }
    registerMenus(registry) {
        registry.unregisterMenuItem('editor/title', EDITOR_COMMANDS.SPLIT_TO_RIGHT.id);
        registry.unregisterMenuItem('editor/title', EDITOR_COMMANDS.CLOSE_ALL_IN_GROUP.id);
    }
    dispose() {
        this._disposables.dispose();
    }
};
__decorate([
    Autowired(IDiffViewerProps),
    __metadata("design:type", Object)
], DiffViewerContribution.prototype, "diffViewerProps", void 0);
__decorate([
    Autowired(WorkbenchEditorService),
    __metadata("design:type", WorkbenchEditorService)
], DiffViewerContribution.prototype, "workbenchEditorService", void 0);
__decorate([
    Autowired(InlineChatHandler),
    __metadata("design:type", InlineChatHandler)
], DiffViewerContribution.prototype, "inlineChatHandler", void 0);
__decorate([
    Autowired(InlineDiffHandler),
    __metadata("design:type", InlineDiffHandler)
], DiffViewerContribution.prototype, "inlineDiffHandler", void 0);
__decorate([
    Autowired(IEditorDocumentModelService),
    __metadata("design:type", Object)
], DiffViewerContribution.prototype, "editorCollectionService", void 0);
__decorate([
    Autowired(AppConfig),
    __metadata("design:type", Object)
], DiffViewerContribution.prototype, "appConfig", void 0);
__decorate([
    Autowired(ILogger),
    __metadata("design:type", Object)
], DiffViewerContribution.prototype, "logger", void 0);
DiffViewerContribution = __decorate([
    Domain(CommandContribution, ClientAppContribution, MenuContribution)
], DiffViewerContribution);
export { DiffViewerContribution };
//# sourceMappingURL=base.js.map