import 'dart:async';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/vo/message.dart';
import 'package:fcs/pages/main/model/base_model.dart';
import 'package:logging/logging.dart';

class MessageModel extends BaseModel {
  final log = Logger('MessageModel');

  List<Message> messages;

  @override
  logout() async {
    if (listener != null) await listener.cancel();
    messages = [];
  }

  Query query;
  DocumentSnapshot prevSnap;
  bool isEnded;
  bool isLoading;
  String userID;
  StreamSubscription<QuerySnapshot> listener;

  static const int rowPerLoad = 20;
  void initQuery(String userID) {
    this.messages = [];
    this.userID = userID;
    this.prevSnap = null;
    query = Firestore.instance
        .collection("$user_collection/$userID/$messages_collection")
        .orderBy('date', descending: true);
    load();
  }

  Future<void> load() async {
    Query _query =
        prevSnap != null ? query.startAfterDocument(prevSnap) : query;
    QuerySnapshot snapshot =
        await _query.limit(rowPerLoad).getDocuments(source: Source.server);

    int count = snapshot.documents.length;
    isEnded = count < rowPerLoad;
    prevSnap = count > 0 ? snapshot.documents[count - 1] : prevSnap;

    snapshot.documents.forEach((e) {
      messages.add(Message.fromMap(e.data, e.documentID));
      if (messages.length == 1) {
        _initListener(e);
      }
    });
    notifyListeners();
  }

  void _initListener(DocumentSnapshot snap) {
    if (listener != null) listener.cancel();

    listener = Firestore.instance
        .collection("$user_collection/$userID/$messages_collection")
        .endBeforeDocument(snap)
        .orderBy('date', descending: true)
        .snapshots(includeMetadataChanges: true)
        .listen((qs) {
      qs.documentChanges.forEach((c) {
        switch (c.type) {
          case DocumentChangeType.added:
            log.info("added!! $c");
            messages.insert(
                0, Message.fromMap(c.document.data, c.document.documentID));
            notifyListeners();
            break;
          case DocumentChangeType.modified:
            log.info("modified!! $c");
            break;
          default:
        }
      });
    });
  }

  Future<void> sendMessage(String msg, String receiverID) {
    Message message = Message(message: msg, receiverID: receiverID);
    return Services.instance.commonService.sendMessage(message);
  }

  Future<void> seenMessages(String ownerID, bool seenByOwner) {
    return Services.instance.commonService.seenMessage(ownerID, seenByOwner);
  }
}
