// Copyright 2020 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 mod

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"golang.org/x/mod/modfile"
	"golang.org/x/tools/internal/lsp/command"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/span"
)

// LensFuncs returns the supported lensFuncs for go.mod files.
func LensFuncs() map[command.Command]source.LensFunc {
	return map[command.Command]source.LensFunc{
		command.UpgradeDependency: upgradeLenses,
		command.Tidy:              tidyLens,
		command.Vendor:            vendorLens,
	}
}

func upgradeLenses(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
	pm, err := snapshot.ParseMod(ctx, fh)
	if err != nil || pm.File == nil {
		return nil, err
	}
	if len(pm.File.Require) == 0 {
		// Nothing to upgrade.
		return nil, nil
	}
	var requires []string
	for _, req := range pm.File.Require {
		requires = append(requires, req.Mod.Path)
	}
	uri := protocol.URIFromSpanURI(fh.URI())
	checkUpgrade, err := command.NewCheckUpgradesCommand("Check for upgrades", command.CheckUpgradesArgs{
		URI:     uri,
		Modules: requires,
	})
	if err != nil {
		return nil, err
	}
	upgradeTransitive, err := command.NewUpgradeDependencyCommand("Upgrade transitive dependencies", command.DependencyArgs{
		URI:        uri,
		AddRequire: false,
		GoCmdArgs:  []string{"-d", "-u", "-t", "./..."},
	})
	if err != nil {
		return nil, err
	}
	upgradeDirect, err := command.NewUpgradeDependencyCommand("Upgrade direct dependencies", command.DependencyArgs{
		URI:        uri,
		AddRequire: false,
		GoCmdArgs:  append([]string{"-d"}, requires...),
	})
	if err != nil {
		return nil, err
	}
	// Put the upgrade code lenses above the first require block or statement.
	rng, err := firstRequireRange(fh, pm)
	if err != nil {
		return nil, err
	}

	return []protocol.CodeLens{
		{Range: rng, Command: checkUpgrade},
		{Range: rng, Command: upgradeTransitive},
		{Range: rng, Command: upgradeDirect},
	}, nil
}

func tidyLens(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
	pm, err := snapshot.ParseMod(ctx, fh)
	if err != nil || pm.File == nil {
		return nil, err
	}
	uri := protocol.URIFromSpanURI(fh.URI())
	cmd, err := command.NewTidyCommand("Run go mod tidy", command.URIArgs{URIs: []protocol.DocumentURI{uri}})
	if err != nil {
		return nil, err
	}
	rng, err := moduleStmtRange(fh, pm)
	if err != nil {
		return nil, err
	}
	return []protocol.CodeLens{{
		Range:   rng,
		Command: cmd,
	}}, nil
}

func vendorLens(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) ([]protocol.CodeLens, error) {
	pm, err := snapshot.ParseMod(ctx, fh)
	if err != nil || pm.File == nil {
		return nil, err
	}
	if len(pm.File.Require) == 0 {
		// Nothing to vendor.
		return nil, nil
	}
	rng, err := moduleStmtRange(fh, pm)
	if err != nil {
		return nil, err
	}
	title := "Create vendor directory"
	uri := protocol.URIFromSpanURI(fh.URI())
	cmd, err := command.NewVendorCommand(title, command.URIArg{URI: uri})
	if err != nil {
		return nil, err
	}
	// Change the message depending on whether or not the module already has a
	// vendor directory.
	vendorDir := filepath.Join(filepath.Dir(fh.URI().Filename()), "vendor")
	if info, _ := os.Stat(vendorDir); info != nil && info.IsDir() {
		title = "Sync vendor directory"
	}
	return []protocol.CodeLens{{Range: rng, Command: cmd}}, nil
}

func moduleStmtRange(fh source.FileHandle, pm *source.ParsedModule) (protocol.Range, error) {
	if pm.File == nil || pm.File.Module == nil || pm.File.Module.Syntax == nil {
		return protocol.Range{}, fmt.Errorf("no module statement in %s", fh.URI())
	}
	syntax := pm.File.Module.Syntax
	return lineToRange(pm.Mapper, fh.URI(), syntax.Start, syntax.End)
}

// firstRequireRange returns the range for the first "require" in the given
// go.mod file. This is either a require block or an individual require line.
func firstRequireRange(fh source.FileHandle, pm *source.ParsedModule) (protocol.Range, error) {
	if len(pm.File.Require) == 0 {
		return protocol.Range{}, fmt.Errorf("no requires in the file %s", fh.URI())
	}
	var start, end modfile.Position
	for _, stmt := range pm.File.Syntax.Stmt {
		if b, ok := stmt.(*modfile.LineBlock); ok && len(b.Token) == 1 && b.Token[0] == "require" {
			start, end = b.Span()
			break
		}
	}

	firstRequire := pm.File.Require[0].Syntax
	if start.Byte == 0 || firstRequire.Start.Byte < start.Byte {
		start, end = firstRequire.Start, firstRequire.End
	}
	return lineToRange(pm.Mapper, fh.URI(), start, end)
}

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