
using Godot;


namespace Rokojori
{  
  [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ]
  public partial class OnSensor: Node
  {
    [Export]
    public Sensor sensor;

    [Export]
    public Action onStart;    

    [Export]
    public Action onActive;    

    [Export]
    public Action onEnd;  

    [Export]
    public Action onDouble; 

    public enum DoubleMode
    {
      Auto,
      Trigger_OnStart_And_OnDouble,
      Trigger_OnDouble_Only      
    }

    [Export]
    public DoubleMode doubleMode = DoubleMode.Auto;

    [Export]
    public float doubleDuration = 0.3f; 

    [Export]
    public bool onlyWhenNotConsumed = true;

    [Export]
    public bool consumeEvent = true;

    
    [ExportGroup("Condition")]    
    [Export]
    public Condition condition;

    [Export]
    public SceneCondition sceneCondition;

    float _lastDownTime = 0;
    float _lastUpTime = 0;

    public override void _Process( double delta )
    {     
      if ( sensor == null )
      {
        return;
      }

      if ( onlyWhenNotConsumed && sensor.consumed )
      {
        this.LogInfo( "Sensor Consumed" );
        return;
      }

      if ( condition != null && ! condition.Evaluate() )
      {
        return;
      }

      if ( sceneCondition != null && ! sceneCondition.Evaluate() )
      {
        return;
      }

      // this.LogInfo( "On Sensor", sensor.value, sensor.isDown );

      var timeNow = Time.GetTicksMsec() / 1000.0f;

      if ( sensor.isDown )
      { 
        var elapsedSinceLast = timeNow - _lastDownTime;
        _lastDownTime = timeNow;

        var isDouble = elapsedSinceLast < doubleDuration;

        var executesStart = true;
        var executesDouble = false;

        if ( isDouble )
        {
          executesDouble = true;

          if ( doubleMode == DoubleMode.Trigger_OnDouble_Only || 
               doubleMode == DoubleMode.Auto && onDouble != null )
          {
            executesStart = false;
          }
        }

        if ( executesStart )
        {
          Action.Trigger( onStart );

          if ( consumeEvent && onStart != null )
          {
            sensor.Consume();
          }
        }

        if ( executesDouble )
        {
          Action.Trigger( onDouble );

          if ( consumeEvent && onDouble != null )
          {
            sensor.Consume();
          }
        }

      }

      if ( sensor.isHold )  
      {
        Action.Trigger( onActive );

        if ( consumeEvent && onActive != null )
        {
          sensor.Consume();
          return;
        }
      }

      if ( sensor.isUp )  
      {
        _lastUpTime = timeNow;
        Action.Trigger( onEnd );

        if ( consumeEvent && onEnd != null )
        {
          sensor.Consume();
          return;
        }
      }

    }
  }
}