using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;

namespace OkonaPad
{
    /// <summary>
    /// An Okona player's controller, surfaced to the game as a standard Unity
    /// <see cref="Gamepad"/>. Because it derives from Gamepad, every normal control
    /// and binding works out of the box: <c>Gamepad.all</c>, <c>buttonSouth</c>,
    /// <c>leftStick</c>, <c>rightTrigger</c>, <c>dpad</c>, <c>&lt;Gamepad&gt;/…</c>
    /// Input Action bindings, etc. The only addition is <see cref="okonaSlot"/>,
    /// the 0-based player slot (P1 = 0) the web layer assigned.
    /// </summary>
    [InputControlLayout(displayName = "Okona Pad", stateType = typeof(GamepadState))]
    public class OkonaPadDevice : Gamepad
    {
        /// <summary>0-based Okona player slot (P1 = 0 … P6 = 5); -1 until assigned.</summary>
        public int okonaSlot { get; internal set; } = -1;

        /// <summary>
        /// What this player is holding — a controller, a paired phone, or the
        /// keyboard. Input is identical either way; this is for the game's own UI
        /// ("Phone joined as P3", a phone-shaped glyph in the lobby).
        /// </summary>
        public OkonaPadState.PadKind okonaKind { get; internal set; }

        /// <summary>
        /// This player's controller is gone — their phone closed its page, their
        /// pad went to sleep — but the slot is held so they get the same player
        /// back if they return. The device deliberately stays alive (that's what
        /// makes returning seamless), so a game that lets players leave mid-round
        /// must poll this: it is the only signal that somebody walked away.
        /// </summary>
        public bool okonaParked { get; internal set; }

        /// <summary>
        /// Standard Unity rumble — <c>Gamepad.SetMotorSpeeds(low, high)</c> — forwarded
        /// to the physical pad through the web layer (window.okonaOnRumble). Games just
        /// call the normal Gamepad API; no Okona-specific code needed.
        /// </summary>
        public override void SetMotorSpeeds(float lowFrequency, float highFrequency)
        {
            base.SetMotorSpeeds(lowFrequency, highFrequency);
            if (okonaSlot >= 0) OkonaInterop.Rumble(okonaSlot, lowFrequency, highFrequency);
        }

        public override void PauseHaptics()
        {
            base.PauseHaptics();
            if (okonaSlot >= 0) OkonaInterop.Rumble(okonaSlot, 0f, 0f);
        }

        public override void ResetHaptics()
        {
            base.ResetHaptics();
            if (okonaSlot >= 0) OkonaInterop.Rumble(okonaSlot, 0f, 0f);
        }
    }
}
