/*
Copyright 2016 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Buildifier, a tool to parse and format BUILD files.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"

	"github.com/bazelbuild/buildtools/build"
	"github.com/bazelbuild/buildtools/buildifier/config"
	"github.com/bazelbuild/buildtools/buildifier/utils"
	"github.com/bazelbuild/buildtools/differ"
	"github.com/bazelbuild/buildtools/wspace"
)

var buildVersion = "redacted"
var buildScmRevision = "redacted"

func usage() {
	fmt.Fprintf(flag.CommandLine.Output(), `usage: buildifier [-d] [-v] [-r] [-config=path.json] [-diff_command=command] [-help] [-multi_diff] [-mode=mode] [-lint=lint_mode] [-path=path] [files...]

Buildifier applies standard formatting to the named Starlark files.  The mode
flag selects the processing: check, diff, fix, or print_if_changed.  In check
mode, buildifier prints a list of files that need reformatting.  In diff mode,
buildifier shows the diffs that it would make.  It creates the diffs by running
a diff command, which can be specified using the -diff_command flag. You can
indicate that the diff command can show differences between more than two files
in the manner of tkdiff by specifying the -multi_diff flag.  In fix mode,
buildifier updates the files that need reformatting and, if the -v flag is
given, prints their names to standard error.  In print_if_changed mode,
buildifier shows the file contents it would write.  The default mode is fix. -d
is an alias for -mode=diff.

The lint flag selects the lint mode to be used: off, warn, fix.
In off mode, the linting is not performed.
In warn mode, buildifier prints warnings for common mistakes and suboptimal
coding practices that include links providing more context and fix suggestions.
In fix mode, buildifier updates the files with all warning resolutions produced
by automated fixes.
The default lint mode is off.

If no files are listed, buildifier reads a Starlark file from standard
input. In fix mode, it writes the reformatted Starlark file to standard output,
even if no changes are necessary.

Buildifier's reformatting depends in part on the path to the file relative
to the workspace directory. Normally buildifier deduces that path from the
file names given, but the path can be given explicitly with the -path
argument. This is especially useful when reformatting standard input,
or in scripts that reformat a temporary copy of a file.

Return codes used by buildifier:

  0: success, everything went well
  1: syntax errors in input
  2: usage errors: invoked incorrectly
  3: unexpected runtime errors: file I/O problems or internal bugs
  4: check mode failed (reformat is needed)

Full list of flags with their defaults:
`)
	flag.PrintDefaults()

	fmt.Fprintf(flag.CommandLine.Output(), `
Buildifier can also be configured via a JSON file.  The location of the file
is given by the -config flag, the BUILDIFIER_CONFIG environment variable, or
a file named '.buildifier.json' at the root of the workspace (e.g., in the same
directory as the WORKSPACE file).  The PWD environment variable or process
working directory is used to help find the workspace root.  If present, the file
is loaded into memory and becomes the base configuration that command line flags
override.  A sample configuration file can be printed to stdout by running
buildifier -config=example. The config file feature can be disabled completely
with -config=off.
`)
}

func main() {
	c := config.New()

	flags := c.FlagSet("buildifier", flag.ExitOnError)
	flag.CommandLine = flags
	flag.Usage = usage
	flags.Parse(os.Args[1:])
	args := flags.Args()

	if c.Help {
		flag.CommandLine.SetOutput(os.Stdout)
		usage()
		fmt.Println()
		os.Exit(0)
	}

	if c.Version {
		fmt.Printf("buildifier version: %s \n", buildVersion)
		fmt.Printf("buildifier scm revision: %s \n", buildScmRevision)
		os.Exit(0)
	}

	if c.ConfigPath == "" {
		c.ConfigPath = config.FindConfigPath("")
	}
	if c.ConfigPath != "" {
		if c.ConfigPath == "example" {
			fmt.Println(config.Example().String())
			os.Exit(0)
		}
		if c.ConfigPath != "off" {
			if err := c.LoadFile(); err != nil {
				fmt.Fprintf(os.Stderr, "buildifier: %s\n", err)
				os.Exit(2)
			}
			// re-parse with new possibly new defaults
			flags = c.FlagSet("buildifier", flag.ExitOnError)
			flag.CommandLine = flags
			flag.Usage = usage
			flags.Parse(os.Args[1:])
		}
	}

	if err := c.Validate(args); err != nil {
		fmt.Fprintf(os.Stderr, "buildifier: %s\n", err)
		os.Exit(2)
	}

	// Pass down debug flags into build package
	build.DisableRewrites = c.DisableRewrites
	build.AllowSort = c.AllowSort

	differ, deprecationWarning := differ.Find()
	if c.DiffCommand != "" {
		differ.Cmd = c.DiffCommand
		differ.MultiDiff = c.MultiDiff
	} else {
		if deprecationWarning && c.Mode == "diff" {
			fmt.Fprintf(os.Stderr, "buildifier: selecting diff program with the BUILDIFIER_DIFF, BUILDIFIER_MULTIDIFF, and DISPLAY environment variables is deprecated, use flags -diff_command and -multi_diff instead\n")
		}
	}

	b := buildifier{c, differ}
	exitCode := b.run(args)

	os.Exit(exitCode)
}

type buildifier struct {
	config *config.Config
	differ *differ.Differ
}

func (b *buildifier) run(args []string) int {
	tf := &utils.TempFile{}
	defer tf.Clean()

	exitCode := 0
	var diagnostics *utils.Diagnostics
	if len(args) == 0 || (len(args) == 1 && (args)[0] == "-") {
		// Read from stdin, write to stdout.
		data, err := io.ReadAll(os.Stdin)
		if err != nil {
			fmt.Fprintf(os.Stderr, "buildifier: reading stdin: %v\n", err)
			return 2
		}
		if b.config.Mode == "fix" {
			b.config.Mode = "pipe"
		}
		var fileDiagnostics *utils.FileDiagnostics
		fileDiagnostics, exitCode = b.processFile("", data, false, tf)
		diagnostics = utils.NewDiagnostics(fileDiagnostics)
	} else {
		files := args
		if b.config.Recursive {
			var err error
			files, err = utils.ExpandDirectories(&args)
			if err != nil {
				fmt.Fprintf(os.Stderr, "buildifier: %v\n", err)
				return 3
			}
		}
		diagnostics, exitCode = b.processFiles(files, tf)
	}

	diagnosticsOutput := diagnostics.Format(b.config.Format, b.config.Verbose)
	if b.config.Format != "" {
		// Explicitly provided --format means the diagnostics are printed to stdout
		fmt.Print(diagnosticsOutput)
		// Exit code should be set to 0 so that other tools know they can safely parse the json
		exitCode = 0
	} else {
		// --format is not provided, stdout is reserved for file contents
		fmt.Fprint(os.Stderr, diagnosticsOutput)
	}

	if err := b.differ.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		return 2
	}

	return exitCode
}

func (b *buildifier) processFiles(files []string, tf *utils.TempFile) (*utils.Diagnostics, int) {
	// Decide how many file reads to run in parallel.
	// At most 100, and at most one per 10 input files.
	nworker := 100
	if n := (len(files) + 9) / 10; nworker > n {
		nworker = n
	}
	runtime.GOMAXPROCS(nworker + 1)

	// Start nworker workers reading stripes of the input
	// argument list and sending the resulting data on
	// separate channels. file[k] is read by worker k%nworker
	// and delivered on ch[k%nworker].
	type result struct {
		file string
		data []byte
		err  error
	}

	ch := make([]chan result, nworker)
	for i := 0; i < nworker; i++ {
		ch[i] = make(chan result, 1)
		go func(i int) {
			for j := i; j < len(files); j += nworker {
				file := files[j]
				data, err := os.ReadFile(file)
				ch[i] <- result{file, data, err}
			}
		}(i)
	}

	exitCode := 0
	fileDiagnostics := []*utils.FileDiagnostics{}

	// Process files. The processing still runs in a single goroutine
	// in sequence. Only the reading of the files has been parallelized.
	// The goal is to optimize for runs where most files are already
	// formatted correctly, so that reading is the bulk of the I/O.
	for i, file := range files {
		res := <-ch[i%nworker]
		if res.file != file {
			fmt.Fprintf(os.Stderr, "buildifier: internal phase error: got %s for %s", res.file, file)
			os.Exit(3)
		}
		if res.err != nil {
			fmt.Fprintf(os.Stderr, "buildifier: %v\n", res.err)
			exitCode = 3
			continue
		}
		fd, newExitCode := b.processFile(file, res.data, len(files) > 1, tf)
		if fd != nil {
			fileDiagnostics = append(fileDiagnostics, fd)
		}
		if newExitCode != 0 {
			exitCode = newExitCode
		}
	}
	return utils.NewDiagnostics(fileDiagnostics...), exitCode
}

// processFile processes a single file containing data.
// It has been read from filename and should be written back if fixing.
func (b *buildifier) processFile(filename string, data []byte, displayFileNames bool, tf *utils.TempFile) (*utils.FileDiagnostics, int) {
	var exitCode int

	displayFilename := filename
	if b.config.WorkspaceRelativePath != "" {
		displayFilename = b.config.WorkspaceRelativePath
	}

	parser := utils.GetParser(b.config.InputType)

	f, err := parser(displayFilename, data)
	if err != nil {
		// Do not use buildifier: prefix on this error.
		// Since it is a parse error, it begins with file:line:
		// and we want that to be the first thing in the error.
		fmt.Fprintf(os.Stderr, "%v\n", err)
		if exitCode < 1 {
			exitCode = 1
		}
		return utils.InvalidFileDiagnostics(displayFilename), exitCode
	}

	if absoluteFilename, err := filepath.Abs(displayFilename); err == nil {
		f.WorkspaceRoot, f.Pkg, f.Label = wspace.SplitFilePath(absoluteFilename)
	}

	warnings := utils.Lint(f, b.config.Lint, &b.config.LintWarnings, b.config.Verbose)
	if len(warnings) > 0 {
		exitCode = 4
	}
	fileDiagnostics := utils.NewFileDiagnostics(f.DisplayPath(), warnings)

	ndata := build.Format(f)

	switch b.config.Mode {
	case "check":
		// check mode: print names of files that need formatting.
		if !bytes.Equal(data, ndata) {
			fileDiagnostics.Formatted = false
			return fileDiagnostics, 4
		}

	case "diff":
		// diff mode: run diff on old and new.
		if bytes.Equal(data, ndata) {
			return fileDiagnostics, exitCode
		}
		outfile, err := tf.WriteTemp(ndata)
		if err != nil {
			fmt.Fprintf(os.Stderr, "buildifier: %v\n", err)
			return fileDiagnostics, 3
		}
		infile := filename
		if filename == "" {
			// data was read from standard filename.
			// Write it to a temporary file so diff can read it.
			infile, err = tf.WriteTemp(data)
			if err != nil {
				fmt.Fprintf(os.Stderr, "buildifier: %v\n", err)
				return fileDiagnostics, 3
			}
		}
		if displayFileNames {
			fmt.Fprintf(os.Stderr, "%v:\n", f.DisplayPath())
		}
		if err := b.differ.Show(infile, outfile); err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			return fileDiagnostics, 4
		}

	case "pipe":
		// pipe mode - reading from stdin, writing to stdout.
		// ("pipe" is not from the command line; it is set above in main.)
		os.Stdout.Write(ndata)

	case "fix":
		// fix mode: update files in place as needed.
		if bytes.Equal(data, ndata) {
			return fileDiagnostics, exitCode
		}

		err := os.WriteFile(filename, ndata, 0666)
		if err != nil {
			fmt.Fprintf(os.Stderr, "buildifier: %s\n", err)
			return fileDiagnostics, 3
		}

		if b.config.Verbose {
			fmt.Fprintf(os.Stderr, "fixed %s\n", f.DisplayPath())
		}
	case "print_if_changed":
		if bytes.Equal(data, ndata) {
			return fileDiagnostics, exitCode
		}

		if _, err := os.Stdout.Write(ndata); err != nil {
			fmt.Fprintf(os.Stderr, "buildifier: error writing output: %v\n", err)
			return fileDiagnostics, 3
		}
	}
	return fileDiagnostics, exitCode
}
