// Copyright 2023 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.

package traceviewer

import (
	
	
	
	
	
)

// TimeHistogram is an high-dynamic-range histogram for durations.
type TimeHistogram struct {
	Count                int
	Buckets              []int
	MinBucket, MaxBucket int
}

// Five buckets for every power of 10.
var logDiv = math.Log(math.Pow(10, 1.0/5))

// Add adds a single sample to the histogram.
func ( *TimeHistogram) ( time.Duration) {
	var  int
	if  > 0 {
		 = int(math.Log(float64()) / logDiv)
	}
	if len(.Buckets) <=  {
		.Buckets = append(.Buckets, make([]int, -len(.Buckets)+1)...)
		.Buckets = .Buckets[:cap(.Buckets)]
	}
	.Buckets[]++
	if  < .MinBucket || .MaxBucket == 0 {
		.MinBucket = 
	}
	if  > .MaxBucket {
		.MaxBucket = 
	}
	.Count++
}

// BucketMin returns the minimum duration value for a provided bucket.
func ( *TimeHistogram) ( int) time.Duration {
	return time.Duration(math.Exp(float64() * logDiv))
}

// ToHTML renders the histogram as HTML.
func ( *TimeHistogram) ( func(,  time.Duration) string) template.HTML {
	if  == nil || .Count == 0 {
		return template.HTML("")
	}

	const  = 400

	 := 0
	for ,  := range .Buckets {
		if  >  {
			 = 
		}
	}

	 := new(strings.Builder)
	fmt.Fprintf(, `<table>`)
	for  := .MinBucket;  <= .MaxBucket; ++ {
		// Tick label.
		if .Buckets[] > 0 {
			fmt.Fprintf(, `<tr><td class="histoTime" align="right"><a href=%s>%s</a></td>`, (.BucketMin(), .BucketMin(+1)), .BucketMin())
		} else {
			fmt.Fprintf(, `<tr><td class="histoTime" align="right">%s</td>`, .BucketMin())
		}
		// Bucket bar.
		 := .Buckets[] *  / 
		fmt.Fprintf(, `<td><div style="width:%dpx;background:blue;position:relative">&nbsp;</div></td>`, )
		// Bucket count.
		fmt.Fprintf(, `<td align="right"><div style="position:relative">%d</div></td>`, .Buckets[])
		fmt.Fprintf(, "</tr>\n")

	}
	// Final tick label.
	fmt.Fprintf(, `<tr><td align="right">%s</td></tr>`, .BucketMin(.MaxBucket+1))
	fmt.Fprintf(, `</table>`)
	return template.HTML(.String())
}