using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace InABox.Core
{
///
/// Class to manage the storing of form data, including the separation of blob and form data.
///
public class DFSaveStorage
{
public Dictionary FormData { get; private set; }
public Dictionary BlobData { get; private set; }
public DFSaveStorage()
{
FormData = new Dictionary();
BlobData = new Dictionary();
}
public int Count() => FormData.Count();
public void AddValue(string key, object? value)
{
FormData.Add(key, value);
}
public void AddBlobValue(string key, object? value)
{
if(value != null)
{
var id = Guid.NewGuid().ToString();
BlobData.Add(id, value);
FormData.Add(key, id);
}
}
public object? GetValue(string key) => FormData.GetValueOrDefault(key);
public DFSaveStorageEntry GetEntry(string key)
{
return new DFSaveStorageEntry(this, key);
}
public DFLoadStorage ToLoadStorage()
{
return new DFLoadStorage(FormData, BlobData);
}
}
public class DFSaveStorageEntry
{
private readonly DFSaveStorage storage;
private readonly string key;
public DFSaveStorageEntry(DFSaveStorage storage, string key)
{
this.storage = storage;
this.key = key;
}
public object? GetValue() => storage.GetValue(key);
public object? GetValue(string subKey) => storage.GetValue($"{key}.{subKey}");
public void SetValue(object? value)
{
storage.AddValue(key, value);
}
public void AddValue(string subKey, object? value)
{
storage.AddValue($"{key}.{subKey}", value);
}
public void SetBlobValue(object? value)
{
storage.AddBlobValue(key, value);
}
public void AddBlobValue(string subKey, object? value)
{
storage.AddBlobValue($"{key}.{subKey}", value);
}
}
public class DFLoadStorage
{
public Dictionary FormData { get; private set; } = new Dictionary();
public DFLoadStorage() : this(new Dictionary(), null)
{
}
public DFLoadStorage(Dictionary formData, Dictionary? blobData)
{
Load(formData, blobData);
}
public void Load(Dictionary formData, Dictionary? blobData)
{
FormData = formData;
if (blobData != null)
{
var updates = new List>();
foreach (var (key, value) in FormData)
{
if ((value is string str && blobData.TryGetValue(str, out var blob))
|| (value is Guid guid && blobData.TryGetValue(guid.ToString(), out blob)))
{
updates.Add(new Tuple(key, blob));
}
}
foreach (var (key, value) in updates)
{
FormData[key] = value;
}
}
}
public void Clear() => FormData.Clear();
public int Count() => FormData.Count();
///
/// Get a value from the storage, returning if the key does not exist.
///
///
///
public object? GetValue(string key)
{
return FormData.GetValueOrDefault(key);
}
[return: MaybeNull]
public T GetValue(string key)
{
if(FormData.TryGetValue(key, out var value))
{
if(value is T t)
{
return t;
}
else if(value is string str)
{
if(Guid.TryParse(str, out var id))
{
if(id is T)
{
return (T)(object)id;
}
else
{
return default;
}
}
try
{
return Serialization.Deserialize(str, strict: true);
}
catch
{
return CoreUtils.ChangeType(value);
}
}
else if(value is JToken jToken)
{
return Serialization.Deserialize(jToken);
}
else
{
return CoreUtils.ChangeType(value);
}
}
return default;
}
public bool HasValue(string key)
{
return FormData.ContainsKey(key);
}
public DFLoadStorageEntry GetEntry(string key)
{
return new DFLoadStorageEntry(this, key);
}
public IEnumerable> Items()
{
return FormData;
}
}
public class DFLoadStorageEntry
{
private readonly DFLoadStorage storage;
private readonly string key;
public DFLoadStorageEntry(DFLoadStorage storage, string key)
{
this.storage = storage;
this.key = key;
}
///
/// Gets the value from the storage entry, returning if it does not exist.
///
///
///
public object? GetValue()
{
return storage.GetValue(key);
}
[return: MaybeNull]
public T GetValue()
{
return storage.GetValue(key);
}
///
/// Gets a sub-value from the storage entry, returning if it does not exist.
///
///
///
public object? GetValue(string subKey)
{
return storage.GetValue($"{key}.{subKey}");
}
[return: MaybeNull]
public T GetValue(string subKey)
{
return storage.GetValue($"{key}.{subKey}");
}
public bool HasValue() => storage.HasValue(key);
public bool HasValue(string subKey) => storage.HasValue($"{key}.{subKey}");
public IEnumerable> SubItems()
{
var prefix = $"{key}.";
foreach(var (key, value) in storage.Items())
{
if (key.StartsWith(prefix))
{
yield return new KeyValuePair(key[prefix.Length..], value);
}
}
}
}
}