<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { localize } from 'vs/nls';
import * as objects from 'vs/base/common/objects';
import { parseArgs } from 'vs/platform/environment/node/argv';
import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { BrowserWindow, ipcMain, screen, Event } from 'electron';
import { ILaunchService } from 'vs/platform/launch/electron-main/launchService';
import { PerformanceInfo, SystemInfo, IDiagnosticsService } from 'vs/platform/diagnostics/electron-main/diagnosticsService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IWindowState } from 'vs/platform/windows/electron-main/windows';

const DEFAULT_BACKGROUND_COLOR = '#1E1E1E';

export class IssueService implements IIssueService {
	_serviceBrand: any;
	_issueWindow: BrowserWindow | null;
	_issueParentWindow: BrowserWindow;
	_processExplorerWindow: BrowserWindow | null;

	constructor(
		private machineId: string,
		private userEnv: IProcessEnvironment,
		@IEnvironmentService private environmentService: IEnvironmentService,
		@ILaunchService private launchService: ILaunchService,
		@ILogService private logService: ILogService,
		@IDiagnosticsService private diagnosticsService: IDiagnosticsService,
		@IWindowsService private windowsService: IWindowsService
	) {
		this.registerListeners();
	}

	private registerListeners(): void {
		ipcMain.on('vscode:issueSystemInfoRequest', (event: Event) => {
			this.getSystemInformation().then(msg => {
				event.sender.send('vscode:issueSystemInfoResponse', msg);
			});
		});

		ipcMain.on('vscode:issuePerformanceInfoRequest', (event: Event) => {
			this.getPerformanceInfo().then(msg => {
				event.sender.send('vscode:issuePerformanceInfoResponse', msg);
			});
		});

		ipcMain.on('vscode:workbenchCommand', (event, arg) => {
			if (this._issueParentWindow) {
				this._issueParentWindow.webContents.send('vscode:runAction', { id: arg, from: 'issueReporter' });
			}
		});

		ipcMain.on('vscode:openExternal', (_, arg) => {
			this.windowsService.openExternal(arg);
		});

		ipcMain.on('vscode:closeIssueReporter', (event: Event) => {
			if (this._issueWindow) {
				this._issueWindow.close();
			}
		});

		ipcMain.on('windowsInfoRequest', (event: Event) => {
			this.launchService.getMainProcessInfo().then(info => {
				event.sender.send('vscode:windowsInfoResponse', info.windows);
			});
		});

	}

	openReporter(data: IssueReporterData): Promise<void> {
		this._issueParentWindow = BrowserWindow.getFocusedWindow();
		const position = this.getWindowPosition(this._issueParentWindow, 700, 800);
		if (!this._issueWindow) {
			this._issueWindow = new BrowserWindow({
				width: position.width,
				height: position.height,
				minWidth: 300,
				minHeight: 200,
				x: position.x,
				y: position.y,
				title: localize('issueReporter', "Issue Reporter"),
				backgroundColor: data.styles.backgroundColor || DEFAULT_BACKGROUND_COLOR
			});

			this._issueWindow.setMenuBarVisibility(false); // workaround for now, until a menu is implemented

			// Modified when testing UI
			const features: IssueReporterFeatures = {};

			this.logService.trace('issueService#openReporter: opening issue reporter');
			this._issueWindow.loadURL(this.getIssueReporterPath(data, features));

			this._issueWindow.on('close', () => this._issueWindow = null);

			this._issueParentWindow.on('closed', () => {
				if (this._issueWindow) {
					this._issueWindow.close();
					this._issueWindow = null;
				}
			});
		}

		this._issueWindow.focus();

		return null;
	}

	openProcessExplorer(data: ProcessExplorerData): Promise<void> {
		// Create as singleton
		if (!this._processExplorerWindow) {
			const parentWindow = BrowserWindow.getFocusedWindow();
			const position = this.getWindowPosition(parentWindow, 800, 300);
			this._processExplorerWindow = new BrowserWindow({
				skipTaskbar: true,
				resizable: true,
				width: position.width,
				height: position.height,
				minWidth: 300,
				minHeight: 200,
				x: position.x,
				y: position.y,
				backgroundColor: data.styles.backgroundColor,
				title: localize('processExplorer', "Process Explorer")
			});

			this._processExplorerWindow.setMenuBarVisibility(false);

			const windowConfiguration = {
				appRoot: this.environmentService.appRoot,
				nodeCachedDataDir: this.environmentService.nodeCachedDataDir,
				windowId: this._processExplorerWindow.id,
				userEnv: this.userEnv,
				machineId: this.machineId,
				data
			};

			const environment = parseArgs(process.argv);
			const config = objects.assign(environment, windowConfiguration);
			for (let key in config) {
				if (config[key] === void 0 || config[key] === null || config[key] === '') {
					delete config[key]; // only send over properties that have a true value
				}
			}

			this._processExplorerWindow.loadURL(`${require.toUrl('vs/code/electron-browser/processExplorer/processExplorer.html')}?config=${encodeURIComponent(JSON.stringify(config))}`);

			this._processExplorerWindow.on('close', () => this._processExplorerWindow = null);

			parentWindow.on('close', () => {
				if (this._processExplorerWindow) {
					this._processExplorerWindow.close();
					this._processExplorerWindow = null;
				}
			});
		}

		// Focus
		this._processExplorerWindow.focus();

		return null;
	}

	private getWindowPosition(parentWindow: BrowserWindow, defaultWidth: number, defaultHeight: number): IWindowState {
		// We want the new window to open on the same display that the parent is in
		let displayToUse: Electron.Display | undefined;
		const displays = screen.getAllDisplays();

		// Single Display
		if (displays.length === 1) {
			displayToUse = displays[0];
		}

		// Multi Display
		else {

			// on mac there is 1 menu per window so we need to use the monitor where the cursor currently is
			if (isMacintosh) {
				const cursorPoint = screen.getCursorScreenPoint();
				displayToUse = screen.getDisplayNearestPoint(cursorPoint);
			}

			// if we have a last active window, use that display for the new window
			if (!displayToUse && parentWindow) {<commit_msg>Fix return of openReporter in issueService<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { localize } from 'vs/nls';
import * as objects from 'vs/base/common/objects';
import { parseArgs } from 'vs/platform/environment/node/argv';
import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { BrowserWindow, ipcMain, screen, Event } from 'electron';
import { ILaunchService } from 'vs/platform/launch/electron-main/launchService';
import { PerformanceInfo, SystemInfo, IDiagnosticsService } from 'vs/platform/diagnostics/electron-main/diagnosticsService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IWindowState } from 'vs/platform/windows/electron-main/windows';

const DEFAULT_BACKGROUND_COLOR = '#1E1E1E';

export class IssueService implements IIssueService {
	_serviceBrand: any;
	_issueWindow: BrowserWindow | null;
	_issueParentWindow: BrowserWindow;
	_processExplorerWindow: BrowserWindow | null;

	constructor(
		private machineId: string,
		private userEnv: IProcessEnvironment,
		@IEnvironmentService private environmentService: IEnvironmentService,
		@ILaunchService private launchService: ILaunchService,
		@ILogService private logService: ILogService,
		@IDiagnosticsService private diagnosticsService: IDiagnosticsService,
		@IWindowsService private windowsService: IWindowsService
	) {
		this.registerListeners();
	}

	private registerListeners(): void {
		ipcMain.on('vscode:issueSystemInfoRequest', (event: Event) => {
			this.getSystemInformation().then(msg => {
				event.sender.send('vscode:issueSystemInfoResponse', msg);
			});
		});

		ipcMain.on('vscode:issuePerformanceInfoRequest', (event: Event) => {
			this.getPerformanceInfo().then(msg => {
				event.sender.send('vscode:issuePerformanceInfoResponse', msg);
			});
		});

		ipcMain.on('vscode:workbenchCommand', (event, arg) => {
			if (this._issueParentWindow) {
				this._issueParentWindow.webContents.send('vscode:runAction', { id: arg, from: 'issueReporter' });
			}
		});

		ipcMain.on('vscode:openExternal', (_, arg) => {
			this.windowsService.openExternal(arg);
		});

		ipcMain.on('vscode:closeIssueReporter', (event: Event) => {
			if (this._issueWindow) {
				this._issueWindow.close();
			}
		});

		ipcMain.on('windowsInfoRequest', (event: Event) => {
			this.launchService.getMainProcessInfo().then(info => {
				event.sender.send('vscode:windowsInfoResponse', info.windows);
			});
		});

	}

	openReporter(data: IssueReporterData): Promise<void> {
		return new Promise(_ => {
			this._issueParentWindow = BrowserWindow.getFocusedWindow();
			const position = this.getWindowPosition(this._issueParentWindow, 700, 800);
			if (!this._issueWindow) {
				this._issueWindow = new BrowserWindow({
					width: position.width,
					height: position.height,
					minWidth: 300,
					minHeight: 200,
					x: position.x,
					y: position.y,
					title: localize('issueReporter', "Issue Reporter"),
					backgroundColor: data.styles.backgroundColor || DEFAULT_BACKGROUND_COLOR
				});

				this._issueWindow.setMenuBarVisibility(false); // workaround for now, until a menu is implemented

				// Modified when testing UI
				const features: IssueReporterFeatures = {};

				this.logService.trace('issueService#openReporter: opening issue reporter');
				this._issueWindow.loadURL(this.getIssueReporterPath(data, features));

				this._issueWindow.on('close', () => this._issueWindow = null);

				this._issueParentWindow.on('closed', () => {
					if (this._issueWindow) {
						this._issueWindow.close();
						this._issueWindow = null;
					}
				});
			}

			this._issueWindow.focus();
		});
	}

	openProcessExplorer(data: ProcessExplorerData): Promise<void> {
		return new Promise(_ => {
			// Create as singleton
			if (!this._processExplorerWindow) {
				const parentWindow = BrowserWindow.getFocusedWindow();
				const position = this.getWindowPosition(parentWindow, 800, 300);
				this._processExplorerWindow = new BrowserWindow({
					skipTaskbar: true,
					resizable: true,
					width: position.width,
					height: position.height,
					minWidth: 300,
					minHeight: 200,
					x: position.x,
					y: position.y,
					backgroundColor: data.styles.backgroundColor,
					title: localize('processExplorer', "Process Explorer")
				});

				this._processExplorerWindow.setMenuBarVisibility(false);

				const windowConfiguration = {
					appRoot: this.environmentService.appRoot,
					nodeCachedDataDir: this.environmentService.nodeCachedDataDir,
					windowId: this._processExplorerWindow.id,
					userEnv: this.userEnv,
					machineId: this.machineId,
					data
				};

				const environment = parseArgs(process.argv);
				const config = objects.assign(environment, windowConfiguration);
				for (let key in config) {
					if (config[key] === void 0 || config[key] === null || config[key] === '') {
						delete config[key]; // only send over properties that have a true value
					}
				}

				this._processExplorerWindow.loadURL(`${require.toUrl('vs/code/electron-browser/processExplorer/processExplorer.html')}?config=${encodeURIComponent(JSON.stringify(config))}`);

				this._processExplorerWindow.on('close', () => this._processExplorerWindow = null);

				parentWindow.on('close', () => {
					if (this._processExplorerWindow) {
						this._processExplorerWindow.close();
						this._processExplorerWindow = null;
					}
				});
			}

			// Focus
			this._processExplorerWindow.focus();
		});
	}

	private getWindowPosition(parentWindow: BrowserWindow, defaultWidth: number, defaultHeight: number): IWindowState {
		// We want the new window to open on the same display that the parent is in
		let displayToUse: Electron.Display | undefined;
		const displays = screen.getAllDisplays();

		// Single Display
		if (displays.length === 1) {
			displayToUse = displays[0];
		}

		// Multi Display
		else {

			// on mac there is 1 menu per window so we need to use the monitor where the cursor currently is
			if (isMacintosh) {
				const cursorPoint = screen.getCursorScreenPoint();
				displayToUse = screen.getDisplayNearestPoint(cursorPoint);
			}

			// if we have a last active window, use that display for the new window
			if (!displayToUse && parentWindow) {
{'fraction_non_alphanumeric': 0.14494257132271213, 'fraction_numerical': 0.0045942941830307525, 'mean_word_length': 3.823445318084346, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '366997', 'n_tokens_mistral': 4583, 'n_tokens_neox': 3804, 'n_words': 843}