//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.PowerShell.EditorServices;
using Microsoft.PowerShell.EditorServices.Extensions;
using Microsoft.PowerShell.EditorServices.Protocol.LanguageServer;
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
using System.Threading.Tasks;

namespace Microsoft.PowerShell.EditorServices.Protocol.Server
{
    internal class LanguageServerEditorOperations : IEditorOperations
    {
        private const bool DefaultPreviewSetting = true;

        private EditorSession editorSession;
        private IMessageSender messageSender;

        public LanguageServerEditorOperations(
            EditorSession editorSession,
            IMessageSender messageSender)
        {
            this.editorSession = editorSession;
            this.messageSender = messageSender;
        }

        public async Task<EditorContext> GetEditorContextAsync()
        {
            ClientEditorContext clientContext =
                await this.messageSender.SendRequestAsync(
                    GetEditorContextRequest.Type,
                    new GetEditorContextRequest(),
                    true);

            return this.ConvertClientEditorContext(clientContext);
        }

        public async Task InsertTextAsync(string filePath, string text, BufferRange insertRange)
        {
            await this.messageSender.SendRequestAsync(
                InsertTextRequest.Type,
                new InsertTextRequest
                {
                    FilePath = filePath,
                    InsertText = text,
                    InsertRange =
                        new Range
                        {
                            Start = new Position
                            {
                                Line = insertRange.Start.Line - 1,
                                Character = insertRange.Start.Column - 1
                            },
                            End = new Position
                            {
                                Line = insertRange.End.Line - 1,
                                Character = insertRange.End.Column - 1
                            }
                        }
                }, false);

            // TODO: Set the last param back to true!
        }

        public Task SetSelectionAsync(BufferRange selectionRange)
        {
            return this.messageSender.SendRequestAsync(
                SetSelectionRequest.Type,
                new SetSelectionRequest
                {
                    SelectionRange =
                        new Range
                        {
                            Start = new Position
                            {
                                Line = selectionRange.Start.Line - 1,
                                Character = selectionRange.Start.Column - 1
                            },
                            End = new Position
                            {
                                Line = selectionRange.End.Line - 1,
                                Character = selectionRange.End.Column - 1
                            }
                        }
                }, true);
        }

        public EditorContext ConvertClientEditorContext(
            ClientEditorContext clientContext)
        {
            ScriptFile scriptFile = this.editorSession.Workspace.CreateScriptFileFromFileBuffer(
                clientContext.CurrentFilePath,
                clientContext.CurrentFileContent);

            return
                new EditorContext(
                    this,
                    scriptFile,
                    new BufferPosition(
                        clientContext.CursorPosition.Line + 1,
                        clientContext.CursorPosition.Character + 1),
                    new BufferRange(
                        clientContext.SelectionRange.Start.Line + 1,
                        clientContext.SelectionRange.Start.Character + 1,
                        clientContext.SelectionRange.End.Line + 1,
                        clientContext.SelectionRange.End.Character + 1),
                    clientContext.CurrentFileLanguage);
        }

        public Task NewFileAsync()
        {
            return
                this.messageSender.SendRequestAsync(
                    NewFileRequest.Type,
                    null,
                    true);
        }

        public Task OpenFileAsync(string filePath)
        {
            return
                this.messageSender.SendRequestAsync(
                    OpenFileRequest.Type,
                    new OpenFileDetails
                    {
                        FilePath = filePath,
                        Preview = DefaultPreviewSetting
                    },
                    true);
        }

        public Task OpenFileAsync(string filePath, bool preview)
        {
            return
                this.messageSender.SendRequestAsync(
                    OpenFileRequest.Type,
                    new OpenFileDetails
                    {
                        FilePath = filePath,
                        Preview = preview
                    },
                    true);
        }

        public Task CloseFileAsync(string filePath)
        {
            return
                this.messageSender.SendRequestAsync(
                    CloseFileRequest.Type,
                    filePath,
                    true);
        }

        public Task SaveFileAsync(string filePath)
        {
            return SaveFileAsync(filePath, null);
        }

        public Task SaveFileAsync(string currentPath, string newSavePath)
        {
            return
                this.messageSender.SendRequestAsync(
                    SaveFileRequest.Type,
                    new SaveFileDetails
                    {
                        FilePath = currentPath,
                        NewPath = newSavePath
                    },
                    true);
        }

        public string GetWorkspacePath()
        {
            return this.editorSession.Workspace.WorkspacePath;
        }

        public string GetWorkspaceRelativePath(string filePath)
        {
            return this.editorSession.Workspace.GetRelativePath(filePath);
        }

        public Task ShowInformationMessageAsync(string message)
        {
            return
                this.messageSender.SendRequestAsync(
                    ShowInformationMessageRequest.Type,
                    message,
                    true);
        }

        public Task ShowErrorMessageAsync(string message)
        {
            return
                this.messageSender.SendRequestAsync(
                    ShowErrorMessageRequest.Type,
                    message,
                    true);
        }

        public Task ShowWarningMessageAsync(string message)
        {
            return
                this.messageSender.SendRequestAsync(
                    ShowWarningMessageRequest.Type,
                    message,
                    true);
        }

        public Task SetStatusBarMessageAsync(string message, int? timeout)
        {
            return
                this.messageSender.SendRequestAsync(
                    SetStatusBarMessageRequest.Type,
                    new StatusBarMessageDetails
                    {
                        Message = message,
                        Timeout = timeout
                    },
                    true);
        }
    }
}