1package list
2
3import (
4	"fmt"
5	"io"
6	"strings"
7
8	"github.com/sensu/sensu-go/cli/elements/globals"
9	padUtf8 "github.com/willf/pad/utf8"
10)
11
12// StrTransform .. use to transform values; typically used to apply unicode colors to cells
13type StrTransform func(string) string
14
15// Config describes detail list
16type Config struct {
17	// Title that is displayed for the list of details
18	Title string
19	// TitleStyle formats the title; optional.
20	TitleStyle StrTransform
21	// RowFormatter transforms /all/ rows; optional.
22	RowFormatter StrTransform
23	// LabelStyle formats the name; optional.
24	LabelStyle StrTransform
25	// Rows describes all rows to display
26	Rows []*Row
27}
28
29// Row of data to display
30type Row struct {
31	// Label of the row
32	Label string
33	// Value to display
34	Value string
35}
36
37// Print (s) out details list given configuration data
38func Print(out io.Writer, cfg *Config) error {
39	listElem := newListElem(cfg)
40	return listElem.write(out)
41}
42
43type listElem struct {
44	title      string
45	titleStyle StrTransform
46	rows       []*rowElem
47}
48
49type rowElem struct {
50	label          string
51	labelStyle     StrTransform
52	labelMemo      string
53	value          string
54	valueFormatter StrTransform
55}
56
57func newListElem(cfg *Config) listElem {
58	writer := listElem{
59		title:      cfg.Title,
60		titleStyle: cfg.TitleStyle,
61	}
62
63	for _, row := range cfg.Rows {
64		writer.rows = append(writer.rows, &rowElem{
65			label:          row.Label,
66			labelStyle:     cfg.LabelStyle,
67			value:          row.Value,
68			valueFormatter: cfg.RowFormatter,
69		})
70	}
71
72	return writer
73}
74
75func (e *listElem) write(out io.Writer) error {
76	if err := e.writeTitle(out); err != nil {
77		return err
78	}
79	return e.writeRows(out)
80}
81
82func (e *listElem) writeTitle(out io.Writer) error {
83	transformer := defaultTitleStyle
84	if e.titleStyle != nil {
85		transformer = e.titleStyle
86	}
87
88	_, err := fmt.Fprintln(out, transformer(e.title))
89	return err
90}
91
92func (e *listElem) writeRows(out io.Writer) error {
93	labelLen := e.longestLabel()
94
95	for _, row := range e.rows {
96		if err := row.write(out, labelLen); err != nil {
97			return err
98		}
99	}
100	return nil
101}
102
103func (e *listElem) longestLabel() (max int) {
104	for _, row := range e.rows {
105		len := row.labelLen()
106		if len > max {
107			max = len
108		}
109	}
110	return
111}
112
113func (e *rowElem) write(out io.Writer, len int) error {
114	_, err := fmt.Fprintf(
115		out,
116		"%s%s\n",
117		padUtf8.Right(e.styledLabel(), len, " "),
118		e.formattedValue(),
119	)
120	return err
121}
122
123func (e *rowElem) styleLabel() string {
124	if e.labelStyle != nil {
125		return e.labelStyle(e.label)
126	}
127	return defaultLabelStyle(e.label)
128}
129
130func (e *rowElem) styledLabel() string {
131	if e.labelMemo == "" {
132		e.labelMemo = e.styleLabel()
133	}
134	return e.labelMemo
135}
136
137func (e *rowElem) labelLen() int {
138	return len(e.styledLabel())
139}
140
141func (e *rowElem) formattedValue() string {
142	if e.valueFormatter != nil {
143		return e.valueFormatter(e.value)
144	}
145	return e.value
146}
147
148// sets the title to bold and prepends '==='
149func defaultTitleStyle(title string) string {
150	return fmt.Sprintf("=== %s", globals.TitleStyle(title))
151}
152
153// appends a colon and a space
154func defaultLabelStyle(name string) string {
155	return fmt.Sprintf("%s: ", strings.Title(name))
156}
157