# -*- coding: utf-8 -*-
"""Unit tests for the :class:`StreamQuery <StreamQuery>` class."""
import pytest


def test_count(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.count` returns an accurate amount."""
    assert cipher_signature.streams.count() == 22


@pytest.mark.parametrize(
    'test_input,expected', [
        ({'progressive': True}, ['22', '43', '18', '36', '17']),
        ({'resolution': '720p'}, ['22', '136', '247']),
        ({'res': '720p'}, ['22', '136', '247']),
        ({'fps': 30, 'resolution': '480p'}, ['135', '244']),
        ({'mime_type': 'audio/mp4'}, ['140']),
        ({'type': 'audio'}, ['140', '171', '249', '250', '251']),
        ({'subtype': '3gpp'}, ['36', '17']),
        ({'abr': '128kbps'}, ['43', '140', '171']),
        ({'bitrate': '128kbps'}, ['43', '140', '171']),
        ({'audio_codec': 'vorbis'}, ['43', '171']),
        ({'video_codec': 'vp9'}, ['248', '247', '244', '243', '242', '278']),
        ({'only_audio': True}, ['140', '171', '249', '250', '251']),
        ({'only_video': True, 'video_codec': 'avc1.4d4015'}, ['133']),
        ({'progressive': True}, ['22', '43', '18', '36', '17']),
        ({'adaptive': True, 'resolution': '1080p'}, ['137', '248']),
        ({'custom_filter_functions': [lambda s: s.itag == '22']}, ['22']),
    ],
)
def test_filters(test_input, expected, cipher_signature):
    """Ensure filters produce the expected results."""
    result = [
        s.itag for s
        in cipher_signature.streams.filter(**test_input).all()
    ]
    assert result == expected


@pytest.mark.parametrize('test_input', ['first', 'last'])
def test_empty(test_input, cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.last` and
    :meth:`~pytube.StreamQuery.first` return None if the resultset is
    empty.
    """
    query = cipher_signature.streams.filter(video_codec='vp20')
    fn = getattr(query, test_input)
    assert fn() is None


def test_get_last(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.last` returns the expected
    :class:`Stream <Stream>`.
    """
    assert cipher_signature.streams.last().itag == '251'


def test_get_first(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.first` returns the expected
    :class:`Stream <Stream>`.
    """
    assert cipher_signature.streams.first().itag == '22'


def test_order_by(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.order_by` sorts the list of
    :class:`Stream <Stream>` instances in the expected order.
    """
    itags = [
        s.itag for s in cipher_signature.streams
        .filter(progressive=True)
        .order_by('itag')
        .all()
    ]

    assert itags == ['17', '18', '22', '36', '43']


def test_order_by_descending(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.desc` sorts the list of
    :class:`Stream <Stream>` instances in the reverse order.
    """
    itags = [
        s.itag for s in cipher_signature.streams
        .filter(progressive=True)
        .order_by('itag')
        .desc()
        .all()
    ]

    assert itags == ['43', '36', '22', '18', '17']


def test_order_by_ascending(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.desc` sorts the list of
    :class:`Stream <Stream>` instances in ascending order.
    """
    itags = [
        s.itag for s in cipher_signature.streams
        .filter(progressive=True)
        .order_by('itag')
        .asc()
        .all()
    ]

    assert itags == ['17', '18', '22', '36', '43']


def test_get_by_itag(cipher_signature):
    """Ensure :meth:`~pytube.StreamQuery.get_by_itag` returns the expected
    :class:`Stream <Stream>`.
    """
    assert cipher_signature.streams.get_by_itag(22).itag == '22'


def test_get_by_non_existent_itag(cipher_signature):
    assert not cipher_signature.streams.get_by_itag(22983)
