import * as vscode from 'vscode';
import { KEYCLOAK_DEVICE_AUTH_URL, KEYCLOAK_TOKEN_CREATE_URL, KEYCLOAK_USER_INFO_URL } from '../config';
import { OPEN_GETTING_STARTED_COMMAND } from '../theia/command';
import BriefingView from '../view/briefingView';
import GettingStartedView from '../view/gettingStartedView';
import { CHOOSE_MISSION_WORKDIR_COMMAND, CommandHandler } from './commandHandler';
import ExtensionStore from './extensionStore';
import KeycloakOAuth2DeviceFlowConnection from './keycloakOAuth2DeviceFlowConnection';

export default class Controller {
	public connection: KeycloakOAuth2DeviceFlowConnection;
	private commandHandler: CommandHandler;
	private briefingView: BriefingView;
	private gettingStartedView: GettingStartedView;
	private extensionStore: ExtensionStore;
	constructor(private context: vscode.ExtensionContext) {
		this.briefingView = new BriefingView();
		this.gettingStartedView = new GettingStartedView(context.extensionUri);
		this.commandHandler = new CommandHandler(this);
		this.connection = new KeycloakOAuth2DeviceFlowConnection(
			KEYCLOAK_DEVICE_AUTH_URL,
			KEYCLOAK_TOKEN_CREATE_URL,
			KEYCLOAK_USER_INFO_URL,
		);
		this.extensionStore = ExtensionStore.getInstance();

		this.init();
	}
	private async init() {
		const that = this;
		vscode.window.registerUriHandler({
			handleUri(uri: vscode.Uri) {
				const queryParams: URLSearchParams = new URLSearchParams(uri.query);
				const action: string | null = queryParams.get('action');

				switch (action) {
					case 'open-challenge':
						that.launchMission(queryParams.get('missionId'));
						break;

					default:
						vscode.window.showInformationMessage('Aucune action trouvée!');
				}
			},
		});

		const exensionStorage = ExtensionStore.getInstance();
		this.gettingStartedView.isAlreadyConnected = !!(await exensionStorage.getAccessToken());
	}
	async chooseMissionWorkdir() {
		const actualMissionWorkDir = this.extensionStore.getMissionWorkdir();

		const folderUri = await vscode.window.showOpenDialog({
			defaultUri: actualMissionWorkDir ? vscode.Uri.file(actualMissionWorkDir) : undefined,
			canSelectFolders: true,
			canSelectFiles: false,
			title: 'Choisis le dossier qui contiendra tes missions',
		});

		if (!folderUri) {
			if (this.extensionStore.getMissionWorkdir()) {
				return;
			}
			this.chooseMissionWorkdir();
		} else {
			this.extensionStore.setMissionWorkdir(folderUri[0].path);
		}
	}
	public async clear() {
		const exensionStorage = ExtensionStore.getInstance();
		await exensionStorage.clear();
		this.gettingStartedView.isAlreadyConnected = false;
	}

	public async authenticate() {
		// WARN generate a new device code every time student clicks on log in button. Should I keep it ?\
		// The answer might be 'yes' because when the student is already authenticated, the log in button should be disabled.
		await this.connection.registerDevice();
		const tokens = await this.connection.getToken({ openLink: Controller.openBrowserWithUrl });
		await this.extensionStore.setAccessToken(tokens.accessToken);
		await this.extensionStore.setRefreshToken(tokens.refreshToken);
		this.gettingStartedView.isAlreadyConnected = true;
	}
	public static openBrowserWithUrl(url: string) {
		vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(url));
	}

	public async launchMission(missionId: string | null) {
		if (missionId) {
			vscode.window.showInformationMessage(`vous lancez la mission ${missionId}`);
			const hadMissionWorkdir = this.extensionStore.getMissionWorkdir() !== undefined;
			if (!hadMissionWorkdir) {
				await vscode.commands.executeCommand(CHOOSE_MISSION_WORKDIR_COMMAND.cmd);
			}

			const hadBeenConnected = (await this.extensionStore.getAccessToken()) !== undefined;

			if (!hadBeenConnected) {
				this.authenticate();
				vscode.window.showInformationMessage('Nouvelle connexion validée');
			} else {
				vscode.window.showInformationMessage('Déjà connecté: session récupérée');
			}

			vscode.commands.executeCommand(OPEN_GETTING_STARTED_COMMAND.cmd);
		}
	}
}