1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../../base-ui/BaseElement';
17import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie';
18import { procedurePool } from '../../database/Procedure';
19import { LitTable } from '../../../base-ui/table/lit-table';
20import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar';
21import '../../../base-ui/progress-bar/LitProgressBar';
22import { getDataNo } from './utils/Utils';
23import './TableNoData';
24import { TableNoData } from './TableNoData';
25import { TabCpuDetailsThreadsHtml } from './TabCpuDetailsThreads.html';
26
27@element('tab-cpu-details-threads')
28export class TabCpuDetailsThreads extends BaseElement {
29  private tableNoData: TableNoData | null | undefined;
30  private cpuDetailsThreadUsageTbl: LitTable | null | undefined;
31  private progress: LitProgressBar | null | undefined;
32  private cpuDetailsThreadPie: LitChartPie | null | undefined;
33  private data: Array<unknown> = [];
34  private cpuDetailsThreadSortColumn: string = '';
35  private sortType: number = 0;
36
37  initElements(): void {
38    this.tableNoData = this.shadowRoot!.querySelector<TableNoData>('#table-no-data');
39    this.progress = this.shadowRoot!.querySelector<LitProgressBar>('#loading');
40    this.cpuDetailsThreadPie = this.shadowRoot!.querySelector<LitChartPie>('#cpu-thread-chart-pie');
41    this.cpuDetailsThreadUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-cpu-usage');
42
43    this.shadowRoot!.querySelector<HTMLDivElement>('.cpu-thread-go-back')!.onclick = (e): void => {
44      if (!this.progress!.loading) {
45        this.parentNode!.querySelector<HTMLDivElement>('.d-box')!.style.display = 'flex';
46        this.setShow = false;
47      }
48    };
49
50    this.cpuDetailsThreadUsageTbl!.addEventListener('row-click', (evt: unknown): void => {
51      // @ts-ignore
52      let data = evt.detail.data;
53      data.isSelected = true;
54      // @ts-ignore
55      if ((evt.detail as unknown).callBack) {
56        // @ts-ignore
57        (evt.detail as unknown).callBack(true);
58      }
59    });
60
61    this.cpuDetailsThreadUsageTbl!.addEventListener('column-click', (evt: unknown): void => {
62      //@ts-ignore
63      this.cpuDetailsThreadSortColumn = evt.detail.key; //@ts-ignore
64      this.sortType = evt.detail.sort;
65      // @ts-ignore
66      this.sortByColumn(evt.detail);
67    });
68    this.cpuDetailsThreadUsageTbl!.addEventListener('row-hover', (evt: unknown): void => {
69      //@ts-ignore
70      if (evt.detail.data) {
71        //@ts-ignore
72        let data = evt.detail.data;
73        data.isHover = true; //@ts-ignore
74        if ((evt.detail as unknown).callBack) {
75          //@ts-ignore
76          (evt.detail as unknown).callBack(true);
77        }
78      }
79      this.cpuDetailsThreadPie?.showHover();
80    });
81  }
82
83  init(cpu: number, it: unknown): void {
84    this.shadowRoot!.querySelector<HTMLDivElement>('.cpu-thread-subheading')!.textContent =
85      //@ts-ignore
86      `Threads in Freq ${it.value}`;
87    this.progress!.loading = true;
88    procedurePool.submitWithName(
89      'logic0',
90      'scheduling-CPU Frequency Thread', //@ts-ignore
91      { cpu: cpu, freq: (it as unknown).value },
92      undefined,
93      (res: unknown): void => {
94        this.progress!.loading = false;
95        this.queryPieChartDataByType(res);
96      }
97    );
98  }
99
100  set setShow(v: boolean) {
101    if (v) {
102      this.style.display = 'flex';
103    } else {
104      this.clearData();
105      this.style.display = 'none';
106    }
107  }
108
109  queryPieChartDataByType(res: unknown): void {
110    //@ts-ignore
111    this.data = res || [];
112    this.data = getDataNo(this.data);
113    this.tableNoData!.noData = this.data.length === 0;
114    this.noData(this.data.length === 0);
115    this.cpuDetailsThreadPie!.config = {
116      appendPadding: 0,
117      data: this.data,
118      angleField: 'dur',
119      colorField: 'tName',
120      radius: 1,
121      label: {
122        type: 'outer',
123      },
124      tip: (obj): string => {
125        return `<div>
126                                <div>t_name:${
127          // @ts-ignore
128          obj.obj.tName
129          }</div> 
130                                <div>tid:${
131          // @ts-ignore
132          obj.obj.tid
133          }</div>
134                                <div>p_name:${
135          // @ts-ignore
136          obj.obj.pName
137          }</div>
138                                <div>p_pid:${
139          // @ts-ignore
140          obj.obj.pid
141          }</div>
142                                <div>duration:${
143          // @ts-ignore
144          obj.obj.durStr
145          }</div>
146                                <div>ratio:${
147          // @ts-ignore
148          obj.obj.ratio
149          }%</div>
150                            </div>
151                                `;
152      },
153      hoverHandler: (data): void => {
154        if (data) {
155          this.cpuDetailsThreadUsageTbl!.setCurrentHover(data);
156        } else {
157          this.cpuDetailsThreadUsageTbl!.mouseOut();
158        }
159      },
160      interactions: [
161        {
162          type: 'element-active',
163        },
164      ],
165    };
166    if (this.cpuDetailsThreadSortColumn !== '') {
167      this.sortByColumn({ key: this.cpuDetailsThreadSortColumn, sort: this.sortType });
168    } else {
169      this.cpuDetailsThreadUsageTbl!.recycleDataSource = this.data;
170    }
171    this.cpuDetailsThreadUsageTbl?.reMeauseHeight();
172  }
173
174  noData(value: boolean): void {
175    this.shadowRoot!.querySelector<HTMLDivElement>('.cpu-thread-chart-box')!.style.display = value ? 'none' : 'block';
176    this.shadowRoot!.querySelector<HTMLDivElement>('.cpu-thread-table-box')!.style.width = value ? '100%' : '60%';
177  }
178
179  clearData(): void {
180    this.cpuDetailsThreadPie!.dataSource = [];
181    this.cpuDetailsThreadUsageTbl!.recycleDataSource = [];
182    this.noData(false);
183  }
184
185  sortByColumn(detail: unknown): void {
186    // @ts-ignore
187    function compare(cpuDetailsThreadProperty, sort, type) {
188      return function (a: unknown, b: unknown) {
189        if (type === 'number') {
190          // @ts-ignore
191          return sort === 2
192            // @ts-ignore
193            ? parseFloat(b[cpuDetailsThreadProperty]) - parseFloat(a[cpuDetailsThreadProperty])
194            // @ts-ignore
195            : parseFloat(a[cpuDetailsThreadProperty]) - parseFloat(b[cpuDetailsThreadProperty]);
196        } else {
197          if (sort === 2) {
198            // @ts-ignore
199            return b[cpuDetailsThreadProperty].toString().localeCompare(a[cpuDetailsThreadProperty].toString());
200          } else {
201            // @ts-ignore
202            return a[cpuDetailsThreadProperty].toString().localeCompare(b[cpuDetailsThreadProperty].toString());
203          }
204        }
205      };
206    }
207
208    // @ts-ignore
209    if (detail.key === 'durStr') {
210      // @ts-ignore
211      detail.key = 'dur';
212      // @ts-ignore
213      this.data.sort(compare(detail.key, detail.sort, 'number'));
214    } else if (
215      // @ts-ignore
216      detail.key === 'value' ||
217      // @ts-ignore
218      detail.key === 'ratio' ||
219      // @ts-ignore
220      detail.key === 'index' ||
221      // @ts-ignore
222      detail.key === 'tid' ||
223      // @ts-ignore
224      detail.key === 'pid'
225    ) {
226      // @ts-ignore
227      this.data.sort(compare(detail.key, detail.sort, 'number'));
228    } else {
229      // @ts-ignore
230      this.data.sort(compare(detail.key, detail.sort, 'string'));
231    }
232    this.cpuDetailsThreadUsageTbl!.recycleDataSource = this.data;
233  }
234
235  initHtml(): string {
236    return TabCpuDetailsThreadsHtml;
237  }
238}
239