// Copyright 2022 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package report

import (
	"crypto/sha256"
	"encoding/binary"
	"fmt"

	"github.com/google/pprof/internal/measurement"
	"github.com/google/pprof/profile"
)

// StackSet holds a set of stacks corresponding to a profile.
//
// Slices in StackSet and the types it contains are always non-nil,
// which makes Javascript code that uses the JSON encoding less error-prone.
type StackSet struct {
	Total   int64         // Total value of the profile.
	Scale   float64       // Multiplier to generate displayed value
	Type    string        // Profile type. E.g., "cpu".
	Unit    string        // One of "B", "s", "GCU", or "" (if unknown)
	Stacks  []Stack       // List of stored stacks
	Sources []StackSource // Mapping from source index to info
}

// Stack holds a single stack instance.
type Stack struct {
	Value   int64 // Total value for all samples of this stack.
	Sources []int // Indices in StackSet.Sources (callers before callees).
}

// StackSource holds function/location info for a stack entry.
type StackSource struct {
	FullName   string
	FileName   string
	UniqueName string // Disambiguates functions with same names
	Inlined    bool   // If true this source was inlined into its caller

	// Alternative names to display (with decreasing lengths) to make text fit.
	// Guaranteed to be non-empty.
	Display []string

	// Places holds the list of stack slots where this source occurs.
	// In particular, if [a,b] is an element in Places,
	// StackSet.Stacks[a].Sources[b] points to this source.
	//
	// No stack will be referenced twice in the Places slice for a given
	// StackSource. In case of recursion, Places will contain the outer-most
	// entry in the recursive stack. E.g., if stack S has source X at positions
	// 4,6,9,10, the Places entry for X will contain [S,4].
	Places []StackSlot

	// Combined count of stacks where this source is the leaf.
	Self int64

	// Color number to use for this source.
	// Colors with high numbers than supported may be treated as zero.
	Color int
}

// StackSlot identifies a particular StackSlot.
type StackSlot struct {
	Stack int // Index in StackSet.Stacks
	Pos   int // Index in Stack.Sources
}

// Stacks returns a StackSet for the profile in rpt.
func (rpt *Report) Stacks() StackSet {
	// Get scale for converting to default unit of the right type.
	scale, unit := measurement.Scale(1, rpt.options.SampleUnit, "default")
	if unit == "default" {
		unit = ""
	}
	if rpt.options.Ratio > 0 {
		scale *= rpt.options.Ratio
	}
	s := &StackSet{
		Total:   rpt.total,
		Scale:   scale,
		Type:    rpt.options.SampleType,
		Unit:    unit,
		Stacks:  []Stack{},       // Ensure non-nil
		Sources: []StackSource{}, // Ensure non-nil
	}
	s.makeInitialStacks(rpt)
	s.fillPlaces()
	s.assignColors()
	return *s
}

func (s *StackSet) makeInitialStacks(rpt *Report) {
	type key struct {
		line    profile.Line
		inlined bool
	}
	srcs := map[key]int{} // Sources identified so far.
	seenFunctions := map[string]bool{}
	unknownIndex := 1
	getSrc := func(line profile.Line, inlined bool) int {
		k := key{line, inlined}
		if i, ok := srcs[k]; ok {
			return i
		}
		x := StackSource{Places: []StackSlot{}} // Ensure Places is non-nil
		if fn := line.Function; fn != nil {
			x.FullName = fn.Name
			x.FileName = fn.Filename
			if !seenFunctions[fn.Name] {
				x.UniqueName = fn.Name
				seenFunctions[fn.Name] = true
			} else {
				// Assign a different name so pivoting picks this function.
				x.UniqueName = fmt.Sprint(fn.Name, "#", fn.ID)
			}
		} else {
			x.FullName = fmt.Sprintf("?%d?", unknownIndex)
			x.UniqueName = x.FullName
			unknownIndex++
		}
		x.Inlined = inlined
		x.Display = shortNameList(x.FullName)
		s.Sources = append(s.Sources, x)
		srcs[k] = len(s.Sources) - 1
		return len(s.Sources) - 1
	}

	// Synthesized root location that will be placed at the beginning of each stack.
	s.Sources = []StackSource{{
		FullName: "root",
		Display:  []string{"root"},
		Places:   []StackSlot{},
	}}

	for _, sample := range rpt.prof.Sample {
		value := rpt.options.SampleValue(sample.Value)
		stack := Stack{Value: value, Sources: []int{0}} // Start with the root

		// Note: we need to reverse the order in the produced stack.
		for i := len(sample.Location) - 1; i >= 0; i-- {
			loc := sample.Location[i]
			for j := len(loc.Line) - 1; j >= 0; j-- {
				line := loc.Line[j]
				inlined := (j != len(loc.Line)-1)
				stack.Sources = append(stack.Sources, getSrc(line, inlined))
			}
		}

		leaf := stack.Sources[len(stack.Sources)-1]
		s.Sources[leaf].Self += value
		s.Stacks = append(s.Stacks, stack)
	}
}

func (s *StackSet) fillPlaces() {
	for i, stack := range s.Stacks {
		seenSrcs := map[int]bool{}
		for j, src := range stack.Sources {
			if seenSrcs[src] {
				continue
			}
			seenSrcs[src] = true
			s.Sources[src].Places = append(s.Sources[src].Places, StackSlot{i, j})
		}
	}
}

func (s *StackSet) assignColors() {
	// Assign different color indices to different packages.
	const numColors = 1048576
	for i, src := range s.Sources {
		pkg := packageName(src.FullName)
		h := sha256.Sum256([]byte(pkg))
		index := binary.LittleEndian.Uint32(h[:])
		s.Sources[i].Color = int(index % numColors)
	}
}
