// Copyright 2014 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 profile

// Implements methods to filter samples from profiles.

import "regexp"

// FilterSamplesByName filters the samples in a profile and only keeps
// samples where at least one frame matches focus but none match ignore.
// Returns true is the corresponding regexp matched at least one sample.
func (p *Profile) FilterSamplesByName(focus, ignore, hide, show *regexp.Regexp) (fm, im, hm, hnm bool) {
	focusOrIgnore := make(map[uint64]bool)
	hidden := make(map[uint64]bool)
	for _, l := range p.Location {
		if ignore != nil && l.matchesName(ignore) {
			im = true
			focusOrIgnore[l.ID] = false
		} else if focus == nil || l.matchesName(focus) {
			fm = true
			focusOrIgnore[l.ID] = true
		}

		if hide != nil && l.matchesName(hide) {
			hm = true
			l.Line = l.unmatchedLines(hide)
			if len(l.Line) == 0 {
				hidden[l.ID] = true
			}
		}
		if show != nil {
			l.Line = l.matchedLines(show)
			if len(l.Line) == 0 {
				hidden[l.ID] = true
			} else {
				hnm = true
			}
		}
	}

	s := make([]*Sample, 0, len(p.Sample))
	for _, sample := range p.Sample {
		if focusedAndNotIgnored(sample.Location, focusOrIgnore) {
			if len(hidden) > 0 {
				var locs []*Location
				for _, loc := range sample.Location {
					if !hidden[loc.ID] {
						locs = append(locs, loc)
					}
				}
				if len(locs) == 0 {
					// Remove sample with no locations (by not adding it to s).
					continue
				}
				sample.Location = locs
			}
			s = append(s, sample)
		}
	}
	p.Sample = s

	return
}

// ShowFrom drops all stack frames above the highest matching frame and returns
// whether a match was found. If showFrom is nil it returns false and does not
// modify the profile.
//
// Example: consider a sample with frames [A, B, C, B], where A is the root.
// ShowFrom(nil) returns false and has frames [A, B, C, B].
// ShowFrom(A) returns true and has frames [A, B, C, B].
// ShowFrom(B) returns true and has frames [B, C, B].
// ShowFrom(C) returns true and has frames [C, B].
// ShowFrom(D) returns false and drops the sample because no frames remain.
func (p *Profile) ShowFrom(showFrom *regexp.Regexp) (matched bool) {
	if showFrom == nil {
		return false
	}
	// showFromLocs stores location IDs that matched ShowFrom.
	showFromLocs := make(map[uint64]bool)
	// Apply to locations.
	for _, loc := range p.Location {
		if filterShowFromLocation(loc, showFrom) {
			showFromLocs[loc.ID] = true
			matched = true
		}
	}
	// For all samples, strip locations after the highest matching one.
	s := make([]*Sample, 0, len(p.Sample))
	for _, sample := range p.Sample {
		for i := len(sample.Location) - 1; i >= 0; i-- {
			if showFromLocs[sample.Location[i].ID] {
				sample.Location = sample.Location[:i+1]
				s = append(s, sample)
				break
			}
		}
	}
	p.Sample = s
	return matched
}

// filterShowFromLocation tests a showFrom regex against a location, removes
// lines after the last match and returns whether a match was found. If the
// mapping is matched, then all lines are kept.
func filterShowFromLocation(loc *Location, showFrom *regexp.Regexp) bool {
	if m := loc.Mapping; m != nil && showFrom.MatchString(m.File) {
		return true
	}
	if i := loc.lastMatchedLineIndex(showFrom); i >= 0 {
		loc.Line = loc.Line[:i+1]
		return true
	}
	return false
}

// lastMatchedLineIndex returns the index of the last line that matches a regex,
// or -1 if no match is found.
func (loc *Location) lastMatchedLineIndex(re *regexp.Regexp) int {
	for i := len(loc.Line) - 1; i >= 0; i-- {
		if fn := loc.Line[i].Function; fn != nil {
			if re.MatchString(fn.Name) || re.MatchString(fn.Filename) {
				return i
			}
		}
	}
	return -1
}

// FilterTagsByName filters the tags in a profile and only keeps
// tags that match show and not hide.
func (p *Profile) FilterTagsByName(show, hide *regexp.Regexp) (sm, hm bool) {
	matchRemove := func(name string) bool {
		matchShow := show == nil || show.MatchString(name)
		matchHide := hide != nil && hide.MatchString(name)

		if matchShow {
			sm = true
		}
		if matchHide {
			hm = true
		}
		return !matchShow || matchHide
	}
	for _, s := range p.Sample {
		for lab := range s.Label {
			if matchRemove(lab) {
				delete(s.Label, lab)
			}
		}
		for lab := range s.NumLabel {
			if matchRemove(lab) {
				delete(s.NumLabel, lab)
			}
		}
	}
	return
}

// matchesName returns whether the location matches the regular
// expression. It checks any available function names, file names, and
// mapping object filename.
func (loc *Location) matchesName(re *regexp.Regexp) bool {
	for _, ln := range loc.Line {
		if fn := ln.Function; fn != nil {
			if re.MatchString(fn.Name) || re.MatchString(fn.Filename) {
				return true
			}
		}
	}
	if m := loc.Mapping; m != nil && re.MatchString(m.File) {
		return true
	}
	return false
}

// unmatchedLines returns the lines in the location that do not match
// the regular expression.
func (loc *Location) unmatchedLines(re *regexp.Regexp) []Line {
	if m := loc.Mapping; m != nil && re.MatchString(m.File) {
		return nil
	}
	var lines []Line
	for _, ln := range loc.Line {
		if fn := ln.Function; fn != nil {
			if re.MatchString(fn.Name) || re.MatchString(fn.Filename) {
				continue
			}
		}
		lines = append(lines, ln)
	}
	return lines
}

// matchedLines returns the lines in the location that match
// the regular expression.
func (loc *Location) matchedLines(re *regexp.Regexp) []Line {
	if m := loc.Mapping; m != nil && re.MatchString(m.File) {
		return loc.Line
	}
	var lines []Line
	for _, ln := range loc.Line {
		if fn := ln.Function; fn != nil {
			if !re.MatchString(fn.Name) && !re.MatchString(fn.Filename) {
				continue
			}
		}
		lines = append(lines, ln)
	}
	return lines
}

// focusedAndNotIgnored looks up a slice of ids against a map of
// focused/ignored locations. The map only contains locations that are
// explicitly focused or ignored. Returns whether there is at least
// one focused location but no ignored locations.
func focusedAndNotIgnored(locs []*Location, m map[uint64]bool) bool {
	var f bool
	for _, loc := range locs {
		if focus, focusOrIgnore := m[loc.ID]; focusOrIgnore {
			if focus {
				// Found focused location. Must keep searching in case there
				// is an ignored one as well.
				f = true
			} else {
				// Found ignored location. Can return false right away.
				return false
			}
		}
	}
	return f
}

// TagMatch selects tags for filtering
type TagMatch func(s *Sample) bool

// FilterSamplesByTag removes all samples from the profile, except
// those that match focus and do not match the ignore regular
// expression.
func (p *Profile) FilterSamplesByTag(focus, ignore TagMatch) (fm, im bool) {
	samples := make([]*Sample, 0, len(p.Sample))
	for _, s := range p.Sample {
		focused, ignored := true, false
		if focus != nil {
			focused = focus(s)
		}
		if ignore != nil {
			ignored = ignore(s)
		}
		fm = fm || focused
		im = im || ignored
		if focused && !ignored {
			samples = append(samples, s)
		}
	}
	p.Sample = samples
	return
}
