using System.Collections;
using System.Collections.Generic;
using Godot;
using System.Text;
using System;

namespace Rokojori
{
  public class MathAudio
  {
    public static int ConcertA_Pitch = 69;
    public static float ConcertA_Frequency = 440.0f;    

    public static float AmplitudeToDecibels( float amplitude ) 
    {
      return Mathf.Log(amplitude) * 20.0f / Mathf.Log(10.0f);
    }
   
    public static float DecibelsToAmplitude( float decibels ) 
    {
      return Mathf.Pow(10.0f, decibels / 20.0f);
    }

    public static float FrequencyToPitch( float frequency ) 
    {
      return ConcertA_Pitch + 12 * Mathf.Log(frequency / ConcertA_Frequency) / Mathf.Log(2.0f);
    }
   
    public static float PitchToFrequency( float pitch ) 
    {
      return ConcertA_Frequency * Mathf.Pow( 2.0f, ( ( pitch - ConcertA_Pitch ) * (1.0f / 12.0f)));
    }

    public static float SemitonesToFrequencyScaler( float semitones ) 
    {
      return Mathf.Pow( 2.0f, semitones / 12.0f);
    }

    public static float OffsetFrequencyBySemitones( float frequency, float semitones )
    {
      return SemitonesToFrequencyScaler( semitones ) * frequency;
    }

    public static float IncrementPhase( float phase, float increment )
    {
      return MathX.Repeat( phase + increment, 1 );
    }

    public static float OneBeatToSeconds( float bpm )
    {
      return 60f / bpm;
    }

    public static float OneSecondToBeats( float bpm )
    {
      return 1f / OneBeatToSeconds( bpm );
    }

    public static float OneSampleToSeconds( float sampleRate )
    {
      return 1f / sampleRate;
    }  

    public static float OneSecondToSamples( float sampleRate )
    {
      return sampleRate;
    }

    public static float OneBeatToSamples( float bpm, float sampleRate )
    {
      var seconds = OneBeatToSeconds( bpm );

      return seconds * OneSecondToSamples( sampleRate );
    }

    public static float OneSampleToBeats( float bpm, float sampleRate )
    {
      var seconds = OneBeatToSeconds( bpm );

      return seconds * OneSecondToSamples( sampleRate );
    }

    
    public static float BeatsToSeconds( float beats, float bpm )
    {
      return beats * OneBeatToSeconds( bpm );    
    }

    public static float SecondsToBeats( float seconds, float bpm )
    {
      return seconds * OneSecondToBeats( bpm );    
    }

    public static float SamplesToSeconds( float samples, float sampleRate )
    {
      return samples * OneSampleToSeconds( sampleRate );    
    }

    public static float SecondsToSamples( float seconds, float sampleRate )
    {
      return seconds * OneSecondToSamples( sampleRate );    
    }

    public static float BeatsToSamples( float beats, float bpm, float sampleRate )
    {
      return beats * OneBeatToSamples( bpm, sampleRate );    
    }

    public static float SamplesToBeats( float samples, float bpm, float sampleRate )
    {
      return samples * OneSampleToBeats( bpm, sampleRate );    
    }


    public static float GetNextLoopPosition( float position, float loopDuration, float loopOffset )
    {
      position -= loopOffset;

      position = Mathf.CeilToInt( position / loopDuration ) * loopDuration;

      return position + loopOffset;
    }

    public static float GetPreviousLoopPosition( float position, float loopDuration, float loopOffset )
    {
      position -= loopOffset;

      position = Mathf.FloorToInt( position / loopDuration ) * loopDuration;

      return position + loopOffset;
    }
  }
}