"""
LRC Parser — Parse synced lyrics in LRC format
"""

import re


class LyricLine:
    """A single line of lyrics with its timestamp."""
    __slots__ = ('time', 'text')

    def __init__(self, time, text):
        self.time = time  # seconds from start
        self.text = text

    def __repr__(self):
        return f"LyricLine({self.time:.2f}, {self.text!r})"


class LRCParser:
    """Parses LRC (synced lyrics) format into structured lyric lines."""

    # Match [MM:SS.xx] or [MM:SS.xxx] followed by text
    TIMESTAMP_RE = re.compile(
        r'\[(\d{1,2}):(\d{2})(?:\.(\d{2,3}))?\]\s*(.*)'
    )
    # Skip metadata tags like [ar:Artist], [ti:Title]
    METADATA_RE = re.compile(r'^\[[a-zA-Z]{2}:')

    @staticmethod
    def parse(lrc_content):
        """
        Parse an LRC-format string into a list of LyricLine, sorted by timestamp.

        LRC format: [MM:SS.xx] Lyric text
        Example:
            [00:17.12] I feel your breath upon my neck
            [00:21.45] A shiver down my spine
        """
        lines = []

        for raw_line in lrc_content.split('\n'):
            trimmed = raw_line.strip()
            if not trimmed:
                continue

            # Skip metadata
            if LRCParser.METADATA_RE.match(trimmed):
                continue

            match = LRCParser.TIMESTAMP_RE.match(trimmed)
            if not match:
                continue

            minutes = int(match.group(1))
            seconds = int(match.group(2))
            frac_str = match.group(3) or '0'
            text = match.group(4).strip()

            # Normalize fractional part
            frac_val = int(frac_str)
            if len(frac_str) == 3:
                fractional = frac_val / 1000.0
            else:
                fractional = frac_val / 100.0

            total_seconds = (minutes * 60.0) + seconds + fractional

            if text:
                lines.append(LyricLine(total_seconds, text))

        lines.sort(key=lambda l: l.time)
        return lines

    @staticmethod
    def current_line_index(position, lines):
        """
        Find the index of the lyric line that should be displayed at the given
        playback position. Returns the last line whose timestamp is <= position,
        or None if before any lyrics.
        """
        if not lines:
            return None

        result = None
        for i, line in enumerate(lines):
            if line.time <= position:
                result = i
            else:
                break
        return result
