namespace ns_view
{
	
	/**
	 * clears the content and focus on the message content input
	 */
	function clear_content
	(
	): void
	{
		let dom_content: HTMLInputElement = document.querySelector<HTMLInputElement>("#content");
		dom_content.value = "";
		dom_content.focus();
	}
	
	
	/**
	 * updates the state (switches between login, connecting and regular "page")
	 */
	function update_state
	(
		model: type_model
	): void
	{
		document.querySelector("body").setAttribute("class", model.state);
	}


	/**
	 * updates the spots (channels and queries)
	 */
	function update_spots
	(
		conf: type_conf,
		model: type_model
	): void
	{
		let dom_spots: HTMLUListElement = document.querySelector("#spots");
		const spots: Array<type_spot> = (
			[]
			.concat(Object.keys(model.channels).map((name) => ({"kind": "channel", "name": name})))
			.concat(Object.keys(model.queries).map((name) => ({"kind": "query", "name": name})))
		);
		dom_spots.textContent = "";
		for (const spot of spots)
		{
			let dom_spot: HTMLLIElement = document.createElement("li");
			dom_spot.classList.add("spot");
			{
				let dom_kind: HTMLSpanElement = document.createElement("span");
				dom_kind.classList.add("spot_kind");
				dom_kind.textContent = spot.kind;
				dom_spot.appendChild(dom_kind);
			}
			{
				let dom_name: HTMLSpanElement = document.createElement("span");
				dom_name.classList.add("spot_sender");
				dom_name.textContent = spot.name;
				dom_spot.appendChild(dom_name);
			}
			dom_spot.classList.toggle("spot_active", ((spot.kind === model.active.kind) && (spot.name === model.active.name)));
			dom_spot.setAttribute("rel", JSON.stringify(spot));
			dom_spots.appendChild(dom_spot);
		}
		// meeh…
		ns_control.setup(conf, model);
		
		clear_content();
	}


	/**
	 * updates the chat entries
	 */
	function update_entries
	(
		model: type_model
	): void
	{
		let dom_entries: HTMLUListElement = document.querySelector("#entries");
		let entries: Array<type_entry>;
		switch (model.active.kind)
		{
			case "channel":
			{
				entries = model.channels[model.active.name].entries;
				break;
			}
			case "query":
			{
				entries = model.queries[model.active.name].entries;
				break;
			}
		}
		dom_entries.textContent = "";
		for (const entry of entries)
		{
			switch (entry.kind)
			{
				default:
				{
					console.warn(`unhandled entry kind '${entry.kind}'`);
					break;
				}
				case enum_entrykind.info:
				{
					let dom_entry: HTMLLIElement = document.createElement("li");
					dom_entry.classList.add("entry");
					dom_entry.classList.add("entry_info");
					{
						let dom_time: HTMLSpanElement = document.createElement("span");
						dom_time.classList.add("entry_time");
						dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19);
						dom_entry.appendChild(dom_time);
					}
					{
						let dom_content: HTMLSpanElement = document.createElement("span");
						dom_content.classList.add("entry_content");
						dom_content.textContent = `-- ${entry.content}`;
						dom_entry.appendChild(dom_content);
					}
					dom_entries.appendChild(dom_entry);
					break;
				}
				case enum_entrykind.message:
				{
					let dom_entry: HTMLLIElement = document.createElement("li");
					dom_entry.classList.add("entry");
					dom_entry.classList.add("entry_message");
					{
						let dom_time: HTMLSpanElement = document.createElement("span");
						dom_time.classList.add("entry_time");
						dom_time.textContent = (new Date(entry.timestamp*1000)).toISOString().slice(11, 19);
						dom_entry.appendChild(dom_time);
					}
					{
						let dom_sender: HTMLSpanElement = document.createElement("span");
						dom_sender.classList.add("entry_sender");
						dom_sender.style.color = get_usercolor(entry.sender);
						dom_sender.textContent = entry.sender;
						dom_entry.appendChild(dom_sender);
					}
					{
						let dom_content: HTMLSpanElement = document.createElement("span");
						dom_content.classList.add("entry_content");
						dom_content.textContent = entry.content;
						dom_entry.appendChild(dom_content);
					}
					dom_entries.appendChild(dom_entry);
					break;
				}
			}
		}
		dom_entries.scrollTo(0, dom_entries["scrollTopMax"]);
	}


	/**
	 * updates the user list
	 */
	function update_users
	(
		conf: type_conf,
		model: type_model
	): void
	{
		let dom_users: HTMLUListElement = document.querySelector("#users");
		dom_users.textContent = "";
		let users: Array<type_user>;
		switch (model.active.kind)
		{
			default:
			{
				console.warn("unhandled kind: " + model.active.kind);
				users = [];
				break;
			}
			case "channel":
			{
				users = model.channels[model.active.name].users;
				break;
			}
			case "query":
			{
				users = [{"name": model.nickname, "role": ""}, {"name": model.active.name, "role": ""}];
				break;
			}
		}
		const users_sorted: Array<type_user> = users.sort
		(
			(x, y) =>
			(
				(x.role >= y.role)
				? -1
				: (
					(x.role === y.role)
					? ((x.name < y.name) ? -1 : +1)
					: +1
				)
			)
		);
		for (const user of users_sorted)
		{
			let dom_user: HTMLLIElement = document.createElement("li");
			dom_user.classList.add("user");
			{
				let dom_role: HTMLSpanElement = document.createElement("span");
				dom_role.textContent = user.role;
				dom_user.appendChild(dom_role);
			}
			{
				let dom_name: HTMLSpanElement = document.createElement("span");
				dom_name.textContent = user.name;
				dom_name.style.color = get_usercolor(user.name);
				dom_user.appendChild(dom_name);
			}
			dom_user.setAttribute("rel", JSON.stringify(user.name));
			dom_users.appendChild(dom_user);
		}
		// meeh…
		ns_control.setup(conf, model);
	}


	/**
	 * sets up the view
	 */
	export function setup
	(
		conf: type_conf,
		model: type_model
	): void
	{
		document.querySelector<HTMLInputElement>("#channel").value = conf.irc.predefined_channel;
		document.querySelector<HTMLInputElement>("#nickname").value = (conf.irc.predefined_nickname_prefix + (Math.random()*100).toFixed(0));
		
		ns_model.listen(model, "state_changed", () => {update_state(model);});
		ns_model.listen(model, "spots_changed", () => {update_spots(conf, model);});
		ns_model.listen(model, "entries_changed", () => {update_entries(model);});
		ns_model.listen(model, "users_changed", () => {update_users(conf, model);});
		ns_model.listen(model, "message_sent", () => {clear_content();});
	}
	
}