
using Godot;
using System.Collections.Generic;
using System.Linq;

namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class CompositorVFX:Node, IFloatDriver
  {
    [Export]
    public CompositorVFXPreset preset;
    
    float _driverValue = 0f;

    [Export( PropertyHint.Range, "0,1" ) ]
    public float driverValue 
    {
      get => _driverValue;

      set 
      {
        _driverValue = value;
        UpdateValue();
      }
    }

    
    [Export]
    public CompositorEffectLayer layer;

    [Export]
    public int priority = 0;
  
    
    public void DuplicateHack()
    {
      #if TOOLS

      var selectedNodes = EditorInterface.Singleton.GetSelection().GetSelectedNodes();
      if ( selectedNodes.Contains( this ) )
      {
        return;
      }

      #endif
      var numEffects = preset.effects.Length;
      
      for ( int i = 0 ; i < numEffects; i++ )
      {
        preset.effects[ i ] = (RokojoriCompositorEffect) preset.effects[ i ].Duplicate();
      }

      UpdateEffects();
    }
    


    public float GetDriverFloatValue()
    {
      return _driverValue;
    }

    public enum ManagingMode
    {
      None,
      Remove_On_Zero_Insert_At_InterMediate,
      Remove_On_NonIntermediate_Insert_Else
    }

    [ExportGroup( "Actions")]
    [Export]
    public Action onChange;

    [Export]
    public Action onZero;

    [Export]
    public Action onOne;

    [Export]
    public Action onIntermediate;

    [ExportGroup("Setup")]
    [Export]
    public ManagingMode managingMode = ManagingMode.Remove_On_Zero_Insert_At_InterMediate;
    
    [Export]
    public CompositorEffectLayout layout;

    [Export]
    public CompositorEffectOwner ownerReference;


    void EnsureOwnerShip()
    {
      // this.LogInfo( "EnsureOwnerShip", ownerReference );
      var undoMarker = UndoGD.Start( "Set Ownership for " + HierarchyName.Of( this ) );
      
      if ( ownerReference == null )
      {
        ownerReference = new CompositorEffectOwner();
        // this.LogInfo( "Created ownership", ownerReference );
        UndoGD.Set( this, nameof( ownerReference ), ownerReference );
      }

      
      preset.effects.ForEach( fx => SetOwnerShip( fx ) );
      
      

      UndoGD.End( undoMarker );
    }

    void SetOwnerShip( RokojoriCompositorEffect effect )
    {
      var id = effect.compositorEffectID;

      if ( id == null )
      {
        id = new RokojoriCompositorEffectID();
        UndoGD.Set( effect, nameof( effect.compositorEffectID ), id );
      }

      if ( id.owner != ownerReference )
      {
        UndoGD.Set( id, nameof( id.owner ), ownerReference );
      }
    }


    public void UpdateValue()
    {
      // this.LogInfo( "Updating value", _driverValue );

      UpdateEffects();

      onChange?.Trigger();

      if ( _driverValue == 0 )
      {
        onZero?.Trigger();
      }
      else if ( _driverValue == 1 )
      {
        onOne?.Trigger();
      }
      else 
      {
        onIntermediate?.Trigger();
      }
    }

    void UpdateEffects()
    {
      if ( preset == null || preset.effects == null || preset.effects.Length == 0 )
      {
        return;
      } 
      
      preset.effects.ForEach( ep => ep.UpdateAnimationTargets( _driverValue ) );

      if ( managingMode != ManagingMode.None )
      {
        EnsureOwnerShip();

        var effects = preset.effects;

        var currentLayout = layout != null ? layout : Unique<CameraManager>.Get().compositorLayout;

        if ( _driverValue == 0 || ( _driverValue == 1 && managingMode == ManagingMode.Remove_On_NonIntermediate_Insert_Else ) )
        {
          currentLayout.Ensure( this, effects, false );
        }
        else
        {
          currentLayout.Ensure( this, effects, true );

          for ( int i = 0; i < effects.Length; i++ )
          {
            preset.effects[ i ] = effects[ i ];
          }
        }        
        
      }
    }

  }
}