package display

/*
   The display package provides utilities for displaying Task Drivers in a
   human-friendly way.
*/

import (
	"fmt"
	"sort"
	"strings"
	"time"

	multierror "github.com/hashicorp/go-multierror"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/task_driver/go/db"
	"go.skia.org/infra/task_driver/go/td"
)

const (
	ELLIPSES        = "..."
	MAX_ERROR_CHARS = 1000
	MAX_ERROR_LINES = 20
)

// StepDisplay represents one step in a single run of a Task Driver.
type StepDisplay struct {
	*td.StepProperties
	Result   td.StepResult `json:"result,omitempty"`
	Errors   []string      `json:"errors,omitempty" go2ts:"ignorenil"`
	Started  time.Time     `json:"started,omitempty"`
	Finished time.Time     `json:"finished,omitempty"`

	Data []*db.StepData `json:"data,omitempty" go2ts:"ignorenil"`

	Steps []*StepDisplay `json:"steps,omitempty" go2ts:"ignorenil"`
}

// StepSlice is a helper for sorting.
type StepSlice []*StepDisplay

func (s StepSlice) Len() int {
	return len(s)
}

func (s StepSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s StepSlice) Less(i, j int) bool {
	return s[i].Started.Before(s[j].Started)
}

// TaskDriverRunDisplay represents a single run of a Task Driver.
type TaskDriverRunDisplay struct {
	Id         string            `json:"id" go2ts:"ignore"`
	Properties *td.RunProperties `json:"properties"`
	*StepDisplay
}

// TaskDriverForDisplay converts a db.TaskDriver into a TaskDriver, which is
// more human-friendly for display purposes.
func TaskDriverForDisplay(t *db.TaskDriverRun) (*TaskDriverRunDisplay, error) {
	rv := &TaskDriverRunDisplay{
		Id:         t.TaskId,
		Properties: t.Properties.Copy(),
	}

	// Create each StepDisplay.
	steps := make(map[string]*StepDisplay, len(t.Steps))
	var helper func(string) error
	helper = func(id string) error {
		if _, ok := steps[id]; ok {
			return nil
		}
		var errs error // Will hold non-critical errors.
		orig, ok := t.Steps[id]
		if !ok {
			// We should do our best to display anyway. Store the
			// error but keep going.
			errs = multierror.Append(errs, fmt.Errorf("Unknown step %s", id))
			return errs
		}
		var data []*db.StepData
		if len(orig.Data) > 0 {
			for _, d := range orig.Data {
				// TODO(borenet): We should try to deep-copy the data.
				data = append(data, d)
			}
		}
		var errorMsgs []string
		for _, errMsg := range orig.Errors {
			errorMsgs = append(errorMsgs, truncateError(errMsg))
		}
		s := &StepDisplay{
			StepProperties: orig.Properties.Copy(),
			Result:         orig.Result,
			Errors:         errorMsgs,
			Started:        orig.Started,
			Finished:       orig.Finished,
			Data:           data,
			Steps:          []*StepDisplay{},
		}
		if orig.Properties.Parent != "" {
			if err := helper(orig.Properties.Parent); err != nil {
				// We should do our best to display anyway.
				// Store the error but keep going.
				errs = multierror.Append(errs, err)
			}
			// Now parent should be in the steps map.
			parent, ok := steps[orig.Properties.Parent]
			if !ok {
				// If our parent isn't in the steps map, then
				// don't bother trying to display this step.
				return multierror.Append(errs, fmt.Errorf("Parent step %s is not present!", orig.Properties.Parent))
			}
			parent.Steps = append(parent.Steps, s)
		}
		steps[s.Id] = s
		return errs
	}
	for _, s := range t.Steps {
		if s.Properties != nil {
			if err := helper(s.Properties.Id); err != nil {
				// The error will be non-nil if any step is missing;
				// we want to do our best to display even if the pubsub
				// messages arrived out of order and we received a
				// message about a child step before its parent, so just
				// ignore the error.
				sklog.Infof("Error when gathering steps: %s", err)
				continue
			}
			if s.Properties.Id == td.StepIDRoot {
				rv.StepDisplay = steps[s.Properties.Id]
			}
		}
	}

	// Sort all steps by start time.
	var sortHelper func(*StepDisplay)
	sortHelper = func(s *StepDisplay) {
		sort.Sort(StepSlice(s.Steps))
		for _, child := range s.Steps {
			sortHelper(child)
		}
	}
	if rv.StepDisplay != nil {
		sortHelper(rv.StepDisplay)
	}

	return rv, nil
}

// truncateError shortens an error message, returning the last part, so as not
// to transfer giant logs to the client. There is an endpoint to retrieve a
// specific error which will return the whole thing.
func truncateError(err string) string {
	lines := strings.Split(err, "\n")
	// Logs often end in a newline; trim any empty line.
	if len(lines) > 0 {
		if lines[len(lines)-1] == "" {
			lines = lines[:len(lines)-1]
		}
	}
	if len(lines) > MAX_ERROR_LINES {
		lines = lines[len(lines)-MAX_ERROR_LINES:]
		lines[0] = ELLIPSES + lines[0]
	}
	rv := strings.Join(lines, "\n")
	if len(rv) > MAX_ERROR_CHARS {
		rv = ELLIPSES + rv[len(rv)-MAX_ERROR_CHARS+len(ELLIPSES):]
	}
	sklog.Infof("Truncating error message of length %d to %d", len(err), len(rv))
	return rv
}
