// Copyright (c) 2024, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

// pregenerate manages generated files in BoringSSL
package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"slices"
	"strings"
	"sync"

	"boringssl.googlesource.com/boringssl/util/build"
)

var (
	check      = flag.Bool("check", false, "Check whether any files need to be updated, without actually updating them")
	numWorkers = flag.Int("num-workers", runtime.NumCPU(), "Runs the given number of workers")
	dryRun     = flag.Bool("dry-run", false, "Skip actually writing any files")
	perlPath   = flag.String("perl", "perl", "Path to the perl command")
	list       = flag.Bool("list", false, "List all generated files, rather than actually run them")
)

func runTask(t Task) error {
	expected, err := t.Run()
	if err != nil {
		return err
	}

	dst := t.Destination()
	dstPath := filepath.FromSlash(dst)
	if *check {
		actual, err := os.ReadFile(dstPath)
		if err != nil {
			if os.IsNotExist(err) {
				err = errors.New("missing file")
			}
			return err
		}

		if !bytes.Equal(expected, actual) {
			return errors.New("file out of date")
		}
		return nil
	}

	if *dryRun {
		fmt.Printf("Would write %d bytes to %q\n", len(expected), dst)
		return nil
	}

	if err := os.MkdirAll(filepath.Dir(dstPath), 0777); err != nil {
		return err
	}
	return os.WriteFile(dstPath, expected, 0666)
}

type taskError struct {
	dst string
	err error
}

func worker(taskChan <-chan Task, errorChan chan<- taskError, wg *sync.WaitGroup) {
	defer wg.Done()
	for t := range taskChan {
		if err := runTask(t); err != nil {
			errorChan <- taskError{t.Destination(), err}
		}
	}
}

func run() error {
	if _, err := os.Stat("BUILDING.md"); err != nil {
		return fmt.Errorf("must be run from BoringSSL source root")
	}

	buildJSON, err := os.ReadFile("build.json")
	if err != nil {
		return err
	}

	// Remove comments. For now, just do a very basic preprocessing step. If
	// needed, we can switch to something well-defined like one of the many
	// dozen different extended JSONs like JSON5.
	lines := bytes.Split(buildJSON, []byte("\n"))
	for i := range lines {
		if idx := bytes.Index(lines[i], []byte("//")); idx >= 0 {
			lines[i] = lines[i][:idx]
		}
	}
	buildJSON = bytes.Join(lines, []byte("\n"))

	var targetsIn map[string]InputTarget
	if err := json.Unmarshal(buildJSON, &targetsIn); err != nil {
		return fmt.Errorf("error decoding build config: %s", err)
	}

	var tasks []Task
	targetsOut := make(map[string]build.Target)
	for name, targetIn := range targetsIn {
		targetOut, targetTasks, err := targetIn.Pregenerate(name)
		if err != nil {
			return err
		}
		targetsOut[name] = targetOut
		tasks = append(tasks, targetTasks...)
	}

	tasks = append(tasks, MakeBuildFiles(targetsOut)...)
	tasks = append(tasks, NewSimpleTask("gen/README.md", func() ([]byte, error) {
		return []byte(readme), nil
	}))

	// Filter tasks by command-line argument.
	if args := flag.Args(); len(args) != 0 {
		var filtered []Task
		for _, t := range tasks {
			dst := t.Destination()
			for _, arg := range args {
				if strings.Contains(dst, arg) {
					filtered = append(filtered, t)
					break
				}
			}
		}
		tasks = filtered
	}

	if *list {
		paths := make([]string, len(tasks))
		for i, t := range tasks {
			paths[i] = t.Destination()
		}
		slices.Sort(paths)
		for _, p := range paths {
			fmt.Println(p)
		}
		return nil
	}

	// Schedule tasks in parallel. Perlasm benefits from running in parallel. The
	// others likely do not, but it is simpler to parallelize them all.
	var wg sync.WaitGroup
	taskChan := make(chan Task, *numWorkers)
	errorChan := make(chan taskError, *numWorkers)
	for i := 0; i < *numWorkers; i++ {
		wg.Add(1)
		go worker(taskChan, errorChan, &wg)
	}

	go func() {
		for _, t := range tasks {
			taskChan <- t
		}
		close(taskChan)
		wg.Wait()
		close(errorChan)
	}()

	var failed bool
	for err := range errorChan {
		fmt.Fprintf(os.Stderr, "Error in file %q: %s\n", err.dst, err.err)
		failed = true
	}
	if failed {
		return errors.New("some files had errors")
	}
	return nil
}

func main() {
	flag.Parse()
	if err := run(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		os.Exit(1)
	}
}

const readme = `# Pre-generated files

This directory contains a number of pre-generated build artifacts. To simplify
downstream builds, they are checked into the repository, rather than dynamically
generated as part of the build.

When developing on BoringSSL, if any inputs to these files are modified, callers
must run the following command to update the generated files:

    go run ./util/pregenerate

To check that files are up-to-date without updating files, run:

    go run ./util/pregenerate -check

This is run on CI to ensure the generated files remain up-to-date.

To speed up local iteration, the tool accepts additional arguments to filter the
files generated. For example, if editing ` + "`aesni-x86_64.pl`" + `, this
command will only update files with "aesni-x86_64" as a substring.

    go run ./util/pregenerate aesni-x86_64

For convenience, all files in this directory, including this README, are managed
by the tool. This means the whole directory may be deleted and regenerated from
scratch at any time.
`
