class User extends Document { final Name name; final Address address; final Gender gender; final Birthday birthday; final Email email; final Weight weight; final Length height; final bool _hasFinishedSignUp; final Iterable myBikes; final Set _authenticationProvider; final Set _notificationTokens; Iterable get notificationToken => _notificationTokens; User updateAuthenticationProvider( List newAuthenticationProvider) { return _copyWith(authenticationProvider: { ..._authenticationProvider, ...newAuthenticationProvider }); } bool get needsEmailVerification => _authenticationProvider.every((authenticationProvider) => authenticationProvider == AuthenticationProvider.email); User finishSignUp() { return _copyWith(hasFinishedSignUp: true); } bool get hasEmailSettings => _authenticationProvider.any((authenticationProvider) => authenticationProvider == AuthenticationProvider.email); User selectBike(Bike bike) { var selectedBike = bike.select(); if (myBikes.every((bike) => bike.mac != selectedBike.mac)) return _copyWith(myBikes: [...myBikes, selectedBike]); return updateBike(bike); } ///If a bike is selected right now, lastSelectedBike is also the currently selected bike Bike get lastSelectedBike => myBikes.sortByDescending((myBike) => myBike.lastTimeSelected).first; User updateBike(Bike bike) { return _copyWith( myBikes: myBikes .map((myBike) => myBike.mac == bike.mac ? bike : myBike.copyWith()) .toList()); } bool get hasFinishedSignUp => _hasFinishedSignUp; factory User(String id, AuthenticationProvider authenticationProvider) { return User._( id: id, ).updateAuthenticationProvider([authenticationProvider]); } User._( {String id, this.name, this.birthday, this.email, bool hasFinishedSignUp = false, this.gender, this.address, Set authenticationProvider = const {}, Set notificationTokens = const {}, this.height, this.weight, this.myBikes = const []}) : _hasFinishedSignUp = hasFinishedSignUp, _authenticationProvider = authenticationProvider, _notificationTokens = notificationTokens, super(id: id); @override User copyWith( {String id, Email email, Name name, Address address, Gender gender, Birthday birthDay, Weight weight, Length height, bool setNameNull = false, bool setAddressNull = false, bool setBirthdayNull = false, bool setWeightNull = false, bool setHeightNull = false, bool setGenderNull = false}) { return _copyWith( id: id, email: email, name: name, address: address, gender: gender, birthday: birthDay, weight: weight, height: height, setAddressNull: setAddressNull, setNameNull: setNameNull, setBirthdayNull: setBirthdayNull, setWeightNull: setWeightNull, setGenderNull: setGenderNull); } User _copyWith( {Email email, Address address, Gender gender, Birthday birthday, Name name, bool hasFinishedSignUp, Set authenticationProvider, Set notificationTokens, Length height, Weight weight, bool setNameNull = false, bool setAddressNull = false, bool setBirthdayNull = false, bool setWeightNull = false, bool setHeightNull = false, bool setGenderNull = false, List myBikes, String id}) { return User._( id: id ?? this.id, myBikes: myBikes ?? this.myBikes, email: email ?? this.email, name: setNameNull ? null : name ?? this.name, hasFinishedSignUp: hasFinishedSignUp ?? _hasFinishedSignUp, address: setAddressNull ? null : address ?? this.address, gender: setGenderNull ? null : gender ?? this.gender, birthday: setBirthdayNull ? null : birthday ?? this.birthday, authenticationProvider: authenticationProvider ?? _authenticationProvider, notificationTokens: notificationTokens ?? _notificationTokens, height: setHeightNull ? null : height ?? this.height, weight: setWeightNull ? null : weight ?? this.weight); } @override List get props => [ name, address, gender, birthday, email, weight, height, myBikes, _hasFinishedSignUp, _authenticationProvider ]; @override Map toMap() => { "name": name?.toMap(), "address": address?.toMap(), "gender": EnumToString.parse(gender), "birthday": birthday?.toMap(), "email": email?.toMap(), "weight": weight?.toMap(), "height": height?.toMap(), "myBikes": myBikes.map((bike) => bike.toMap()).toList(), "hasFinishedSignUp": _hasFinishedSignUp, "authenticationProvider": _authenticationProvider .map((provider) => EnumToString.parse(provider)) .toList() }; User.fromMap(Map map) : name = map["name"] == null ? null : Name.fromMap(map["name"] as Map), address = map["address"] == null ? null : Address.fromMap(map["address"] as Map), gender = EnumToString.fromString(Gender.values, map["gender"] as String), birthday = map["birthday"] == null ? null : Birthday.fromMap(map["birthday"] as Map), email = map["email"] == null ? null : Email.fromMap(map["email"] as Map), weight = map["weight"] == null ? null : Weight.fromMap(map["weight"] as Map), height = map["height"] == null ? null : Length.fromMap(map["height"] as Map), myBikes = (map["myBikes"] as List) .map((dynamic bikeMap) => Bike.fromMap(bikeMap as Map)) .toList(), _hasFinishedSignUp = map["hasFinishedSignUp"] as bool, _authenticationProvider = (map["authenticationProvider"] as List) .map((dynamic providerMap) => EnumToString.fromString( AuthenticationProvider.values, providerMap as String)) .toSet(), _notificationTokens = map["notificationTokens"] == null ? null : (map["notificationTokens"] as List).toSet(), super.fromMap(map); }