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/entities/fcs_shipment.dart';
import 'package:fcs/helpers/paginator.dart';
import 'package:fcs/pages/main/model/base_model.dart';
import 'package:logging/logging.dart';

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

  StreamSubscription<QuerySnapshot> listener;
  List<FcsShipment> _fcsShipments = [];
  List<FcsShipment> get fcsShipments => _selectedIndex == 1
      ? _fcsShipments
      : List<FcsShipment>.from(_shipped.values);

  Paginator _shipped;
  bool isLoading = false;
  int _selectedIndex = 1;
  set selectedIndex(int index) {
    _selectedIndex = index;
    notifyListeners();
  }

  get selectedIndex => _selectedIndex;

  @override
  void privilegeChanged() {
    super.privilegeChanged();
    _loadFcsShipments();
  }

  initData() {
    _selectedIndex = 1;
    _loadFcsShipments();

    if (_shipped != null) _shipped.close();
    _shipped = _getShipped();
    _shipped.load();
  }

  Future<void> _loadFcsShipments() async {
    if (user == null || !user.hasFcsShipments()) return;
    String path = "/$fcs_shipment_collection/";
    if (listener != null) listener.cancel();
    _fcsShipments = [];
    try {
      listener = Firestore.instance
          .collection("$path")
          .where("status", isEqualTo: fcs_shipment_confirmed_status)
          .where("is_deleted", isEqualTo: false)
          .orderBy("shipment_number", descending: true)
          .snapshots()
          .listen((QuerySnapshot snapshot) {
        _fcsShipments.clear();
        _fcsShipments = snapshot.documents.map((documentSnapshot) {
          var s = FcsShipment.fromMap(
              documentSnapshot.data, documentSnapshot.documentID);
          return s;
        }).toList();
        notifyListeners();
      });
    } catch (e) {
      log.warning("Error!! $e");
    }
  }

  Paginator _getShipped() {
    if (user == null || !user.hasFcsShipments()) return null;

    var pageQuery = Firestore.instance
        .collection("/$fcs_shipment_collection")
        .where("status", isEqualTo: fcs_shipment_shipped_status)
        .where("is_deleted", isEqualTo: false)
        .orderBy("shipment_number", descending: true);
    var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) {
      return FcsShipment.fromMap(data, id);
    });
    return paginator;
  }

  Future<void> loadMore() async {
    if (_shipped.ended || _selectedIndex == 1) return;
    isLoading = true;
    notifyListeners();
    await _shipped.load(onFinished: () {
      isLoading = false;
      notifyListeners();
    });
  }

  Future<void> refresh() async {
    if (_selectedIndex == 1) return;
    await _shipped.refresh(onFinished: () {
      notifyListeners();
    });
  }

  Future<List<FcsShipment>> getActiveFcsShipments() async {
    List<FcsShipment> fcsShipments = [];
    try {
      var snaps = await Firestore.instance
          .collection("/$fcs_shipment_collection")
          .where("status", isEqualTo: fcs_shipment_confirmed_status)
          .getDocuments(source: Source.server);
      fcsShipments = snaps.documents.map((documentSnapshot) {
        var fcs = FcsShipment.fromMap(
            documentSnapshot.data, documentSnapshot.documentID);
        return fcs;
      }).toList();
    } catch (e) {
      log.warning("Error!! $e");
    }
    return fcsShipments;
  }

  Future<FcsShipment> getFcsShipment(String id) async {
    try {
      var snap = await Firestore.instance
          .collection("/$fcs_shipment_collection")
          .document(id)
          .get(source: Source.server);
      var fcs = FcsShipment.fromMap(snap.data, snap.documentID);

      return fcs;
    } catch (e) {
      log.warning("Error!! $e");
    }
    return null;
  }

  Future<List<FcsShipment>> getInvoiceFcsShipments() async {
    List<FcsShipment> fcsShipments = [];
    try {
      var snaps = await Firestore.instance
          .collection("/$fcs_shipment_collection")
          .where("pending_invoice_user_count", isGreaterThan: 0)
          .getDocuments(source: Source.server);
      fcsShipments = snaps.documents.map((documentSnapshot) {
        var fcs = FcsShipment.fromMap(
            documentSnapshot.data, documentSnapshot.documentID);
        return fcs;
      }).toList();
    } catch (e) {
      log.warning("Error!! $e");
    }
    return fcsShipments;
  }

  void initUser(user) {
    super.initUser(user);
  }

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

  Future<void> create(FcsShipment fcsShipment) {
    return Services.instance.fcsShipmentService.createFcsShipment(fcsShipment);
  }

  Future<void> update(FcsShipment fcsShipment) {
    return Services.instance.fcsShipmentService.updateFcsShipment(fcsShipment);
  }

  Future<void> ship(FcsShipment fcsShipment) {
    return Services.instance.fcsShipmentService.ship(fcsShipment);
  }

  Future<String> report(FcsShipment fcsShipment) {
    return Services.instance.fcsShipmentService.report(fcsShipment);
  }
}
