import unittest
import librosa
from src.relative_mode import relative_mode

class TestRelativeMode(unittest.TestCase):

    def test_relative_mode_default(self):
        # Load the audio file
        filename = 'data/Bach_1_Gould_0_Major_bachGould1971.wav'
        y, sr = librosa.load(filename)

        # Run the relative_mode function with default parameters
        RM, RM_segments = relative_mode(y=y, sr=sr)

        # Assert that the result matches the expected value
        self.assertAlmostEqual(RM['tondeltamax'][0], 0.258, places=3)

    def test_relative_mode_remove_percussive(self):
        # Load the audio file
        filename = 'data/Bach_1_Gould_0_Major_bachGould1971.wav'
        y, sr = librosa.load(filename)

        # Run the relative_mode function with remove_percussive=True
        RM, RM_segments = relative_mode(y=y, sr=sr, remove_percussive=True)

        # Assert that the result is within a reasonable range (example value, adjust as needed)
        self.assertTrue(-1.0 <= RM['tondeltamax'][0] <= 1.0)

    def test_relative_mode_different_parameters(self):
        # Load the audio file
        filename = 'data/Bach_1_Gould_0_Major_bachGould1971.wav'
        y, sr = librosa.load(filename)

        # Run the relative_mode function with different parameters
        RM, RM_segments = relative_mode(y=y, sr=sr, winlen=5.0, hoplen=2.0, cropfirst=1, croplast=10)

        # Assert that the result is within a reasonable range (example value, adjust as needed)
        self.assertTrue(-1.0 <= RM['tondeltamax'][0] <= 1.0)
        self.assertGreater(len(RM_segments), 0)  # Ensure segments are generated

    def test_relative_mode_short_audio(self):
        # Create a very short audio signal
        y = librosa.tone(440, sr=22050, duration=0.1)  # 0.1 seconds of a 440 Hz tone
        sr = 22050

        # Run the relative_mode function
        RM, RM_segments = relative_mode(y=y, sr=sr)

        # Assert that the result is within a reasonable range
        self.assertTrue(-1.0 <= RM['tondeltamax'][0] <= 1.0)
        self.assertGreaterEqual(len(RM_segments), 0)  # Allow zero segments for very short audio

    def test_relative_mode_invalid_input(self):
        # Test with invalid input (non-audio data)
        with self.assertRaises(TypeError):
            relative_mode(y=None, sr=22050)  # Invalid audio input

        with self.assertRaises(TypeError):
            relative_mode(y=[1, 2, 3], sr=22050)  # Invalid audio type

if __name__ == "__main__":
    unittest.main()