import 'package:flutter/foundation.dart';

import '../../../core/contracts/playback.dart';
import '../../../providers/subtitle_settings_provider.dart';

enum InitialSubtitleSelectionType { unchanged, disabled, track }


class InitialSubtitleSelection {
  final InitialSubtitleSelectionType type;
  final EmbySubtitleTrack? track;

  const InitialSubtitleSelection._({required this.type, this.track});

  static const unchanged = InitialSubtitleSelection._(
    type: InitialSubtitleSelectionType.unchanged,
  );

  static const disabled = InitialSubtitleSelection._(
    type: InitialSubtitleSelectionType.disabled,
  );

  const InitialSubtitleSelection.track(EmbySubtitleTrack selectedTrack)
    : this._(type: InitialSubtitleSelectionType.track, track: selectedTrack);
}


InitialSubtitleSelection resolveInitialSubtitleSelection({
  required List<EmbySubtitleTrack> subtitles,
  required int? preferredSubtitleStreamIndex,
  required int? defaultSubtitleStreamIndex,
  required RememberedSubtitleTrack? rememberedSubtitle,
}) {
  if (preferredSubtitleStreamIndex != null &&
      preferredSubtitleStreamIndex >= 0) {
    return _selectionForStreamIndex(subtitles, preferredSubtitleStreamIndex);
  }

  if (rememberedSubtitle != null) {
    if (rememberedSubtitle.isNone) {
      return InitialSubtitleSelection.disabled;
    }

    final rememberedStreamIndex = matchRememberedSubtitle(
      rememberedSubtitle,
      subtitles,
    );
    if (rememberedStreamIndex != null) {
      return _selectionForStreamIndex(subtitles, rememberedStreamIndex);
    }
  }

  if (preferredSubtitleStreamIndex != null &&
      preferredSubtitleStreamIndex < 0) {
    return InitialSubtitleSelection.disabled;
  }

  if (defaultSubtitleStreamIndex != null && defaultSubtitleStreamIndex >= 0) {
    return _selectionForStreamIndex(subtitles, defaultSubtitleStreamIndex);
  }

  if (defaultSubtitleStreamIndex == -1) {
    return InitialSubtitleSelection.disabled;
  }

  return InitialSubtitleSelection.unchanged;
}

InitialSubtitleSelection _selectionForStreamIndex(
  List<EmbySubtitleTrack> subtitles,
  int streamIndex,
) {
  final selectedTrack = subtitles
      .where((subtitle) => subtitle.index == streamIndex)
      .firstOrNull;
  return selectedTrack == null
      ? InitialSubtitleSelection.unchanged
      : InitialSubtitleSelection.track(selectedTrack);
}


@visibleForTesting
int? matchRememberedSubtitle(
  RememberedSubtitleTrack remembered,
  List<EmbySubtitleTrack> subtitles,
) {
  if (subtitles.isEmpty) return null;

  final wantedLanguage = remembered.language?.toLowerCase();
  final wantedTitle = remembered.title?.toLowerCase();

  if (wantedLanguage != null && wantedTitle != null) {
    for (final subtitle in subtitles) {
      if (subtitle.language?.toLowerCase() == wantedLanguage &&
          subtitle.title?.toLowerCase() == wantedTitle) {
        return subtitle.index;
      }
    }
  }

  if (wantedTitle != null) {
    for (final subtitle in subtitles) {
      if (subtitle.title?.toLowerCase() == wantedTitle) {
        return subtitle.index;
      }
    }
  }

  if (wantedLanguage != null) {
    for (final subtitle in subtitles) {
      if (subtitle.language?.toLowerCase() == wantedLanguage) {
        return subtitle.index;
      }
    }
  }

  for (final subtitle in subtitles) {
    if (subtitle.index == remembered.streamIndex) {
      return subtitle.index;
    }
  }

  return null;
}
