import vscode, {
	Disposable,
	Event,
	EventEmitter,
	FileChangeEvent,
	FileChangeType,
	FileStat,
	FileSystemError,
	FileSystemProvider,
	FileType,
	Uri,
	workspace,
} from 'vscode';
import { CODING_MR_SCHEME } from '../common';
import { makeCommentRangeProvider, ReviewComment } from '../reviewCommentController';
import { BuiltinGitProvider } from './builtinGit';
import { _getMRComments } from '../codingApi';
import { ReadonlyFileSystemProvider } from './ReadonlyFileSystemProvider';
import TurndownService from 'turndown';
import { IDiffComment } from '../privateCodingApiType';

export interface ICachedCommentThreads {
	[key: string]: vscode.CommentThread[];
}

export interface ICachedCommentController {
	[key: string]: vscode.CommentController;
}

export class CodingMergeRequestFileSystemProvider extends ReadonlyFileSystemProvider {
	static scheme = CODING_MR_SCHEME;

	private repositoryInit = false;
	private cachedCommentThreads: ICachedCommentThreads = {};
	private cachedCommentControllers: ICachedCommentController = {};

	constructor(protected gitAPI: BuiltinGitProvider) {
		super();
	}

	async waitForRepos(milliseconds: number): Promise<void> {
		const openPromise = new Promise<void>(resolve => {
			let eventDisposable: Disposable | undefined = undefined;

			eventDisposable = this.gitAPI.onDidOpenRepository(() => {
				eventDisposable?.dispose();
				eventDisposable = undefined;
				resolve();
			});
		});

		let timeout: NodeJS.Timeout | undefined;
		const timeoutPromise = new Promise<void>(resolve => {
			timeout = setTimeout(() => resolve(), milliseconds);
		});
		await Promise.race([openPromise, timeoutPromise]);

		if (timeout) {
			clearTimeout(timeout);
		}
	}

	async readFile(uri: Uri): Promise<Uint8Array> {
		if (!this.repositoryInit) {
			await this.waitForRepos(5000);
			this.repositoryInit = true;
		}

		const [repository] = this.gitAPI.repositories;

		const query = JSON.parse(uri.query);
		const absolutePath = repository.rootUri.path + uri.path;
		let content: string = '';

		if (!query || query.isEmpty) {
			return new TextEncoder().encode('');
		}

		try {
			// `git show commit:filePath`
			content = await repository.show(query.commit, absolutePath);
		} catch (error) {
			console.log('error', error);
			await repository.getCommit(query.commit);
		}

		return new TextEncoder().encode(content || '');
	}
}
