// 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 cache

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/mod/modfile"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/gocommand"
	"golang.org/x/tools/internal/lsp/debug/tag"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/memoize"
	"golang.org/x/tools/internal/packagesinternal"
	"golang.org/x/tools/internal/span"
	errors "golang.org/x/xerrors"
)

const (
	ModTidyError = "go mod tidy"
	SyntaxError  = "syntax"
)

type modKey struct {
	sessionID string
	cfg       string
	gomod     string
	view      string
}

type modTidyKey struct {
	sessionID       string
	cfg             string
	gomod           string
	imports         string
	unsavedOverlays string
	view            string
}

type modHandle struct {
	handle *memoize.Handle
	file   source.FileHandle
	cfg    *packages.Config
}

type modData struct {
	memoize.NoCopy

	// origfh is the file handle for the original go.mod file.
	origfh source.FileHandle

	// origParsedFile contains the parsed contents that are used to diff with
	// the ideal contents.
	origParsedFile *modfile.File

	// origMapper is the column mapper for the original go.mod file.
	origMapper *protocol.ColumnMapper

	// idealParsedFile contains the parsed contents for the go.mod file
	// after it has been "tidied".
	idealParsedFile *modfile.File

	// unusedDeps is the map containing the dependencies that are left after
	// removing the ones that are identical in the original and ideal go.mods.
	unusedDeps map[string]*modfile.Require

	// missingDeps is the map containing the dependencies that are left after
	// removing the ones that are identical in the original and ideal go.mods.
	missingDeps map[string]*modfile.Require

	// upgrades is a map of path->version that contains any upgrades for the go.mod.
	upgrades map[string]string

	// why is a map of path->explanation that contains all the "go mod why" contents
	// for each require statement.
	why map[string]string

	// parseErrors are the errors that arise when we diff between a user's go.mod
	// and the "tidied" go.mod.
	parseErrors []source.Error

	// err is any error that occurs while we are calculating the parseErrors.
	err error
}

func (mh *modHandle) String() string {
	return mh.File().URI().Filename()
}

func (mh *modHandle) File() source.FileHandle {
	return mh.file
}

func (mh *modHandle) Parse(ctx context.Context) (*modfile.File, *protocol.ColumnMapper, error) {
	v := mh.handle.Get(ctx)
	if v == nil {
		return nil, nil, errors.Errorf("no parsed file for %s", mh.File().URI())
	}
	data := v.(*modData)
	return data.origParsedFile, data.origMapper, data.err
}

func (mh *modHandle) Upgrades(ctx context.Context) (*modfile.File, *protocol.ColumnMapper, map[string]string, error) {
	v := mh.handle.Get(ctx)
	if v == nil {
		return nil, nil, nil, errors.Errorf("no parsed file for %s", mh.File().URI())
	}
	data := v.(*modData)
	return data.origParsedFile, data.origMapper, data.upgrades, data.err
}

func (mh *modHandle) Why(ctx context.Context) (*modfile.File, *protocol.ColumnMapper, map[string]string, error) {
	v := mh.handle.Get(ctx)
	if v == nil {
		return nil, nil, nil, errors.Errorf("no parsed file for %s", mh.File().URI())
	}
	data := v.(*modData)
	return data.origParsedFile, data.origMapper, data.why, data.err
}

func (s *snapshot) ModHandle(ctx context.Context, fh source.FileHandle) (source.ModHandle, error) {
	if err := s.awaitLoaded(ctx); err != nil {
		return nil, err
	}
	uri := fh.URI()
	if handle := s.getModHandle(uri); handle != nil {
		return handle, nil
	}
	realURI, tempURI := s.view.ModFiles()
	folder := s.View().Folder().Filename()
	cfg := s.Config(ctx)
	key := modKey{
		sessionID: s.view.session.id,
		cfg:       hashConfig(cfg),
		gomod:     fh.Identity().String(),
		view:      folder,
	}
	h := s.view.session.cache.store.Bind(key, func(ctx context.Context) interface{} {
		ctx, done := event.Start(ctx, "cache.ModHandle", tag.URI.Of(uri))
		defer done()

		contents, err := fh.Read()
		if err != nil {
			return &modData{
				err: err,
			}
		}
		parsedFile, err := modfile.Parse(uri.Filename(), contents, nil)
		if err != nil {
			return &modData{
				err: err,
			}
		}
		data := &modData{
			origfh:         fh,
			origParsedFile: parsedFile,
			origMapper: &protocol.ColumnMapper{
				URI:       uri,
				Converter: span.NewContentConverter(uri.Filename(), contents),
				Content:   contents,
			},
		}
		// If the go.mod file is not the view's go.mod file, then we just want to parse.
		if uri != realURI {
			return data
		}

		// If we have a tempModfile, copy the real go.mod file content into the temp go.mod file.
		if tempURI != "" {
			if err := ioutil.WriteFile(tempURI.Filename(), contents, os.ModePerm); err != nil {
				return &modData{
					err: err,
				}
			}
		}
		// Only get dependency upgrades if the go.mod file is the same as the view's.
		if err := dependencyUpgrades(ctx, cfg, folder, data); err != nil {
			return &modData{
				err: err,
			}
		}
		// Only run "go mod why" if the go.mod file is the same as the view's.
		if err := goModWhy(ctx, cfg, folder, data); err != nil {
			return &modData{
				err: err,
			}
		}
		return data
	})
	s.mu.Lock()
	defer s.mu.Unlock()
	s.modHandles[uri] = &modHandle{
		handle: h,
		file:   fh,
		cfg:    cfg,
	}
	return s.modHandles[uri], nil
}

func goModWhy(ctx context.Context, cfg *packages.Config, folder string, data *modData) error {
	if len(data.origParsedFile.Require) == 0 {
		return nil
	}
	// Run "go mod why" on all the dependencies to get information about the usages.
	inv := gocommand.Invocation{
		Verb:       "mod",
		Args:       []string{"why", "-m"},
		BuildFlags: cfg.BuildFlags,
		Env:        cfg.Env,
		WorkingDir: folder,
	}
	for _, req := range data.origParsedFile.Require {
		inv.Args = append(inv.Args, req.Mod.Path)
	}
	stdout, err := packagesinternal.GetGoCmdRunner(cfg).Run(ctx, inv)
	if err != nil {
		return err
	}
	whyList := strings.Split(stdout.String(), "\n\n")
	if len(whyList) <= 1 || len(whyList) != len(data.origParsedFile.Require) {
		return nil
	}
	data.why = make(map[string]string, len(data.origParsedFile.Require))
	for i, req := range data.origParsedFile.Require {
		data.why[req.Mod.Path] = whyList[i]
	}
	return nil
}

func dependencyUpgrades(ctx context.Context, cfg *packages.Config, folder string, data *modData) error {
	if len(data.origParsedFile.Require) == 0 {
		return nil
	}
	// Run "go list -mod readonly -u -m all" to be able to see which deps can be
	// upgraded without modifying mod file.
	inv := gocommand.Invocation{
		Verb:       "list",
		Args:       []string{"-mod", "readonly", "-u", "-m", "all"},
		BuildFlags: cfg.BuildFlags,
		Env:        cfg.Env,
		WorkingDir: folder,
	}
	stdout, err := packagesinternal.GetGoCmdRunner(cfg).Run(ctx, inv)
	if err != nil {
		return err
	}
	upgradesList := strings.Split(stdout.String(), "\n")
	if len(upgradesList) <= 1 {
		return nil
	}
	data.upgrades = make(map[string]string)
	for _, upgrade := range upgradesList[1:] {
		// Example: "github.com/x/tools v1.1.0 [v1.2.0]"
		info := strings.Split(upgrade, " ")
		if len(info) < 3 {
			continue
		}
		dep, version := info[0], info[2]
		latest := version[1:]                    // remove the "["
		latest = strings.TrimSuffix(latest, "]") // remove the "]"
		data.upgrades[dep] = latest
	}
	return nil
}

func (mh *modHandle) Tidy(ctx context.Context) (*modfile.File, *protocol.ColumnMapper, map[string]*modfile.Require, []source.Error, error) {
	v := mh.handle.Get(ctx)
	if v == nil {
		return nil, nil, nil, nil, errors.Errorf("no parsed file for %s", mh.File().URI())
	}
	data := v.(*modData)
	return data.origParsedFile, data.origMapper, data.missingDeps, data.parseErrors, data.err
}

func (s *snapshot) ModTidyHandle(ctx context.Context, realfh source.FileHandle) (source.ModTidyHandle, error) {
	if handle := s.getModTidyHandle(); handle != nil {
		return handle, nil
	}

	realURI, tempURI := s.view.ModFiles()
	cfg := s.Config(ctx)
	options := s.View().Options()
	folder := s.View().Folder().Filename()
	gocmdRunner := s.view.gocmdRunner

	wsPackages, err := s.WorkspacePackages(ctx)
	if ctx.Err() != nil {
		return nil, ctx.Err()
	}
	if err != nil {
		return nil, err
	}
	imports, err := hashImports(ctx, wsPackages)
	if err != nil {
		return nil, err
	}
	s.mu.Lock()
	overlayHash := hashUnsavedOverlays(s.files)
	s.mu.Unlock()
	key := modTidyKey{
		sessionID:       s.view.session.id,
		view:            folder,
		imports:         imports,
		unsavedOverlays: overlayHash,
		gomod:           realfh.Identity().Identifier,
		cfg:             hashConfig(cfg),
	}
	h := s.view.session.cache.store.Bind(key, func(ctx context.Context) interface{} {
		// Check the case when the tempModfile flag is turned off.
		if realURI == "" || tempURI == "" {
			return &modData{}
		}

		ctx, done := event.Start(ctx, "cache.ModTidyHandle", tag.URI.Of(realURI))
		defer done()

		realContents, err := realfh.Read()
		if err != nil {
			return &modData{
				err: err,
			}
		}
		realMapper := &protocol.ColumnMapper{
			URI:       realURI,
			Converter: span.NewContentConverter(realURI.Filename(), realContents),
			Content:   realContents,
		}
		origParsedFile, err := modfile.Parse(realURI.Filename(), realContents, nil)
		if err != nil {
			if parseErr, err := extractModParseErrors(ctx, realURI, realMapper, err, realContents); err == nil {
				return &modData{
					parseErrors: []source.Error{parseErr},
				}
			}
			return &modData{
				err: err,
			}
		}

		// Copy the real go.mod file content into the temp go.mod file.
		if err := ioutil.WriteFile(tempURI.Filename(), realContents, os.ModePerm); err != nil {
			return &modData{
				err: err,
			}
		}

		// We want to run "go mod tidy" to be able to diff between the real and the temp files.
		inv := gocommand.Invocation{
			Verb:       "mod",
			Args:       []string{"tidy"},
			BuildFlags: cfg.BuildFlags,
			Env:        cfg.Env,
			WorkingDir: folder,
		}
		if _, err := gocmdRunner.Run(ctx, inv); err != nil {
			return &modData{
				err: err,
			}
		}

		// Go directly to disk to get the temporary mod file, since it is always on disk.
		tempContents, err := ioutil.ReadFile(tempURI.Filename())
		if err != nil {
			return &modData{
				err: err,
			}
		}
		idealParsedFile, err := modfile.Parse(tempURI.Filename(), tempContents, nil)
		if err != nil {
			// We do not need to worry about the temporary file's parse errors since it has been "tidied".
			return &modData{
				err: err,
			}
		}

		data := &modData{
			origfh:          realfh,
			origParsedFile:  origParsedFile,
			origMapper:      realMapper,
			idealParsedFile: idealParsedFile,
			unusedDeps:      make(map[string]*modfile.Require, len(origParsedFile.Require)),
			missingDeps:     make(map[string]*modfile.Require, len(idealParsedFile.Require)),
		}
		// Get the dependencies that are different between the original and ideal mod files.
		for _, req := range origParsedFile.Require {
			data.unusedDeps[req.Mod.Path] = req
		}
		for _, req := range idealParsedFile.Require {
			origDep := data.unusedDeps[req.Mod.Path]
			if origDep != nil && origDep.Indirect == req.Indirect {
				delete(data.unusedDeps, req.Mod.Path)
			} else {
				data.missingDeps[req.Mod.Path] = req
			}
		}
		data.parseErrors, data.err = modRequireErrors(options, data)

		for _, req := range data.missingDeps {
			if data.unusedDeps[req.Mod.Path] != nil {
				delete(data.missingDeps, req.Mod.Path)
			}
		}
		return data
	})
	s.mu.Lock()
	defer s.mu.Unlock()
	s.modTidyHandle = &modHandle{
		handle: h,
		file:   realfh,
		cfg:    cfg,
	}
	return s.modTidyHandle, nil
}

// extractModParseErrors processes the raw errors returned by modfile.Parse,
// extracting the filenames and line numbers that correspond to the errors.
func extractModParseErrors(ctx context.Context, uri span.URI, m *protocol.ColumnMapper, parseErr error, content []byte) (source.Error, error) {
	re := regexp.MustCompile(`.*:([\d]+): (.+)`)
	matches := re.FindStringSubmatch(strings.TrimSpace(parseErr.Error()))
	if len(matches) < 3 {
		event.Error(ctx, "could not parse golang/x/mod error message", parseErr)
		return source.Error{}, parseErr
	}
	line, err := strconv.Atoi(matches[1])
	if err != nil {
		return source.Error{}, parseErr
	}
	lines := strings.Split(string(content), "\n")
	if len(lines) <= line {
		return source.Error{}, errors.Errorf("could not parse goland/x/mod error message, line number out of range")
	}
	// The error returned from the modfile package only returns a line number,
	// so we assume that the diagnostic should be for the entire line.
	endOfLine := len(lines[line-1])
	sOffset, err := m.Converter.ToOffset(line, 0)
	if err != nil {
		return source.Error{}, err
	}
	eOffset, err := m.Converter.ToOffset(line, endOfLine)
	if err != nil {
		return source.Error{}, err
	}
	spn := span.New(uri, span.NewPoint(line, 0, sOffset), span.NewPoint(line, endOfLine, eOffset))
	rng, err := m.Range(spn)
	if err != nil {
		return source.Error{}, err
	}
	return source.Error{
		Category: SyntaxError,
		Message:  matches[2],
		Range:    rng,
		URI:      uri,
	}, nil
}

// modRequireErrors extracts the errors that occur on the require directives.
// It checks for directness issues and unused dependencies.
func modRequireErrors(options source.Options, data *modData) ([]source.Error, error) {
	var errors []source.Error
	for dep, req := range data.unusedDeps {
		if req.Syntax == nil {
			continue
		}
		// Handle dependencies that are incorrectly labeled indirect and vice versa.
		if data.missingDeps[dep] != nil && req.Indirect != data.missingDeps[dep].Indirect {
			directErr, err := modDirectnessErrors(options, data, req)
			if err != nil {
				return nil, err
			}
			errors = append(errors, directErr)
		}
		// Handle unused dependencies.
		if data.missingDeps[dep] == nil {
			rng, err := rangeFromPositions(data.origfh.URI(), data.origMapper, req.Syntax.Start, req.Syntax.End)
			if err != nil {
				return nil, err
			}
			edits, err := dropDependencyEdits(options, data, req)
			if err != nil {
				return nil, err
			}
			errors = append(errors, source.Error{
				Category: ModTidyError,
				Message:  fmt.Sprintf("%s is not used in this module.", dep),
				Range:    rng,
				URI:      data.origfh.URI(),
				SuggestedFixes: []source.SuggestedFix{{
					Title: fmt.Sprintf("Remove dependency: %s", dep),
					Edits: map[span.URI][]protocol.TextEdit{data.origfh.URI(): edits},
				}},
			})
		}
	}
	return errors, nil
}

// modDirectnessErrors extracts errors when a dependency is labeled indirect when it should be direct and vice versa.
func modDirectnessErrors(options source.Options, data *modData, req *modfile.Require) (source.Error, error) {
	rng, err := rangeFromPositions(data.origfh.URI(), data.origMapper, req.Syntax.Start, req.Syntax.End)
	if err != nil {
		return source.Error{}, err
	}
	if req.Indirect {
		// If the dependency should be direct, just highlight the // indirect.
		if comments := req.Syntax.Comment(); comments != nil && len(comments.Suffix) > 0 {
			end := comments.Suffix[0].Start
			end.LineRune += len(comments.Suffix[0].Token)
			end.Byte += len([]byte(comments.Suffix[0].Token))
			rng, err = rangeFromPositions(data.origfh.URI(), data.origMapper, comments.Suffix[0].Start, end)
			if err != nil {
				return source.Error{}, err
			}
		}
		edits, err := changeDirectnessEdits(options, data, req, false)
		if err != nil {
			return source.Error{}, err
		}
		return source.Error{
			Category: ModTidyError,
			Message:  fmt.Sprintf("%s should be a direct dependency.", req.Mod.Path),
			Range:    rng,
			URI:      data.origfh.URI(),
			SuggestedFixes: []source.SuggestedFix{{
				Title: fmt.Sprintf("Make %s direct", req.Mod.Path),
				Edits: map[span.URI][]protocol.TextEdit{data.origfh.URI(): edits},
			}},
		}, nil
	}
	// If the dependency should be indirect, add the // indirect.
	edits, err := changeDirectnessEdits(options, data, req, true)
	if err != nil {
		return source.Error{}, err
	}
	return source.Error{
		Category: ModTidyError,
		Message:  fmt.Sprintf("%s should be an indirect dependency.", req.Mod.Path),
		Range:    rng,
		URI:      data.origfh.URI(),
		SuggestedFixes: []source.SuggestedFix{{
			Title: fmt.Sprintf("Make %s indirect", req.Mod.Path),
			Edits: map[span.URI][]protocol.TextEdit{data.origfh.URI(): edits},
		}},
	}, nil
}

// dropDependencyEdits gets the edits needed to remove the dependency from the go.mod file.
// As an example, this function will codify the edits needed to convert the before go.mod file to the after.
// Before:
// 	module t
//
// 	go 1.11
//
// 	require golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee
// After:
// 	module t
//
// 	go 1.11
func dropDependencyEdits(options source.Options, data *modData, req *modfile.Require) ([]protocol.TextEdit, error) {
	if err := data.origParsedFile.DropRequire(req.Mod.Path); err != nil {
		return nil, err
	}
	data.origParsedFile.Cleanup()
	newContents, err := data.origParsedFile.Format()
	if err != nil {
		return nil, err
	}
	// Reset the *modfile.File back to before we dropped the dependency.
	data.origParsedFile.AddNewRequire(req.Mod.Path, req.Mod.Version, req.Indirect)
	// Calculate the edits to be made due to the change.
	diff := options.ComputeEdits(data.origfh.URI(), string(data.origMapper.Content), string(newContents))
	edits, err := source.ToProtocolEdits(data.origMapper, diff)
	if err != nil {
		return nil, err
	}
	return edits, nil
}

// changeDirectnessEdits gets the edits needed to change an indirect dependency to direct and vice versa.
// As an example, this function will codify the edits needed to convert the before go.mod file to the after.
// Before:
// 	module t
//
// 	go 1.11
//
// 	require golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee
// After:
// 	module t
//
// 	go 1.11
//
// 	require golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee // indirect
func changeDirectnessEdits(options source.Options, data *modData, req *modfile.Require, indirect bool) ([]protocol.TextEdit, error) {
	var newReq []*modfile.Require
	prevIndirect := false
	// Change the directness in the matching require statement.
	for _, r := range data.origParsedFile.Require {
		if req.Mod.Path == r.Mod.Path {
			prevIndirect = req.Indirect
			req.Indirect = indirect
		}
		newReq = append(newReq, r)
	}
	data.origParsedFile.SetRequire(newReq)
	data.origParsedFile.Cleanup()
	newContents, err := data.origParsedFile.Format()
	if err != nil {
		return nil, err
	}
	// Change the dependency back to the way it was before we got the newContents.
	for _, r := range data.origParsedFile.Require {
		if req.Mod.Path == r.Mod.Path {
			req.Indirect = prevIndirect
		}
		newReq = append(newReq, r)
	}
	data.origParsedFile.SetRequire(newReq)
	// Calculate the edits to be made due to the change.
	diff := options.ComputeEdits(data.origfh.URI(), string(data.origMapper.Content), string(newContents))
	edits, err := source.ToProtocolEdits(data.origMapper, diff)
	if err != nil {
		return nil, err
	}
	return edits, nil
}

func rangeFromPositions(uri span.URI, m *protocol.ColumnMapper, s, e modfile.Position) (protocol.Range, error) {
	line, col, err := m.Converter.ToPosition(s.Byte)
	if err != nil {
		return protocol.Range{}, err
	}
	start := span.NewPoint(line, col, s.Byte)

	line, col, err = m.Converter.ToPosition(e.Byte)
	if err != nil {
		return protocol.Range{}, err
	}
	end := span.NewPoint(line, col, e.Byte)

	spn := span.New(uri, start, end)
	rng, err := m.Range(spn)
	if err != nil {
		return protocol.Range{}, err
	}
	return rng, nil
}
