/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright 2021 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

'use strict';

import vscode = require('vscode');
import { getGoConfig } from './config';
import { daysBetween, flushSurveyConfig, getStateConfig, minutesBetween, timeMinute } from './goSurvey';
import { GoExtensionContext } from './context';
import { getGoVersion } from './util';

// Start and end dates of the survey.
export const startDate = new Date('May 31 2022 00:00:00 GMT');
export const endDate = new Date('June 21 2022 00:00:00 GMT');

// DeveloperSurveyConfig is the set of global properties used to determine if
// we should prompt a user to take the gopls survey.
export interface DeveloperSurveyConfig {
	// prompt is true if the user can be prompted to take the survey.
	// It is false if the user has responded "Never" to the prompt.
	prompt?: boolean;

	// datePromptComputed is the date on which the value of the prompt field
	// was set. It is usually the same as lastDatePrompted, but not
	// necessarily.
	datePromptComputed?: Date;

	// lastDatePrompted is the most recent date that the user has been prompted.
	lastDatePrompted?: Date;

	// lastDateAccepted is the most recent date that the user responded "Yes"
	// to the survey prompt. The user need not have completed the survey.
	lastDateAccepted?: Date;
}

export function maybePromptForDeveloperSurvey(goCtx: GoExtensionContext) {
	// First, check the value of the 'go.survey.prompt' setting to see
	// if the user has opted out of all survey prompts.
	const goConfig = getGoConfig();
	if (goConfig.get('survey.prompt') === false) {
		return;
	}
	const now = new Date();
	let cfg = shouldPromptForSurvey(now, getDeveloperSurveyConfig());
	if (!cfg) {
		return;
	}
	if (!cfg.prompt) {
		return;
	}
	const callback = async () => {
		const currentTime = new Date();

		// Make sure the user has been idle for at least a minute.
		if (minutesBetween(goCtx.lastUserAction, currentTime) < 1) {
			setTimeout(callback, 5 * timeMinute);
			return;
		}
		cfg = await promptForDeveloperSurvey(cfg ?? {}, now);
		if (cfg) {
			flushSurveyConfig(developerSurveyConfig, cfg);
		}
	};
	callback();
}

// shouldPromptForSurvey decides if we should prompt the given user to take the
// survey. It returns the DeveloperSurveyConfig if we should prompt, and
// undefined if we should not prompt.
export function shouldPromptForSurvey(now: Date, cfg: DeveloperSurveyConfig): DeveloperSurveyConfig | undefined {
	// TODO(rstambler): Merge checks for surveys into a setting.

	// Don't prompt if the survey hasn't started or is over.
	if (!inDateRange(startDate, endDate, now)) {
		return;
	}

	// Reset the values if we're outside of the previous survey period.
	if (cfg.datePromptComputed && !inDateRange(startDate, endDate, cfg.datePromptComputed)) {
		cfg = {};
	}
	// If the prompt value is undefined, then this is the first activation
	// for this survey period, so decide if we should prompt the user. This
	// is done by generating a random number in the range [0, 1) and checking
	// if it is < probability.
	if (cfg.prompt === undefined) {
		const probability = 0.1;
		cfg.datePromptComputed = now;
		cfg.prompt = Math.random() < probability;
	}
	flushSurveyConfig(developerSurveyConfig, cfg);
	if (!cfg.prompt) {
		return;
	}

	// Check if the user has taken the survey in the current survey period.
	// Don't prompt them if they have.
	if (cfg.lastDateAccepted) {
		if (inDateRange(startDate, endDate, cfg.lastDateAccepted)) {
			return;
		}
	}

	// Check if the user has been prompted for the survey in the last 5 days.
	// Don't prompt them if they have been.
	if (cfg.lastDatePrompted) {
		const daysSinceLastPrompt = daysBetween(now, cfg.lastDatePrompted);
		// Don't prompt twice on the same day, even if it's the last day of the
		// survey.
		if (daysSinceLastPrompt < 1) {
			return;
		}
		// If the survey will end in 5 days, prompt on the next day.
		// Otherwise, wait for 5 days.
		if (daysBetween(now, endDate) > 5) {
			return;
		}
	}
	return cfg;
}

export async function promptForDeveloperSurvey(cfg: DeveloperSurveyConfig, now: Date): Promise<DeveloperSurveyConfig> {
	let selected = await vscode.window.showInformationMessage(
		// TODO(rstambler): Figure out how to phrase this.
		`Looks like you are coding in Go! Would you like to help ensure that Go is meeting your needs
by participating in this 10-minute survey before ${endDate.toDateString()}?`,
		'Yes',
		'Remind me later',
		'Never'
	);

	// Update the time last asked.
	cfg.lastDatePrompted = now;
	cfg.datePromptComputed = now;

	switch (selected) {
		case 'Yes':
			{
				cfg.lastDateAccepted = now;
				cfg.prompt = true;
				const goV = await getGoVersion();
				const goVersion = goV ? goV.format(true) : 'na';
				const useGopls = getGoConfig()?.get('useLanguageServer') === true ? 'true' : 'false';
				const surveyURL = `https://google.qualtrics.com/jfe/form/SV_7O3x4IZKiUn0QCO?s=p&go=${goVersion}&gopls=${useGopls}`;
				await vscode.env.openExternal(vscode.Uri.parse(surveyURL));
			}
			break;
		case 'Remind me later':
			cfg.prompt = true;

			vscode.window.showInformationMessage("No problem! We'll ask you again another time.");
			break;
		case 'Never':
			cfg.prompt = false;

			selected = await vscode.window.showInformationMessage(
				`No problem! We won't ask again.
If you'd like to opt-out of all survey prompts, you can set 'go.survey.prompt' to false.`,
				'Open Settings'
			);
			switch (selected) {
				case 'Open Settings':
					vscode.commands.executeCommand('workbench.action.openSettings', 'go.survey.prompt');
					break;
				default:
					break;
			}
			break;
		default:
			// If the user closes the prompt without making a selection, treat it
			// like a "Not now" response.
			cfg.prompt = true;

			break;
	}
	return cfg;
}

export const developerSurveyConfig = 'developerSurveyConfig';

export function getDeveloperSurveyConfig(): DeveloperSurveyConfig {
	return getStateConfig(developerSurveyConfig) as DeveloperSurveyConfig;
}

// Assumes that end > start.
export function inDateRange(start: Date, end: Date, date: Date): boolean {
	// date is before the start time.
	if (date.getTime() - start.getTime() < 0) {
		return false;
	}
	// end is before the date.
	if (end.getTime() - date.getTime() < 0) {
		return false;
	}
	return true;
}
