package main

import (
	"os"
	"os/user"
	"runtime"
	"strings"

	log "github.com/Sirupsen/logrus"
	shellquote "github.com/kballard/go-shellquote"
	"github.com/pkg/errors"
	"github.com/stvp/rollbar"
	"github.com/urfave/cli"
	"google.golang.org/grpc/grpclog"

	"code.justin.tv/dta/euls"
)

const (
	identityPoolID       = "us-east-1:beb102e6-b612-49aa-925a-15769fc2e048"
	accountID            = "043714768218"
	mobileAnalyticsAppID = "a2e882c6c3f34f4b89f12a50e6a063fa"
	rollbarToken         = "6d514565627e4bf796840d9e47c9d40f"
)

var (
	// GitCommit at build time
	GitCommit string
	// Build is the time of the build
	Build string

	app = cli.NewApp()
)

func init() {
	app.Name = "rpstool"
	app.Usage = "cli client for metric service"
	app.Version = strings.Join([]string{GitCommit, Build, runtime.Version()}, ".")
	app.HelpName = "rpstool"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "rps-addr",
			Value:  "rockpaperscissors.internal.justin.tv:80",
			EnvVar: "RPS_ADDR",
		},
		cli.BoolFlag{
			Name: "verbose",
		},
	}
	app.Before = func(c *cli.Context) error {
		if !c.GlobalBool("verbose") {
			log.SetLevel(log.ErrorLevel)
		}
		return nil
	}

	grpclog.SetLogger(log.StandardLogger())
	euls.SetLogger(log.StandardLogger())

	rollbar.Token = rollbarToken
	rollbar.Environment = app.Name
}

func newEulsClient() euls.Client {
	username := "unknown"
	usr, err := user.Current()
	if err == nil {
		username = usr.Username
	}

	config := &euls.Config{
		AccountID:      accountID,
		IdentityPoolID: identityPoolID,
		AppID:          mobileAnalyticsAppID,
		Client: euls.ClientContext{
			ClientID:       username,
			AppTitle:       app.Name,
			AppVersionName: app.Version,
		},
	}
	client, err := euls.NewAsyncClient(config)
	if err != nil {
		log.Warn(err)
		client, _ = euls.NewNoopClient(config)
	}
	return client
}

func reportPanicToRollbar() {
	if r := recover(); r != nil {
		err, ok := r.(error)
		if !ok {
			err = errors.Errorf("panic: %v", r)
		}
		rollbar.ErrorWithStackSkip(rollbar.CRIT, err, 3,
			&rollbar.Field{Name: "version", Data: app.Version})
		panic(r)
	}
}

func main() {
	defer rollbar.Wait()
	defer reportPanicToRollbar()

	eulsClient := newEulsClient()
	if err := eulsClient.StartSession(); err != nil {
		log.Warn(err)
	}
	defer func() {
		if err := eulsClient.StopSession(); err != nil {
			log.Warn(err)
		}
	}()

	argsStr := shellquote.Join(os.Args[1:]...)
	if err := eulsClient.PutEvent("run", map[string]*string{"args": &argsStr}, nil); err != nil {
		log.Warn(err)
	}

	err := app.Run(os.Args)
	if err != nil {
		errStr := err.Error()
		if putErr := eulsClient.PutEvent("error", map[string]*string{"error": &errStr}, nil); putErr != nil {
			log.Warn(putErr)
		}
		log.Fatal(err)
	}
}
