// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package langserver

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"

	"github.com/sourcegraph/go-lsp"
	"github.com/sourcegraph/jsonrpc2"

	"fidl-lsp/analysis"
	"fidl-lsp/state"
)

// LspServer is a wrapper around a LangHandler.
type LspServer struct {
	jsonrpc2.Handler
}

// LangHandler implements jsonrpc2.Handler, an interface with one Handle method.
// It fields all LSP requests from the client, and sends back responses and
// notifications.
//
// LangHandler has a *state.FileSystem, which keeps track of the the language
// editor's open files (in the future, to support concurrency, this state can be
// wrapped in e.g. an RWLock).
//
// LangHandler also has an *analysis.Analyzer,
// which is used to compile and extract insights from files being edited.
type LangHandler struct {
	cfg      lsp.ServerCapabilities
	init     *lsp.InitializeParams
	shutdown bool

	log *log.Logger

	fs *state.FileSystem

	analyzer *analysis.Analyzer
}

// NewDefaultConfig returns a default configuration for the language server.
func NewDefaultConfig() lsp.ServerCapabilities {
	return lsp.ServerCapabilities{
		DocumentFormattingProvider: true,
		TextDocumentSync: &lsp.TextDocumentSyncOptionsOrKind{
			Options: &lsp.TextDocumentSyncOptions{
				OpenClose: true,
				Change:    lsp.TDSKIncremental,
			},
		},
	}
}

// NewLangHandler returns a LangHandler with the given configuration, logger,
// and set of CompiledLibraries.
func NewLangHandler(cfg lsp.ServerCapabilities, trace *log.Logger, fidlProject analysis.CompiledLibraries) *LangHandler {
	return &LangHandler{
		log:      trace,
		cfg:      cfg,
		fs:       state.NewFileSystem(),
		analyzer: analysis.NewAnalyzer(fidlProject),
	}
}

// Handle fields an LSP request or notification.
// If there is an internal server error, it will be logged and an empty response
// will be sent to the client. If there is an error in the request, an error
// reponse will be sent.
func (h *LangHandler) Handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) {
	if resp, handleErr := h.handle(ctx, conn, req); handleErr == nil {
		if resp != nil {
			if err := conn.Reply(ctx, req.ID, resp); err != nil {
				h.log.Printf("error on conn.Reply: %s\n", err)
			}
		}
	} else {
		switch handleErr.(type) {
		case *jsonrpc2.Error:
			h.log.Printf("got a request we couldn't handle: %s\n", req.Method)
			if err := conn.ReplyWithError(ctx, req.ID, handleErr.(*jsonrpc2.Error)); err != nil {
				h.log.Printf("error on conn.ReplyWithError: %s\n", err)
			}
		default:
			// If the error is not a jsonrpc2.Error, this means that we had an
			// internal server error and were unable to meet the request. Rather
			// than pass that error on to the client, we should log the error
			// and reply with an empty response so the client is not waiting for
			// a response.
			h.log.Printf("err on handling `%s`: %s\n", req.Method, handleErr)
			if err := conn.Reply(ctx, req.ID, resp); err != nil {
				h.log.Printf("error on conn.Reply: %s\n", err)
			}
		}
	}
}

// Notify sends an LSP notification.
func (h *LangHandler) Notify(ctx context.Context, conn *jsonrpc2.Conn, method string, notif interface{}) {
	if err := conn.Notify(ctx, method, notif); err != nil {
		h.log.Printf("error on conn.Reply: %s\n", err)
	}
}

// The general pattern of the `handle` callback is as follows:
//
// * receive a notification from the client indicating a change of state -->
//   pass the change to the FileSystem -->
//   trigger a re-analysis of the file that was changed -->
//   publish diagnostics on that file.
//
// * receive a request from the client -->
//   request the relevant analysis from the Analyzer, passing it a snapshot of
//   the state of the FileSystem -->
//   wrap the analysis in relevant LSP type/object and send to the client.
func (h *LangHandler) handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) (result interface{}, err error) {
	switch req.Method {
	case "initialize":
		// TODO: if server receives any request before `initialize`, it should
		// respond with error code: -32002
		if h.init != nil {
			return nil, &jsonrpc2.Error{
				Code:    jsonrpc2.CodeInvalidRequest,
				Message: "language server is already initialized",
			}
		}
		if req.Params == nil {
			return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams}
		}
		var params lsp.InitializeParams
		if err := json.Unmarshal(*req.Params, &params); err != nil {
			return nil, err
		}
		h.init = &params
		return lsp.InitializeResult{Capabilities: h.cfg}, nil

	case "initialized":
		// A notification that the client is ready to receive requests. Ignore
		return nil, nil

	case "shutdown":
		// TODO: if server receives any request after `shutdown`, it should
		// respond with an error: InvalidRequest.
		h.shutdown = true
		h.analyzer.Cleanup()
		return nil, nil

	case "exit":
		if h.shutdown {
			os.Exit(0)
		} else {
			os.Exit(1)
		}
		return nil, nil

	case "textDocument/didOpen":
		if req.Params == nil {
			return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams}
		}
		var params lsp.DidOpenTextDocumentParams
		if err := json.Unmarshal(*req.Params, &params); err != nil {
			return nil, err
		}

		h.handleOpenFile(params)
		if err := h.analyzer.Analyze(h.fs, state.EditorFile(params.TextDocument.URI)); err != nil {
			h.log.Println(err)
		}
		h.publishDiagnostics(ctx, conn, params.TextDocument.URI)
		return nil, nil

	case "textDocument/didClose":
		if req.Params == nil {
			return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams}
		}
		var params lsp.DidCloseTextDocumentParams
		if err := json.Unmarshal(*req.Params, &params); err != nil {
			return nil, err
		}

		h.handleCloseFile(params)
		// TODO: remove diagnostics associated with this file?
		return nil, nil

	case "textDocument/didChange":
		if req.Params == nil {
			return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams}
		}
		var params lsp.DidChangeTextDocumentParams
		if err := json.Unmarshal(*req.Params, &params); err != nil {
			return nil, err
		}

		h.handleDidChange(params)
		if err := h.analyzer.Analyze(h.fs, state.EditorFile(params.TextDocument.URI)); err != nil {
			h.log.Println(err)
		}
		h.publishDiagnostics(ctx, conn, params.TextDocument.URI)
		return nil, nil

	case "textDocument/formatting":
		if req.Params == nil {
			return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams}
		}
		var params lsp.DocumentFormattingParams
		if err := json.Unmarshal(*req.Params, &params); err != nil {
			return nil, err
		}

		return h.handleFormat(params)

	default:
		return nil, &jsonrpc2.Error{
			Code:    jsonrpc2.CodeMethodNotFound,
			Message: fmt.Sprintf("method not supported: %s", req.Method),
		}
	}
}
