1import { DataFrame, PanelData, Field, getFieldDisplayName, ReducerID } from '@grafana/data';
2import {
3  getColorDimension,
4  getScaledDimension,
5  getTextDimension,
6  getResourceDimension,
7  ColorDimensionConfig,
8  DimensionSupplier,
9  ResourceDimensionConfig,
10  ScaleDimensionConfig,
11  TextDimensionConfig,
12} from 'app/features/dimensions';
13import { config } from '@grafana/runtime';
14
15export function getColorDimensionFromData(
16  data: PanelData | undefined,
17  cfg: ColorDimensionConfig
18): DimensionSupplier<string> {
19  if (data?.series && cfg.field) {
20    for (const frame of data.series) {
21      const d = getColorDimension(frame, cfg, config.theme2);
22      if (!d.isAssumed || data.series.length === 1) {
23        return d;
24      }
25    }
26  }
27  return getColorDimension(undefined, cfg, config.theme2);
28}
29
30export function getScaleDimensionFromData(
31  data: PanelData | undefined,
32  cfg: ScaleDimensionConfig
33): DimensionSupplier<number> {
34  if (data?.series && cfg.field) {
35    for (const frame of data.series) {
36      const d = getScaledDimension(frame, cfg);
37      if (!d.isAssumed || data.series.length === 1) {
38        return d;
39      }
40    }
41  }
42  return getScaledDimension(undefined, cfg);
43}
44
45export function getResourceDimensionFromData(
46  data: PanelData | undefined,
47  cfg: ResourceDimensionConfig
48): DimensionSupplier<string> {
49  if (data?.series && cfg.field) {
50    for (const frame of data.series) {
51      const d = getResourceDimension(frame, cfg);
52      if (!d.isAssumed || data.series.length === 1) {
53        return d;
54      }
55    }
56  }
57  return getResourceDimension(undefined, cfg);
58}
59
60export function getTextDimensionFromData(
61  data: PanelData | undefined,
62  cfg: TextDimensionConfig
63): DimensionSupplier<string> {
64  if (data?.series && cfg.field) {
65    for (const frame of data.series) {
66      const d = getTextDimension(frame, cfg);
67      if (!d.isAssumed || data.series.length === 1) {
68        return d;
69      }
70    }
71  }
72  return getTextDimension(undefined, cfg);
73}
74
75export function findField(frame?: DataFrame, name?: string): Field | undefined {
76  if (!frame || !name?.length) {
77    return undefined;
78  }
79
80  for (const field of frame.fields) {
81    if (name === field.name) {
82      return field;
83    }
84    const disp = getFieldDisplayName(field, frame);
85    if (name === disp) {
86      return field;
87    }
88  }
89  return undefined;
90}
91
92export function findFieldIndex(frame?: DataFrame, name?: string): number | undefined {
93  if (!frame || !name?.length) {
94    return undefined;
95  }
96
97  for (let i = 0; i < frame.fields.length; i++) {
98    const field = frame.fields[i];
99    if (name === field.name) {
100      return i;
101    }
102    const disp = getFieldDisplayName(field, frame);
103    if (name === disp) {
104      return i;
105    }
106  }
107  return undefined;
108}
109
110export function getLastNotNullFieldValue<T>(field: Field): T {
111  const calcs = field.state?.calcs;
112  if (calcs) {
113    const v = calcs[ReducerID.lastNotNull];
114    if (v != null) {
115      return v as T;
116    }
117  }
118
119  const data = field.values;
120  let idx = data.length - 1;
121  while (idx >= 0) {
122    const v = data.get(idx--);
123    if (v != null) {
124      return v;
125    }
126  }
127  return undefined as any;
128}
129