using System;
using System.Collections;
using System.Collections.Generic;
namespace Luneraria.Core
{
///
/// Map with a defined iteration order: insertion order; removing a key keeps the order of
/// the others and a key added again goes to the end. The rules iterate buildings, effects
/// and damage-over-time entries; with this map that order never depends on hashing or on
/// the history of a Dictionary (docs/port/U1-RULES.md, determinism).
///
public sealed class OrderedMap : IEnumerable>
{
readonly Dictionary _index = new Dictionary();
readonly List _keys = new List();
readonly List _values = new List();
public int Count { get { return _keys.Count; } }
public IReadOnlyList Keys { get { return _keys; } }
public IReadOnlyList Values { get { return _values; } }
public bool ContainsKey(TKey key) { return _index.ContainsKey(key); }
public TValue this[TKey key]
{
get { return _values[_index[key]]; }
set
{
int at;
if (_index.TryGetValue(key, out at))
{
_values[at] = value;
return;
}
_index[key] = _keys.Count;
_keys.Add(key);
_values.Add(value);
}
}
public bool TryGetValue(TKey key, out TValue value)
{
int at;
if (_index.TryGetValue(key, out at))
{
value = _values[at];
return true;
}
value = default(TValue);
return false;
}
public TValue GetValueOrDefault(TKey key, TValue fallback)
{
int at;
return _index.TryGetValue(key, out at) ? _values[at] : fallback;
}
public bool Remove(TKey key)
{
int at;
if (!_index.TryGetValue(key, out at))
return false;
_keys.RemoveAt(at);
_values.RemoveAt(at);
_index.Remove(key);
for (int i = at; i < _keys.Count; i++)
_index[_keys[i]] = i;
return true;
}
public void Clear()
{
_index.Clear();
_keys.Clear();
_values.Clear();
}
/// Copy in the same order; values are copied with the given function.
public OrderedMap Clone(Func copy = null)
{
var result = new OrderedMap();
for (int i = 0; i < _keys.Count; i++)
result[_keys[i]] = copy != null ? copy(_values[i]) : _values[i];
return result;
}
public IEnumerator> GetEnumerator()
{
for (int i = 0; i < _keys.Count; i++)
yield return new KeyValuePair(_keys[i], _values[i]);
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
}