// Copyright 2015 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.

// This file contains the implementation of the 'gomvpkg' command
// whose main function is in golang.org/x/tools/cmd/gomvpkg.

package rename

// TODO(matloob):
// - think about what happens if the package is moving across version control systems.
// - dot imports are not supported. Make sure it's clearly documented.

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/build"
	"go/format"
	"go/token"
	exec "golang.org/x/sys/execabs"
	"log"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"text/template"

	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/refactor/importgraph"
)

// Move, given a package path and a destination package path, will try
// to move the given package to the new path. The Move function will
// first check for any conflicts preventing the move, such as a
// package already existing at the destination package path. If the
// move can proceed, it builds an import graph to find all imports of
// the packages whose paths need to be renamed. This includes uses of
// the subpackages of the package to be moved as those packages will
// also need to be moved. It then renames all imports to point to the
// new paths, and then moves the packages to their new paths.
func Move(ctxt *build.Context, from, to, moveTmpl string) error {
	srcDir, err := srcDir(ctxt, from)
	if err != nil {
		return err
	}

	// This should be the only place in the program that constructs
	// file paths.
	fromDir := buildutil.JoinPath(ctxt, srcDir, filepath.FromSlash(from))
	toDir := buildutil.JoinPath(ctxt, srcDir, filepath.FromSlash(to))
	toParent := filepath.Dir(toDir)
	if !buildutil.IsDir(ctxt, toParent) {
		return fmt.Errorf("parent directory does not exist for path %s", toDir)
	}

	// Build the import graph and figure out which packages to update.
	_, rev, errors := importgraph.Build(ctxt)
	if len(errors) > 0 {
		// With a large GOPATH tree, errors are inevitable.
		// Report them but proceed.
		fmt.Fprintf(os.Stderr, "While scanning Go workspace:\n")
		for path, err := range errors {
			fmt.Fprintf(os.Stderr, "Package %q: %s.\n", path, err)
		}
	}

	// Determine the affected packages---the set of packages whose import
	// statements need updating.
	affectedPackages := map[string]bool{from: true}
	destinations := make(map[string]string) // maps old import path to new import path
	for pkg := range subpackages(ctxt, srcDir, from) {
		for r := range rev[pkg] {
			affectedPackages[r] = true
		}
		destinations[pkg] = strings.Replace(pkg, from, to, 1)
	}

	// Load all the affected packages.
	iprog, err := loadProgram(ctxt, affectedPackages)
	if err != nil {
		return err
	}

	// Prepare the move command, if one was supplied.
	var cmd string
	if moveTmpl != "" {
		if cmd, err = moveCmd(moveTmpl, fromDir, toDir); err != nil {
			return err
		}
	}

	m := mover{
		ctxt:             ctxt,
		rev:              rev,
		iprog:            iprog,
		from:             from,
		to:               to,
		fromDir:          fromDir,
		toDir:            toDir,
		affectedPackages: affectedPackages,
		destinations:     destinations,
		cmd:              cmd,
	}

	if err := m.checkValid(); err != nil {
		return err
	}

	m.move()

	return nil
}

// srcDir returns the absolute path of the srcdir containing pkg.
func srcDir(ctxt *build.Context, pkg string) (string, error) {
	for _, srcDir := range ctxt.SrcDirs() {
		path := buildutil.JoinPath(ctxt, srcDir, pkg)
		if buildutil.IsDir(ctxt, path) {
			return srcDir, nil
		}
	}
	return "", fmt.Errorf("src dir not found for package: %s", pkg)
}

// subpackages returns the set of packages in the given srcDir whose
// import path equals to root, or has "root/" as the prefix.
func subpackages(ctxt *build.Context, srcDir string, root string) map[string]bool {
	var subs = make(map[string]bool)
	buildutil.ForEachPackage(ctxt, func(pkg string, err error) {
		if err != nil {
			log.Fatalf("unexpected error in ForEachPackage: %v", err)
		}

		// Only process the package root, or a sub-package of it.
		if !(strings.HasPrefix(pkg, root) &&
			(len(pkg) == len(root) || pkg[len(root)] == '/')) {
			return
		}

		p, err := ctxt.Import(pkg, "", build.FindOnly)
		if err != nil {
			log.Fatalf("unexpected: package %s can not be located by build context: %s", pkg, err)
		}
		if p.SrcRoot == "" {
			log.Fatalf("unexpected: could not determine srcDir for package %s: %s", pkg, err)
		}
		if p.SrcRoot != srcDir {
			return
		}

		subs[pkg] = true
	})
	return subs
}

type mover struct {
	// iprog contains all packages whose contents need to be updated
	// with new package names or import paths.
	iprog *loader.Program
	ctxt  *build.Context
	// rev is the reverse import graph.
	rev importgraph.Graph
	// from and to are the source and destination import
	// paths. fromDir and toDir are the source and destination
	// absolute paths that package source files will be moved between.
	from, to, fromDir, toDir string
	// affectedPackages is the set of all packages whose contents need
	// to be updated to reflect new package names or import paths.
	affectedPackages map[string]bool
	// destinations maps each subpackage to be moved to its
	// destination path.
	destinations map[string]string
	// cmd, if not empty, will be executed to move fromDir to toDir.
	cmd string
}

func (m *mover) checkValid() error {
	const prefix = "invalid move destination"

	match, err := regexp.MatchString("^[_\\pL][_\\pL\\p{Nd}]*$", path.Base(m.to))
	if err != nil {
		panic("regexp.MatchString failed")
	}
	if !match {
		return fmt.Errorf("%s: %s; gomvpkg does not support move destinations "+
			"whose base names are not valid go identifiers", prefix, m.to)
	}

	if buildutil.FileExists(m.ctxt, m.toDir) {
		return fmt.Errorf("%s: %s conflicts with file %s", prefix, m.to, m.toDir)
	}
	if buildutil.IsDir(m.ctxt, m.toDir) {
		return fmt.Errorf("%s: %s conflicts with directory %s", prefix, m.to, m.toDir)
	}

	for _, toSubPkg := range m.destinations {
		if _, err := m.ctxt.Import(toSubPkg, "", build.FindOnly); err == nil {
			return fmt.Errorf("%s: %s; package or subpackage %s already exists",
				prefix, m.to, toSubPkg)
		}
	}

	return nil
}

// moveCmd produces the version control move command used to move fromDir to toDir by
// executing the given template.
func moveCmd(moveTmpl, fromDir, toDir string) (string, error) {
	tmpl, err := template.New("movecmd").Parse(moveTmpl)
	if err != nil {
		return "", err
	}

	var buf bytes.Buffer
	err = tmpl.Execute(&buf, struct {
		Src string
		Dst string
	}{fromDir, toDir})
	return buf.String(), err
}

func (m *mover) move() error {
	filesToUpdate := make(map[*ast.File]bool)

	// Change the moved package's "package" declaration to its new base name.
	pkg, ok := m.iprog.Imported[m.from]
	if !ok {
		log.Fatalf("unexpected: package %s is not in import map", m.from)
	}
	newName := filepath.Base(m.to)
	for _, f := range pkg.Files {
		// Update all import comments.
		for _, cg := range f.Comments {
			c := cg.List[0]
			if c.Slash >= f.Name.End() &&
				sameLine(m.iprog.Fset, c.Slash, f.Name.End()) &&
				(f.Decls == nil || c.Slash < f.Decls[0].Pos()) {
				if strings.HasPrefix(c.Text, `// import "`) {
					c.Text = `// import "` + m.to + `"`
					break
				}
				if strings.HasPrefix(c.Text, `/* import "`) {
					c.Text = `/* import "` + m.to + `" */`
					break
				}
			}
		}
		f.Name.Name = newName // change package decl
		filesToUpdate[f] = true
	}

	// Look through the external test packages (m.iprog.Created contains the external test packages).
	for _, info := range m.iprog.Created {
		// Change the "package" declaration of the external test package.
		if info.Pkg.Path() == m.from+"_test" {
			for _, f := range info.Files {
				f.Name.Name = newName + "_test" // change package decl
				filesToUpdate[f] = true
			}
		}

		// Mark all the loaded external test packages, which import the "from" package,
		// as affected packages and update the imports.
		for _, imp := range info.Pkg.Imports() {
			if imp.Path() == m.from {
				m.affectedPackages[info.Pkg.Path()] = true
				m.iprog.Imported[info.Pkg.Path()] = info
				if err := importName(m.iprog, info, m.from, path.Base(m.from), newName); err != nil {
					return err
				}
			}
		}
	}

	// Update imports of that package to use the new import name.
	// None of the subpackages will change their name---only the from package
	// itself will.
	for p := range m.rev[m.from] {
		if err := importName(m.iprog, m.iprog.Imported[p], m.from, path.Base(m.from), newName); err != nil {
			return err
		}
	}

	// Update import paths for all imports by affected packages.
	for ap := range m.affectedPackages {
		info, ok := m.iprog.Imported[ap]
		if !ok {
			log.Fatalf("unexpected: package %s is not in import map", ap)
		}
		for _, f := range info.Files {
			for _, imp := range f.Imports {
				importPath, _ := strconv.Unquote(imp.Path.Value)
				if newPath, ok := m.destinations[importPath]; ok {
					imp.Path.Value = strconv.Quote(newPath)

					oldName := path.Base(importPath)
					if imp.Name != nil {
						oldName = imp.Name.Name
					}

					newName := path.Base(newPath)
					if imp.Name == nil && oldName != newName {
						imp.Name = ast.NewIdent(oldName)
					} else if imp.Name == nil || imp.Name.Name == newName {
						imp.Name = nil
					}
					filesToUpdate[f] = true
				}
			}
		}
	}

	for f := range filesToUpdate {
		var buf bytes.Buffer
		if err := format.Node(&buf, m.iprog.Fset, f); err != nil {
			log.Printf("failed to pretty-print syntax tree: %v", err)
			continue
		}
		tokenFile := m.iprog.Fset.File(f.Pos())
		writeFile(tokenFile.Name(), buf.Bytes())
	}

	// Move the directories.
	// If either the fromDir or toDir are contained under version control it is
	// the user's responsibility to provide a custom move command that updates
	// version control to reflect the move.
	// TODO(matloob): If the parent directory of toDir does not exist, create it.
	//      For now, it's required that it does exist.

	if m.cmd != "" {
		// TODO(matloob): Verify that the windows and plan9 cases are correct.
		var cmd *exec.Cmd
		switch runtime.GOOS {
		case "windows":
			cmd = exec.Command("cmd", "/c", m.cmd)
		case "plan9":
			cmd = exec.Command("rc", "-c", m.cmd)
		default:
			cmd = exec.Command("sh", "-c", m.cmd)
		}
		cmd.Stderr = os.Stderr
		cmd.Stdout = os.Stdout
		if err := cmd.Run(); err != nil {
			return fmt.Errorf("version control system's move command failed: %v", err)
		}

		return nil
	}

	return moveDirectory(m.fromDir, m.toDir)
}

// sameLine reports whether two positions in the same file are on the same line.
func sameLine(fset *token.FileSet, x, y token.Pos) bool {
	return fset.Position(x).Line == fset.Position(y).Line
}

var moveDirectory = func(from, to string) error {
	return os.Rename(from, to)
}
