using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Codice.Client.Common;
using Codice.Client.Common.Threading;
using Codice.Client.Common.WebApi;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Home.Repositories;
using PlasticGui.WorkspaceWindow.Home.Workspaces;
using Unity.PlasticSCM.Editor.AssetUtils.Processor;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
{
internal class CreateWorkspaceView :
IPlasticDialogCloser,
IWorkspacesRefreshableView
{
internal interface ICreateWorkspaceListener
{
void OnWorkspaceCreated(WorkspaceInfo wkInfo, bool isGluonMode);
}
internal CreateWorkspaceView(
UVCSWindow parentWindow,
ICreateWorkspaceListener listener,
IPlasticWebRestApi plasticWebRestApi,
IPlasticAPI plasticApi,
string workspacePath)
{
mParentWindow = parentWindow;
mCreateWorkspaceListener = listener;
mWorkspacePath = workspacePath;
mPlasticWebRestApi = plasticWebRestApi;
mPlasticApi = plasticApi;
mProgressControls = new ProgressControlsForViews();
mWorkspaceOperations = new WorkspaceOperations(this, mProgressControls, null);
mCreateWorkspaceState = CreateWorkspaceViewState.BuildForProjectDefaults();
Initialize(plasticWebRestApi, plasticApi);
}
internal void Update()
{
mProgressControls.UpdateProgress(mParentWindow);
}
internal void OnGUI()
{
if (Event.current.type == EventType.Layout)
{
mProgressControls.ProgressData.CopyInto(
mCreateWorkspaceState.ProgressData);
}
string repository = mCreateWorkspaceState.Repository;
DrawCreateWorkspace.ForState(
SelectRepository,
CreateRepository,
ValidateAndCreateWorkspace,
mParentWindow,
mPlasticWebRestApi,
mPlasticApi,
mDefaultServer,
ref mCreateWorkspaceState);
if (repository == mCreateWorkspaceState.Repository)
return;
SynchronizeRepositoryAndWorkspace();
}
void Initialize(
IPlasticWebRestApi plasticWebRestApi,
IPlasticAPI plasticApi)
{
((IProgressControls) mProgressControls).ShowProgress(string.Empty);
WorkspaceInfo[] allWorkspaces = null;
IList allRepositories = null;
string repositoryProject = null;
string localProjectFolder = !string.IsNullOrEmpty(CloudProjectSettings.projectName)
? CloudProjectSettings.projectName
: Application.productName;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mDefaultServer = GetDefaultServer.FromConfig(plasticWebRestApi);
allWorkspaces = plasticApi.GetAllWorkspacesArray();
allRepositories = plasticApi.GetAllRepositories(mDefaultServer, true);
if (OrganizationsInformation.IsUnityOrganization(mDefaultServer))
{
List<string> serverProjects = GetProjectNames.
FromOrganization(plasticApi, mDefaultServer);
if (serverProjects.Count == 0)
{
return;
}
// If any of the organization projects match in name with the local project, we select it.
// Otherwise, we return the first project in alphabetic order
repositoryProject = serverProjects.Contains(localProjectFolder)
? localProjectFolder
: serverProjects.First();
}
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls) mProgressControls).HideProgress();
if (waiter.Exception != null)
{
DisplayException(mProgressControls, waiter.Exception);
return;
}
UpdateProposedRepositoryAndWorkspace(allRepositories, repositoryProject, allWorkspaces);
mParentWindow.Repaint();
});
}
void UpdateProposedRepositoryAndWorkspace(
IList repositories,
string repositoryProject,
WorkspaceInfo[] workspaces)
{
string serverSpecPart = string.Format("@{0}", ResolveServer.ToDisplayString(mDefaultServer));
mCreateWorkspaceState.Repository = ValidRepositoryName.Get(
string.Format("{0}{1}", mCreateWorkspaceState.Repository, serverSpecPart),
repositories);
if (repositoryProject != null)
{
mCreateWorkspaceState.Repository = CloudProjectRepository.BuildFullyQualifiedName(
repositoryProject, mCreateWorkspaceState.Repository);
}
string proposedWorkspaceName = mCreateWorkspaceState.Repository.Replace(serverSpecPart, string.Empty);
mCreateWorkspaceState.WorkspaceName = CreateWorkspaceDialogUserAssistant.GetNonExistingWkNameForName(
proposedWorkspaceName, workspaces);
mDialogUserAssistant = CreateWorkspaceDialogUserAssistant.ForWkPathAndName(
mWorkspacePath,
workspaces);
SynchronizeRepositoryAndWorkspace();
}
void SynchronizeRepositoryAndWorkspace()
{
if (mDialogUserAssistant == null)
{
return;
}
mDialogUserAssistant.RepositoryChanged(
mCreateWorkspaceState.Repository,
mCreateWorkspaceState.WorkspaceName,
mWorkspacePath);
mCreateWorkspaceState.WorkspaceName = mDialogUserAssistant.GetProposedWorkspaceName();
}
void SelectRepository(string repository)
{
mCreateWorkspaceState.Repository = repository;
SynchronizeRepositoryAndWorkspace();
}
void CreateRepository(RepositoryCreationData data)
{
if (!data.Result)
return;
((IProgressControls)mProgressControls).ShowProgress(
PlasticLocalization.GetString(
PlasticLocalization.Name.CreatingRepository,
data.RepName));
RepositoryInfo createdRepository = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter();
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
createdRepository = PlasticGui.Plastic.API.CreateRepository(
data.ServerName, data.RepName);
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls)mProgressControls).HideProgress();
if (waiter.Exception != null)
{
DisplayException(mProgressControls, waiter.Exception);
return;
}
if (createdRepository == null)
return;
mCreateWorkspaceState.Repository = createdRepository.GetRepSpec().ToDisplayString();
SynchronizeRepositoryAndWorkspace();
mParentWindow.Repaint();
});
}
void ValidateAndCreateWorkspace(CreateWorkspaceViewState state)
{
// We need a conversion here because the actual repSpec is used during the AsyncValidation
// to call UpdateLastUsedRepositoryPreference. Also, it is the one to be used during wk creation
RepositorySpec repSpec = OrganizationsInformation.TryResolveRepositorySpecFromInput(state.Repository);
if (repSpec == null)
{
((IProgressControls) mProgressControls).ShowError(
PlasticLocalization.Name.UnresolvedRepository.GetString(state.Repository));
return;
}
mWkCreationData = BuildCreationDataFromState(state, mWorkspacePath, repSpec);
// AsyncValidation calls IPlasticDialogCloser.CloseDialog() when the validation is ok
WorkspaceCreationValidation.AsyncValidation(mWkCreationData, this, mProgressControls);
}
void IPlasticDialogCloser.CloseDialog()
{
((IProgressControls) mProgressControls).ShowProgress(string.Empty);
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
RepositorySpec repSpec = new SpecGenerator().GenRepositorySpec(
false, mWkCreationData.Repository, CmConnection.Get().UnityOrgResolver);
bool repositoryExist = PlasticGui.Plastic.API.CheckRepositoryExists(
repSpec.Server, repSpec.Name);
if (!repositoryExist)
PlasticGui.Plastic.API.CreateRepository(repSpec.Server, repSpec.Name);
},
/*afterOperationDelegate*/ delegate
{
((IProgressControls)mProgressControls).HideProgress();
if (waiter.Exception != null)
{
DisplayException(mProgressControls, waiter.Exception);
return;
}
mWkCreationData.Result = true;
mWorkspaceOperations.CreateWorkspace(mWkCreationData);
// the operation calls IWorkspacesRefreshableView.RefreshAndSelect
// when the workspace is created
});
}
void IWorkspacesRefreshableView.RefreshAndSelect(WorkspaceInfo wkInfo)
{
GetWindowIfOpened.BranchExplorer()?.OnWorkspaceCreated(wkInfo);
PerformInitialCheckin.IfRepositoryIsEmpty(
wkInfo,
mWkCreationData.Repository,
mWkCreationData.IsGluonWorkspace,
PlasticGui.Plastic.API,
mProgressControls,
mCreateWorkspaceListener,
mParentWindow);
UnityCloudProjectLinkMonitor.CheckCloudProjectAlignmentAsync(wkInfo);
}
static WorkspaceCreationData BuildCreationDataFromState(
CreateWorkspaceViewState state,
string workspacePath,
RepositorySpec repSpec)
{
return new WorkspaceCreationData(
state.WorkspaceName,
workspacePath,
repSpec.ToString(),
state.WorkspaceMode == CreateWorkspaceViewState.WorkspaceModes.Gluon,
false);
}
static void DisplayException(
IProgressControls progressControls,
Exception ex)
{
ExceptionsHandler.LogException(
"CreateWorkspaceView", ex);
progressControls.ShowError(
ExceptionsHandler.GetCorrectExceptionMessage(ex));
}
WorkspaceCreationData mWkCreationData;
CreateWorkspaceViewState mCreateWorkspaceState;
CreateWorkspaceDialogUserAssistant mDialogUserAssistant;
string mDefaultServer;
readonly WorkspaceOperations mWorkspaceOperations;
readonly ProgressControlsForViews mProgressControls;
readonly string mWorkspacePath;
readonly ICreateWorkspaceListener mCreateWorkspaceListener;
readonly UVCSWindow mParentWindow;
readonly IPlasticAPI mPlasticApi;
readonly IPlasticWebRestApi mPlasticWebRestApi;
}
}