using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using UnityEngine;

namespace Framework.GuardianSaveSystem
{
    /// <summary>
    /// A data collection for a specific gameObject in the game world. Also keeps track
    /// of the object id and the components on the object, though this is not currently used.
    /// The prefab name is required to recreate the object if it does not exist in the 
    /// scene.
    /// </summary>
    [Serializable]
    public class ObjectDataMap //: Dictionary<string, object>
    {
        public int id; // The instance id of the gameObject that this ObjectDataMap stores data for
        public Dictionary<int, Type> components; // A component list for this gameObject (not used)
        public Dictionary<string, object> data; // The object data to save, a map of names to object values 
        public string prefabName; // The name of the prefab to load if this obhect does not exist in the current scene

        /// <summary>
        /// Instantiates a new <see cref="ObjectDataMap"/> instance.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="prefabName"></param>
        /// <param name="components"></param>
        public ObjectDataMap(int id, string prefabName, Dictionary<int, Type> components) : this(id, prefabName)
        {
            this.components = components;
        }

        /// <summary>
        /// Instantiates a new <see cref="ObjectDataMap"/> instance.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="prefabName"></param>
        public ObjectDataMap(int id, string prefabName)
        {
            this.id = id;
            this.prefabName = prefabName;
            this.components = new Dictionary<int, Type>();
            this.data = new Dictionary<string, object>();
        }

        /// <summary>
        /// Adds a new data key value pair to the data map.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(string key, object value)
        {
            data.Add(key, value);
        }

        /// <summary>
        /// Gets a value from the data map by key name.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            return (T)data[key];
        }

        /// <summary>
        /// Checks whether or not the data map contains a given key.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(string key)
        {
            return data.ContainsKey(key);
        }

        /// <summary>
        /// Get the id of the <see cref="GameObject"/> that this data map relates to.
        /// </summary>
        /// <returns></returns>
        public int GetId()
        {
            return this.id;
        }

        /// <summary>
        /// Gets the name of the prefab that this object data map should create if the 
        /// related <see cref="GameObject"/> cannot be found.
        /// </summary>
        /// <returns></returns>
        public string GetPrefabName()
        {
            return this.prefabName;
        }

        /// <summary>
        /// Sets the components list on this data map. Not used.
        /// </summary>
        /// <param name="components"></param>
        public void SetComponents(Component[] components)
        {
            // Store their names
            this.components = new Dictionary<int, Type>();
            for (int i = 0; i < components.Length; i++)
            {
                this.components.Add(components[i].GetInstanceID(), components[i].GetType());
            }
        }

        /// <summary>
        /// Gets the component list on this data map.
        /// </summary>
        /// <returns></returns>
        public Dictionary<int, Type> GetComponents()
        {
            return this.components;
        }
    }
}
