// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The expvar package provides a standardized interface to public variables,
// such as operation counters in servers. It exposes these variables via
// HTTP at /debug/vars in JSON format.
//
// Operations to set or modify these public variables are atomic.
//
// In addition to adding the HTTP handler, this package registers the
// following variables:
//
//	cmdline   os.Args
//	memstats  runtime.Memstats
//
// The package is sometimes only imported for the side effect of
// registering its HTTP handler and the above variables.  To use it
// this way, simply link this package into your program:
//	import _ "expvar"
//
package expvar

import (
	"bytes"
	"fmt"
	"http"
	"json"
	"log"
	"os"
	"runtime"
	"strconv"
	"sync"
)

// Var is an abstract type for all exported variables.
type Var interface {
	String() string
}

// Int is a 64-bit integer variable, and satisfies the Var interface.
type Int struct {
	i  int64
	mu sync.Mutex
}

func (v *Int) String() string { return strconv.Itoa64(v.i) }

func (v *Int) Add(delta int64) {
	v.mu.Lock()
	defer v.mu.Unlock()
	v.i += delta
}

func (v *Int) Set(value int64) {
	v.mu.Lock()
	defer v.mu.Unlock()
	v.i = value
}

// Map is a string-to-Var map variable, and satisfies the Var interface.
type Map struct {
	m  map[string]Var
	mu sync.Mutex
}

// KeyValue represents a single entry in a Map.
type KeyValue struct {
	Key   string
	Value Var
}

func (v *Map) String() string {
	v.mu.Lock()
	defer v.mu.Unlock()
	b := new(bytes.Buffer)
	fmt.Fprintf(b, "{")
	first := true
	for key, val := range v.m {
		if !first {
			fmt.Fprintf(b, ", ")
		}
		fmt.Fprintf(b, "\"%s\": %v", key, val.String())
		first = false
	}
	fmt.Fprintf(b, "}")
	return b.String()
}

func (v *Map) Init() *Map {
	v.m = make(map[string]Var)
	return v
}

func (v *Map) Get(key string) Var {
	v.mu.Lock()
	defer v.mu.Unlock()
	return v.m[key]
}

func (v *Map) Set(key string, av Var) {
	v.mu.Lock()
	defer v.mu.Unlock()
	v.m[key] = av
}

func (v *Map) Add(key string, delta int64) {
	v.mu.Lock()
	defer v.mu.Unlock()
	av, ok := v.m[key]
	if !ok {
		av = new(Int)
		v.m[key] = av
	}

	// Add to Int; ignore otherwise.
	if iv, ok := av.(*Int); ok {
		iv.Add(delta)
	}
}

// TODO(rsc): Make sure map access in separate thread is safe.
func (v *Map) iterate(c chan<- KeyValue) {
	for k, v := range v.m {
		c <- KeyValue{k, v}
	}
	close(c)
}

func (v *Map) Iter() <-chan KeyValue {
	c := make(chan KeyValue)
	go v.iterate(c)
	return c
}

// String is a string variable, and satisfies the Var interface.
type String struct {
	s string
}

func (v *String) String() string { return strconv.Quote(v.s) }

func (v *String) Set(value string) { v.s = value }

// IntFunc wraps a func() int64 to create a value that satisfies the Var interface.
// The function will be called each time the Var is evaluated.
type IntFunc func() int64

func (v IntFunc) String() string { return strconv.Itoa64(v()) }

// StringFunc wraps a func() string to create value that satisfies the Var interface.
// The function will be called each time the Var is evaluated.
type StringFunc func() string

func (f StringFunc) String() string { return strconv.Quote(f()) }


// All published variables.
var vars map[string]Var = make(map[string]Var)
var mutex sync.Mutex

// Publish declares an named exported variable. This should be called from a
// package's init function when it creates its Vars. If the name is already
// registered then this will log.Panic.
func Publish(name string, v Var) {
	mutex.Lock()
	defer mutex.Unlock()
	if _, existing := vars[name]; existing {
		log.Panicln("Reuse of exported var name:", name)
	}
	vars[name] = v
}

// Get retrieves a named exported variable.
func Get(name string) Var {
	return vars[name]
}

// RemoveAll removes all exported variables.
// This is for tests; don't call this on a real server.
func RemoveAll() {
	mutex.Lock()
	defer mutex.Unlock()
	vars = make(map[string]Var)
}

// Convenience functions for creating new exported variables.

func NewInt(name string) *Int {
	v := new(Int)
	Publish(name, v)
	return v
}

func NewMap(name string) *Map {
	v := new(Map).Init()
	Publish(name, v)
	return v
}

func NewString(name string) *String {
	v := new(String)
	Publish(name, v)
	return v
}

// TODO(rsc): Make sure map access in separate thread is safe.
func iterate(c chan<- KeyValue) {
	for k, v := range vars {
		c <- KeyValue{k, v}
	}
	close(c)
}

func Iter() <-chan KeyValue {
	c := make(chan KeyValue)
	go iterate(c)
	return c
}

func expvarHandler(w http.ResponseWriter, r *http.Request) {
	w.SetHeader("content-type", "application/json; charset=utf-8")
	fmt.Fprintf(w, "{\n")
	first := true
	for name, value := range vars {
		if !first {
			fmt.Fprintf(w, ",\n")
		}
		first = false
		fmt.Fprintf(w, "%q: %s", name, value)
	}
	fmt.Fprintf(w, "\n}\n")
}

func memstats() string {
	b, _ := json.MarshalIndent(&runtime.MemStats, "", "\t")
	return string(b)
}

func cmdline() string {
	b, _ := json.Marshal(os.Args)
	return string(b)
}

func init() {
	http.Handle("/debug/vars", http.HandlerFunc(expvarHandler))
	Publish("cmdline", StringFunc(cmdline))
	Publish("memstats", StringFunc(memstats))
}
