/*
 * 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 lib_hashmap
	{
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export type type_hashmap<type_key, type_value> =
			{
				hashfunction : (key : type_key)=>string;
				store : {[hashvalue : string] : {key : type_key; value : type_value;}};
			}
		;
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export function create<type_key, type_value>
			(
				hashfunction : (key : type_key)=>string
			)
			: type_hashmap<type_key, type_value>
			{
				return {
					"hashfunction": hashfunction,
					"store": {},
				};
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export function set<type_key, type_value>
			(
				hashmap : type_hashmap<type_key, type_value>,
				key : type_key,
				value : type_value
			)
			: void
			{
				let hashvalue : string = hashmap.hashfunction(key);
				hashmap.store[hashvalue] = {"key": key, "value": value};
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export function get<type_key, type_value>
			(
				hashmap : type_hashmap<type_key, type_value>,
				key : type_key
			)
			: lib_errormonade.type_errormonade<type_value>
			{
				let hashvalue : string = hashmap.hashfunction(key);
				if (hashvalue in hashmap.store)
					{
						let value : type_value = hashmap.store[hashvalue].value;
						return (lib_errormonade.create_just<type_value>(value));
					}
				else
					{
						return (lib_errormonade.create_nothing<type_value>());
					}
			}
		
		
		/**
		 * @author kcf <vidofnir@folksprak.org>
		 */
		export function iterate<type_key, type_value>
			(
				hashmap : type_hashmap<type_key, type_value>,
				procedure : (key ?: type_key, value ?: type_value)=>void
			)
			: void
			{
				Object.keys(hashmap.store).forEach
					(
						(hashvalue) =>
							{
								let paar : {key : type_key; value : type_value;} = hashmap.store[hashvalue];
								procedure(paar.key, paar.value);
							}
					)
				;
			}
		
	}

