package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
)

var (
	EnvFilePath = flag.String("f", ".env", "environment file")

	EnvVarRegex     = regexp.MustCompile(`^(.*?)=(.*?)$`)
	EnvCommentRegex = regexp.MustCompile(`^[ \t]*#.*?$`)
)

func main() {
	flag.Parse()

	envFile, err := os.Open(*EnvFilePath)
	if err != nil {
		panic(err)
	}
	defer envFile.Close()

	envVars := parseEnvFile(envFile)
	args := flag.Args()

	newEnv := append(os.Environ(), envVars...)

	if len(args) == 0 {
		for _, envVar := range newEnv {
			fmt.Println(envVar)
		}
		return
	}

	cmd := exec.Command(args[0], args[1:]...)
	cmd.Env = newEnv

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			os.Exit(exitErr.ExitCode())
			return
		} else {
			panic(err)
		}
	}
}

func parseEnvFile(r io.Reader) []string {
	env := make([]string, 0)
	s := bufio.NewScanner(r)
	l := 0
	for s.Scan() {
		l++

		matches := EnvVarRegex.FindStringSubmatch(s.Text())
		if len(matches) != 0 {
			key, value := matches[1], os.ExpandEnv(matches[2])
			env = append(env, fmt.Sprintf("%s=%s", key, value))
		} else if !EnvCommentRegex.MatchString(s.Text()) {
			panic(fmt.Sprintf("invalid env syntax on line %d", l))
		}
	}

	return env
}
