import 'package:drift/drift.dart'; import 'package:tallee/data/db/database.dart'; import 'package:tallee/data/db/tables/player_group_table.dart'; import 'package:tallee/data/db/tables/player_table.dart'; import 'package:tallee/data/models/player.dart'; part 'player_group_dao.g.dart'; @DriftAccessor(tables: [PlayerGroupTable, PlayerTable]) class PlayerGroupDao extends DatabaseAccessor with _$PlayerGroupDaoMixin { PlayerGroupDao(super.db); /* Create */ /// Adds a [player] to a group with the given [groupId]. /// If the player is already in the group, no action is taken. /// If the player does not exist in the player table, they are added. /// Returns `true` if the player was added, otherwise `false`. Future addPlayerToGroup({ required Player player, required String groupId, }) async { if (await isPlayerInGroup(playerId: player.id, groupId: groupId)) { return false; } if (!await db.playerDao.playerExists(playerId: player.id)) { await db.playerDao.addPlayer(player: player); } await into(playerGroupTable).insert( PlayerGroupTableCompanion.insert(playerId: player.id, groupId: groupId), ); return true; } /* Read */ /// Retrieves all players belonging to a specific group by [groupId]. Future> getPlayersOfGroup({required String groupId}) async { final query = select(playerGroupTable).join([ innerJoin( playerTable, playerTable.id.equalsExp(playerGroupTable.playerId), ), ])..where(playerGroupTable.groupId.equals(groupId)); final results = await query.map((row) => row.readTable(playerTable)).get(); return results .map( (result) => Player( id: result.id, createdAt: result.createdAt, name: result.name, nameCount: result.nameCount, description: result.description, ), ) .toList(); } /// Checks if a player with [playerId] is in the group with [groupId]. /// Returns `true` if the player is in the group, otherwise `false`. Future isPlayerInGroup({ required String playerId, required String groupId, }) async { final query = select(playerGroupTable) ..where((p) => p.playerId.equals(playerId) & p.groupId.equals(groupId)); final result = await query.getSingleOrNull(); return result != null; } /* Update */ /// Replaces all players in a group with the provided list of players. /// Removes all existing players from the group and adds the new players. /// Also adds any new players to the player table if they don't exist. /// Returns `true` if the group exists and players were replaced, `false` otherwise. Future replaceGroupPlayers({ required String groupId, required List newPlayers, }) async { if (!await db.groupDao.groupExists(groupId: groupId)) return false; if (newPlayers.isEmpty) return false; await db.transaction(() async { // Remove all existing players from the group final deleteQuery = delete(db.playerGroupTable) ..where((p) => p.groupId.equals(groupId)); await deleteQuery.go(); // Add new players to the player table if they don't exist await Future.wait( newPlayers.map((player) async { if (!await db.playerDao.playerExists(playerId: player.id)) { await db.playerDao.addPlayer(player: player); } }), ); // Add the new players to the group await db.batch( (b) => b.insertAll( db.playerGroupTable, newPlayers .map( (player) => PlayerGroupTableCompanion.insert( playerId: player.id, groupId: groupId, ), ) .toList(), mode: InsertMode.insertOrReplace, ), ); }); return true; } /* Delete */ /// Removes a player from a group based on [playerId] and [groupId]. /// Returns `true` if more than 0 rows were affected, otherwise `false`. Future removePlayerFromGroup({ required String playerId, required String groupId, }) async { final query = delete(playerGroupTable) ..where((p) => p.playerId.equals(playerId) & p.groupId.equals(groupId)); final rowsAffected = await query.go(); return rowsAffected > 0; } }