using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using JsonRpc.Standard.Contracts;
using LanguageServer.VsCode.Contracts;
using Upsilon.BoundTypes;

namespace UpsilonLanguageServer.Services
{
    [JsonRpcScope(MethodPrefix = "workspace/")]
    public class WorkspaceService : UpsilonLanguageServiceBase
    {
        [JsonRpcMethod(IsNotification = true)]
        public async Task DidChangeConfiguration(SettingsRoot settings)
        {
            Session.Settings = settings.UpsilonLanguageServer;
            foreach (var doc in Session.Documents.Values)
            {
                var diag = await DiagnosticProvider.LintDocument(doc.Document, doc, Session.Settings.MaxNumberOfProblems);
                await Client.Document.PublishDiagnostics(doc.Document.Uri, diag);
            }
        }

        [JsonRpcMethod(IsNotification = true)]
        public async Task DidChangeWatchedFiles(ICollection<FileEvent> changes)
        {
            foreach (var change in changes)
            {
                if (!change.Uri.IsFile) continue;
                var localPath = change.Uri.AbsolutePath;
                if (string.Equals(Path.GetExtension(localPath), ".yup", StringComparison.InvariantCultureIgnoreCase))
                {
                    // If the file has been removed, we will clear the lint result about it.
                    // Note that pass null to PublishDiagnostics may mess up the client.
                    if (change.Type == FileChangeType.Deleted)
                    {
                        await Client.Document.PublishDiagnostics(change.Uri, new Diagnostic[0]);
                    }
                }
                else if (string.Equals(Path.GetExtension(localPath), ".lua", StringComparison.InvariantCultureIgnoreCase))
                {
                    // If the file has been removed, we will clear the lint result about it.
                    // Note that pass null to PublishDiagnostics may mess up the client.
                    if (change.Type == FileChangeType.Deleted)
                    {
                        await Client.Document.PublishDiagnostics(change.Uri, new Diagnostic[0]);
                    }
                }
                else if (string.Equals(Path.GetExtension(localPath), ".json",
                    StringComparison.InvariantCultureIgnoreCase))
                {
                    var name = Path.GetFileName(localPath);
                    if (string.Equals(name, "types.json",
                        StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (change.Type == FileChangeType.Created || change.Type == FileChangeType.Changed)
                        {
                            BoundTypeParser.LoadBoundTypes(File.ReadAllText(localPath));
                            foreach (var doc in Session.Documents.Values)
                            {
                                var diag = await DiagnosticProvider.LintDocument(doc.Document, doc, Session.Settings.MaxNumberOfProblems);
                                await Client.Document.PublishDiagnostics(doc.Document.Uri, diag);
                            }
                        }
                    }
                    else if (string.Equals(name, "static.json",
                        StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (change.Type == FileChangeType.Created || change.Type == FileChangeType.Changed)
                        {
                            BoundTypeParser.LoadStaticVariables(File.ReadAllText(localPath));
                            foreach (var doc in Session.Documents.Values)
                            {
                                var diag = await DiagnosticProvider.LintDocument(doc.Document, doc, Session.Settings.MaxNumberOfProblems);
                                await Client.Document.PublishDiagnostics(doc.Document.Uri, diag);
                            }
                        }
                    }
                }
            }
        }
    }
}
