// Copyright 2019 The Fuchsia 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 main

import (
	"archive/tar"
	"compress/bzip2"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"time"

	"go.fuchsia.dev/fuchsia/tools/debug/elflib"
	"go.fuchsia.dev/fuchsia/tools/lib/color"
	"go.fuchsia.dev/fuchsia/tools/lib/logger"
	"go.fuchsia.dev/fuchsia/tools/lib/osmisc"
	"go.fuchsia.dev/fuchsia/tools/lib/subprocess"
)

var (
	debugArchive   string
	buildDir       string
	buildIDDirIn   string
	buildIDDirOut  string
	outputManifest string
	cpu            string
	osName         string
	depfile        string
	dumpSyms       string
	colors         color.EnableColor
	level          logger.LogLevel
	timeout        time.Duration
	tasks          int
)

var (
	errNoBuildIDDir = fmt.Errorf("Could not find a .build-id directory")
)

func init() {
	colors = color.ColorAuto
	level = logger.WarningLevel

	flag.StringVar(&debugArchive, "debug-archive", "", "path to archive of debug binaries")
	flag.StringVar(&buildDir, "build-dir", "", "path to the build directory")
	flag.StringVar(&buildIDDirIn, "build-id-dir-in", "", "path to an input .build-id directory")
	flag.StringVar(&buildIDDirOut, "build-id-dir-out", "", "path to an output .build-id directory to populate")
	flag.StringVar(&outputManifest, "output-manifest", "", "path to output a json manifest of debug binaries to")
	flag.StringVar(&cpu, "cpu", "", "the architecture of the binaries in the archive")
	flag.StringVar(&osName, "os", "", "the os of the binaries in the archive")
	flag.StringVar(&depfile, "depfile", "", "the depfile to emit")
	flag.StringVar(&dumpSyms, "dump-syms", "", "the path to the dump_syms tool")
	flag.Var(&colors, "color", "use color in output, can be never, auto, always")
	flag.Var(&level, "level", "output verbosity, can be fatal, error, warning, info, debug or trace")
	flag.DurationVar(&timeout, "timeout", 0, "the amount of time to wait on all dump_syms tasks")
	// By default we set the number of tasks to 2 times the number of CPUs. The expectation is that its
	// good to have many more tasks than CPUs because the tasks are IO bound.
	flag.IntVar(&tasks, "j", 2*runtime.NumCPU(), "the number of concurrent tasks to run at once")
}

type binary struct {
	CPU      string `json:"cpu"`
	Debug    string `json:"debug"`
	BuildID  string `json:"elf_build_id"`
	OS       string `json:"os"`
	Breakpad string `json:"breakpad"`
}

type binaryRef struct {
	ref      elflib.BinaryFileRef
	breakpad string
}

// We don't want extensions to be matched when we look for substring matches, so
// convenient just to drop it from consideration when validating the directory
// layout.
var buildIDFileNoExtRE = regexp.MustCompile("^([0-9a-f][0-9a-f])/([0-9a-f]+)$")

func isBuildIDDir(ctx context.Context, dir string, contents []os.FileInfo) bool {
	for _, info := range contents {
		// Some special files are allowed and expected.
		if info.Name() == "LICENSE" || info.Name()[0] == '.' {
			continue
		}
		logger.Tracef(ctx, "checking %s", info.Name())
		// Outside of particular special files, everything should be a directory.
		if !info.IsDir() {
			logger.Tracef(ctx, "%s wasn't a directory", info.Name())
			return false
		}
		// The directory name should be a hex byte.
		if len(info.Name()) != 2 {
			return false
		}
		if _, err := strconv.ParseUint(info.Name(), 16, 8); err != nil {
			logger.Tracef(ctx, "%s wasn't valid hex digit: %v", info.Name(), err)
			return false
		}
		// Now that we know the directory name was a 2 digit hex value, it's safe
		// to assume its most likely a .build-id directory and we can check to see
		// if it contains the sorts of files we expect
		files, err := ioutil.ReadDir(filepath.Join(dir, info.Name()))
		if err != nil {
			logger.Tracef(ctx, "%s couldn't read directory: %v", info.Name(), err)
			return false
		}
		logger.Tracef(ctx, "checking %s/... to see if it has the right files", info.Name())
		for _, file := range files {
			path := filepath.Join(info.Name(), file.Name())
			logger.Tracef(ctx, "checking %s for validity", path)
			// We should exclusively have files here.
			if file.IsDir() {
				logger.Tracef(ctx, "%s was a directory, not a file", path)
				return false
			}
			if !buildIDFileNoExtRE.MatchString(trimExt(path)) {
				logger.Tracef(ctx, "%s didn't match", path)
				return false
			}
		}
	}
	return true
}

func trimExt(p string) string {
	return strings.TrimSuffix(p, filepath.Ext(p))
}

// getStartDir allows us to be flexible in what we accept for debugArchive.
// This lets us use both a directory and a file for the time being allowing
// for an easy soft transistion as needed.
func getStartDir() (string, error) {
	if debugArchive == "" {
		return buildIDDirIn, nil
	}
	// If the debug archive was passed, just return the first ancestor
	// directory that exists. This allows flexibility in transitioning away
	// from specifying the debug archive altogether. The common two cases are
	// (1) the debug archive still exists and we will unpack the contents in
	// the parent directory, or
	// (2) the debug archive and some unnecessary nesting no longer exist, and
	// some ancestor directory is where the unpacked contents now await
	// processing.
	dir := filepath.Dir(debugArchive)
	for dir != "" && dir != "/" && dir != "." {
		info, err := os.Stat(dir)
		if err == nil {
			if !info.IsDir() {
				return "", fmt.Errorf("ancestor directory %s of %s is actually a file", dir, debugArchive)
			}
			return dir, nil
		} else if !os.IsNotExist(err) {
			return "", err
		}
		dir = filepath.Dir(dir)
	}
	return "", fmt.Errorf("no ancestor directory of %s exists", debugArchive)
}

// In the case where a debug archive is specified but is nonexistent, as will
// happen during the transition away from specifying the parameter altogether,
// this means that a raw .build-id dir is now being supplied. To allow
// flexibility around the relative path between the debug archive specification
// and this directory, we telescoped out in getStartDir to degugArchive's
// first existent ancestor directory; here we now telescope back in and look for
// the first .build-id subdirectory.
func findBuildIDDir(ctx context.Context, startDir string) (string, error) {
	logger.Tracef(ctx, "determining if %s is a .build-id directory", startDir)
	infos, err := ioutil.ReadDir(startDir)
	if err != nil {
		return "", err
	}
	if isBuildIDDir(ctx, startDir, infos) {
		return startDir, nil
	}
	for _, info := range infos {
		if !info.IsDir() {
			continue
		}
		dir, err := findBuildIDDir(ctx, filepath.Join(startDir, info.Name()))
		if err == nil {
			return dir, nil
		} else if err != errNoBuildIDDir {
			return "", err
		}
	}
	return "", errNoBuildIDDir
}

// runDumpSyms starts a dump_syms command using `br` that converts an ELF file
// with debug info into a breakpad syms file. If the breakpad syms file has already
// been created, dump_syms will not run. This allows many instances of this tool to
// run at the same time without duplicating work. Note that creating a file with
// O_EXCL is atomic.
func runDumpSyms(ctx context.Context, br *BatchRunner, in, out string) error {
	file, err := osmisc.CreateFile(out, os.O_WRONLY|os.O_EXCL)
	// If the file already exists, don't bother recreating it. This saves a massive
	// amount of computation and is atomic.
	if os.IsExist(err) {
		logger.Tracef(ctx, "file %s already existed: %v", out, err)
		return nil
	} else if err != nil {
		return err
	}
	cmd := []string{dumpSyms, "-r", "-n", "<_>", "-o", "Fuchsia", in}
	br.Enqueue(cmd, file, os.Stderr, func() {
		file.Close()
	})
	return nil
}

// produceSymbols takes an input .build-id directory and produces breakpad symbols
// for each binary in the output .build-id directory.
func produceSymbols(ctx context.Context, inputBuildIDDir string, br *BatchRunner) ([]binaryRef, error) {
	logger.Tracef(ctx, "about to walk build-id-dir")
	refs, err := elflib.WalkBuildIDDir(inputBuildIDDir)
	if err != nil {
		return nil, fmt.Errorf("while calling dump_syms for %s: %w", inputBuildIDDir, err)
	}

	logger.Tracef(ctx, "about spin up dump_syms")
	outs := []binaryRef{}
	for _, ref := range refs {
		out := filepath.Join(buildIDDirOut, ref.BuildID[:2], ref.BuildID[2:]+".sym")
		logger.Tracef(ctx, "spun up dump_syms for %s", out)
		if err := runDumpSyms(ctx, br, ref.Filepath, out); err != nil {
			return nil, fmt.Errorf("while calling dump_syms for %s: %v", ref.Filepath, err)
		}
		outs = append(outs, binaryRef{ref, out})
	}
	return outs, nil
}

// unpack takes debugArchive and unpacks each debug binary. On seeing a debug binary
// dump_syms is invoked for it using `br` as well.
func unpack(ctx context.Context, br *BatchRunner) ([]binaryRef, error) {
	// unpack each debug binary into buildIDDirOut
	file, err := os.Open(debugArchive)
	if err != nil {
		return nil, fmt.Errorf("while unpacking %s: %w", debugArchive, err)
	}
	defer file.Close()
	// The file is bzip2 compressed
	tr := tar.NewReader(bzip2.NewReader(file))
	out := []binaryRef{}
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		} else if err != nil {
			return nil, fmt.Errorf("while reading %s: %w", debugArchive, err)
		} else if hdr.Typeflag == tar.TypeDir {
			continue
		}

		matches := buildIDFileNoExtRE.FindStringSubmatch(trimExt(hdr.Name))
		if matches == nil {
			logger.Warningf(ctx, "%s in %s was not a debug binary", hdr.Name, debugArchive)
			continue
		}
		logger.Tracef(ctx, "Reading %s from %s", hdr.Name, debugArchive)
		if len(matches) != 3 {
			panic("The list of matches isn't as expected")
		}
		buildID := matches[1] + matches[2]
		unpackFilePath := filepath.Join(buildIDDirOut, hdr.Name)

		ok, err := osmisc.FileExists(unpackFilePath)
		if err != nil {
			return nil, err
		} else if ok {
			continue
		}
		outFile, err := osmisc.CreateFile(unpackFilePath, os.O_WRONLY)
		if err != nil {
			return nil, fmt.Errorf("while attempting to write %s from %s to %s: %w", hdr.Name, debugArchive, unpackFilePath, err)
		}
		if _, err := io.Copy(outFile, tr); err != nil {
			outFile.Close()
			return nil, fmt.Errorf("while attempting to write %s from %s to %s: %w", hdr.Name, debugArchive, unpackFilePath, err)
		}
		outFile.Close()
		bfr := elflib.NewBinaryFileRef(unpackFilePath, buildID)
		if err := bfr.Verify(); err != nil {
			return nil, fmt.Errorf("while attempting to verify %s copied from %s: %w", unpackFilePath, debugArchive, err)
		}
		symbolFile := filepath.Join(buildIDDirOut, bfr.BuildID[:2], bfr.BuildID[2:]+".sym")
		logger.Tracef(ctx, "adding dump_syms command for %s -> %s", bfr.Filepath, symbolFile)
		if err := runDumpSyms(ctx, br, bfr.Filepath, symbolFile); err != nil {
			return nil, fmt.Errorf("running dumpSyms on %s to produce %s: %w", bfr.Filepath, symbolFile, err)
		}
		out = append(out, binaryRef{bfr, symbolFile})
	}
	return out, nil
}

func writeManifest(bfrs []binaryRef) error {
	out := []binary{}
	for _, bfr := range bfrs {
		// Even though these files live outside of the build directory,
		// relativize them as is conventional for build API metadata.
		relDebug, err := filepath.Rel(buildDir, bfr.ref.Filepath)
		if err != nil {
			return err
		}
		relBreakpad, err := filepath.Rel(buildDir, bfr.breakpad)
		if err != nil {
			return err
		}
		out = append(out, binary{
			CPU:      cpu,
			Debug:    relDebug,
			BuildID:  bfr.ref.BuildID,
			Breakpad: relBreakpad,
			OS:       osName,
		})
	}
	file, err := osmisc.CreateFile(outputManifest, os.O_WRONLY)
	if err != nil {
		return fmt.Errorf("while writing json to %s: %w", outputManifest, err)
	}
	defer file.Close()
	enc := json.NewEncoder(file)
	enc.SetIndent("", "  ")
	if err = enc.Encode(out); err != nil {
		return fmt.Errorf("while writing json to %s: %w", outputManifest, err)
	}
	return nil
}

func main() {
	flag.Parse()
	log := logger.NewLogger(level, color.NewColor(colors), os.Stderr, os.Stderr, "")

	ctx, cancel := context.WithCancel(context.Background())
	ctx = logger.WithLogger(ctx, log)
	if buildDir == "" {
		log.Fatalf("-build-dir is required.")
	}
	if buildIDDirOut == "" {
		log.Fatalf("-build-id-dir-out is required.")
	}
	if buildIDDirIn == "" && debugArchive == "" {
		log.Fatalf("one of -build-id-dir-in or -debug-archive is required.")
	}
	if outputManifest == "" {
		log.Fatalf("-output-manifest is required.")
	}
	if depfile == "" {
		log.Fatalf("-depfile is required.")
	}

	// This action should rerun if the input .build-id directory or debug archive changes.
	var dep string
	if buildIDDirIn != "" {
		empty, err := osmisc.DirIsEmpty(buildIDDirIn)
		if err != nil {
			log.Fatalf("while checking if build-id-dir-in existed: %v", err)
		}
		if empty {
			if err := writeManifest(nil); err != nil {
				log.Fatalf("failed to write empty manifest: %v", err)
			}
			log.Tracef("%s does not exist, no work needed", buildIDDirIn)
			return
		}
		dep = buildIDDirIn
	} else {
		dep = debugArchive
	}
	relDep, err := filepath.Rel(buildDir, dep)
	if err != nil {
		log.Fatalf("failed to relativize %s: %v", dep, err)
	}
	depfileContents := fmt.Sprintf("%s: %s", outputManifest, relDep)
	if err := ioutil.WriteFile(depfile, []byte(depfileContents), os.ModePerm); err != nil {
		log.Fatalf("failed to write depfile: %v", err)
	}

	// If the input .build-id directory is empty and no debug archive is
	// provided, then there is no real work to do: bail.
	if debugArchive == "" {
		empty, err := osmisc.DirIsEmpty(buildIDDirIn)
		if err != nil {
			log.Fatalf("error in checking state of build-id dir: %v", err)
		}
		if empty {
			if err := writeManifest(nil); err != nil {
				log.Fatalf("failed to write empty manifest: %v", err)
			}
			log.Infof("build-id directory is empty; no work to do")
			return
		}
	}

	br := newBatchRunner(ctx, &subprocess.Runner{}, tasks)

	exists, err := osmisc.FileExists(debugArchive)
	if err != nil {
		log.Fatalf("while checking if archive existed: %v", err)
	}

	bfrs := []binaryRef{}

	log.Tracef("checking!")
	if exists {
		log.Tracef("archive existed")
		bfrs, err = unpack(ctx, br)
		if err != nil {
			log.Fatalf("%v", err)
		}
	} else {
		startDir, err := getStartDir()
		if err != nil {
			log.Fatalf("could not find the start dir: %v", err)
		}
		log.Tracef("found %s as start directory", startDir)
		dir, err := findBuildIDDir(ctx, startDir)
		if err != nil {
			log.Fatalf("while finding .build-id directory: %v", err)
		}
		bfrs, err = produceSymbols(ctx, dir, br)
	}

	// TODO: write the manifest to a tmp file and rename it into place.
	log.Tracef("writing manifest now")
	if err = writeManifest(bfrs); err != nil {
		log.Fatalf("%v", err)
	}

	log.Tracef("manifest written")

	// Before we wait on all the dump_syms calls we need to ensure that we time out eventully
	log.Tracef("waiting on all dump_syms calls to finish")
	if timeout != 0 {
		time.AfterFunc(timeout, cancel)
	}
	if err := br.Wait(); err != nil {
		log.Fatalf("while waiting on dump_syms to finish: %v", err)
	}
	log.Tracef("finished")
}
