using UnityEngine;
///
/// Статический фасад для унифицированного доступа к системе ввода.
/// Предоставляет глобальный интерфейс для работы с управлением независимо от выбранного источника.
///
///
/// Этот класс является точкой входа для всей игровой логики, работающей с вводом.
/// Автоматически инициализирует выбранный источник управления (клавиатура или COM-порт)
/// и предоставляет статические методы для удобного доступа из любого места кода.
///
/// Использование:
/// 1. Настройте тип ввода в инспекторе
/// 2. Вызовите Initialize() при старте игры
/// 3. Используйте статические методы для проверки ввода
///
public class In : MonoBehaviour
{
[Header("Выбор источника управления")]
[SerializeField] private InputSourceType inputType;
/// Возвращает true, если выбран COM-режим (нужны физические платы)
public bool UsesCOM => inputType == InputSourceType.COM;
static InputSource source;
// вспомогательный экземпляр клавиатурного источника для локальной проверки (фолбэк при COM)
static KeyboardInput keyboardOverride;
public static System.Action ButtonEvent; // на неё подписываемся в GameMenager обновляем таймер
///
/// Инициализирует систему ввода на основе выбранного типа.
/// Должен быть вызван один раз при запуске приложения.
///
///
/// Создает соответствующий экземпляр InputSource:
/// - KeyboardInput для тестирования на клавиатуре
/// - COMinput для работы с периферийной платой
///
public void Initialize()
{
source = inputType switch
{
InputSourceType.Keyboard => new KeyboardInput(),
InputSourceType.COM => new COMinput(),
_ => throw new System.NotImplementedException()
};
var success = source.Initialize();
if (!success) Debug.LogWarning("Не удалось проинициалзировать источник управления.");
}
// ================================================================================
// СТАТИЧЕСКИЕ МЕТОДЫ ДЛЯ РАБОТЫ С ФИЗИЧЕСКИМИ ПИНАМИ
// ================================================================================
/// Проверяет состояние конкретной кнопки по её физическому пину
public static bool GetButton(ButtonPinMapping button) => source.GetButton(button);
/// Проверяет нажатие кнопки по пину в текущем кадре
public static bool GetButtonDown(ButtonPinMapping button)
{
bool result = source.GetButtonDown(button);
if(result) ButtonEvent?.Invoke();
else if (source is COMinput)
{
// для режима COM позволяем секретную кнопку также срабатывать с клавиатуры
if (button == ButtonPinMapping.secret1 || button == ButtonPinMapping.secret2)
{
if (keyboardOverride == null)
{
keyboardOverride = new KeyboardInput();
try { keyboardOverride.Initialize(); } catch { /* ignore */ }
}
try
{
if (keyboardOverride != null && keyboardOverride.GetButtonDown(button))
{
ButtonEvent?.Invoke();
return true;
}
}
catch { /* ignore potential errors from KeyboardInput */ }
}
}
return result;
}
/// Проверяет отпускание кнопки по пину в текущем кадре
public static bool GetButtonUp(ButtonPinMapping button) => source.GetButtonUp(button);
/// Проверяет состояние кнопки по числовому индексу пина
public static bool GetButton(int pinindex) => source.GetButton(pinindex);
/// Проверяет нажатие кнопки по индексу пина в текущем кадре
public static bool GetButtonDown(int pinindex) => source.GetButtonDown(pinindex);
/// Проверяет отпускание кнопки по индексу пина в текущем кадре
public static bool GetButtonUp(int pinindex) => source != null && source.GetButtonUp(pinindex);
// ================================================================================
// СТАТИЧЕСКИЕ МЕТОДЫ ДЛЯ РАБОТЫ С АБСТРАКТНЫМИ ДЕЙСТВИЯМИ ИГРОКОВ
// ================================================================================
/// Проверяет состояние действия для любого из игроков
public static bool GetButtonAnyPlayer(PlayerAction button) => source != null && source.GetButtonAnyPlayer(button);
/// Проверяет начало действия любым игроком в текущем кадре
public static bool GetButtonDownAnyPlayer(PlayerAction button) => source != null && source.GetButtonDownAnyPlayer(button);
/// Проверяет завершение действия любым игроком в текущем кадре
public static bool GetButtonUpAnyPlayer(PlayerAction button) => source != null && source.GetButtonUpAnyPlayer(button);
/// Проверяет состояние действия для текущего активного игрока
public static bool GetButtonCurrentPlayer(PlayerAction button) => source != null && source.GetButtonCurrentPlayer(button);
/// Проверяет начало действия текущим игроком в текущем кадре
public static bool GetButtonDownCurrentPlayer(PlayerAction button) => source != null && source.GetButtonDownCurrentPlayer(button);
/// Проверяет завершение действия текущим игроком в текущем кадре
public static bool GetButtonUpCurrentPlayer(PlayerAction button) => source != null && source.GetButtonUpCurrentPlayer(button);
}