/**
* Copyright 2019 The Knights Of Unity, created by Pawel Stolarczyk
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using DemoGame.Scripts.Clans;
using DemoGame.Scripts.Friends;
using DemoGame.Scripts.Menus;
using DemoGame.Scripts.Profile;
using DemoGame.Scripts.Session;
using Nakama;
using UnityEngine;
using UnityEngine.UI;
namespace DemoGame.Scripts.Leaderboards
{
///
/// Manages leaderboards UI.
///
public class LeaderboardPanel : Menu
{
#region Fields
///
/// Parent for all leaderboards records.
///
[SerializeField] private RectTransform _userList = null;
///
/// Prefab of a single leaderboard record.
///
[SerializeField] private LeaderboardEntry _leaderboardEntryPrefab = null;
///
/// Maximum number of records displayed on a single page.
///
[SerializeField] private int _recordsPerPage = 100;
#region Buttons
///
/// Shows global leaderboard.
///
[SerializeField] private Button _showGlobal = null;
///
/// Shows clan leaderboards.
///
[SerializeField] private Button _showClan = null;
///
/// Shows friends leaderboards.
///
[SerializeField] private Button _showFriends = null;
///
/// Shows next page of leaderboard results.
///
[SerializeField] private Button _nextPageButton = null;
///
/// Shows previous page of leaderboard results.
///
[SerializeField] private Button _prevPageButton = null;
#endregion
///
/// Invoked upon clicking .
///
private Action _nextPage;
///
/// Invoked upon clicking .
///
private Action _prevPage;
#endregion
#region Properties
///
/// Returns from for easier access.
///
private Client Client { get { return NakamaSessionManager.Instance.Client; } }
///
/// Returns from for easier access.
///
private ISession Session { get { return NakamaSessionManager.Instance.Session; } }
#endregion
#region Mono
///
/// Calls method upon connecting to Nakama.
///
private void Awake()
{
base.SetBackButtonHandler(MenuManager.Instance.HideTopMenu);
if (NakamaSessionManager.Instance.IsConnected == false)
{
NakamaSessionManager.Instance.OnConnectionSuccess += Init;
}
else
{
Init();
}
}
#endregion
#region Methods
///
/// Adds handlers to buttons.
///
private void Init()
{
NakamaSessionManager.Instance.OnConnectionSuccess -= Init;
_showClan.onClick.AddListener(() => ShowClanLeaderboards(null));
_showGlobal.onClick.AddListener(() => ShowGlobalLeaderboards(null));
_showFriends.onClick.AddListener(() => ShowFriendsLeaderboards(null));
ShowGlobalLeaderboards();
}
#region RecordListFilling
///
/// Fills with user records sorted by the score.
///
public async void ShowGlobalLeaderboards(string cursor = null)
{
IApiLeaderboardRecordList records = await LeaderboardManager.GetGlobalLeaderboarsAsync(Client, Session, _recordsPerPage, cursor);
if (records != null)
{
SetLeaderboardsCursor(records, ShowGlobalLeaderboards);
FillLeaderboard(records.Records);
_showFriends.interactable = true;
_showClan.interactable = true;
_showGlobal.interactable = false;
}
}
///
/// Fills with records of all members of the clan local user belongs to.
///
public async void ShowClanLeaderboards(string cursor)
{
IUserGroupListUserGroup clan = await ClanManager.GetUserClanAsync(Client, Session);
if (clan == null)
{
return;
}
IApiLeaderboardRecordList records = await LeaderboardManager.GetClanLeaderboarsAsync(Client, Session, clan.Group, _recordsPerPage, cursor);
if (records != null)
{
SetLeaderboardsCursor(records, ShowClanLeaderboards);
FillLeaderboard(records.OwnerRecords);
_showFriends.interactable = true;
_showClan.interactable = false;
_showGlobal.interactable = true;
}
}
///
/// Gets ids of all friends of local user and displays their records.
/// This also includes local user.
///
public async void ShowFriendsLeaderboards(string cursor)
{
IApiFriends friends = await FriendsManager.LoadFriendsAsync(Client, Session);
if (friends == null)
{
return;
}
IApiLeaderboardRecordList records = await LeaderboardManager.GetFriendsLeaderboarsAsync(Client, Session, friends.Friends, _recordsPerPage, cursor);
if (records != null)
{
SetLeaderboardsCursor(records, ShowFriendsLeaderboards);
FillLeaderboard(records.OwnerRecords);
_showFriends.interactable = false;
_showClan.interactable = true;
_showGlobal.interactable = true;
}
}
#endregion
///
/// Sets and onClick events.
/// If there is no next or previous page, disables interactions with these buttons.
///
///
/// Contains and
/// responsible for iterating through pages.
///
///
/// Method used to receive . This method will be called to iterate
/// through pages using cursors.
///
private void SetLeaderboardsCursor(IApiLeaderboardRecordList records, Action caller)
{
if (records.PrevCursor != null)
{
_prevPageButton.interactable = true;
_prevPageButton.onClick.RemoveAllListeners();
_prevPageButton.onClick.AddListener(() => caller(records.PrevCursor));
}
else
{
_prevPageButton.interactable = false;
}
if (records.NextCursor != null)
{
_nextPageButton.interactable = true;
_nextPageButton.onClick.RemoveAllListeners();
_nextPageButton.onClick.AddListener(() => caller(records.NextCursor));
}
else
{
_nextPageButton.interactable = false;
}
}
///
/// Destroys every child of , then
/// creates an instance of for each record.
///
private void FillLeaderboard(IEnumerable recordList)
{
foreach (Transform entry in _userList)
{
Destroy(entry.gameObject);
}
int rank = 1;
string localId = NakamaSessionManager.Instance.Account.User.Id;
foreach (IApiLeaderboardRecord record in recordList)
{
LeaderboardEntry entry = Instantiate(_leaderboardEntryPrefab, _userList);
string username = record.Username;
if (localId == record.OwnerId)
{
username += " (You)";
}
entry.SetPlayer(username, rank, record.Score, () => OnProfileClicked(record.OwnerId));
rank += 1;
}
}
///
/// Invoked whenever user clicks button of a record.
///
private async void OnProfileClicked(string userId)
{
IApiUser user = await NakamaSessionManager.Instance.GetUserInfoAsync(userId, null);
if (user != null)
{
ProfilePopup.Instance.Show(userId);
}
}
///
/// Checks whether local user is a member of a clan, then disables or enables
/// button accordingly. Shows this menu.
///
public async override void Show()
{
Client client = NakamaSessionManager.Instance.Client;
ISession session = NakamaSessionManager.Instance.Session;
// If local user is not a member of a clan, disable clan leaderboards
IUserGroupListUserGroup clan = await ClanManager.GetUserClanAsync(client, session);
if (clan != null)
{
_showClan.gameObject.SetActive(true);
}
else
{
// User is not a member of any clan
// Hiding clan score tab
if (_showClan.interactable == true)
{
// Last showed tab is clan tab
// Switching to other tab
ShowGlobalLeaderboards();
}
_showClan.gameObject.SetActive(false);
}
base.Show();
}
#endregion
}
}