import 'dart:async';
import 'package:imagini/core/imagini_application.dart';
import 'package:imagini/api/imagini_api_repository.dart';
import 'package:imagini/graphql/imagini_graphql.dart';
import 'package:cached_network_image/cached_network_image.dart';

class HomeBloc{

  final ImaginiApplication _application;
  ImaginiAPIRepository _imaginiAPI;

  final _loginController = StreamController<bool>.broadcast();
  Stream<bool> get loginResult => _loginController.stream;

  final _authenticatedController = StreamController<bool>.broadcast();
  Stream<bool> get authenticatedResult => _authenticatedController.stream;

  Map<int, List<MediaItems$Query$MediaItemResponse$MediaItem>> _pagedMediaItemListCache =
    Map<int, List<MediaItems$Query$MediaItemResponse$MediaItem>>();

  int totalMediaItems;
  int _pageSize = 50;

  HomeBloc(this._application){
    _init();
  }

  void _init(){
    _imaginiAPI = _application.imaginiAPI;
  }

  void dispose(){
    _loginController.close();
    _authenticatedController.close();
  }

  Future<CachedNetworkImage> getMedia(int index, derivedContentWidth) async {
    MediaItems$Query$MediaItemResponse$MediaItem mediaDetails = await getMediaDetails(index);
    if (mediaDetails == null)
      return null;
    int derivedContentHeight = (mediaDetails.height / mediaDetails.width * derivedContentWidth).ceil();
    return _imaginiAPI.getImage(mediaDetails.fileName, derivedContentWidth, derivedContentHeight);
  }

  Future<MediaItems$Query$MediaItemResponse$MediaItem> getMediaDetails(int index) async {
    int itemPage = (index / _pageSize).ceil();
    int indexOnPage = index % _pageSize;

    if (!_pagedMediaItemListCache.containsKey(itemPage))
      await _cachePage(itemPage);

    return _pagedMediaItemListCache[itemPage][indexOnPage];
  }

  _cachePage(int itemPage) async {
    MediaItems$Query newItems = await _imaginiAPI.mediaItems(Page(page: itemPage));
    totalMediaItems = newItems.mediaItems.page.total;
    _pagedMediaItemListCache[itemPage] = newItems.mediaItems.data;
  }

  checkAuthentication(){
    _authenticatedController.addStream(_imaginiAPI.isAuthenticated());
  }

  attemptHome(String username, password, server){
    _loginController.addStream(_imaginiAPI.login(username, password, server));
  }
}
