
class TimedSubtitle {
  final Duration start;
  final Duration end;
  final String text;

  const TimedSubtitle({
    required this.start,
    required this.end,
    required this.text,
  });
}


class EmbeddedSubtitleCues {
  final List<TimedSubtitle> _cues = [];

  bool get isEmpty => _cues.isEmpty;


  void add(double startSec, double endSec, List<String> lines) {
    final text = lines
        .map((s) => s.trim())
        .where((s) => s.isNotEmpty)
        .join('\n');
    if (text.isEmpty) return;

    final start = _toDuration(startSec);
    final end = _toDuration(endSec);
    if (end < start) return;

    final at = _lowerBound(start);
    for (var i = at; i < _cues.length && _cues[i].start == start; i++) {
      if (_cues[i].end == end && _cues[i].text == text) return;
    }
    _cues.insert(at, TimedSubtitle(start: start, end: end, text: text));
  }


  List<String> textAt(Duration position) {
    final out = <String>[];
    for (final cue in _cues) {
      if (position < cue.start) break;
      if (position <= cue.end) out.addAll(cue.text.split('\n'));
    }
    return out;
  }

  void clear() => _cues.clear();

  static Duration _toDuration(double seconds) =>
      Duration(milliseconds: (seconds * 1000).round());


  int _lowerBound(Duration start) {
    int lo = 0;
    int hi = _cues.length;
    while (lo < hi) {
      final mid = (lo + hi) >> 1;
      if (_cues[mid].start < start) {
        lo = mid + 1;
      } else {
        hi = mid;
      }
    }
    return lo;
  }
}
