use once_cell::sync::Lazy;
use rand::seq::SliceRandom;
use std::io::BufRead;

static FONTS: &[&str] = &[
	"Albura/Albura-Regular.ttf",
	"AmaticSC-Bold.ttf",
	"Exo-Regular.otf",
	"EBGaramond08-Regular.otf",
	"Gidole-Regular.ttf",
	"Londrina/LondrinaBook-Regular.otf",
	"PlayenSans/PlayenSans-Regular.otf",
	"Playfulist.otf",
	"ProzaLibre-Regular.ttf",
];

static USER_AGENTS: &[&str] = &[
	r"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.44",
	r"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0",
	r"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
	r"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/111.0",
	r"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
];

static WORDS: Lazy<Vec<String>> = Lazy::new(|| {
	let file = std::fs::File::open("lefff-3.4.mlex").unwrap();
	let file_buf = std::io::BufReader::new(file);

	let mut words = Vec::new();
	for line in file_buf.lines() {
		let line = line.unwrap();
		if line.as_bytes().first() != Some(&b't') {
			continue;
		}
		let mut cols = line.split('\t');
		let Some(word) = cols.next() else {
			continue
		};
		let class = cols.next();
		match class {
			Some("nc") => {}
			Some("adj") => {
				let Some(flex) = cols.nth(1) else {
					continue
				};
				if flex.contains('p') || flex.contains('m') {
					continue;
				}
			}
			_ => continue,
		}
		let mut capitalized = String::from("T");
		capitalized.push_str(&word[1..]);
		words.push(capitalized);
	}
	//eprintln!("Words: {}", words.len());
	words
});

#[tokio::main]
async fn main() {
	Lazy::force(&WORDS);

	tide::log::start();
	let mut app = tide::new();

	app.at("/").get(handle_request);

	app.listen(std::net::SocketAddr::new(
		std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)),
		8137,
	))
	.await
	.unwrap();
}

async fn handle_request<'a>(_req: tide::Request<()>) -> tide::Result<tide::Response> {
	let mut rng = rand::thread_rng();
	let word = WORDS.choose(&mut rng).unwrap();

	let client = reqwest::blocking::Client::builder()
		.user_agent(*USER_AGENTS.choose(&mut rng).unwrap())
		.build()
		.unwrap();

	let resp = match client
		.get(format!(
			"https://www.bing.com/images/search?q={word}&FORM=HDRSC3"
		))
		.send()
	{
		Ok(resp) => resp,
		Err(e) => {
			eprintln!("Error requesting: {e:?}");
			return Ok(tide::Response::builder(500)
				.content_type(tide::http::mime::PLAIN)
				.body("Error requesting search engine")
				.build());
		}
	};
	if !resp.status().is_success() {
		eprintln!("Search engine status: {}", resp.status());
		return Ok(tide::Response::builder(500)
			.content_type(tide::http::mime::PLAIN)
			.body(format!("Search engine status: {}", resp.status()))
			.build());
	}
	let page = match resp.text() {
		Ok(page) => page,
		Err(e) => {
			eprintln!("Error getting text: {e:?}");
			return Ok(tide::Response::builder(500)
				.content_type(tide::http::mime::PLAIN)
				.body("Error reading search result")
				.build());
		}
	};

	let pattern = r#"mediaurl="#;
	let url_start = match page.find(pattern) {
		Some(idx) => idx,
		None => {
			eprintln!("Error: cannot find pattern");
			return Ok(tide::Response::builder(500)
				.content_type(tide::http::mime::PLAIN)
				.body("Error: pattern not found in search result")
				.build());
		}
	} + pattern.len();
	let Some(url_len) = page[url_start..].find('&') else {
		eprintln!("Error: cannot find url end");
			return Ok(tide::Response::builder(500)
				.content_type(tide::http::mime::PLAIN)
				.body("Error: url end not found in search result")
				.build());
	};
	if url_len > 1024 {
		eprintln!("Error: url too long {url_len}");
		return Ok(tide::Response::builder(500)
			.content_type(tide::http::mime::PLAIN)
			.body("Error: url too long in search result")
			.build());
	}
	let img_url_encoded = &page[url_start..url_start + url_len];
	let img_url = match percent_encoding::percent_decode_str(img_url_encoded).decode_utf8() {
		Ok(img_url) => img_url,
		Err(e) => {
			eprintln!("Error: percent decoding url {e:?}");
			return Ok(tide::Response::builder(500)
				.content_type(tide::http::mime::PLAIN)
				.body("Error: cannot decode url from search result")
				.build());
		}
	};
	if img_url.contains('"') {
		panic!("url contains quotes");
	}
	let font = *FONTS.choose(&mut rng).unwrap();

	Ok(tide::Response::builder(200)
		.header("Access-Control-Allow-Origin", "*")
		.header("Access-Control-Allow-Headers", "*")
		.content_type(tide::http::mime::HTML)
		.body(format!(r#"<!doctype html>
<html lang="fr">
	<head>
		<meta charset="utf-8"/>
		<title>MLeTomatic</title>
		<!--<script type="text/javascript" src="//txmn.tk/js/jquery.js"></script>-->
		<style type="text/css">
@font-face {{
	font-family: CustomFont;
	src: url("//txmn.tk/fonts/{font}");
}}
body {{
	text-align: center;
}}
h1, #pitch {{
	font-family: CustomFont;
	font-weight: normal;
}}
#img {{
	max-width: 100%;
	max-height: 100vh;
}}
</style>
	</head>
	<body>
		<h1>Monnaie Libre et {word}</h1>
		<!--<p id="pitch"><noscript>Active JavaScript pour découvrir pourquoi tu devrais rejoindre l'association Monnaie Libre et {word}&#8239;!</noscript></p>-->
		<img id="img" alt="{word}" src="{img_url}"/>
		<div id="info">
			<p><a href="https://git.txmn.tk/tuxmain/MLeTomatic">MLeTomatic</a>, parce qu'on ne fait pas d'mlet sans casser des nœuds &#8211; Images trouvées par Bing, soumises au droit d'auteur. Mots tirés de Lefff, lire la licence dans le dépôt.</p>
		</div>
		<script type="text/javascript">
/*window.onload = function() {{
	$.ajax({{
		method: "POST",
		url: "https://api.openai.com/v1/engines/text-davinci-003/completions",
		data: JSON.stringify({{
			"prompt":"Rédige un court flyer pour l'association \"Monnaie Libre et {word}\", en accentuant l'aspect \"{word}\".",
			"max_tokens":250,
			"temperature":1,
			"top_p":1,
			"n":1,
			"stream":false,
			"echo":false,
			"presence_penalty":0,
			"frequency_penalty":0,
			"best_of":1
		}}),
		success: function(resp) {{
			document.getElementById("pitch").innerHTML = resp.choices[0].text;
		}},
		dataType: "json",
		contentType: "application/json; charset=utf-8"
	}});
}};*/
</script>
	</body>
</html>"#))
		.build())
}
