/*
 * @license Private Source License v1.0.0
 * @copyright 2023 Reinhardt Weyers
 *
 * @author Reinhardt Weyers
 *
 * @version 0.1.0
 * 
 * Created On: 04/12/25
 * Last edited: 04/12/25
 */

using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// A dictionary that can be serialized by Unity.
/// This class extends the standard Dictionary to support Unity serialization.
/// </summary>
[Serializable]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    /// <summary>
    /// List of keys to be serialized.
    /// </summary>
    [SerializeField]
    private List<TKey> keys = new List<TKey>();

    /// <summary>
    /// List of values to be serialized.
    /// </summary>
    [SerializeField]
    private List<TValue> values = new List<TValue>();

    /// <summary>
    /// Prepares the dictionary data to be serialized.
    /// This method clears the existing keys and values lists and then populates them with the dictionary's data.
    /// </summary>
    public void OnBeforeSerialize()
    {
        keys.Clear();
        values.Clear();
        foreach (KeyValuePair<TKey, TValue> pair in this)
        {
            keys.Add(pair.Key);
            values.Add(pair.Value);
        }
    }

    /// <summary>
    /// Restores the dictionary data after deserialization.
    /// This method clears the dictionary and then populates it using the serialized keys and values lists.
    /// </summary>
    /// <exception cref="Exception">
    /// Thrown if the keys and values lists have different counts after deserialization.
    /// </exception>
    public void OnAfterDeserialize()
    {
        this.Clear();

        if (keys.Count != values.Count)
        {
            throw new Exception(string.Format("There are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable.", keys.Count, values.Count));
        }

        for (int i = 0; i < keys.Count; i++)
        {
            this.Add(keys[i], values[i]);
        }
    }
}
