<commit_before>import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

import '../../../../core/error/failure.dart';
import '../../../../core/helpers/failure_mapper_helper.dart';
import '../../../image_url/domain/usecases/get_image_url.dart';
import '../../../logging/domain/usecases/logging.dart';
import '../../domain/entities/metadata_item.dart';
import '../../domain/usecases/get_children_metadata.dart';

part 'children_metadata_event.dart';
part 'children_metadata_state.dart';

String _tautulliIdCache;
Map<int, List<MetadataItem>> _metadataCache = {};

class ChildrenMetadataBloc
    extends Bloc<ChildrenMetadataEvent, ChildrenMetadataState> {
  final GetChildrenMetadata getChildrenMetadata;
  final GetImageUrl getImageUrl;
  final Logging logging;

  ChildrenMetadataBloc({
    @required this.getChildrenMetadata,
    @required this.getImageUrl,
    @required this.logging,
  }) : super(ChildrenMetadataInitial());

  @override
  Stream<ChildrenMetadataState> mapEventToState(
    ChildrenMetadataEvent event,
  ) async* {
    if (event is ChildrenMetadataFetched) {
      if (_tautulliIdCache == event.tautulliId &&
          _metadataCache.containsKey(event.ratingKey)) {
        yield ChildrenMetadataSuccess(
          childrenMetadataList: _metadataCache[event.ratingKey],
        );
      } else {
        yield ChildrenMetadataInProgress();

        final failureOrChildrenMetadata = await getChildrenMetadata(
          tautulliId: event.tautulliId,
          ratingKey: event.ratingKey,
        );

        yield* failureOrChildrenMetadata.fold(
          (failure) async* {
            logging.error(
              'ChildrenMetadata: Failed to fetch children metadata for rating key ${event.ratingKey}',
            );

            yield ChildrenMetadataFailure(
              failure: failure,
              message: FailureMapperHelper.mapFailureToMessage(failure),
              suggestion: FailureMapperHelper.mapFailureToSuggestion(failure),
            );
          },
          (childrenMetadataList) async* {
            if (childrenMetadataList.isNotEmpty) {
              final String mediaType = childrenMetadataList.first.mediaType;

              await _sortList(
                mediaType: mediaType,
                childrenMetadataList: childrenMetadataList,
              );

              await _getImages(
                list: childrenMetadataList,
                tautulliId: event.tautulliId,
              );

              _metadataCache[event.ratingKey] = childrenMetadataList;

              yield ChildrenMetadataSuccess(
                childrenMetadataList: childrenMetadataList,
              );
            }
          },
        );
      }
    }
  }

  Future<void> _sortList({
    @required String mediaType,
    @required List<MetadataItem> childrenMetadataList,
  }) async {
    // Sort by year if album leave sort alone if movie/show/artist
    // and by mediaIndex for everything else
    if (mediaType == 'album') {
      childrenMetadataList.sort((a, b) => b.year.compareTo(a.year));
    } else if (!['movie', 'show', 'artist'].contains(mediaType)) {
      childrenMetadataList.sort((a, b) => a.mediaIndex.compareTo(b.mediaIndex));
    }
  }

  Future<void> _getImages({
    @required List<MetadataItem> list,
    @required String tautulliId,
  }) async {
    for (MetadataItem metadataItem in list) {
      //* Fetch and assign image URLs
      String posterFallback;

      // Assign values for posterFallback
      switch (metadataItem.mediaType) {
        case ('movie'):
        case ('clip'):
          posterFallback = 'poster';
          break;
        case ('episode'):<commit_msg>Fix hangup on trying to sort albums with no year.<commit_after>import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

import '../../../../core/error/failure.dart';
import '../../../../core/helpers/failure_mapper_helper.dart';
import '../../../image_url/domain/usecases/get_image_url.dart';
import '../../../logging/domain/usecases/logging.dart';
import '../../domain/entities/metadata_item.dart';
import '../../domain/usecases/get_children_metadata.dart';

part 'children_metadata_event.dart';
part 'children_metadata_state.dart';

String _tautulliIdCache;
Map<int, List<MetadataItem>> _metadataCache = {};

class ChildrenMetadataBloc
    extends Bloc<ChildrenMetadataEvent, ChildrenMetadataState> {
  final GetChildrenMetadata getChildrenMetadata;
  final GetImageUrl getImageUrl;
  final Logging logging;

  ChildrenMetadataBloc({
    @required this.getChildrenMetadata,
    @required this.getImageUrl,
    @required this.logging,
  }) : super(ChildrenMetadataInitial());

  @override
  Stream<ChildrenMetadataState> mapEventToState(
    ChildrenMetadataEvent event,
  ) async* {
    if (event is ChildrenMetadataFetched) {
      if (_tautulliIdCache == event.tautulliId &&
          _metadataCache.containsKey(event.ratingKey)) {
        yield ChildrenMetadataSuccess(
          childrenMetadataList: _metadataCache[event.ratingKey],
        );
      } else {
        yield ChildrenMetadataInProgress();

        final failureOrChildrenMetadata = await getChildrenMetadata(
          tautulliId: event.tautulliId,
          ratingKey: event.ratingKey,
        );

        yield* failureOrChildrenMetadata.fold(
          (failure) async* {
            logging.error(
              'ChildrenMetadata: Failed to fetch children metadata for rating key ${event.ratingKey}',
            );

            yield ChildrenMetadataFailure(
              failure: failure,
              message: FailureMapperHelper.mapFailureToMessage(failure),
              suggestion: FailureMapperHelper.mapFailureToSuggestion(failure),
            );
          },
          (childrenMetadataList) async* {
            if (childrenMetadataList.isNotEmpty) {
              final String mediaType = childrenMetadataList.first.mediaType;

              await _sortList(
                mediaType: mediaType,
                childrenMetadataList: childrenMetadataList,
              );

              await _getImages(
                list: childrenMetadataList,
                tautulliId: event.tautulliId,
              );

              _metadataCache[event.ratingKey] = childrenMetadataList;

              yield ChildrenMetadataSuccess(
                childrenMetadataList: childrenMetadataList,
              );
            }
          },
        );
      }
    }
  }

  Future<void> _sortList({
    @required String mediaType,
    @required List<MetadataItem> childrenMetadataList,
  }) async {
    // Sort by year if album leave sort alone if movie/show/artist
    // and by mediaIndex for everything else
    if (mediaType == 'album') {
      childrenMetadataList.sort((a, b) {
        if (a.year != null && b.year != null) {
          return b.year.compareTo(a.year);
        }
        return 0;
      });
    } else if (!['movie', 'show', 'artist'].contains(mediaType)) {
      childrenMetadataList.sort((a, b) => a.mediaIndex.compareTo(b.mediaIndex));
    }
  }

  Future<void> _getImages({
    @required List<MetadataItem> list,
    @required String tautulliId,
  }) async {
    for (MetadataItem metadataItem in list) {
      //* Fetch and assign image URLs
      String posterFallback;

      // Assign values for posterFallback
      switch (metadataItem.mediaType) {
        case ('movie'):
        case ('clip'):
          posterFallback = 'poster';
          break;
        case ('episode'):
{'fraction_non_alphanumeric': 0.109471742853379, 'fraction_numerical': 0.00013173494928204451, 'mean_word_length': 2.5262424523920113, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7059020', 'n_tokens_mistral': 2063, 'n_tokens_neox': 2045, 'n_words': 424}