// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
// ReSharper disable MemberCanBePrivate.Global
namespace Doozy.Runtime.Common
{
/// List database of key and value pairs
/// Key type
/// Value type
[SuppressMessage("ReSharper", "InconsistentNaming")]
[Serializable]
public class ListDatabase : IListDatabase
{
private readonly Type m_keyType;
private readonly Type m_valueType;
/// Database of keys and lists of values
public Dictionary> Database { get; }
/// All the keys in the database
public Dictionary>.KeyCollection Keys => Database.Keys;
/// All the values in the database
public Dictionary>.ValueCollection Values => Database.Values;
public ListDatabase()
{
m_keyType = typeof(TKey);
m_valueType = typeof(TValue);
Database = new Dictionary>();
}
/// Add a new key to the database with the default value
/// New key
public void Add(TKey key)
{
if (Database.ContainsKey(key)) return;
Database.Add(key, new List());
}
/// Add a new key to the database with the given value
/// New key
/// New value
public void Add(TKey key, TValue value)
{
if (ContainsKey(key))
{
if (ContainsValue(key, value))
return;
if (Database[key] == null)
Database[key] = new List();
Database[key].Add(value);
return;
}
Database.Add(key, new List {value});
}
/// Clear the database
public void Clear() =>
Database.Clear();
/// Check if the database contains the given key
/// Key to search for
/// True or False
public bool ContainsKey(TKey key) =>
Database.ContainsKey(key);
/// Check if the database contains the given key and value pair
/// Key to search for
/// Value to search for
/// True or False
public bool ContainsValue(TKey key, TValue value) =>
ContainsKey(key) && Database[key].Contains(value);
/// Check if the database contains the given value
/// Value to search for
/// True or False
public bool ContainsValue(TValue value) =>
Database.Keys.Any(key => Database[key].Contains(value));
/// Get the number of keys in the database
/// Number of keys in the database
public int CountKeys() =>
Database.Keys.Count;
/// Get the number of values for the given key
/// Key to search for
/// Number of values for the given key
public int CountValues(TKey key) =>
Database.ContainsKey(key)
? Database[key].Count
: 0;
/// Get a list of all the values for the given key
/// Key to search for
/// A new List with all the values for the given key
public List GetValues(TKey key) =>
key == null || !ContainsKey(key) || Database[key] == null
? new List()
: Database[key].ToList();
/// Get a list of all the keys in the database
/// A new list with all the keys in the database
public List GetKeys() =>
Keys.ToList();
/// Remove the given key from the database
/// Key to remove
public void Remove(TKey key)
{
if (!ContainsKey(key)) return;
Database.Remove(key);
}
/// Remove the value from the given key
/// Key to search for
/// Value to remove
/// If TRUE and the list of values is empty, the key will be removed as well
public void Remove(TKey key, TValue value, bool deleteEmptyKey = true)
{
if (!ContainsValue(key, value)) return;
Database[key].Remove(value);
if (!deleteEmptyKey) return;
if (Database[key].Count == 0) Database.Remove(key);
}
/// Remove the value from the database
/// Value to remove
/// If TRUE and the list of values is empty, the key will be removed as well
public void Remove(TValue value, bool deleteEmptyKey = true)
{
if (!ContainsValue(value)) return;
var keysToRemove = new List();
foreach (TKey key in Database.Keys.Where(key => Database[key].Contains(value)))
{
Database[key].Remove(value);
if (!deleteEmptyKey) continue;
if (Database[key].Count == 0) keysToRemove.Add(key);
}
if (!deleteEmptyKey) return;
foreach (TKey key in keysToRemove) Database.Remove(key);
}
/// Validate the database by removing null entries
/// If TRUE and empty keys are found, they will be removed
public void Validate(bool deleteEmptyKeys = true)
{
var keysToRemove = new List();
foreach (TKey key in Database.Keys)
{
for (int i = Database[key].Count - 1; i >= 0; i--)
{
TValue value = Database[key][i];
if (value != null) continue;
Database[key].RemoveAt(i);
}
if (!deleteEmptyKeys) continue;
if (Database[key].Count == 0) keysToRemove.Add(key);
}
if (!deleteEmptyKeys) return;
foreach (TKey key in keysToRemove) Database.Remove(key);
}
}
}