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

package main

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

	"google.golang.org/appengine"
	"google.golang.org/appengine/datastore"
)

// perfSummaryHandler draws the main benchmarking page.
func perfChangesHandler(w http.ResponseWriter, r *http.Request) {
	d := goDash
	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(templateFile("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")
	}
}
