// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AmazonGameLiftPlugin.Core.AccountManagement.Models;
using AmazonGameLiftPlugin.Core.BucketManagement.Models;
using AmazonGameLiftPlugin.Core.SettingsManagement.Models;
using AmazonGameLiftPlugin.Core.Shared;
using UnityEditor;
using UnityEngine;
namespace AmazonGameLift.Editor
{
///
/// A view model for .
///
internal class BootstrapSettings
{
public const int CreationMode = 0;
public const int SelectionMode = 1;
public const int NoneLifeCyclePolicyIndex = 0;
private const int DefaultLifeCyclePolicyIndex = 0;
private readonly Status _status = new Status();
private readonly BucketUrlFormatter _bucketUrlFormatter = new BucketUrlFormatter();
private readonly BucketPolicy[] _lifecyclePolicies;
private readonly TextProvider _textProvider;
private readonly IBucketNameFormatter _bucketFormatter;
private readonly ILogger _logger;
private readonly CoreApi _coreApi;
private readonly BootstrapUtility _bootstrapUtility;
private List _existingBuckets = new List();
public IReadStatus Status => _status;
public IReadOnlyList ExistingBuckets => _existingBuckets;
public string[] AllLifecyclePolicyNames { get; }
///
/// Is set by , or .
///
public string CurrentRegion { get; private set; }
///
/// Updated in or .
///
public string CurrentBucketName { get; private set; }
public string CurrentBucketUrl { get; private set; }
public bool HasCurrentBucket { get; private set; }
///
/// Generated from .
///
public string BucketName { get; set; }
public int LifeCyclePolicyIndex { get; set; }
public bool CanCreate => !string.IsNullOrEmpty(BucketName);
public bool IsBucketListLoaded { get; private set; }
public bool CanSaveSelectedBucket =>
_existingBuckets.Count != 0
&& CurrentRegion != null
&& !string.IsNullOrEmpty(BucketName);
public int SelectedMode { get; set; }
public event Action> OnBucketsLoaded = default;
public BootstrapSettings(IEnumerable lifecyclePolicies,
IEnumerable lifecyclePolicyNames, TextProvider textProvider,
IBucketNameFormatter bucketFormatter, ILogger logger, CoreApi coreApi = null,
BootstrapUtility bootstrapUtility = null)
{
if (lifecyclePolicies is null)
{
throw new ArgumentNullException(nameof(lifecyclePolicies));
}
if (lifecyclePolicyNames is null)
{
throw new ArgumentNullException(nameof(lifecyclePolicyNames));
}
_lifecyclePolicies = lifecyclePolicies.ToArray();
_textProvider = textProvider ?? throw new ArgumentNullException(nameof(textProvider));
_bucketFormatter = bucketFormatter ?? throw new ArgumentNullException(nameof(bucketFormatter));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_coreApi = coreApi ?? CoreApi.SharedInstance;
_bootstrapUtility = bootstrapUtility ?? BootstrapUtility.SharedInstance;
LifeCyclePolicyIndex = DefaultLifeCyclePolicyIndex;
AllLifecyclePolicyNames = lifecyclePolicyNames.ToArray();
}
public async Task SetUp(CancellationToken cancellationToken = default)
{
await RefreshExistingBuckets(cancellationToken);
}
public void SelectBucket(string name)
{
if (BucketName == name)
{
return;
}
BucketName = name;
// Reset if we select a new valid bucket
_status.IsDisplayed &= string.IsNullOrEmpty(BucketName);
}
public void CreateBucket()
{
if (!CanCreate)
{
return;
}
GetBootstrapDataResponse bootstrapResponse = _bootstrapUtility.GetBootstrapData();
if (!bootstrapResponse.Success)
{
OnBucketCreationFailure(bootstrapResponse);
return;
}
CreateBucketResponse createResponse = _coreApi.CreateBucket(bootstrapResponse.Profile, bootstrapResponse.Region, BucketName);
if (createResponse.Success)
{
OnBucketCreated(bootstrapResponse.Profile, bootstrapResponse.Region, BucketName);
}
else
{
OnBucketCreationFailure(createResponse);
}
}
public void SaveSelectedBucket()
{
if (!CanSaveSelectedBucket)
{
_logger.Log(DevStrings.OperationInvalid, LogType.Error);
return;
}
PutSettingResponse bucketNameResponse = _coreApi.PutSetting(SettingsKeys.CurrentBucketName, BucketName);
if (!bucketNameResponse.Success)
{
SetErrorStatus(Strings.StatusBootstrapFailedTemplate, bucketNameResponse);
_logger.LogResponseError(bucketNameResponse);
return;
}
HasCurrentBucket = true;
CurrentBucketName = BucketName;
CurrentBucketUrl = _bucketUrlFormatter.Format(CurrentBucketName, CurrentRegion);
SetInfoStatus(Strings.StatusBootstrapUpdateComplete);
}
///
/// Sets to true when complete.
///
public async Task RefreshExistingBuckets(CancellationToken cancellationToken = default)
{
IsBucketListLoaded = false;
_status.IsDisplayed = false;
_existingBuckets.Clear();
try
{
GetSettingResponse profileResponse = _coreApi.GetSetting(SettingsKeys.CurrentProfileName);
if (!profileResponse.Success)
{
SetErrorStatus(Strings.StatusGetProfileFailed);
_logger.LogResponseError(profileResponse);
return;
}
GetSettingResponse regionResponse = _coreApi.GetSetting(SettingsKeys.CurrentRegion);
if (!regionResponse.Success || !_coreApi.IsValidRegion(regionResponse.Value))
{
SetErrorStatus(Strings.StatusGetRegionFailed);
_logger.LogResponseError(regionResponse);
return;
}
GetBucketsResponse bucketsResponse = await Task.Run(() => _coreApi.ListBuckets(profileResponse.Value, regionResponse.Value), cancellationToken);
if (!bucketsResponse.Success)
{
SetErrorStatus(Strings.StatusBootstrapFailedTemplate, bucketsResponse);
_logger.LogResponseError(bucketsResponse);
return;
}
_existingBuckets = bucketsResponse.Buckets.ToList();
}
catch (TaskCanceledException)
{
throw;
}
catch (Exception ex)
{
_logger.LogException(ex);
throw;
}
finally
{
IsBucketListLoaded = true;
OnBucketsLoaded?.Invoke(_existingBuckets);
}
}
public void Refresh()
{
RefreshBucketName();
RefreshCurrentBucket();
}
public void RefreshCurrentBucket()
{
GetSettingResponse bucketNameResponse = _coreApi.GetSetting(SettingsKeys.CurrentBucketName);
CurrentBucketName = bucketNameResponse.Success ? bucketNameResponse.Value : null;
GetSettingResponse currentRegionResponse = _coreApi.GetSetting(SettingsKeys.CurrentRegion);
bool isRegionValid = _coreApi.IsValidRegion(currentRegionResponse.Value);
CurrentRegion = currentRegionResponse.Success && isRegionValid ? currentRegionResponse.Value : null;
HasCurrentBucket = !string.IsNullOrEmpty(CurrentBucketName) && isRegionValid;
if (HasCurrentBucket)
{
CurrentBucketUrl = _bucketUrlFormatter.Format(CurrentBucketName, CurrentRegion);
return;
}
CurrentBucketName = null;
CurrentBucketUrl = null;
if (!isRegionValid)
{
CurrentRegion = null;
}
}
public void RefreshBucketName()
{
CurrentRegion = null;
BucketName = null;
GetSettingResponse currentRegionResponse = _coreApi.GetSetting(SettingsKeys.CurrentRegion);
if (!currentRegionResponse.Success || !_coreApi.IsValidRegion(currentRegionResponse.Value))
{
SetErrorStatus(Strings.StatusGetRegionFailed);
_logger.LogResponseError(currentRegionResponse);
return;
}
CurrentRegion = currentRegionResponse.Value;
GetSettingResponse profileResponse = _coreApi.GetSetting(SettingsKeys.CurrentProfileName);
if (!profileResponse.Success)
{
SetErrorStatus(Strings.StatusGetProfileFailed);
_logger.LogResponseError(profileResponse);
return;
}
RetrieveAccountIdByCredentialsResponse accountIdResponse = _coreApi.RetrieveAccountId(profileResponse.Value);
if (!accountIdResponse.Success)
{
SetErrorStatus(Strings.StatusBootstrapFailedTemplate, accountIdResponse);
_logger.LogResponseError(accountIdResponse);
return;
}
BucketName = _bucketFormatter.FormatBucketName(accountIdResponse.AccountId, CurrentRegion);
}
private void SetInfoStatus(string statusKey)
{
SetStatus(statusKey, MessageType.Info);
}
private void SetErrorStatus(string statusKey)
{
SetStatus(statusKey, MessageType.Error);
}
private void SetErrorStatus(string statusKey, Response errorResponse)
{
string errorTemplate = _textProvider.Get(statusKey);
string message = string.Format(errorTemplate, _textProvider.GetError(errorResponse.ErrorCode), errorResponse.ErrorMessage);
_status.SetMessage(message, MessageType.Error);
_status.IsDisplayed = true;
}
private void SetStatus(string statusKey, MessageType messageType)
{
_status.SetMessage(_textProvider.Get(statusKey), messageType);
_status.IsDisplayed = true;
}
private void OnBucketCreated(string profileName, string region, string bucketName)
{
PutSettingResponse bucketNameResponse = _coreApi.PutSetting(SettingsKeys.CurrentBucketName, bucketName);
if (!bucketNameResponse.Success)
{
OnBucketCreationFailure(bucketNameResponse);
return;
}
BucketPolicy policy = _lifecyclePolicies[LifeCyclePolicyIndex];
if (policy != BucketPolicy.None)
{
PutLifecycleConfigurationResponse putPolicyResponse = _coreApi.PutBucketLifecycleConfiguration(profileName, region, bucketName, policy);
if (!putPolicyResponse.Success)
{
_logger.LogResponseError(putPolicyResponse);
}
}
SetInfoStatus(Strings.StatusBootstrapComplete);
RefreshCurrentBucket();
}
private void OnBucketCreationFailure(Response response)
{
SetErrorStatus(Strings.StatusBootstrapFailedTemplate, response);
_logger.LogResponseError(response);
}
}
}