package subcmd

import (
	"context"
	"flag"
	"log"
	"net"
	"net/http"

	"code.justin.tv/beefcake/server/internal/beefcakeserver"
	"code.justin.tv/beefcake/server/internal/client"
	"github.com/google/subcommands"
)

// Serve the twirp server in the foreground
type Serve struct {
	Logger *log.Logger

	addr string
	env  string
}

// Name implements subcommands
func (cmd Serve) Name() string {
	return "serve"
}

// Synopsis implements subcommands
func (cmd Serve) Synopsis() string {
	return "serve beefcake"
}

// Usage implements subcommands
func (cmd Serve) Usage() string {
	return `serve -addr [addr]

  Example: Listen on :8080.

    serve -addr :8080

`
}

// SetFlags implements subcommands
func (cmd *Serve) SetFlags(f *flag.FlagSet) {
	f.StringVar(&cmd.addr, "addr", "", "address to serve on.")
	f.StringVar(&cmd.env, "env", "", "env to serve.")
}

// Execute implements subcommands
func (cmd Serve) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
	if err := cmd.execute(ctx); err != nil {
		cmd.Logger.Print(err.Error())
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}

func (cmd Serve) execute(ctx context.Context) error {
	netListener, err := net.Listen("tcp", cmd.addr)
	if err != nil {
		return err
	}

	clientLoader, err := client.EnvironmentLoader(cmd.env)
	if err != nil {
		return err
	}

	handler, err := beefcakeserver.New(clientLoader)
	if err != nil {
		return err
	}

	cmd.Logger.Printf("Serving on: %s", cmd.addr)
	return http.Serve(netListener, handler)
}
