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

// +build appengine

package build

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"
	"sort"
	"strconv"

	"appengine"
	"appengine/datastore"
)

func init() {
	http.HandleFunc("/perf", perfChangesHandler)
}

// perfSummaryHandler draws the main benchmarking page.
func perfChangesHandler(w http.ResponseWriter, r *http.Request) {
	d := dashboardForRequest(r)
	c := d.Context(appengine.NewContext(r))

	page, _ := strconv.Atoi(r.FormValue("page"))
	if page < 0 {
		page = 0
	}

	pc, err := GetPerfConfig(c, r)
	if err != nil {
		logErr(w, r, err)
		return
	}

	commits, err := dashPerfCommits(c, page)
	if err != nil {
		logErr(w, r, err)
		return
	}

	// Fetch PerfResult's for the commits.
	var uiCommits []*perfChangesCommit
	rc := MakePerfResultCache(c, commits[0], false)

	// But first compare tip with the last release.
	if page == 0 {
		res0 := &PerfResult{CommitHash: knownTags[lastRelease]}
		if err := datastore.Get(c, res0.Key(c), res0); err != nil && err != datastore.ErrNoSuchEntity {
			logErr(w, r, fmt.Errorf("getting PerfResult: %v", err))
			return
		}
		if err != datastore.ErrNoSuchEntity {
			uiCom, err := handleOneCommit(pc, commits[0], rc, res0)
			if err != nil {
				logErr(w, r, err)
				return
			}
			uiCom.IsSummary = true
			uiCom.ParentHash = lastRelease
			uiCommits = append(uiCommits, uiCom)
		}
	}

	for _, com := range commits {
		uiCom, err := handleOneCommit(pc, com, rc, nil)
		if err != nil {
			logErr(w, r, err)
			return
		}
		uiCommits = append(uiCommits, uiCom)
	}

	p := &Pagination{}
	if len(commits) == commitsPerPage {
		p.Next = page + 1
	}
	if page > 0 {
		p.Prev = page - 1
		p.HasPrev = true
	}

	data := &perfChangesData{d, p, uiCommits}

	var buf bytes.Buffer
	if err := perfChangesTemplate.Execute(&buf, data); err != nil {
		logErr(w, r, err)
		return
	}

	buf.WriteTo(w)
}

func handleOneCommit(pc *PerfConfig, com *Commit, rc *PerfResultCache, baseRes *PerfResult) (*perfChangesCommit, error) {
	uiCom := new(perfChangesCommit)
	uiCom.Commit = com
	res1 := rc.Get(com.Num)
	for builder, benchmarks1 := range res1.ParseData() {
		for benchmark, data1 := range benchmarks1 {
			if benchmark != "meta-done" || !data1.OK {
				uiCom.NumResults++
			}
			if !data1.OK {
				v := new(perfChangesChange)
				v.diff = 10000
				v.Style = "fail"
				v.Builder = builder
				v.Link = fmt.Sprintf("log/%v", data1.Artifacts["log"])
				v.Val = builder
				v.Hint = builder
				if benchmark != "meta-done" {
					v.Hint += "/" + benchmark
				}
				m := findMetric(uiCom, "failure")
				m.BadChanges = append(m.BadChanges, v)
			}
		}
		res0 := baseRes
		if res0 == nil {
			var err error
			res0, err = rc.NextForComparison(com.Num, builder)
			if err != nil {
				return nil, err
			}
			if res0 == nil {
				continue
			}
		}
		changes := significantPerfChanges(pc, builder, res0, res1)
		changes = dedupPerfChanges(changes)
		for _, ch := range changes {
			v := new(perfChangesChange)
			v.Builder = builder
			v.Benchmark, v.Procs = splitBench(ch.Bench)
			v.diff = ch.Diff
			v.Val = fmt.Sprintf("%+.2f%%", ch.Diff)
			v.Hint = fmt.Sprintf("%v/%v", builder, ch.Bench)
			v.Link = fmt.Sprintf("perfdetail?commit=%v&commit0=%v&builder=%v&benchmark=%v", com.Hash, res0.CommitHash, builder, v.Benchmark)
			m := findMetric(uiCom, ch.Metric)
			if v.diff > 0 {
				v.Style = "bad"
				m.BadChanges = append(m.BadChanges, v)
			} else {
				v.Style = "good"
				m.GoodChanges = append(m.GoodChanges, v)
			}
		}
	}

	// Sort metrics and changes.
	for _, m := range uiCom.Metrics {
		sort.Sort(m.GoodChanges)
		sort.Sort(m.BadChanges)
	}
	sort.Sort(uiCom.Metrics)
	// Need at least one metric for UI.
	if len(uiCom.Metrics) == 0 {
		uiCom.Metrics = append(uiCom.Metrics, &perfChangesMetric{})
	}
	uiCom.Metrics[0].First = true
	return uiCom, nil
}

// Find builder-procs with the maximum absolute diff for every benchmark-metric, drop the rest.
func dedupPerfChanges(changes []*PerfChange) (deduped []*PerfChange) {
	maxDiff := make(map[string]float64)
	maxBench := make(map[string]string)
	// First, find the maximum.
	for _, ch := range changes {
		bench, _ := splitBench(ch.Bench)
		k := bench + "|" + ch.Metric
		v := ch.Diff
		if v < 0 {
			v = -v
		}
		if maxDiff[k] < v {
			maxDiff[k] = v
			maxBench[k] = ch.Builder + "|" + ch.Bench
		}
	}
	// Then, remove the rest.
	for _, ch := range changes {
		bench, _ := splitBench(ch.Bench)
		k := bench + "|" + ch.Metric
		if maxBench[k] == ch.Builder+"|"+ch.Bench {
			deduped = append(deduped, ch)
		}
	}
	return
}

func findMetric(c *perfChangesCommit, metric string) *perfChangesMetric {
	for _, m := range c.Metrics {
		if m.Name == metric {
			return m
		}
	}
	m := new(perfChangesMetric)
	m.Name = metric
	c.Metrics = append(c.Metrics, m)
	return m
}

type uiPerfConfig struct {
	Builders    []uiPerfConfigElem
	Benchmarks  []uiPerfConfigElem
	Metrics     []uiPerfConfigElem
	Procs       []uiPerfConfigElem
	CommitsFrom []uiPerfConfigElem
	CommitsTo   []uiPerfConfigElem
}

type uiPerfConfigElem struct {
	Name     string
	Selected bool
}

var perfChangesTemplate = template.Must(
	template.New("perf_changes.html").Funcs(tmplFuncs).ParseFiles("build/perf_changes.html"),
)

type perfChangesData struct {
	Dashboard  *Dashboard
	Pagination *Pagination
	Commits    []*perfChangesCommit
}

type perfChangesCommit struct {
	*Commit
	IsSummary  bool
	NumResults int
	Metrics    perfChangesMetricSlice
}

type perfChangesMetric struct {
	Name        string
	First       bool
	BadChanges  perfChangesChangeSlice
	GoodChanges perfChangesChangeSlice
}

type perfChangesChange struct {
	Builder   string
	Benchmark string
	Link      string
	Hint      string
	Style     string
	Val       string
	Procs     int
	diff      float64
}

type perfChangesMetricSlice []*perfChangesMetric

func (l perfChangesMetricSlice) Len() int      { return len(l) }
func (l perfChangesMetricSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l perfChangesMetricSlice) Less(i, j int) bool {
	if l[i].Name == "failure" || l[j].Name == "failure" {
		return l[i].Name == "failure"
	}
	return l[i].Name < l[j].Name
}

type perfChangesChangeSlice []*perfChangesChange

func (l perfChangesChangeSlice) Len() int      { return len(l) }
func (l perfChangesChangeSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l perfChangesChangeSlice) Less(i, j int) bool {
	vi, vj := l[i].diff, l[j].diff
	if vi > 0 && vj > 0 {
		return vi > vj
	} else if vi < 0 && vj < 0 {
		return vi < vj
	} else {
		panic("comparing positive and negative diff")
	}
}
