package com.foxx.androidcast.media;

import com.foxx.androidcast.CastSettings;
import com.foxx.androidcast.network.CastCodecFlags;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class AudioNegotiatorTest {

    @Test
    public void autoPrefersAacOverPcmPassthrough() {
        CastSettings settings = new CastSettings();
        int mask = CastCodecFlags.AUDIO_AAC | CastCodecFlags.AUDIO_PCM;

        CodecPriorityCatalog.AudioNegotiationDecision decision =
                CodecPriorityCatalog.decideBestAudioCodec(mask, mask, settings);
        assertNotNull(decision);
        assertEquals(CastSettings.AudioCodec.AAC, decision.codec);
    }

    @Test
    public void compileTimeScoreOrderAacBeforePcm() {
        CastSettings settings = new CastSettings();
        int aac = CodecPriorityCatalog.priorityScore(CastSettings.AudioCodec.AAC, settings);
        int pcm = CodecPriorityCatalog.priorityScore(CastSettings.AudioCodec.PASSTHROUGH_DEBUG, settings);
        assertTrue(aac < pcm);
    }

    @Test
    public void autoFallsBackToAacWithoutOpusOnLink() {
        CastSettings settings = new CastSettings();
        int mask = CastCodecFlags.AUDIO_AAC | CastCodecFlags.AUDIO_PCM;

        CastSettings.AudioCodec picked = AudioNegotiator.negotiate(
                mask, mask, CastSettings.AudioCodec.AUTO, settings);
        assertEquals(CastSettings.AudioCodec.AAC, picked);
    }

    @Test
    public void explicitOpusUnavailableFallsBackToAuto() {
        CastSettings settings = new CastSettings();
        int mask = CastCodecFlags.AUDIO_AAC;

        CastSettings.AudioCodec picked = AudioNegotiator.negotiate(
                mask, mask, CastSettings.AudioCodec.OPUS, settings);
        assertEquals(CastSettings.AudioCodec.AAC, picked);
    }

    @Test
    public void explicitOpusNegotiatesWhenLinkSupportsOpus() {
        CastSettings settings = new CastSettings();
        int mask = CastCodecFlags.AUDIO_AAC | CastCodecFlags.AUDIO_OPUS;

        CastSettings.AudioCodec picked = AudioNegotiator.negotiate(
                mask, mask, CastSettings.AudioCodec.OPUS, settings);
        assertEquals(CastSettings.AudioCodec.OPUS, picked);
    }

    @Test
    public void explicitSpeexNegotiatesWhenLinkSupportsSpeex() {
        CastSettings settings = new CastSettings();
        int mask = CastCodecFlags.AUDIO_AAC | CastCodecFlags.AUDIO_SPEEX;

        CastSettings.AudioCodec picked = AudioNegotiator.negotiate(
                mask, mask, CastSettings.AudioCodec.SPEEX, settings);
        assertEquals(CastSettings.AudioCodec.SPEEX, picked);
    }

    @Test
    public void manualPreferenceOrderIsFixedInCatalog() {
        CastSettings.AudioCodec[] order = CodecPriorityCatalog.manualAudioPreferences();
        assertEquals(CastSettings.AudioCodec.OPUS, order[0]);
        assertEquals(CastSettings.AudioCodec.AAC, order[1]);
        assertEquals(CastSettings.AudioCodec.SPEEX, order[2]);
        assertEquals(CastSettings.AudioCodec.PASSTHROUGH_DEBUG, order[3]);
    }
}
