// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
using System.Runtime.InteropServices;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;

namespace UnityEngine.InputSystem.XR.Haptics
{
    [StructLayout(LayoutKind.Explicit, Size = kSize)]
    public unsafe struct SendBufferedHapticCommand : IInputDeviceCommandInfo
    {
        static FourCC Type => new FourCC('X', 'H', 'U', '0');

        private const int kMaxHapticBufferSize = 1024;
        private const int kSize = InputDeviceCommand.kBaseCommandSize + (sizeof(int) * 2) + (kMaxHapticBufferSize * sizeof(byte));

        public FourCC typeStatic => Type;

        [FieldOffset(0)]
        private InputDeviceCommand baseCommand;

        [FieldOffset(InputDeviceCommand.kBaseCommandSize)]
        private int channel;

        [FieldOffset(InputDeviceCommand.kBaseCommandSize + sizeof(int))]
        private int bufferSize;

        [FieldOffset(InputDeviceCommand.kBaseCommandSize + (sizeof(int) * 2))]
        private fixed byte buffer[kMaxHapticBufferSize];

        public static SendBufferedHapticCommand Create(byte[] rumbleBuffer)
        {
            if (rumbleBuffer == null)
                throw new System.ArgumentNullException(nameof(rumbleBuffer));

            var rumbleBufferSize = Mathf.Min(kMaxHapticBufferSize, rumbleBuffer.Length);
            var newCommand = new SendBufferedHapticCommand
            {
                baseCommand = new InputDeviceCommand(Type, kSize),
                bufferSize = rumbleBufferSize
            };

            //TODO TOMB: There must be a more effective, bulk copy operation for fixed buffers than this.
            //Replace if found.
            var commandPtr = &newCommand;
            fixed(byte* src = rumbleBuffer)
            {
                for (int cpyIndex = 0; cpyIndex < rumbleBufferSize; cpyIndex++)
                    commandPtr->buffer[cpyIndex] = src[cpyIndex];
            }

            return newCommand;
        }
    }
}
#endif