using Godot;
using System.Collections.Generic;

namespace Rokojori
{  
  [Tool]
  [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/KeySensor.svg")]
  public partial class KeySensor : Sensor, iOnInputSensor
  {
    [Export]
    public Key key;
    
    [Export]
    public KeyLocation keyLocation = KeyLocation.Unspecified;

    [ExportGroup( "Modifiers")]
    [Export] 
    public Trillean ctrlHold = Trillean.Any;

    [Export]
    public Trillean altHold = Trillean.Any;

    [Export]
    public Trillean shiftHold = Trillean.Any;

    public bool modifiersEnabled => ! TrilleanLogic.AllAny( ctrlHold, altHold, shiftHold );

    public enum ModifiersMode
    {
      Hold_Modifiers_Only_On_Down,
      Hold_Modifiers_All_The_Time
    }

    [Export]
    public ModifiersMode modifiersMode;
    
    float _lastInput = 0;

    public override string ToString()
    {
      return RJLog.GetInfo( this, key, keyLocation, "Ctrl/Alt/Shift:" + ctrlHold + "/" + altHold + "/" + shiftHold );
    }

    protected override void UpdateValue()
    {
      SetFloatValue( _lastInput );
    }

    public void _Input( InputEvent ev )
    {
      var keyEvent = ev as InputEventKey;


      if ( keyEvent == null )
      {
        return;
      } 

      if ( keyEvent.Keycode != key )
      {
        return;
      }

      if ( keyLocation != KeyLocation.Unspecified && keyEvent.Location != KeyLocation.Unspecified )
      { 
        if ( keyEvent.Location != keyLocation )
        {
          return;
        }
      }

      var checkModifiers = modifiersEnabled && 
                           ( 
                            ModifiersMode.Hold_Modifiers_All_The_Time == modifiersMode ||
                           _lastInput == 0 && ModifiersMode.Hold_Modifiers_Only_On_Down == modifiersMode 
                           );

      if ( checkModifiers )
      {

        if ( ! TrilleanLogic.Matches( ctrlHold, keyEvent.CtrlPressed ) )
        {
          _lastInput = 0; 
          return;
        }

        if ( ! TrilleanLogic.Matches( altHold, keyEvent.AltPressed ) )
        {
          _lastInput = 0;
          return;
        }

        if ( ! TrilleanLogic.Matches( shiftHold, keyEvent.ShiftPressed ) )
        {
          _lastInput = 0;
          return;
        }
      }

      _lastInput = keyEvent.IsPressed() ? 1 : 0; 

      UpdateSensorUsage();
      

  
    }

    public override List<InputIcon> GetInputIcons()
    {
      var icon = new KeyIcon();
      icon.key = key;

      return new List<InputIcon>(){ icon };
    }

    public static bool IsModifierKey( Key key )
    {
      return Lists.IsOneOf( key, Key.Ctrl, Key.Alt, Key.Shift, Key.Meta );
    }
        
  }
}