using System;

////REVIEW: this (and the generated C# wrappers) really should be a struct but we can't inherit :/

////TODO: nuke Clone()

namespace UnityEngine.Experimental.Input
{
    /// <summary>
    /// Base class for wrappers generated by the input asset importer.
    /// </summary>
    /// <remarks>
    /// Has a custom property drawer that allows dropping assets onto the
    /// wrapper property.
    /// </remarks>
    [Serializable]
    public class InputActionAssetReference : ICloneable
    {
        /// <summary>
        /// The asset being referenced.
        /// </summary>
        public InputActionAsset asset
        {
            get { return m_Asset; }
            protected set { m_Asset = value; }
        }

        public InputActionAssetReference()
        {
        }

        public InputActionAssetReference(InputActionAsset asset)
        {
            m_Asset = asset;
        }

        public void Enable()
        {
            var sets = asset.actionMaps;
            for (var i = 0; i < sets.Count; ++i)
                sets[i].Enable();
        }

        public void Disable()
        {
            var sets = asset.actionMaps;
            for (var i = 0; i < sets.Count; ++i)
                sets[i].Disable();
        }

        /// <summary>
        /// Duplicate the referenced <see cref="asset"/> and all its action maps and actions.
        /// </summary>
        /// <remarks>
        /// This method is useful to be able to use the same asset multiple times but configure it
        /// differently each time. A common example of this use case is local multiplayer where each
        /// player uses the same set of actions supported by the game but each player's actions are
        /// configured to respond to just the devices assigned to the specific player.
        /// </remarks>
        public virtual void MakePrivateCopyOfActions()
        {
            if (asset == null)
                return;

            // Make a duplicate that keeps all GUIDs but nukes all callbacks and such.
            asset = ScriptableObject.Instantiate(asset);
        }

        public InputActionAssetReference Clone()
        {
            var clone = (InputActionAssetReference)MemberwiseClone();
            return clone;
        }

        object ICloneable.Clone()
        {
            throw new NotImplementedException();
        }

        public static implicit operator InputActionAsset(InputActionAssetReference reference)
        {
            return reference.m_Asset;
        }

        [SerializeField] private InputActionAsset m_Asset;
    }
}
