
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System;
using Godot;


namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class CameraEffect:Resource
  {
    [Export]
    public CameraEffectTargetAnimationCurve[] animations = new CameraEffectTargetAnimationCurve[ 0 ];

    [Export]
    public TimeLine timeline;

    public float maxDuration 
    {
      get
      {
        var max = 0f;

        for ( int i = 0; i < animations.Length; i++ )
        {
          max = Mathf.Max( animations[ i ].duration, max ); 
        }

        return max;
      }

    }
  }

  public class CameraEffectRunner
  {
    public CameraEffect effect;
    public Vector3 position;
    public Quaternion rotation;
    public float fov;
    public float timePosition = 0;

    public bool isFinished => timePosition >= effect.maxDuration;
    public float timelineOffset = 0;

    List<Vector3> randomOffsets = new List<Vector3>();

    public CameraEffectRunner( CameraEffect effect )
    {
      this.effect = effect;
      Start();
    }

    void Start()
    {
      timelineOffset = effect.timeline.position;
      randomOffsets = new List<Vector3>();

      Arrays.ForEach( effect.animations, ( a => randomOffsets.Add( a.Randomize() ) ) ) ;
    }

    public void Update()
    { 
      float timeLinePosition = effect.timeline.position;
      timePosition = timeLinePosition - timelineOffset;

      position = Vector3.Zero;
      rotation = Quaternion.Identity;
      fov = 0;

      for ( int i = 0; i < effect.animations.Length; i++)
      {
        Apply( effect.animations[ i ], i );
      }
    }    

    void Apply( CameraEffectTargetAnimationCurve curve, int index )
    { 
      var value = curve.Sample( timePosition, randomOffsets[ index ] );

      if ( curve.flipScaleYRandomly && GodotRandom.Get().FlipCoin() )
      {
        value = -value;
      }

      if ( CameraEffectTargetType.Position_X == curve.target )
      {
        position.X += value;
      }
      else if ( CameraEffectTargetType.Position_Y == curve.target )
      {
        position.Y += value;
      }
      else if ( CameraEffectTargetType.Position_Z == curve.target )
      {
        position.Z += value;
      }

      else if ( CameraEffectTargetType.Rotation_X == curve.target )
      {
        rotation *= Math3D.RotateXDegrees( value );
      }
      else if ( CameraEffectTargetType.Rotation_Y == curve.target )
      {
        rotation *= Math3D.RotateYDegrees( value );
      }
      else if ( CameraEffectTargetType.Rotation_Z == curve.target )
      {
        rotation *= Math3D.RotateZDegrees( value );
      }

      else if ( CameraEffectTargetType.FOV == curve.target )
      {
        fov += value;
      }

    }
  }
}