import 'package:objectbox/objectbox.dart';

@Entity()
class Connection {
  @Id()
  int obId;

  ConnectionStatus status;

  int get dbStatus => status.code;

  set dbStatus(int value) => status = ConnectionStatus.fromValue(value);

  final String name;

  final String handle;

  @Unique(onConflict: ConflictStrategy.replace)
  final String id;

  final String profileUrl;

  final String network;

  final String avatarUrl;

  final String note;

  final int? followerCount;

  final int? followingCount;

  final int? statusesCount;

  @Property(type: PropertyType.date)
  final DateTime? lastStatus;

  @Property(type: PropertyType.date)
  final DateTime lastUpdateTime;

  Connection({
    this.obId = 0,
    this.status = ConnectionStatus.unknown,
    this.name = '',
    this.handle = '',
    this.id = '',
    String? profileUrl,
    this.network = '',
    String? avatarUrl,
    DateTime? lastUpdateTime,
    this.note = '',
    this.followerCount,
    this.followingCount,
    this.statusesCount,
    this.lastStatus,
  })  : profileUrl = profileUrl ?? '',
        avatarUrl = avatarUrl ?? '',
        lastUpdateTime = lastUpdateTime ?? DateTime.now();

  bool get isEmpty =>
      name.isEmpty &&
      id.isEmpty &&
      network.isEmpty &&
      status == ConnectionStatus.unknown;

  bool get isNotEmpty => !isEmpty;

  Connection copy({
    int? obId,
    ConnectionStatus? status,
    String? name,
    String? handle,
    String? id,
    String? profileUrl,
    String? network,
    String? avatarUrl,
    DateTime? lastUpdateTime,
    String? note,
    int? followerCount,
    int? followingCount,
    int? statusesCount,
    DateTime? lastStatus,
  }) =>
      Connection(
        obId: obId ?? this.obId,
        status: status ?? this.status,
        name: name ?? this.name,
        handle: handle ?? this.handle,
        id: id ?? this.id,
        profileUrl: profileUrl ?? this.profileUrl,
        network: network ?? this.network,
        avatarUrl: avatarUrl ?? this.avatarUrl,
        lastUpdateTime: lastUpdateTime ?? this.lastUpdateTime,
        note: note ?? this.note,
        followerCount: followerCount ?? this.followerCount,
        followingCount: followingCount ?? this.followingCount,
        statusesCount: statusesCount ?? this.statusesCount,
        lastStatus: lastStatus ?? this.lastStatus,
      );

  @override
  String toString() {
    return 'Connection{status: $status, name: $name, id: $id, handle: $handle, profileUrl: $profileUrl, network: $network, avatar: $avatarUrl}';
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Connection && runtimeType == other.runtimeType && id == other.id;

  @override
  int get hashCode => id.hashCode;
}

enum ConnectionStatus {
  blocked(0),
  youFollowThem(1),
  theyFollowYou(2),
  mutual(3),
  you(4),
  none(5),
  unknown(6),
  ;

  final int code;

  const ConnectionStatus(this.code);

  factory ConnectionStatus.fromValue(int value) {
    return ConnectionStatus.values.where((e) => e.code == value).first;
  }
}

extension FriendStatusWriter on ConnectionStatus {
  String label() {
    switch (this) {
      case ConnectionStatus.youFollowThem:
        return "You Follow Them";
      case ConnectionStatus.theyFollowYou:
        return "They Follow You";
      case ConnectionStatus.mutual:
        return "Follow each other";
      case ConnectionStatus.none:
        return "Not connected";
      case ConnectionStatus.you:
        return "You";
      case ConnectionStatus.unknown:
        return 'Unknown';
      case ConnectionStatus.blocked:
        return 'Blocked';
    }
  }
}
