// 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().Identity().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().Identity().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().Identity().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().Identity().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 {
	uri := fh.Identity().URI
	if handle := s.getModHandle(uri); handle != nil {
		return handle
	}

	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(ctx)
		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]
}

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().Identity().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(ctx)
		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.Identity().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.Identity().URI,
				SuggestedFixes: []source.SuggestedFix{{
					Title: fmt.Sprintf("Remove dependency: %s", dep),
					Edits: map[span.URI][]protocol.TextEdit{data.origfh.Identity().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.Identity().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.Identity().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.Identity().URI,
			SuggestedFixes: []source.SuggestedFix{{
				Title: fmt.Sprintf("Make %s direct", req.Mod.Path),
				Edits: map[span.URI][]protocol.TextEdit{data.origfh.Identity().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.Identity().URI,
		SuggestedFixes: []source.SuggestedFix{{
			Title: fmt.Sprintf("Make %s indirect", req.Mod.Path),
			Edits: map[span.URI][]protocol.TextEdit{data.origfh.Identity().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.Identity().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.Identity().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
}
