// 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 {
	// Confirm that the file's language ID is related to Go.
	uri := span.NewURI(params.TextDocument.URI)
	snapshots, err := s.session.DidModifyFile(ctx, source.FileModification{
		URI:        uri,
		Action:     source.Open,
		Version:    params.TextDocument.Version,
		Text:       []byte(params.TextDocument.Text),
		LanguageID: params.TextDocument.LanguageID,
	})
	if err != nil {
		return err
	}
	snapshot, _, err := snapshotOf(s.session, uri, snapshots)
	if err != nil {
		return err
	}
	fh, err := snapshot.GetFile(uri)
	if err != nil {
		return err
	}
	// Only run diagnostics on file open for Go files.
	switch fh.Identity().Kind {
	case source.Go:
		go s.diagnoseFile(snapshot, fh)
	}
	return nil
}

func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error {
	uri := span.NewURI(params.TextDocument.URI)
	text, err := s.changedText(ctx, uri, params.ContentChanges)
	if err != nil {
		return err
	}
	snapshots, err := s.session.DidModifyFile(ctx, source.FileModification{
		URI:     uri,
		Action:  source.Change,
		Version: params.TextDocument.Version,
		Text:    text,
	})
	if err != nil {
		return err
	}
	snapshot, view, err := snapshotOf(s.session, uri, snapshots)
	if err != nil {
		return err
	}
	// 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,
		})
	}
	fh, err := snapshot.GetFile(uri)
	if err != nil {
		return err
	}
	// Run diagnostics for Go files and for mod files.
	switch fh.Identity().Kind {
	case source.Go:
		go s.diagnoseFile(snapshot, fh)
	case source.Mod:
		// TODO(rstambler): Modifying the go.mod file should trigger workspace-level diagnostics.
		go s.diagnoseModfile(snapshot)
	}
	return nil
}

func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.DidChangeWatchedFilesParams) error {
	// Keep track of each change's view and final snapshot.
	views := make(map[source.View]source.Snapshot)
	for _, change := range params.Changes {
		uri := span.NewURI(change.URI)
		ctx := telemetry.File.With(ctx, uri)

		// Do nothing if the file is open in the editor.
		// The editor is the source of truth.
		if s.session.IsOpen(uri) {
			continue
		}
		snapshots, err := s.session.DidModifyFile(ctx, source.FileModification{
			URI:    uri,
			Action: changeTypeToFileAction(change.Type),
			OnDisk: true,
		})
		if err != nil {
			return err
		}
		snapshot, _, err := snapshotOf(s.session, uri, snapshots)
		if err != nil {
			return err
		}
		views[snapshot.View()] = snapshot
	}
	// Diagnose all resulting snapshots.
	for view, snapshot := range views {
		go s.diagnoseSnapshot(view.BackgroundContext(), snapshot)
	}
	return nil
}

func (s *Server) didSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error {
	c := source.FileModification{
		URI:     span.NewURI(params.TextDocument.URI),
		Action:  source.Save,
		Version: params.TextDocument.Version,
	}
	if params.Text != nil {
		c.Text = []byte(*params.Text)
	}
	snapshots, err := s.session.DidModifyFile(ctx, c)
	if err != nil {
		return err
	}
	snapshot, _, err := snapshotOf(s.session, c.URI, snapshots)
	if err != nil {
		return err
	}
	go s.diagnoseModfile(snapshot)
	return err
}

func (s *Server) didClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
	_, err := s.session.DidModifyFile(ctx, source.FileModification{
		URI:     span.NewURI(params.TextDocument.URI),
		Action:  source.Close,
		Version: -1,
		Text:    nil,
	})
	return err
}

// snapshotOf returns the snapshot corresponding to the view for the given file URI.
func snapshotOf(session source.Session, uri span.URI, snapshots []source.Snapshot) (source.Snapshot, source.View, error) {
	view, err := session.ViewOf(uri)
	if err != nil {
		return nil, nil, err
	}
	for _, s := range snapshots {
		if s.View() == view {
			return s, view, nil
		}
	}
	return nil, nil, errors.Errorf("bestSnapshot: no snapshot for %s", uri)
}

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 (s *Server) changedText(ctx context.Context, uri span.URI, changes []protocol.TextDocumentContentChangeEvent) ([]byte, error) {
	if len(changes) == 0 {
		return nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "no content changes provided")
	}

	// Check if the client sent the full content of the file.
	// We accept a full content change even if the server expected incremental changes.
	if len(changes) == 1 && changes[0].Range == nil && changes[0].RangeLength == 0 {
		return []byte(changes[0].Text), nil
	}

	return s.applyIncrementalChanges(ctx, uri, changes)
}

func (s *Server) applyIncrementalChanges(ctx context.Context, uri span.URI, changes []protocol.TextDocumentContentChangeEvent) ([]byte, error) {
	content, _, err := s.session.GetFile(uri).Read(ctx)
	if err != nil {
		return nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "file not found (%v)", err)
	}
	for _, change := range changes {
		// Make sure to update column mapper along with the content.
		converter := span.NewContentConverter(uri.Filename(), content)
		m := &protocol.ColumnMapper{
			URI:       uri,
			Converter: converter,
			Content:   content,
		}
		if change.Range == nil {
			return nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "unexpected nil range for change")
		}
		spn, err := m.RangeSpan(*change.Range)
		if err != nil {
			return nil, err
		}
		if !spn.HasOffset() {
			return nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInternalError, "invalid range for content change")
		}
		start, end := spn.Start().Offset(), spn.End().Offset()
		if end < start {
			return nil, 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 content, nil
}

func changeTypeToFileAction(ct protocol.FileChangeType) source.FileAction {
	switch ct {
	case protocol.Changed:
		return source.Change
	case protocol.Created:
		return source.Create
	case protocol.Deleted:
		return source.Delete
	}
	return source.UnknownFileAction
}
