


//
//   TRANSLATION
//

window.language_names = new Intl.DisplayNames([window.settings.language], { type: 'region' });

// See also language_codes_data in index.html TODO: how do these two relate?
window.language_codes_lookup = {
    "aa": {
        "two": "aa",
        "three": "aar",
        "name": "Afar"
    },
    "ab": {
        "two": "ab",
        "three": "abk",
        "name": "Abkhazian"
    },
    "af": {
        "two": "af",
        "three": "afr",
        "name": "Afrikaans"
    },
    "ak": {
        "two": "ak",
        "three": "aka",
        "name": "Akan"
    },
    "sq": {
        "two": "sq",
        "three": "alb",
        "name": "Albanian"
    },
    "am": {
        "two": "am",
        "three": "amh",
        "name": "Amharic"
    },
    "ar": {
        "two": "ar",
        "three": "ara",
        "name": "Arabic"
    },
    "an": {
        "two": "an",
        "three": "arg",
        "name": "Aragonese"
    },
    "hy": {
        "two": "hy",
        "three": "arm",
        "name": "Armenian"
    },
    "as": {
        "two": "as",
        "three": "asm",
        "name": "Assamese"
    },
    "av": {
        "two": "av",
        "three": "ava",
        "name": "Avaric"
    },
    "ae": {
        "two": "ae",
        "three": "ave",
        "name": "Avestan"
    },
    "ay": {
        "two": "ay",
        "three": "aym",
        "name": "Aymara"
    },
    "az": {
        "two": "az",
        "three": "aze",
        "name": "Azerbaijani"
    },
    "ba": {
        "two": "ba",
        "three": "bak",
        "name": "Bashkir"
    },
    "bm": {
        "two": "bm",
        "three": "bam",
        "name": "Bambara"
    },
    "eu": {
        "two": "eu",
        "three": "baq",
        "name": "Basque"
    },
    "be": {
        "two": "be",
        "three": "bel",
        "name": "Belarusian"
    },
    "bn": {
        "two": "bn",
        "three": "ben",
        "name": "Bengali"
    },
    "bh": {
        "two": "bh",
        "three": "bih",
        "name": "Bihari"
    },
    "bi": {
        "two": "bi",
        "three": "bis",
        "name": "Bislama"
    },
    "bs": {
        "two": "bs",
        "three": "bos",
        "name": "Bosnian"
    },
    "br": {
        "two": "br",
        "three": "bre",
        "name": "Breton"
    },
    "bg": {
        "two": "bg",
        "three": "bul",
        "name": "Bulgarian"
    },
    "my": {
        "two": "my",
        "three": "bur",
        "name": "Burmese"
    },
    "ca": {
        "two": "ca",
        "three": "cat",
        "name": "Catalan"
    },
    "ch": {
        "two": "ch",
        "three": "cha",
        "name": "Chamorro"
    },
    "ce": {
        "two": "ce",
        "three": "che",
        "name": "Chechen"
    },
    "zh": {
        "two": "zh",
        "three": "chi",
        "name": "Chinese"
    },
    "cu": {
        "two": "cu",
        "three": "chu",
        "name": "Church Slavic"
    },
    "cv": {
        "two": "cv",
        "three": "chv",
        "name": "Chuvash"
    },
    "kw": {
        "two": "kw",
        "three": "cor",
        "name": "Cornish"
    },
    "co": {
        "two": "co",
        "three": "cos",
        "name": "Corsican"
    },
    "cr": {
        "two": "cr",
        "three": "cre",
        "name": "Cree"
    },
    "cs": {
        "two": "cs",
        "three": "cze",
        "name": "Czech"
    },
    "da": {
        "two": "da",
        "three": "dan",
        "name": "Danish"
    },
    "dv": {
        "two": "dv",
        "three": "div",
        "name": "Divehi"
    },
    "nl": {
        "two": "nl",
        "three": "dut",
        "name": "Dutch"
    },
    "dz": {
        "two": "dz",
        "three": "dzo",
        "name": "Dzongkha"
    },
    "en": {
        "two": "en",
        "three": "eng",
        "name": "English"
    },
    "eo": {
        "two": "eo",
        "three": "epo",
        "name": "Esperanto"
    },
    "et": {
        "two": "et",
        "three": "est",
        "name": "Estonian"
    },
    "ee": {
        "two": "ee",
        "three": "ewe",
        "name": "Ewe"
    },
    "fo": {
        "two": "fo",
        "three": "fao",
        "name": "Faroese"
    },
    "fj": {
        "two": "fj",
        "three": "fij",
        "name": "Fijian"
    },
    "fi": {
        "two": "fi",
        "three": "fin",
        "name": "Finnish"
    },
    "fr": {
        "two": "fr",
        "three": "fre",
        "name": "French"
    },
    "fy": {
        "two": "fy",
        "three": "fry",
        "name": "Western Frisian"
    },
    "ff": {
        "two": "ff",
        "three": "ful",
        "name": "Fulah"
    },
    "ka": {
        "two": "ka",
        "three": "geo",
        "name": "Georgian"
    },
    "de": {
        "two": "de",
        "three": "ger",
        "name": "German"
    },
    "gd": {
        "two": "gd",
        "three": "gla",
        "name": "Gaelic"
    },
    "ga": {
        "two": "ga",
        "three": "gle",
        "name": "Irish"
    },
    "gl": {
        "two": "gl",
        "three": "glg",
        "name": "Galician"
    },
    "gv": {
        "two": "gv",
        "three": "glv",
        "name": "Manx"
    },
    "el": {
        "two": "el",
        "three": "gre",
        "name": "Greek"
    },
    "gn": {
        "two": "gn",
        "three": "grn",
        "name": "Guarani"
    },
    "gu": {
        "two": "gu",
        "three": "guj",
        "name": "Gujarati"
    },
    "ht": {
        "two": "ht",
        "three": "hat",
        "name": "Haitian"
    },
    "ha": {
        "two": "ha",
        "three": "hau",
        "name": "Hausa"
    },
    "he": {
        "two": "he",
        "three": "heb",
        "name": "Hebrew"
    },
    "hz": {
        "two": "hz",
        "three": "her",
        "name": "Herero"
    },
    "hi": {
        "two": "hi",
        "three": "hin",
        "name": "Hindi"
    },
    "ho": {
        "two": "ho",
        "three": "hmo",
        "name": "Hiri Motu"
    },
    "hr": {
        "two": "hr",
        "three": "hrv",
        "name": "Croatian"
    },
    "hu": {
        "two": "hu",
        "three": "hun",
        "name": "Hungarian"
    },
    "ig": {
        "two": "ig",
        "three": "ibo",
        "name": "Igbo"
    },
    "is": {
        "two": "is",
        "three": "ice",
        "name": "Icelandic"
    },
    "io": {
        "two": "io",
        "three": "ido",
        "name": "Ido"
    },
    "ii": {
        "two": "ii",
        "three": "iii",
        "name": "Sichuan Yi"
    },
    "iu": {
        "two": "iu",
        "three": "iku",
        "name": "Inuktitut"
    },
    "ie": {
        "two": "ie",
        "three": "ile",
        "name": "Interlingue"
    },
    "ia": {
        "two": "ia",
        "three": "ina",
        "name": "Interlingua"
    },
    "id": {
        "two": "id",
        "three": "ind",
        "name": "Indonesian"
    },
    "ik": {
        "two": "ik",
        "three": "ipk",
        "name": "Inupiaq"
    },
    "it": {
        "two": "it",
        "three": "ita",
        "name": "Italian"
    },
    "jv": {
        "two": "jv",
        "three": "jav",
        "name": "Javanese"
    },
    "ja": {
        "two": "ja",
        "three": "jpn",
        "name": "Japanese"
    },
    "kl": {
        "two": "kl",
        "three": "kal",
        "name": "Kalaallisut"
    },
    "kn": {
        "two": "kn",
        "three": "kan",
        "name": "Kannada"
    },
    "ks": {
        "two": "ks",
        "three": "kas",
        "name": "Kashmiri"
    },
    "kr": {
        "two": "kr",
        "three": "kau",
        "name": "Kanuri"
    },
    "kk": {
        "two": "kk",
        "three": "kaz",
        "name": "Kazakh"
    },
    "km": {
        "two": "km",
        "three": "khm",
        "name": "Central Khmer"
    },
    "ki": {
        "two": "ki",
        "three": "kik",
        "name": "Kikuyu"
    },
    "rw": {
        "two": "rw",
        "three": "kin",
        "name": "Kinyarwanda"
    },
    "ky": {
        "two": "ky",
        "three": "kir",
        "name": "Kirghiz"
    },
    "kv": {
        "two": "kv",
        "three": "kom",
        "name": "Komi"
    },
    "kg": {
        "two": "kg",
        "three": "kon",
        "name": "Kongo"
    },
    "ko": {
        "two": "ko",
        "three": "kor",
        "name": "Korean"
    },
    "kj": {
        "two": "kj",
        "three": "kua",
        "name": "Kuanyama"
    },
    "ku": {
        "two": "ku",
        "three": "kur",
        "name": "Kurdish"
    },
    "lo": {
        "two": "lo",
        "three": "lao",
        "name": "Lao"
    },
    "la": {
        "two": "la",
        "three": "lat",
        "name": "Latin"
    },
    "lv": {
        "two": "lv",
        "three": "lav",
        "name": "Latvian"
    },
    "li": {
        "two": "li",
        "three": "lim",
        "name": "Limburgan"
    },
    "ln": {
        "two": "ln",
        "three": "lin",
        "name": "Lingala"
    },
    "lt": {
        "two": "lt",
        "three": "lit",
        "name": "Lithuanian"
    },
    "lb": {
        "two": "lb",
        "three": "ltz",
        "name": "Luxembourgish"
    },
    "lu": {
        "two": "lu",
        "three": "lub",
        "name": "Luba-Katanga"
    },
    "lg": {
        "two": "lg",
        "three": "lug",
        "name": "Ganda"
    },
    "mk": {
        "two": "mk",
        "three": "mac",
        "name": "Macedonian"
    },
    "mh": {
        "two": "mh",
        "three": "mah",
        "name": "Marshallese"
    },
    "ml": {
        "two": "ml",
        "three": "mal",
        "name": "Malayalam"
    },
    "mi": {
        "two": "mi",
        "three": "mao",
        "name": "Maori"
    },
    "mr": {
        "two": "mr",
        "three": "mar",
        "name": "Marathi"
    },
    "ms": {
        "two": "ms",
        "three": "may",
        "name": "Malay"
    },
    "mg": {
        "two": "mg",
        "three": "mlg",
        "name": "Malagasy"
    },
    "mt": {
        "two": "mt",
        "three": "mlt",
        "name": "Maltese"
    },
    "mn": {
        "two": "mn",
        "three": "mon",
        "name": "Mongolian"
    },
    "na": {
        "two": "na",
        "three": "nau",
        "name": "Nauru"
    },
    "nv": {
        "two": "nv",
        "three": "nav",
        "name": "Navajo"
    },
    "nr": {
        "two": "nr",
        "three": "nbl",
        "name": "Ndebele, South"
    },
    "nd": {
        "two": "nd",
        "three": "nde",
        "name": "Ndebele, North"
    },
    "ng": {
        "two": "ng",
        "three": "ndo",
        "name": "Ndonga"
    },
    "ne": {
        "two": "ne",
        "three": "nep",
        "name": "Nepali"
    },
    "nn": {
        "two": "nn",
        "three": "nno",
        "name": "Norwegian Nynorsk"
    },
    "nb": {
        "two": "nb",
        "three": "nob",
        "name": "Bokmål, Norwegian"
    },
    "no": {
        "two": "no",
        "three": "nor",
        "name": "Norwegian"
    },
    "ny": {
        "two": "ny",
        "three": "nya",
        "name": "Chichewa"
    },
    "oc": {
        "two": "oc",
        "three": "oci",
        "name": "Occitan"
    },
    "oj": {
        "two": "oj",
        "three": "oji",
        "name": "Ojibwa"
    },
    "or": {
        "two": "or",
        "three": "ori",
        "name": "Oriya"
    },
    "om": {
        "two": "om",
        "three": "orm",
        "name": "Oromo"
    },
    "os": {
        "two": "os",
        "three": "oss",
        "name": "Ossetian"
    },
    "pa": {
        "two": "pa",
        "three": "pan",
        "name": "Panjabi"
    },
    "fa": {
        "two": "fa",
        "three": "per",
        "name": "Persian"
    },
    "pi": {
        "two": "pi",
        "three": "pli",
        "name": "Pali"
    },
    "pl": {
        "two": "pl",
        "three": "pol",
        "name": "Polish"
    },
    "pt": {
        "two": "pt",
        "three": "por",
        "name": "Portuguese"
    },
    "ps": {
        "two": "ps",
        "three": "pus",
        "name": "Pushto"
    },
    "qu": {
        "two": "qu",
        "three": "que",
        "name": "Quechua"
    },
    "rm": {
        "two": "rm",
        "three": "roh",
        "name": "Romansh"
    },
    "ro": {
        "two": "ro",
        "three": "rum",
        "name": "Romanian"
    },
    "rn": {
        "two": "rn",
        "three": "run",
        "name": "Rundi"
    },
    "ru": {
        "two": "ru",
        "three": "rus",
        "name": "Russian"
    },
    "sg": {
        "two": "sg",
        "three": "sag",
        "name": "Sango"
    },
    "sa": {
        "two": "sa",
        "three": "san",
        "name": "Sanskrit"
    },
    "si": {
        "two": "si",
        "three": "sin",
        "name": "Sinhala"
    },
    "sk": {
        "two": "sk",
        "three": "slo",
        "name": "Slovak"
    },
    "sl": {
        "two": "sl",
        "three": "slv",
        "name": "Slovenian"
    },
    "se": {
        "two": "se",
        "three": "sme",
        "name": "Northern Sami"
    },
    "sm": {
        "two": "sm",
        "three": "smo",
        "name": "Samoan"
    },
    "sn": {
        "two": "sn",
        "three": "sna",
        "name": "Shona"
    },
    "sd": {
        "two": "sd",
        "three": "snd",
        "name": "Sindhi"
    },
    "so": {
        "two": "so",
        "three": "som",
        "name": "Somali"
    },
    "st": {
        "two": "st",
        "three": "sot",
        "name": "Sotho, Southern"
    },
    "es": {
        "two": "es",
        "three": "spa",
        "name": "Spanish"
    },
    "sc": {
        "two": "sc",
        "three": "srd",
        "name": "Sardinian"
    },
    "sr": {
        "two": "sr",
        "three": "srp",
        "name": "Serbian"
    },
    "ss": {
        "two": "ss",
        "three": "ssw",
        "name": "Swati"
    },
    "su": {
        "two": "su",
        "three": "sun",
        "name": "Sundanese"
    },
    "sw": {
        "two": "sw",
        "three": "swa",
        "name": "Swahili"
    },
    "sv": {
        "two": "sv",
        "three": "swe",
        "name": "Swedish"
    },
    "ty": {
        "two": "ty",
        "three": "tah",
        "name": "Tahitian"
    },
    "ta": {
        "two": "ta",
        "three": "tam",
        "name": "Tamil"
    },
    "tt": {
        "two": "tt",
        "three": "tat",
        "name": "Tatar"
    },
    "te": {
        "two": "te",
        "three": "tel",
        "name": "Telugu"
    },
    "tg": {
        "two": "tg",
        "three": "tgk",
        "name": "Tajik"
    },
    "tl": {
        "two": "tl",
        "three": "tgl",
        "name": "Tagalog"
    },
    "th": {
        "two": "th",
        "three": "tha",
        "name": "Thai"
    },
    "bo": {
        "two": "bo",
        "three": "tib",
        "name": "Tibetan"
    },
    "ti": {
        "two": "ti",
        "three": "tir",
        "name": "Tigrinya"
    },
    "to": {
        "two": "to",
        "three": "ton",
        "name": "Tonga"
    },
    "tn": {
        "two": "tn",
        "three": "tsn",
        "name": "Tswana"
    },
    "ts": {
        "two": "ts",
        "three": "tso",
        "name": "Tsonga"
    },
    "tk": {
        "two": "tk",
        "three": "tuk",
        "name": "Turkmen"
    },
    "tr": {
        "two": "tr",
        "three": "tur",
        "name": "Turkish"
    },
    "tw": {
        "two": "tw",
        "three": "twi",
        "name": "Twi"
    },
    "ug": {
        "two": "ug",
        "three": "uig",
        "name": "Uighur"
    },
    "uk": {
        "two": "uk",
        "three": "ukr",
        "name": "Ukrainian"
    },
    "ur": {
        "two": "ur",
        "three": "urd",
        "name": "Urdu"
    },
    "uz": {
        "two": "uz",
        "three": "uzb",
        "name": "Uzbek"
    },
    "ve": {
        "two": "ve",
        "three": "ven",
        "name": "Venda"
    },
    "vi": {
        "two": "vi",
        "three": "vie",
        "name": "Vietnamese"
    },
    "vo": {
        "two": "vo",
        "three": "vol",
        "name": "Volapük"
    },
    "cy": {
        "two": "cy",
        "three": "wel",
        "name": "Welsh"
    },
    "wa": {
        "two": "wa",
        "three": "wln",
        "name": "Walloon"
    },
    "wo": {
        "two": "wo",
        "three": "wol",
        "name": "Wolof"
    },
    "xh": {
        "two": "xh",
        "three": "xho",
        "name": "Xhosa"
    },
    "yi": {
        "two": "yi",
        "three": "yid",
        "name": "Yiddish"
    },
    "yo": {
        "two": "yo",
        "three": "yor",
        "name": "Yoruba"
    },
    "za": {
        "two": "za",
        "three": "zha",
        "name": "Zhuang"
    },
    "zu": {
        "two": "zu",
        "three": "zul",
        "name": "Zulu"
    }
}








let translation_worker_error_count = 0;
let translation_files_to_cache = ['./translation_module.js','./translation_worker.js'];
let translation_files = {};
let translation_previous_percentage = 2;
let last_time_progress_updated = 0;

async function create_translation_worker(){
	//console.log("in create_translation_worker");
	
	if(window.translation_worker != null){
		console.warn("create_translation_worker: window.translation_worker wasn't null initially");
	}
	else{
		//console.log("create_translation_worker: OK, indow.translation_worker was initially null");
	}
	
	return new Promise((resolve, reject) => {
		
		window.translation_worker = null;
		window.real_translation_worker = null;
		
		window.real_translation_worker = new Worker('./translation_worker.js', {
		  	type: 'module'
		})
		window.translation_worker = new PromiseWorker(window.real_translation_worker);
		
		//console.log("translation_module: window.translation_worker: ", window.translation_worker);
		
		
		window.real_translation_worker.addEventListener('message', e => {
			//console.log("translation_module: received message from real_translation_worker: ", e.data);

		
			if(typeof e.data.status == 'string'){
				if(e.data.status == 'progress'){
					//console.log("translation worker sent download progress message: ", e.data);
					if(typeof e.data.file == 'string'){
						translation_files[e.data.file] = e.data;
					
						if(last_time_progress_updated < (Date.now() - 1000)){ // rate limiter
							last_time_progress_updated = Date.now();
						
							//console.log("translation_files: ", translation_files);
			
							let total_bytes = 0;
							let loaded_bytes = 0;
							let translation_file_names = keyz(translation_files);
							if(translation_file_names.length > 3){
								for(let w = 0; w < translation_file_names.length; w++){
									if(typeof translation_files[translation_file_names[w]].total == 'number' && typeof translation_files[translation_file_names[w]].loaded == 'number'){
										total_bytes += translation_files[translation_file_names[w]].total;
										loaded_bytes += translation_files[translation_file_names[w]].loaded;
									}
					
								}
							}
							if(total_bytes > 0){
								//console.log("translation worker sent download progress message, and calculated total_bytes is now: ", total_bytes);
								let download_size_el = document.querySelector('.message.pane-translation.download-progress-chat-message .download-message-footer .ai-model-size');
								if(download_size_el){
									//console.log("total_bytes: ", total_bytes);
									//console.log("total_bytes/100000000: ", total_bytes/100000000);
									//console.log("total_bytes/100000000 rounded: ", Math.round(total_bytes / 100000000));
									let gigas = Math.round(total_bytes / 100000000) / 10
									//const file_total = (Math.round(total_bytes / (100000000)) / 10);
									if(gigas > 0.1){
										download_size_el.innerHTML = '<span class="ai-model-size-number">' + gigas + '</span><span class="ai-model-size-gb">GB</span>';
									}
									
								}
								
								let percentage = (loaded_bytes / total_bytes) * 100;
								
								let translation_progress_el = document.getElementById('download-progress-translation');
								if(translation_progress_el == null){
									console.error("translation (down)load progress element is missing");
									add_chat_message('current','translation','download_progress#setting---');
									translation_progress_el = document.getElementById('download-progress-translation');
								}
								
								
								if(translation_previous_percentage > percentage){
									translation_previous_percentage = 0;
									if(translation_progress_el){
										translation_progress_el.value = 0;
									}
									
								}
								else{
									if(translation_progress_el){
										translation_progress_el.value = loaded_bytes / total_bytes; //e.data.progress / 100;
									}
							
									if(loaded_bytes == total_bytes >= 1000000){
										//console.log("loading translation model seems to be complete. Resetting downloaded files list");
										translation_files = {};
										translation_previous_percentage = 0;
									}
								}
								
								if(percentage == 100){
									setTimeout(() => {
										let download_translation_el = document.querySelector('.message.pane-translation.download-progress-chat-message');
										if(download_translation_el){
											download_translation_el.remove();
										}
									},3000);
								}
							
								
							
							}
							
						}
					}
					
					
					
					
					
					
				
				}
				else if(e.data.status == 'exists'){
					//console.log("translation worker sent exists message");
					window.translation_worker_exists = true;
					resolve(true);
				}
				
				else if(e.data.status == 'pipeline_constructed'){
					//console.log("translation worker sent pipeline_constructed message");
					if(document.body.classList.contains('show-rewrite')){
						flash_message(get_translation("Translation_AI_has_loaded"));
					}
					
				}
				
				else if(e.data.status == 'ready'){
					//console.log("translation worker sent ready message");
					window.translation_worker_busy = false;
					add_chat_message('current','developer',get_translation('Translation_AI_has_loaded'));
					let translation_progress_el = document.getElementById('download-progress-translation');
					if(translation_progress_el){
						//console.log("found download progress element");
						const translation_progress_message_el = translation_progress_el.closest('.message');
						if(translation_progress_message_el){
							//console.log("adding download-complete-chat-message class to translation download message");
							translation_progress_message_el.classList.add('download-complete-chat-message');
						}
						translation_progress_el.classList.add('download-complete-chat-message');
						translation_progress_el.removeAttribute('id');
						setTimeout(() => {
							translation_progress_message_el.remove();
						},500);
					}
					else{
						console.error("translation became ready, but cannot find loading progress indicator element");
					}
				}
			
				else if(e.data.status == 'initiate'){
					//console.log("translation worker sent initiate message");
				}
			
				//https://huggingface.co/Xenova/opus-mt-nl-en/resolve/main/onnx/decoder_model_merged_quantized.onnx?download=true
			
				else if(e.data.status == 'download'){
					//console.log("translation worker sent download message: ", e.data.file);
					const file_to_cache = 'https://www.huggingface.co/' + e.data.name + '/resolve/main/' + e.data.file;
					//console.log("translation worker: file to cache: ", file_to_cache)
					
					
				}
			
				else if(e.data.status == 'download_required'){
					//console.log("translation worker sent 'download_required' message.");
					flash_message(get_translation("A_model_has_to_be_downloaded_from_the_internet_but_there_is_no_internet_connection"), 4000, 'fail');
				}
			
				else if(e.data.status == 'done'){
					//console.log("translation worker sent 'done' message. Seems to be for a file being done downloading");
				}
			
				else if(e.data.status == 'update'){
					//console.log("translation worker sent update: ", e.data);
					if(typeof e.data.data == 'object' && e.data.data != null && e.data.data.length){
						set_chat_status(e.data.data[0],2);
					}
				}
				else if(e.data.status == 'translation_progress'){
					//console.log("translation worker sent translation progress update: ", e.data);
					if(typeof e.data.task != 'undefined' && typeof e.data.task.index == 'number' && typeof e.data.sentences_count == 'number' && typeof e.data.sentences_total == 'number' && typeof e.data.sentence == 'string'){
						let document_translation_progress_bar_el = document.getElementById('translation-progress-bar' + e.data.task.index);
						if(document_translation_progress_bar_el){
							document_translation_progress_bar_el.value = e.data.sentences_count / e.data.sentences_total;
						}
						let document_translation_progress_next_sentence_el = document.getElementById('translation-progress-next-sentence' + e.data.task.index);
						if(document_translation_progress_next_sentence_el){
							document_translation_progress_next_sentence_el.textContent = e.data.sentence;
						}
						
						let simple_task_details_sentence_el = document.getElementById('simple-task-details-sentence' + e.data.task.index);
						if(simple_task_details_sentence_el){
							simple_task_details_sentence_el.textContent = e.data.sentence;
						}
						
					}
					else{
						console.error("translation worker progress update message did not have all expected attributes: ", e.data);
					}
				}
				else if(e.data.status == 'chunk'){
					//console.log("translation worker sent translated chunk: ", e.data, "\ntask: ", e.data.task);
					
					
					let task_index = null;
					if(typeof e.data.task != 'undefined' && typeof e.data.task.index == 'number'){
						
						window.handle_chunk(e.data.task, e.data.response_so_far, '',  e.data.chunk);
						
						task_index = e.data.task.index;
						if(typeof e.data.task.parent_index == 'number'){
							//console.log("translation worker sent translated chunk, and the task has a parent task with index: ", e.data.task.parent_index);
							task_index = e.data.task.parent_index;
						}
					}
					if(typeof e.data.sentences_count == 'number' && typeof e.data.sentences_total == 'number'){
						let translation_progress_count_el = document.getElementById('rewrite-results-count-wrapper' + task_index);
						if(translation_progress_count_el){
							//console.log("OK, found translation task count-wrapper element, in which to place the progress percentage");
							translation_progress_count_el.textContent = (Math.floor((e.data.sentences_count / e.data.sentences_total) * 1000) / 10) + '%';
						}
					}
				}
			
				else if(e.data.status == 'complete' || e.data.status == 'translation_complete' || e.data.status == 'translation_interrupted'){
					window.translation_worker_busy = false;
					set_chat_status('',2);
					//console.log('GOT TRANSLATION COMPLETE.  e.data.status, e.data: ', e.data.status, e.data);
					//console.log('GOT TRANSLATION COMPLETE.  e.data.translation: ', e.data.translation);
					//console.log('GOT TRANSLATION COMPLETE.  e.data.task: ', e.data.task);
				
					if(e.data.status == 'translation_interrupted' && typeof e.data.task != 'undefined'){
						window.handle_completed_task(e.data.task,false,{'state':'interrupted'});
					}
					else if(e.data.translation == null){
						console.error("translation translation was null");
						window.handle_completed_task(e.data.task,false,{'state':'failed'});
					}
					else if(typeof e.data.translation != 'undefined'){
						//console.log("translation worker returned translation: ", e.data.translation);
					
						if(Array.isArray(e.data.translation)){
							//console.log("typeof translation is array");
							window.handle_completed_task(e.data.task,e.data.translation[0].translation_text);
						}
						else if(typeof e.data.translation == 'object'){
							if(typeof e.data.translation.text == 'string'){
								//console.log("GOT TEXT: ", e.data.translation.text);
								window.handle_completed_task(e.data.task,e.data.translation.text);
							}
						}
						else if(typeof e.data.translation == 'string'){
							//console.log("GOT TEXT e.data.translation: ", e.data.translation);
							window.handle_completed_task(e.data.task, e.data.translation);
						}
					}
					else{
						console.error("translation was not in translation e.data?");
						window.handle_completed_task(e.data.task,false,{'state':'failed'});
					}
				
				}
				
				else if(e.data.status == 'error'){
					console.error("translation worker sent an error message: ", e.data);
					if(typeof e.data.error == 'string'){
						console.error("translation worker error is: ", e.data.error);
						if(e.data.error.indexOf('no available backend found') != -1){
							flash_message(get_translation('A_model_needs_to_be_downloaded_but_there_is_no_internet_connection'),10000,'warn');
						}
						else if(e.data.error.indexOf('sentence to translate was not found') != -1){
							console.error("translation worker sent 'sentence to translate was not found' error: ", e.data);
							flash_message(get_translation('An_error_occured'),4000,'error');
						}else{
							console.error("translation worker sent unanticipated error: ", e.data);
							flash_message(get_translation('An_error_occured'),4000,'error');
						}
						if(typeof e.data.task != 'undefined' && e.data.task != null){
							window.clean_up_dead_task(e.data.task);
						}
						
					}
					
					window.translation_worker_busy = false;
				}
				else{
					//console.log("translation worker sent an unexpected content message: ", e.data);
					window.translation_worker_busy = false;
				}
			}
			
	
		});


		window.real_translation_worker.addEventListener('error', (error) => {
			console.error("ERROR: translation_worker sent error. terminating!. Error was: ", error, error.message);
			translation_worker_error_count++;
		
			window.real_translation_worker.terminate();
			window.translation_worker = null;
			window.translation_worker_busy = false;
			if(typeof error != 'undefined' && translation_worker_error_count < 10){
				setTimeout(() => {
					//console.log("attempting to restart translation worker");
					create_translation_worker();
				},1000);
			}
			else{
				console.error("translation_worker errored out");
			}
		});
		
		
	});
	
	
	
	
}



window.do_translation = async function (task){ // translation_queue_item
	//console.log("in do_translation. Task: ", task);
	
	//await caches.open(window.cache_name).then((my_cache) => my_cache.add(e.data.file))
	//await create_translation_worker();
	
	return new Promise((resolve, reject) => {
		
		if(task == null){
			console.error("do_translation: task was null");
			reject(false);
			return false
		}
	
		if(window.translation_worker_busy == true){
			console.error("do_translation: ABORTING. window.translation_worker_busy was already true. task: ", task);
			reject(false);
			return false
		}
		
		window.translation_worker_busy = true;
		
		
		if(window.translation_worker == null){
			//console.log("do_translation: calling create_translation_worker");
			create_translation_worker()
			.then((value) => {
				//console.log("do_translation: .then: create_translation_worker should be done now. value: ",value);
				//console.log("do_translation: window.translation_worker: ", window.translation_worker);
			
				if(window.translation_worker == null){
					console.error("do_translation: creating translation promise worker failed");
					reject(false);
				}
				else{
					console.warn("do_translation: window.translation_worker seems to exist: ", window.translation_worker);
					//translation_worker.postMessage({'task':task});
			
					window.translation_worker.postMessage({
						'task':task
					})
					.then((response) => {
						//console.error("\n\nOK\n\ndo_translation: in promiseWorker then\n\n");
						//console.log("promise worker response: ", response);
						resolve(response);
						return response;
					})
					.catch((err) => {
						console.error("do_translation: translation promise worker: received error which was caught in worker: ", err);
						window.clean_up_dead_task(task);
						reject(false);
						return false;
					})
			
				}
			
			})
			.then((value) => {
				//console.log("do_translation: start promise worker: final then: value: ", value);
				resolve(value);
			})
			.catch((err) => {
				console.error("do_translation: caught error from create_translation_worker: ", err);
			})
		}
		else{
			//console.log("do_translation: worker already existed. doing postMessage. sending:  task,translation_worker: ", task, window.translation_worker);
			
			window.translation_worker.postMessage({
				'task':task
			})
			.then((response) => {
				console.error("\n\nOK\n\ndo_translation: in translation promiseWorker.then\n\n");
				//console.log("translation promise worker response: ", response);
				resolve(response);
				return response;
			})
			.catch((err) => {
				console.error("do_translation: promise translation worker: received error which was caught in worker: ", err);
				reject(false);
				return false;
			})
		}
		
		
	});
	
}



window.interrupt_translation = async function (){
	//console.log("in interrupt_translation");
	if(window.real_translation_worker != null){
		window.real_translation_worker.postMessage({'action':interrupt})
	}
}


window.add_and_do_translation = async function (task,detect_language=true){
	//console.log("in add_and_do_translation. task: ", task);
	return new Promise((resolve, reject) => {
		
		let language_detection_result = null;
		let detected_language = window.settings.language;
		if(typeof task.input_language == 'string'){
			detected_language = task.input_language;
		}
		
		let source_text = null;
		if(typeof task.text == 'string' && task.text.length > 10){
			source_text = task.text;
		}
		else if(typeof task.prompt == 'string' && task.prompt.length > 10){
			source_text = task.prompt;
		}
		else if(typeof task.sentence == 'string' && task.sentence.length > 10){
			source_text = task.sentence;
		}
		
		if(typeof source_text != 'string'){
			console.error("add_and_do_translation: no string to translate");
			reject(null);
			return
		}
		
		add_script('./js/eld.M60.min.js')
		.then((value) => {

			//console.log("add_and_do_translation: loaded language detection script? value: ", value);
			//console.log("add_and_do_translation: language detection script: eld.info: ", eld.info() );

			if(typeof source_text == 'string' && translation_details_el.open){
				//detected_language = window.settings.input_language;
				
				if((window.settings.auto_detect_input_language && typeof task.input_language != 'string') || detect_language === true){
					language_detection_result = eld.detect(source_text);
					if(typeof language_detection_result.language == 'string' && language_detection_result.isReliable()){
						detected_language = language_detection_result.language;
					}
					else{
						detected_language = window.settings.input_language;
					}
				}
				else{
					detected_language = window.settings.input_language;
				}
				
			}
			if(typeof task.input_language != 'string'){
				task['input_language'] = detected_language;
			}

			if(typeof task['output_language'] == 'undefined'){
				if(typeof window.settings.output_language == 'string'){
					task['output_language'] = window.settings.output_language;
				}
				else{
					console.error("no window.settings.output_language set?  window.settings: ", window.settings);
					task['output_language'] = translation_output_language_select_el;
				}
			}
			
			//console.log("add_and_do_translation: language_detection_result: ", language_detection_result, source_text);

			return add_script('./translation_module.js');

		})
		.then((value) => {
			//console.log("add_and_do_translation: translation_module should now be loaded. value: ", value);

			//window.translation_worker_busy = true;
			document.body.classList.add('doing-translation');
			
			
			//console.log("add_and_do_translation: final 'detected' input language: ", detected_language);
			
			window.do_translation(task)
			.then((value) => {
				//console.log("add_and_do_translation: interval: do_translation was resolved.  value: ", value);
			
				if(value && typeof value.task != 'undefined' && typeof value.translation != 'undefined'){
					//console.log("add_and_do_translation: do_translation resolved a task and translation: ", value);
					resolve(value);
				}
				else{
					reject(task);
				}				
				window.translation_worker_busy = false;
				document.body.classList.remove('doing-translation');
			})
			.catch((err) => {
				console.error("main: do_translation was rejected. err: ", err);
				window.translation_worker_busy = false;
				document.body.classList.remove('doing-translation');
				flash_message(get_translation('Translation_failed'),3000,'fail');
				reject(task);
			})


		})
		.catch((err) => {
			console.error("Caught general error in add_and_do_translation: ", err);
			reject(task);
		})
		
	})
	
}

























