import { c } from './lib/Log';


interface AutocompleteOutput {
	sentences: {
		value: string;
		time:  number;
	}[];
	time: number;
}

export class Api {
	
	private static ENDPOINT = 
		// `http://coconut-proxy.huggingface.test`
		// `http://coconuthf.eastus.cloudapp.azure.com:6006`
		// "http://localhost:6006"
		// `https://transformer.huggingface.co`
		`https://wvnbdkpga3d4aev9.us-east-1.aws.endpoints.huggingface.cloud`
	;
	static shared = new Api();
	
	private async postAutocomplete(
		params: {
			inputs: {
				context:         string;
				kwargs: {
					model_size?:     string; /// 'small' | 'medium',
					top_p?:          number; /// float between 0 and 1
					temperature?:    number; /// float between 0 and 100
					step_size?:      number;
					kl_scale?:       number;
					gm_scale?:       number;
					num_iterations?: number;
					gen_length?:     number;
					max_time?:       number; /// <- if we want to limit the response time. (in sec)
					bow_or_discrim?: string;
					use_sampling?:   boolean;
				}
			}
		}
	): Promise<any> {
		const init = {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify(params),
		}

		const response = await fetch(Api.ENDPOINT, init)
		const result = JSON.parse(await response.json())
		return result
	}
	
	/**
	 * Demo-specific helpers
	 */
	async postWithSettings(
		params: {
			context:     string;
		}
	): Promise<AutocompleteOutput> {
		/// Retrieve all settings params then launch the request.
		const model_size = 
			document.querySelector('.decoder-settings .setting.model_size .js-val')!.textContent
		|| undefined;
		
		const parseSliderVal = (sel: string): number | undefined => {
			const x = document.querySelector(sel);
			if (x && x.textContent) {
				return Number(x.textContent);
			}
			return undefined;
		};
		
		const top_p            = parseSliderVal('.decoder-settings .setting.top_p .js-val');
		const temperature      = parseSliderVal('.decoder-settings .setting.temperature .js-val');
		const step_size        = parseSliderVal('.decoder-settings .setting.step_size .js-val');
		const kl_scale         = parseSliderVal('.decoder-settings .setting.kl_scale .js-val');
		const gm_scale         = parseSliderVal('.decoder-settings .setting.gm_scale .js-val');
		const num_iterations   = parseSliderVal('.decoder-settings .setting.num_iterations .js-val');
		const gen_length       = parseSliderVal('.decoder-settings .setting.gen_length .js-val');
		const max_time         = parseSliderVal('.decoder-settings .setting.max_time .js-val');
		
		const bow_or_discrim = (
			document.querySelector<HTMLInputElement>('.decoder-settings input[name=bow_or_discrim]:checked') || {}
		).value;
		const use_sampling = (
			document.querySelector<HTMLInputElement>('.decoder-settings input[name=use_sampling]') || {}
		).checked;

		const sent_params = {
			inputs: {
				...params,
				kwargs: {
					model_size,
					top_p,
					temperature,
					step_size,
					kl_scale,
					gm_scale,
					num_iterations,
					gen_length,
					max_time,
					bow_or_discrim,
					use_sampling,
				}
			}
		}
		return this.postAutocomplete(sent_params);
	}
	
	/**
	 * Edit AJAX endpoint
	 * 
	 * Contrary to the autocomplete endpoint,
	 * this is on server,
	 * not on backend.
	 */
	async postEdit(body: any): Promise<boolean> {
		const doc = (<any>window).doc as { [index: string]: string };
		if (!doc || !doc.longId) {
			throw new Error(`invalid doc`);
		}
		
		const path = `/edit/${doc.model}/${doc.longId}/${doc.shortId}`;
		
		const response = await fetch(path, {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify(body),
		});
		return response.ok;
	}
	
	/**
	 * Duplicate AJAX endpoint
	 * 
	 * Contrary to the autocomplete endpoint,
	 * this is on server,
	 * not on backend.
	 */
	async postDuplicate(): Promise<string> {
		const doc = (<any>window).doc as { [index: string]: string };
		if (!doc || !doc.shortId) {
			throw new Error(`invalid doc`);
		}
		
		const path = `/duplicate/${doc.shortId}`;
		const response = await fetch(path, {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
		});
		const url = await response.text();
		c.log('[new url]', url);
		
		return url;
	}
}