/*
 * Verrückte Turing-Maschinen — A turing complete game
 * Copyright (C) 2016-2018 kcf <vidofnir@folksprak.org>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

namespace mod_vtm.mod_manifestation.mod_web.mod_game
	{
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function text_postprocess(text : string) : string
			{
				let vars : {[name : string] : string} = {};
				for (let i : int = 0; i <= 3; i += 1)
					vars["s" + i.toFixed(0)] = ("<span class=\"symbol_" + i.toFixed(0) + "\">&nbsp;&nbsp;</span>");
				return lib_string.stance(text, vars);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export type type_game =
			{
				model : mod_model.mod_game.type_game;
				area : Element;
				intervall : lib_errormonade.type_errormonade<any>;
			}
		;
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function create
			(
				model : mod_model.mod_game.type_game,
				area : Element
			)
			: type_game
			{
				return {
					"model": model,
					"area": area,
					"intervall": (lib_errormonade.create_nothing<any>()),
				};
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export function create_extended
			(
				model : mod_model.mod_game.type_game,
				area : Element
			)
			: type_manifestation<mod_model.mod_game.type_game>
			{
				return (
					lib_call.wrap
						(
							"web_game",
							create(model, area)
						)
				);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function update_task(game : type_game) : void
			{
				document.querySelector("#task_text").innerHTML = (
					text_postprocess
						(
							mod_vtm.mod_model.mod_task.text
								(
									mod_vtm.mod_model.mod_game.task_read(game.model)
								)
						)
				);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function update_world(game : type_game) : void
			{
				let node_svg : lib_xml.type_node = lib_svg.root
					(
						-4, -4,
						+4, +4,
						800, 800,
						[mod_manifestation.view(mod_svg.mod_game.create_extended(game.model))]
					)
				;
				game.area.innerHTML = lib_xml.view(node_svg);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function update_token(game : type_game) : void
			{
				let node_svg : lib_xml.type_node = lib_svg.root
					(
						-4, -4,
						+4, +4,
						800, 800,
						[mod_manifestation.view(mod_svg.mod_game.create_extended(game.model))]
					)
				;
				game.area.innerHTML = lib_xml.view(node_svg);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function update_mode(game : type_game) : void
			{
				let status : string;
				switch (mod_vtm.mod_model.mod_game.mode_read(game.model))
					{
						case mod_vtm.mod_model.mod_mode.initial:
							{
								status = lib_translate.get("model.modes.initial");
								break;
							}
						case mod_vtm.mod_model.mod_mode.uncertain:
							{
								status = lib_translate.get("model.modes.uncertain");
								break;
							}
						case mod_vtm.mod_model.mod_mode.wrong:
							{
								status = lib_translate.get("model.modes.wrong");
								break;
							}
						case mod_vtm.mod_model.mod_mode.correct:
							{
								status = lib_translate.get("model.modes.correct");
								break;
							}
						default:
							{
								let message : string = "unbehandelter Modus";
								throw (new Error(message));
								break;
							}
					}
				document.querySelector("#task_status").textContent = status;
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function update_buttons(game : type_game) : void
			{
				let mode : mod_vtm.mod_model.mod_mode.type_mode = mod_vtm.mod_model.mod_game.mode_read(game.model);
				let class_ : string;
				switch (mode)
					{
						case mod_vtm.mod_model.mod_mode.initial:
							{
								class_ = "initial";
								break;
							}
						case mod_vtm.mod_model.mod_mode.uncertain:
							{
								class_ = (
									lib_errormonade.filled<any>(game.intervall)
									? "uncertain_running"
									: "uncertain_standing"
								);
								break;
							}
						case mod_vtm.mod_model.mod_mode.wrong:
						case mod_vtm.mod_model.mod_mode.correct:
							{
								class_ = "done";
								break;
							}
						default:
							{
								throw (new Error("unbehandelt!"));
								break;
							}
					}
				document.querySelector("#buttons").setAttribute("class", class_);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function view(game : type_game) : void
			{
				update_task(game);
				update_world(game);
				update_token(game);
				update_mode(game);
				update_buttons(game);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function stop(game : type_game) : void
			{
				if (lib_errormonade.filled(game.intervall))
					{
						clearInterval(lib_errormonade.read(game.intervall));
						game.intervall = (lib_errormonade.create_nothing<any>());
					}
				else
					{
						let message : string = "kein Intervall gesetzt";
						console.warn(message);
					}
				update_buttons(game);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function resume(game : type_game) : void
			{
				mod_vtm.mod_model.mod_game.resume(game.model);
				let mode : mod_vtm.mod_model.mod_mode.type_mode = mod_vtm.mod_model.mod_game.mode_read(game.model);
				if (mode <= 1)
					{
						// nothing tun
					}
				else
					{
						stop(game);
					}
				update_buttons(game);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function testen(game : type_game) : void
			{
				let handle : any = setInterval(() => resume(game), 500);
				game.intervall = (lib_errormonade.create_just<any>(handle));
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function edit(game : type_game) : void
			{
				stop(game);
				mod_vtm.mod_model.mod_game.reset(game.model);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function clear(game : type_game) : void
			{
				mod_vtm.mod_model.mod_game.world_clear(game.model);
				mod_vtm.mod_model.mod_game.reset(game.model);
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		function bind(game : type_game) : void
			{
				let spot_determine = (target : EventTarget) =>
					{
						let spot : lib_errormonade.type_errormonade<mod_vtm.mod_model.mod_spot.type_spot>;
						let dom_tile : Element = target["closest"](".tile");
						if (dom_tile == null)
							{
								spot = (lib_errormonade.create_nothing<mod_vtm.mod_model.mod_spot.type_spot>());
							}
						else
							{
								let rel : string = dom_tile.getAttribute("rel")
								spot = (lib_errormonade.create_just<mod_vtm.mod_model.mod_spot.type_spot>(mod_vtm.mod_model.mod_spot.from_hash(rel)));
							}
						return spot;
					}
				;
				mod_vtm.mod_model.mod_game.listen
					(
						game.model,
						"change_task",
						(data) =>
							{
								update_task(game);
							}
					)
				;
				mod_vtm.mod_model.mod_game.listen
					(
						game.model,
						"change_world",
						(data) =>
							{
								update_world(game);
							}
					)
				;
				mod_vtm.mod_model.mod_game.listen
					(
						game.model,
						"change_token",
						(data) =>
							{
								update_token(game);
							}
					)
				;
				mod_vtm.mod_model.mod_game.listen
					(
						game.model,
						"change_mode",
						(data) =>
							{
								update_mode(game);
								update_buttons(game);
							}
					)
				;
				// Links-Klick
				game.area.addEventListener
					(
						"click",
						event =>
							{
								event.preventDefault();
								let spot_ : lib_errormonade.type_errormonade<mod_vtm.mod_model.mod_spot.type_spot> = spot_determine(event.target);
								if (lib_errormonade.filled(spot_))
									{
										mod_vtm.mod_model.mod_game.world_tile_change(game.model, lib_errormonade.read(spot_), false);
									}
								else
									{
										console.info("-- kein Feld");
									}
							}
					)
				;
				// Rechts-Klick
				game.area.addEventListener
					(
						"contextmenu",
						event =>
							{
								event.preventDefault();
								let spot_ : lib_errormonade.type_errormonade<mod_vtm.mod_model.mod_spot.type_spot> = spot_determine(event.target);
								if (lib_errormonade.filled(spot_))
									{
										mod_vtm.mod_model.mod_game.world_tile_change(game.model, lib_errormonade.read(spot_), true);
									}
								else
									{
										console.info("-- kein Feld");
									}
							}
					)
				;
				// Mausrad
				game.area.addEventListener
					(
						"wheel",
						event =>
							{
								event.preventDefault();
								let spot_ : lib_errormonade.type_errormonade<mod_vtm.mod_model.mod_spot.type_spot> = spot_determine(event.target);
								if (lib_errormonade.filled(spot_))
									{
										let increment : int = ((event["deltaY"] < 0) ? -1 : +1);
										mod_vtm.mod_model.mod_game.world_tile_rotate(game.model, lib_errormonade.read(spot_), increment);
									}
								else
									{
										console.info("-- kein Feld");
									}
							}
					)
				;
				// Schritt
				document.querySelector("#button_step").addEventListener
					(
						"click",
						event =>
							{
								stop(game);
								resume(game);
							}
					)
				;
				// Testen
				document.querySelector("#button_test").addEventListener
					(
						"click",
						event =>
							{
								testen(game);
							}
					)
				;
				// stop
				document.querySelector("#button_stop").addEventListener
					(
						"click",
						event =>
							{
								stop(game);
							}
					)
				;
				// edit
				document.querySelector("#button_edit").addEventListener
					(
						"click",
						event =>
							{
								edit(game);
							}
					)
				;
				// Leeren
				document.querySelector("#button_clear").addEventListener
					(
						"click",
						event =>
							{
								clear(game);
							}
					)
				;
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		lib_trait.attend<signature_manifestation<mod_vtm.mod_model.mod_game.type_game, void>>
			(
				trait_manifestation,
				"web_game",
				{
					"view": (manifestation) => view(manifestation.data),
					"bind": (manifestation) => bind(manifestation.data),
				}
			)
		;
		
	}

