// Copyright 2020 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 (
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// program represents an external program by its executable path.
type program struct {
	path string
}

// findProgram searches the directories in bin for the named program. It returns
// an error if the program cannot be found.
func findProgram(name string, bin []string) (program, error) {
	path, err := findFile(name, bin)
	return program{path}, err
}

// findFile searches the directories in dirs for the file with the given name.
// It returns the full path, or an error if the file cannot be found.
func findFile(name string, dirs []string) (string, error) {
	for _, dir := range dirs {
		path := filepath.Join(dir, name)
		if _, err := os.Stat(path); err == nil {
			return path, nil
		}
	}
	return "", fmt.Errorf("cannot find %s (searched in %s)", name, strings.Join(dirs, ", "))
}

/// runResult stores the result of running a program.
type runResult struct {
	// True if the exit code is zero, false otherwise.
	success bool
	// Standard output.
	stdout string
	// Standard error.
	stderr string
}

// normalErrorExitCode is the exit code indicating that a program failed in a
// normal or expected way. For example, fidlc exits with this code when it finds
// a syntax error. We conservatively assume this is the only nonzero exit code
// occurring under normal conditions, and that all others indicate an abnormal
// error, e.g. a segfault. This ensures that we never expose abnormal failures
// to the user. Instead, we log them and return 500 Internal Server Error.
//
// We choose the value 1 because this is used for general errors:
// https://fuchsia.dev/fuchsia-src/concepts/api/cli#execution_success_and_failure
// The rubric allows other exit codes too, so we might need to expand this in
// the future if fidlbolt uses programs that exit with codes besides 0 and 1.
const normalErrorExitCode = 1

// run runs a program with arguments. If it fails to launch or exits with a code
// other than 0 or normalErrorExitCode, returns an error. If ctx is cancelled
// while the program is running, stops the program and returns an error.
func (p program) run(ctx context.Context, arg ...string) (runResult, error) {
	cmd := exec.CommandContext(ctx, p.path, arg...)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	switch err := cmd.Run().(type) {
	case nil:
		return runResult{
			success: true,
			stdout:  stdout.String(),
			stderr:  stderr.String(),
		}, nil
	case *exec.ExitError:
		if err.ExitCode() != normalErrorExitCode {
			return runResult{}, p.augmentError(err, arg, stdout.String(), stderr.String())
		}
		return runResult{
			success: false,
			stdout:  stdout.String(),
			stderr:  stderr.String(),
		}, nil
	default:
		return runResult{}, err
	}
}

// runInfallible is like run, but for programs that are not expected to fail. It
// returns an error for any nonzero exit code, including normalErrorExitCode.
func (p program) runInfallible(ctx context.Context, arg ...string) (runResult, error) {
	cmd := exec.CommandContext(ctx, p.path, arg...)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	switch err := cmd.Run().(type) {
	case nil:
		return runResult{
			success: true,
			stdout:  stdout.String(),
			stderr:  stderr.String(),
		}, nil
	case *exec.ExitError:
		return runResult{}, p.augmentError(err, arg, stdout.String(), stderr.String())
	default:
		return runResult{}, err
	}
}

// augmentError adds diagnostic information to err.
func (p program) augmentError(err *exec.ExitError, args []string, stdout, stderr string) error {
	return fmt.Errorf(
		`%v
program: %v
args: %v
exit code: %d
--- begin stdout ---
%s
--- end stdout ---
--- begin stderr ---
%s
--- end stderr ---`, err, p.path, args, err.ExitCode(), stdout, stderr)
}

// A tempDir is temporary directory.
type tempDir struct {
	path string
}

// newTempDir creates a new temporary directory.
func newTempDir() (tempDir, error) {
	path, err := ioutil.TempDir("", "fidlbolt-")
	return tempDir{path}, err
}

// join returns a path inside the temporary directory.
func (d tempDir) join(elem ...string) string {
	elem = append([]string{d.path}, elem...)
	return filepath.Join(elem...)
}

// createFile creates a file in the temporary directory, writes content to it,
// and returns its path.
func (d tempDir) createFile(name, content string) (string, error) {
	f, err := os.Create(d.join(name))
	if err != nil {
		return "", err
	}
	defer f.Close()
	if _, err = f.WriteString(content); err != nil {
		return "", err
	}
	return f.Name(), nil
}

// readFile creates a response from a file in the temporary directory.
func (d tempDir) readFile(name string) (string, error) {
	b, err := ioutil.ReadFile(d.join(name))
	if err != nil {
		return "", err
	}
	return string(b), nil
}
