// Copyright 2015 The Vanadium 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 (
	"encoding/json"
	"fmt"
	"io"
	"runtime"
	"time"

	"v.io/v23/context"
	"v.io/x/lib/cmdline"
	"v.io/x/ref/lib/v23cmd"
	"v.io/x/ref/runtime/internal/rpc/stress/internal"
)

var (
	cpus        int
	payloadSize int
)

func init() {
	cmdLoadTest.Flags.DurationVar(&duration, "duration", 1*time.Minute, "duration of the test to run")
	cmdLoadTest.Flags.IntVar(&cpus, "cpu", 0, "number of cpu cores to use; if zero, use the number of servers to test")
	cmdLoadTest.Flags.IntVar(&payloadSize, "payload-size", 1000, "size of payload in bytes")
	cmdLoadTest.Flags.StringVar(&outFormat, "format", "text", "Stats output format; either text or json")
}

type loadStats struct {
	Iterations uint64
	MsecPerRpc float64
	Qps        float64
	QpsPerCore float64
}

var cmdLoadTest = &cmdline.Command{
	Runner:   v23cmd.RunnerFunc(runLoadTest),
	Name:     "load",
	Short:    "Run load test",
	Long:     "Run load test",
	ArgsName: "<server> ...",
	ArgsLong: "<server> ... A list of servers to connect to.",
}

func runLoadTest(ctx *context.T, env *cmdline.Env, args []string) error {
	if len(args) == 0 {
		return env.UsageErrorf("no server specified")
	}
	if outFormat != "text" && outFormat != "json" {
		return env.UsageErrorf("invalid output format: %s\n", outFormat)
	}

	cores := cpus
	if cores == 0 {
		cores = len(args)
	}
	runtime.GOMAXPROCS(cores)

	fmt.Fprintf(env.Stdout, "starting load test against %d server(s) using %d core(s)...\n", len(args), cores)
	fmt.Fprintf(env.Stdout, "payloadSize: %d, duration: %v\n", payloadSize, duration)

	start := time.Now()
	done := make(chan loadStats)
	for _, server := range args {
		go func(server string) {
			var stats loadStats

			start := time.Now()
			stats.Iterations = internal.CallEcho(ctx, server, payloadSize, duration)
			elapsed := time.Since(start)

			stats.Qps = float64(stats.Iterations) / elapsed.Seconds()
			stats.MsecPerRpc = 1000 / stats.Qps
			done <- stats
		}(server)
	}
	var merged loadStats
	for i := 0; i < len(args); i++ {
		stats := <-done
		merged.Iterations += stats.Iterations
		merged.MsecPerRpc += stats.MsecPerRpc
		merged.Qps += stats.Qps
	}
	merged.MsecPerRpc /= float64(len(args))
	merged.QpsPerCore = merged.Qps / float64(cores)
	elapsed := time.Since(start)
	fmt.Printf("done after %v\n", elapsed)
	return outLoadStats(env.Stdout, outFormat, "load stats:", &merged)
}

func outLoadStats(w io.Writer, format, title string, stats *loadStats) error {
	switch format {
	case "text":
		fmt.Fprintf(w, "%s\n", title)
		fmt.Fprintf(w, "\tnumber of RPCs:\t\t%d\n", stats.Iterations)
		fmt.Fprintf(w, "\tlatency (msec/rpc):\t%.2f\n", stats.MsecPerRpc)
		fmt.Fprintf(w, "\tqps:\t\t\t%.2f\n", stats.Qps)
		fmt.Fprintf(w, "\tqps/core:\t\t%.2f\n", stats.QpsPerCore)
	case "json":
		b, err := json.Marshal(stats)
		if err != nil {
			return err
		}
		fmt.Fprintf(w, "%s%s\n", title, b)
	default:
		return fmt.Errorf("invalid output format: %s\n", format)
	}
	return nil
}
