// Copyright 2019 The Go 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 lsp

import (
	"bytes"
	"context"
	"fmt"

	"golang.org/x/tools/internal/jsonrpc2"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/lsp/telemetry"
	"golang.org/x/tools/internal/span"
	errors "golang.org/x/xerrors"
)

func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
	uri := span.NewURI(params.TextDocument.URI)
	text := []byte(params.TextDocument.Text)
	version := params.TextDocument.Version

	// Confirm that the file's language ID is related to Go.
	fileKind := source.DetectLanguage(params.TextDocument.LanguageID, uri.Filename())

	// Open the file.
	s.session.DidOpen(ctx, uri, fileKind, version, text)

	view, err := s.session.ViewOf(uri)
	if err != nil {
		return err
	}
	// Run diagnostics on the newly-changed file.
	go s.diagnostics(view.BackgroundContext(), view.Snapshot(), uri)

	return nil
}

func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {
	options := s.session.Options()
	if len(params.ContentChanges) < 1 {
		return jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "no content changes provided")
	}

	uri := span.NewURI(params.TextDocument.URI)

	// Check if the client sent the full content of the file.
	// We accept a full content change even if the server expected incremental changes.
	text, isFullChange := fullChange(params.ContentChanges)

	// We only accept an incremental change if the server expected it.
	if !isFullChange {
		switch options.TextDocumentSyncKind {
		case protocol.Full:
			return errors.Errorf("expected a full content change, received incremental changes for %s", uri)
		case protocol.Incremental:
			// Determine the new file content.
			var err error
			text, err = s.applyChanges(ctx, uri, params.ContentChanges)
			if err != nil {
				return err
			}
		}
	}
	// Cache the new file content and send fresh diagnostics.
	view, err := s.session.ViewOf(uri)
	if err != nil {
		return err
	}
	view.SetContent(ctx, uri, params.TextDocument.Version, []byte(text))
	// Ideally, we should be able to specify that a generated file should be opened as read-only.
	// Tell the user that they should not be editing a generated file.
	if s.wasFirstChange(uri) && source.IsGenerated(ctx, view, uri) {
		s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
			Message: fmt.Sprintf("Do not edit this file! %s is a generated file.", uri.Filename()),
			Type:    protocol.Warning,
		})
	}

	// Run diagnostics on the newly-changed file.
	go s.diagnostics(view.BackgroundContext(), view.Snapshot(), uri)

	return nil
}

func (s *Server) wasFirstChange(uri span.URI) bool {
	if s.changedFiles == nil {
		s.changedFiles = make(map[span.URI]struct{})
	}
	_, ok := s.changedFiles[uri]
	return ok
}

func fullChange(changes []protocol.TextDocumentContentChangeEvent) (string, bool) {
	if len(changes) > 1 {
		return "", false
	}
	// The length of the changes must be 1 at this point.
	// TODO: This breaks if you insert a character at the beginning of the file.
	if changes[0].Range == nil && changes[0].RangeLength == 0 {
		return changes[0].Text, true
	}

	return "", false
}

func (s *Server) applyChanges(ctx context.Context, uri span.URI, changes []protocol.TextDocumentContentChangeEvent) (string, error) {
	content, _, err := s.session.GetFile(uri, source.UnknownKind).Read(ctx)
	if err != nil {
		return "", jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "file not found (%v)", err)
	}
	for _, change := range changes {
		// Update column mapper along with the content.
		converter := span.NewContentConverter(uri.Filename(), content)
		m := &protocol.ColumnMapper{
			URI:       uri,
			Converter: converter,
			Content:   content,
		}

		spn, err := m.RangeSpan(*change.Range) // Could Range be nil here?
		if err != nil {
			return "", err
		}
		if !spn.HasOffset() {
			return "", jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "invalid range for content change")
		}
		start, end := spn.Start().Offset(), spn.End().Offset()
		if end < start {
			return "", jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "invalid range for content change")
		}
		var buf bytes.Buffer
		buf.Write(content[:start])
		buf.WriteString(change.Text)
		buf.Write(content[end:])
		content = buf.Bytes()
	}
	return string(content), nil
}

func (s *Server) didSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {
	s.session.DidSave(span.NewURI(params.TextDocument.URI), params.TextDocument.Version)
	return nil
}

func (s *Server) didClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
	uri := span.NewURI(params.TextDocument.URI)
	ctx = telemetry.URI.With(ctx, uri)
	s.session.DidClose(uri)
	view, err := s.session.ViewOf(uri)
	if err != nil {
		return err
	}
	view.SetContent(ctx, uri, -1, nil)
	return nil
}
