using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Unity.Cloud.Collaborate.Assets;
using Unity.Cloud.Collaborate.Models;
using Unity.Cloud.Collaborate.Views;
using Unity.Cloud.Collaborate.Models.Structures;
using UnityEngine;
using UnityEngine.Assertions;
namespace Unity.Cloud.Collaborate.Presenters
{
internal class HistoryPresenter : IHistoryPresenter
{
internal const int pageSize = 10;
internal const string historyEntrySelectedId = "history-entry-selected";
int m_MaxPages;
bool m_IsStarted;
[NotNull]
readonly IHistoryView m_View;
[NotNull]
readonly IHistoryModel m_HistoryModel;
[NotNull]
readonly IMainModel m_MainModel;
public HistoryPresenter([NotNull] IHistoryView view, [NotNull] IHistoryModel historyModel, [NotNull] IMainModel mainModel)
{
m_View = view;
m_HistoryModel = historyModel;
m_MainModel = mainModel;
}
///
public void Start()
{
Assert.IsFalse(m_IsStarted, "The presenter has already been started.");
m_IsStarted = true;
m_HistoryModel.HistoryListUpdated += OnHistoryListUpdated;
m_HistoryModel.SelectedRevisionReceived += OnSelectedRevisionReceived;
m_HistoryModel.EntryCountUpdated += OnEntryCountUpdated;
m_HistoryModel.HistoryListReceived += OnHistoryListReceived;
m_HistoryModel.BusyStatusUpdated += OnBusyStatusUpdated;
m_HistoryModel.StateChanged += OnStateChanged;
PopulateInitialData();
}
///
public void Stop()
{
Assert.IsTrue(m_IsStarted, "The presenter has already been stopped.");
m_IsStarted = false;
m_HistoryModel.HistoryListUpdated -= OnHistoryListUpdated;
m_HistoryModel.SelectedRevisionReceived -= OnSelectedRevisionReceived;
m_HistoryModel.EntryCountUpdated -= OnEntryCountUpdated;
m_HistoryModel.HistoryListReceived -= OnHistoryListReceived;
m_HistoryModel.BusyStatusUpdated -= OnBusyStatusUpdated;
m_HistoryModel.StateChanged -= OnStateChanged;
m_MainModel.UnregisterBackNavigation(historyEntrySelectedId);
}
///
/// Refresh state from the model.
///
void OnStateChanged()
{
PopulateInitialData();
}
///
/// Populate the view with the initial data from the model.
///
void PopulateInitialData()
{
m_View.SetBusyStatus(m_HistoryModel.Busy);
if (!string.IsNullOrEmpty(m_HistoryModel.SelectedRevisionId))
{
m_HistoryModel.RequestSingleRevision(m_HistoryModel.SelectedRevisionId);
}
else if (!string.IsNullOrEmpty(m_HistoryModel.SavedRevisionId))
{
m_HistoryModel.RequestSingleRevision(m_HistoryModel.SavedRevisionId);
}
else
{
// Request initial data
m_HistoryModel.RequestPageOfRevisions(pageSize);
}
m_HistoryModel.RequestEntryNumber();
}
///
/// Event handler to receive updated busy status.
///
/// New busy status.
void OnBusyStatusUpdated(bool busy)
{
m_View.SetBusyStatus(busy);
}
///
/// Event handler to receive requested history list.
///
/// Received history list.
void OnHistoryListReceived(IReadOnlyList list)
{
if (list == null)
{
// Return back to first page of entries
m_HistoryModel.PageNumber = 0;
m_HistoryModel.RequestPageOfRevisions(pageSize);
Debug.LogError("Request page does not exist.");
return;
}
m_MainModel.UnregisterBackNavigation(historyEntrySelectedId);
m_View.SetHistoryList(list);
}
///
/// Event handler to receive updated history entry count.
///
/// New entry count.
void OnEntryCountUpdated(int? count)
{
if (count == null)
{
Debug.LogError("Unable to fetch number of revisions");
return;
}
m_MaxPages = (count.Value - 1) / pageSize;
m_View.SetPage(m_HistoryModel.PageNumber, m_MaxPages);
}
///
/// Event handler to receive requested single revision.
///
/// Received single revision.
void OnSelectedRevisionReceived(IHistoryEntry entry)
{
if (entry == null)
{
// Return back to all revisions list
m_HistoryModel.RequestPageOfRevisions(pageSize);
Debug.LogError("Unable to find requested revision");
return;
}
m_MainModel.RegisterBackNavigation(historyEntrySelectedId, StringAssets.allHistory, OnBackEvent);
m_View.SetSelection(entry);
}
///
/// Event handler for when the model has received a message of an updated history list.
///
void OnHistoryListUpdated()
{
// Request updated number of entries.
m_HistoryModel.RequestEntryNumber();
// Request either single revision or list of revisions depending on current state.
if (m_HistoryModel.IsRevisionSelected)
{
Assert.AreNotEqual(string.Empty, m_HistoryModel.SelectedRevisionId, "There should be a revision id at this point.");
m_HistoryModel.RequestSingleRevision(m_HistoryModel.SelectedRevisionId);
}
else
{
m_HistoryModel.RequestPageOfRevisions(pageSize);
}
}
///
/// Event handler for when the back button is pressed.
///
void OnBackEvent()
{
// Return back to all revisions list
m_HistoryModel.RequestPageOfRevisions(pageSize);
}
///
public void PrevPage()
{
m_HistoryModel.PageNumber = Math.Max(m_HistoryModel.PageNumber - 1, 0);
m_HistoryModel.RequestPageOfRevisions(pageSize);
m_View.SetPage(m_HistoryModel.PageNumber, m_MaxPages);
}
///
public void NextPage()
{
m_HistoryModel.PageNumber = Math.Min(m_HistoryModel.PageNumber + 1, m_MaxPages);
m_HistoryModel.RequestPageOfRevisions(pageSize);
m_View.SetPage(m_HistoryModel.PageNumber, m_MaxPages);
}
///
public string SelectedRevisionId
{
set
{
if (m_HistoryModel.SelectedRevisionId == value) return;
m_HistoryModel.RequestSingleRevision(value);
}
}
///
public void RequestGoto(string revisionId, HistoryEntryStatus status)
{
switch (status) {
case HistoryEntryStatus.Ahead:
m_HistoryModel.RequestUpdateTo(revisionId);
break;
case HistoryEntryStatus.Current:
m_HistoryModel.RequestRestoreTo(revisionId);
break;
case HistoryEntryStatus.Behind:
m_HistoryModel.RequestGoBackTo(revisionId);
break;
default:
throw new ArgumentOutOfRangeException(nameof(status), status, null);
}
}
///
public bool SupportsRevert => m_HistoryModel.SupportsRevert;
///
public void RequestRevert(string revisionId, IReadOnlyList files)
{
m_HistoryModel.RequestRevert(revisionId, files);
}
}
}