/*
	Periodically report the status of all attached Android devices to InfluxDB.
*/

package main

import (
	"encoding/json"
	"flag"
	"time"

	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/exec"
	"go.skia.org/infra/go/influxdb"
	"go.skia.org/infra/go/metrics2"
	"go.skia.org/infra/go/sklog"
)

const (
	MEASUREMENT = "android-stats"
)

var (
	frequency   = flag.String("frequency", "1m", "How often to send data.")
	local       = flag.Bool("local", false, "Whether or not we're running in local testing mode.")
	statsScript = flag.String("stats_script", "", "Script to run which generates stats.")

	influxHost     = flag.String("influxdb_host", influxdb.DEFAULT_HOST, "The InfluxDB hostname.")
	influxUser     = flag.String("influxdb_name", influxdb.DEFAULT_USER, "The InfluxDB username.")
	influxPassword = flag.String("influxdb_password", influxdb.DEFAULT_PASSWORD, "The InfluxDB password.")
	influxDatabase = flag.String("influxdb_database", influxdb.DEFAULT_DATABASE, "The InfluxDB database.")
)

// reportStats drills down recursively until it hits a non-map value,
// then reports that value with the measurement as given above, tags for device,
// serial, and stat name, which is composed of the remaining map keys, eg.
// device=Nexus_5X serial=002e3da61560d3d4 stat=battery-level
func reportStats(device, serial, stat string, val interface{}) {
	float, ok := val.(float64)
	if ok {
		tags := map[string]string{
			"device": device,
			"serial": serial,
			"stat":   stat,
		}
		sklog.Infof("%s %v = %v", MEASUREMENT, tags, float)
		metrics2.GetFloat64Metric(MEASUREMENT, map[string]string{}).Update(float)
		return
	}
	m, ok := val.(map[string]interface{})
	if ok {
		for k, v := range m {
			reportStats(device, serial, stat+"-"+k, v)
		}
	}
}

// generateStats runs the statistics generation script, parses its output, and
// reports the data into InfluxDB.
//
// The script produces data in this format:
// {
//   "Nexus_5X": {
//     "002e3da61560d3d4": {
//       "battery": {
//         "ac": 0,
//         "health": 2,
//         "level": 100,
//         "max": 500000,
//         "present": 1,
//         "status": 5,
//         "temp": 282,
//         "usb": 1,
//         "voltage": 4311,
//         "wireless": 0
//       },
//       "temperature": 28.0
//     }
//   }
// }
//
func generateStats() error {
	output, err := exec.RunSimple(*statsScript)
	if err != nil {
		return err
	}

	res := map[string]map[string]map[string]interface{}{}
	if err := json.Unmarshal([]byte(output), &res); err != nil {
		return err
	}

	for device, deviceStats := range res {
		for serial, statMap := range deviceStats {
			for stat, val := range statMap {
				reportStats(device, serial, stat, val)
			}
		}
	}

	return nil
}

func main() {
	defer common.LogPanic()
	common.InitWithMetrics2("android_stats", influxHost, influxUser, influxPassword, influxDatabase, local)

	if *statsScript == "" {
		sklog.Fatal("You must provide --stats_script.")
	}

	pollFreq, err := time.ParseDuration(*frequency)
	if err != nil {
		sklog.Fatalf("Invalid value for frequency %q: %s", *frequency, err)
	}

	if err := generateStats(); err != nil {
		sklog.Fatal(err)
	}
	for _ = range time.Tick(pollFreq) {
		if err := generateStats(); err != nil {
			sklog.Error(err)
		}
	}
}
