using AGXUnity;
using AGXUnity.IO.OpenPLX;
using System;
using System.Collections.Generic;
using UnityEngine.InputSystem;

/// <summary>
/// This class is a utility class to connect named InputActions to their corresponding OpenPLX inputs.
/// This is currently done by checking the float value of the specified action and scaling them by a provided value.
/// </summary>
public class InputActionMapper
{
  private InputActionMap m_map = null;
  private List<Tuple<InputTarget, InputAction, float, float>> m_signalMap = null;

  /// <summary>
  /// Add a simple map from a provided action to the given input signal and apply the provided scale.
  /// </summary>
  /// <param name="signal">The input to propagate the InputAction signal to</param>
  /// <param name="actionName">The name of the Action to map</param>
  /// <param name="scale">The scale factor to apply to the axis value</param>
  public void CreateMap( InputTarget signal, string actionName, float scale = 1.0f, float offset = 0.0f )
  {
    m_signalMap.Add( Tuple.Create( signal, m_map[ actionName ], scale, offset ) );
  }

  /// <summary>
  /// Creates a new mapper given an InputActionAsset and a name of an ActionMap in the given asset
  /// </summary>
  /// <param name="actionAsset">The InputActionAsset to map from</param>
  /// <param name="mapName">The name of the ActionMap to map from</param>
  public InputActionMapper( InputActionAsset actionAsset, string mapName )
  {
    m_map = actionAsset.FindActionMap( mapName );
    m_map.Enable();

    m_signalMap = new List<Tuple<InputTarget, InputAction, float, float>>();

    // Setup signal propagation
    Simulation.Instance.StepCallbacks.PreStepForward += Pre;
  }

  void Pre()
  {
    // Propagate signals to their mapped OpenPLX inputs
    foreach ( var (signal, action, scale, offset) in m_signalMap ) {
      var value = action.ReadValue<float>() * scale + offset;
      signal.SendSignal( value );
    }
  }
}