@using Ardalis.GuardClauses
@using SharpIDE.Application.Features.SolutionDiscovery
@using SharpIDE.Photino.Services
@using BlazorMonaco.Editor

@inject RefreshOpenFileService RefreshOpenFileService

<style>
    #my-editor-id {
        height: calc(100% - 24px);
	    width: calc(100% - 5px); /* the monaco editor is a pain regarding resizes */
    }
</style>
<MudStack Class="ma-0 pa-0" Spacing="0" Style="@(_internalSelectedFile is null ? "visibility: hidden; height: 100%" : "height: 100%")">
		<MudText>
			@_internalSelectedFile?.Name
			@if (_unsavedEdits)
			{
				<span>*</span>
			}
		</MudText>
	<StandaloneCodeEditor @ref="_codeEditorRef" Id="my-editor-id" ConstructionOptions="@EditorConstructionOptions" OnDidChangeModelContent="IfDirtyMarkDirty" OnDidBlurEditorText="@SaveFileToDisk" />
</MudStack>

@code {
	[Parameter, EditorRequired]
	public SharpIdeFile? SelectedFile { get; set; }
	private SharpIdeFile? _internalSelectedFile;

	private string? _fileContent;
	private bool _unsavedEdits = false;

	StandaloneCodeEditor _codeEditorRef = null!;

	protected override async Task OnParametersSetAsync()
	{
		if (_internalSelectedFile is not null)
		{
			await SaveFileToDisk();
		}
		if (SelectedFile is null) return;
		_internalSelectedFile = SelectedFile;
		var model = await _codeEditorRef.GetModel();
		ArgumentNullException.ThrowIfNull(model);
		await model.SetValue(string.Empty);
		await ReadFile();
		await model.SetValue(_fileContent);
		_unsavedEdits = false;
		StateHasChanged();
	}

	protected override async Task OnInitializedAsync()
	{
		RefreshOpenFileService.RefreshOpenFile += async () =>
		{
			Console.WriteLine("RefreshOpenFileService.RefreshOpenFile called");
			await ReadFile();
			var model = await _codeEditorRef.GetModel();
			ArgumentNullException.ThrowIfNull(model);
			await model.SetValue(_fileContent);
			StateHasChanged();
		};
	}

	private async Task ReadFile()
	{
		Guard.Against.Null(_internalSelectedFile);
		var fileInfo = new FileInfo(_internalSelectedFile.Path);
		if (!fileInfo.Exists)
		{
			throw new FileNotFoundException($"File not found: {_internalSelectedFile.Path}");
		}
		var fileContent = await File.ReadAllTextAsync(_internalSelectedFile.Path);
		_fileContent = fileContent;
	}

	private async Task SaveFileToDisk()
	{
		Guard.Against.Null(_internalSelectedFile);
		if (_unsavedEdits is false)
		{
			return;
		}

		ArgumentNullException.ThrowIfNull(_codeEditorRef, nameof(_codeEditorRef));
		var editorTextValue = await _codeEditorRef.GetValue();
		await File.WriteAllTextAsync(_internalSelectedFile.Path, editorTextValue);
		_fileContent = editorTextValue;
		_unsavedEdits = false;
	}

	private async Task IfDirtyMarkDirty()
	{
		// Probably quite non-performant
		if (await _codeEditorRef.GetValue() != _fileContent)
		{
			_unsavedEdits = true;
		}
		else
		{
			_unsavedEdits = false;
		}
	}

	private static StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
	{
		return new StandaloneEditorConstructionOptions
		{
			AutomaticLayout = true,
			Language = "csharp",
			Theme = "vs-dark",
			ScrollBeyondLastLine = false,
			FontSize = 18,
			Value = string.Empty
		};
	}
}
