package org.ntlab.tampoposerver.services;
import org.ntlab.tampoposerver.models.FriendPair;
import org.ntlab.tampoposerver.models.FriendRequest;
import org.ntlab.tampoposerver.models.User;
import org.ntlab.tampoposerver.repositories.FriendRepository;
import org.ntlab.tampoposerver.repositories.FriendRequestRepository;
import org.ntlab.tampoposerver.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
// MEMO: ユーザーのトークンを認証するところはUserRepositoryに任せる
// MEMO: フレンド系の操作で認証が必要な場合はここで対応する
@Service
public class FriendService {
private final UserRepository userRepository;
private final FriendRepository friendRepository;
private final FriendRequestRepository friendRequestRepository;
//臨時
@PostConstruct
public void init() {
// 起動時に test0-test1 のペアをユーザーに紐付ける
FriendPair defaultPair = friendRepository.find(0);
if (defaultPair != null) {
userRepository.addFriendPair(defaultPair.getUser0Id(), defaultPair);
userRepository.addFriendPair(defaultPair.getUser1Id(), defaultPair);
}
System.out.println("Default friend pair (test0 <-> test1) initialized.");
}
@Autowired
public FriendService(UserRepository userRepository, FriendRepository friendRepository, FriendRequestRepository friendRequestRepository) {
this.userRepository = userRepository;
this.friendRepository = friendRepository;
this.friendRequestRepository = friendRequestRepository;
}
/**
* 新しいフレンドリクエストを作成する
*
* @param token APIリクエストをしてきたユーザーの認証用トークン
* @param senderId フレンドリクエストを送ったユーザーのユーザーID
* @param receiverId フレンドリクエストを受け取ったユーザーのユーザーID
* @return 作成されたフレンドリクエストのインスタンス(tokenに対応したユーザーがsenderIdでもreceiverIdにも関係しない場合は{@code Optional.empty()})
* @apiNote {@code token} が有効かどうか、{@code senderId}と{@code receiverId}に対応したユーザーがそれぞれ存在するかどうかは別に判定が必要
*/
public FriendRequest createFriendRequest(String token, String senderId, String receiverId) {
User sender = userRepository.getUser(senderId);
User receiver = userRepository.getUser(receiverId);
if (!sender.getToken().equals(token) && !receiver.getToken().equals(token)) {
return null;
}
return friendRequestRepository.create(new FriendRequest(senderId, receiverId));
}
/**
* ユーザー自身に関連するフレンドリクエストをすべて返す
*
* @param token ユーザー認証用のトークン
* @return ユーザー自身に関連するすべてのフレンドリクエストのインスタンス(リクエストがなければ空のリスト)
* @apiNote {@code token} が有効かどうかは別に判定が必要
*/
public ArrayList<FriendRequest> getFriendRequests(String token) {
ArrayList<FriendRequest> results = new ArrayList<>();
Collection<FriendRequest> allRequests = friendRequestRepository.findAll();
for (FriendRequest request : allRequests) {
User sender = userRepository.getUser(request.getSenderId());
User receiver = userRepository.getUser(request.getReceiverId());
if ((sender.getToken() != null && sender.getToken().equals(token)) || (receiver.getToken() != null && receiver.getToken().equals(token))) {
results.add(request);
}
}
return results;
}
/**
* 指定したフレンドリクエストを削除する
*
* @param token APIリクエストをしてきたユーザーの認証用トークン
* @param friendRequestId 削除する対象のフレンドリクエストのID
* @return 削除に成功したらtrue, それ以外はfalse
* @apiNote {@code token} が有効かどうかは別に判定が必要
*/
public boolean removeFriendRequest(String token, int friendRequestId) {
FriendRequest targetRequest = friendRequestRepository.find(friendRequestId);
if (targetRequest == null) {
return false;
}
User sender = userRepository.getUser(targetRequest.getSenderId());
User receiver = userRepository.getUser(targetRequest.getReceiverId());
if (!sender.getToken().equals(token) && !receiver.getToken().equals(token)) {
return false;
}
return friendRequestRepository.delete(friendRequestId);
}
/**
* 新しくフレンドペアを作成する
*
* @param user0Id 片方のユーザーのユーザーID
* @param user1Id もう一方のユーザーのユーザーID
* @return 追加されたフレンドペアのインスタンス(エラーがあった場合は{@code Optional.empty()})
* @apiNote {@code token} が有効かどうかは別に判定が必要
*/
public FriendPair createFriendPair(String user0Id, String user1Id) {
// フレンドリクエストを検索して削除する
FriendRequest acceptedRequest = friendRequestRepository.findAll().stream().filter((req) -> {
return (req.getSenderId().equals(user0Id) && req.getReceiverId().equals(user1Id)) || (req.getSenderId().equals(user1Id) && req.getReceiverId().equals(user0Id));
}).findFirst().orElse(null);
if (acceptedRequest == null) {
return null;
}
friendRequestRepository.delete(acceptedRequest.getId());
// フレンドを追加する
FriendPair createdPair = friendRepository.add(new FriendPair(user0Id, user1Id));
userRepository.addFriendPair(user0Id, createdPair);
userRepository.addFriendPair(user1Id, createdPair);
return createdPair;
}
/**
* 指定したフレンドのペアを取得する
*
* @param token APIリクエストをしてきたユーザーの認証用トークン
* @param friendPairId 取得する対象のフレンドペアのID
* @return 渡したフレンドペアのIDに対応したフレンドペア
* @apiNote {@code token} が有効かどうかは別に判定が必要
*/
public FriendPair getFriendPair(String token, int friendPairId) {
FriendPair foundPair = friendRepository.find(friendPairId);
if (foundPair == null) {
// System.out.println("FriendPair not found for id: " + friendPairId);
return null;
}
User user0 = userRepository.getUser(foundPair.getUser0Id());
User user1 = userRepository.getUser(foundPair.getUser1Id());
// if (!user0.getToken().equals(token) && !user1.getToken().equals(token)) {
// if (!user0.getToken().equals(token) && !user1.getToken().equals(token)) {
// System.out.println("Token mismatch! Provided: " + token);
// System.out.println("user0 token: " + user0.getToken());
// System.out.println("user1 token: " + user1.getToken());
// return null;
// }
// System.out.println("Token valid, returning pair");
// return null;
// }
return foundPair;
}
/**
* 指定したフレンドのペアを削除する
*
* @param token APIリクエストをしてきたユーザーの認証用トークン
* @param friendPairId 削除する対象のフレンドペアのID
* @return 削除に成功したらtrue, それ以外はfalse
*/
public boolean removeFriendPair(String token, int friendPairId) {
FriendPair foundPair = friendRepository.find(friendPairId);
if (foundPair == null) {
return false;
}
User user0 = userRepository.getUser(foundPair.getUser0Id());
User user1 = userRepository.getUser(foundPair.getUser1Id());
if (!user0.getToken().equals(token) && !user1.getToken().equals(token)) {
return false;
}
// フレンドペアを削除する
return friendRepository.delete(friendPairId) && userRepository.deleteFriendPair(user0.getUserId(), foundPair) && userRepository.deleteFriendPair(user1.getUserId(), foundPair);
}
/**
* ユーザーIDが{@code userId}のユーザーとフレンドになっているユーザーのIDをすべて返す
*
* @param token APIリクエストをしてきたユーザーの認証用トークン
* @param userId APIリクエストをしてきたユーザーのID
* @return ユーザーIDが {@code userId} のユーザーとフレンドになっているユーザーすべてのID
* @apiNote ペアがない場合は空の配列、トークンとユーザーIDで認証できなければnullを返す
*/
public ArrayList<String> getFriendIds(String token, String userId) {
User user = userRepository.getUser(userId);
if (user == null || !user.getToken().equals(token)) {
return null;
}
ArrayList<String> friendIds = new ArrayList<>();
for (FriendPair friendPair : user.getFriendPairs()) {
if (friendPair.getUser0Id().equals(user.getUserId())) {
friendIds.add(friendPair.getUser1Id());
} else {
friendIds.add(friendPair.getUser0Id());
}
}
return friendIds;
}
}