# This file is part of yle-dl.
#
# Copyright 2010-2026 Antti Ajanki and others
#
# Yle-dl is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Yle-dl is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with yle-dl. If not, see <https://www.gnu.org/licenses/>.

import logging
from .backends import DASHHLSBackend
from .ffmpeg import Ffprobe
from .streamflavor import StreamFlavor, failed_flavor

logger = logging.getLogger('yledl')


def probe_flavors(
    manifest_url: str, is_live: bool, ffprobe: Ffprobe
) -> list[StreamFlavor]:
    try:
        programs = ffprobe.show_programs_for_url(manifest_url)
        return programs_to_stream_flavors(programs, manifest_url, is_live)
    except ValueError as ex:
        return [failed_flavor(f'Failed to probe stream: {str(ex)}')]


def programs_to_stream_flavors(
    programs: dict, manifest_url: str, is_live: bool
) -> list[StreamFlavor]:
    res: list[StreamFlavor] = []
    for program in programs.get('programs', []):
        streams = program.get('streams', [])
        any_stream_is_video = any(
            x['codec_type'] == 'video' for x in streams if 'codec_type' in x
        )
        widths = [x['width'] for x in streams if 'width' in x]
        heights = [x['height'] for x in streams if 'height' in x]
        bitrate = program.get('tags', {}).get('variant_bitrate')
        if bitrate:
            bitrate = int(bitrate) / 1000
        # Take (arbitrarily) the min of subtitle start times. Usually all start times are equal.
        subtitle_start_times = [
            float(s['start_time'])
            for s in streams
            if s['codec_type'] == 'subtitle' and 'start_time' in s
        ]
        shared_subtitle_start_time = (
            min(subtitle_start_times) if subtitle_start_times else None
        )
        pid = program.get('program_id')
        res.append(
            StreamFlavor(
                media_type='video' if any_stream_is_video else 'audio',
                height=heights[0] if heights else None,
                width=widths[0] if widths else None,
                bitrate=bitrate,
                subtitle_start_time=shared_subtitle_start_time,
                streams=[
                    DASHHLSBackend(
                        manifest_url,
                        long_probe=True,
                        program_id=pid,
                        is_live=is_live,
                        experimental_subtitles=True,
                    )
                ],
            )
        )

    res = _drop_duplicates(res)
    return sorted(res, key=lambda x: (x.height or 0, x.bitrate or 0))


def _drop_duplicates(stream_flavors: list[StreamFlavor]) -> list[StreamFlavor]:
    def flavor_key(s: StreamFlavor):
        return (
            s.width,
            s.height,
            s.bitrate,
            next((x.url for x in s.streams), None),
        )

    unique = {flavor_key(s): s for s in stream_flavors}
    return list(unique.values())
