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 '../../../base-ui/radiobox/LitRadioBox';
18import { LitRadioBox } from '../../../base-ui/radiobox/LitRadioBox';
19import '../../../base-ui/slider/LitSlider';
20import { LitSlider } from '../../../base-ui/slider/LitSlider';
21import '../../../base-ui/popover/LitPopover';
22import { info } from '../../../log/Log';
23import { SpApplication } from '../../SpApplication';
24import { NUM_200, NUM_30, NUM_3600, NUM_60, NUM_64 } from '../../bean/NumBean';
25import { SpRecordSettingHtml } from './SpRecordSetting.html';
26
27@element('record-setting')
28export class SpRecordSetting extends BaseElement {
29  private memoryBufferSlider: LitSlider | undefined;
30  private maxDurationSliders: LitSlider | undefined;
31  private radioBox: LitRadioBox | undefined;
32  private longTraceRadio: LitRadioBox | undefined;
33  private bufferNumber: HTMLElement | undefined;
34  private durationNumber: HTMLElement | undefined;
35  private outputPath: HTMLInputElement | undefined;
36  private lastMemoryValue: string | undefined;
37  private lastDurationValue: string | undefined;
38  private maxSizeInput: HTMLInputElement | undefined;
39  isRecordTemplate: boolean = false;
40
41  get longTraceSingleFileMaxSize(): number {
42    let maxFileSizeEl = this.shadowRoot?.querySelector<HTMLInputElement>('.max_size_result');
43    if (maxFileSizeEl) {
44      return Number(maxFileSizeEl.value);
45    }
46    return NUM_200;
47  }
48
49  get recordMod(): boolean {
50    if (this.radioBox) {
51      return this.radioBox.checked;
52    }
53    return false;
54  }
55
56  get longOutPath(): string {
57    if (this.outputPath && this.outputPath.value !== '' && this.outputPath.value !== 'long_trace') {
58      return `/data/local/tmp/${this.outputPath.value}/`;
59    }
60    return '/data/local/tmp/long_trace/';
61  }
62
63  get output(): string {
64    if (SpApplication.isLongTrace && !this.isRecordTemplate) {
65      if (this.outputPath && this.outputPath.value !== 'long_trace/' && this.outputPath.value !== '') {
66        return `/data/local/tmp/${this.outputPath.value}/hiprofiler_data.htrace`;
67      }
68      return '/data/local/tmp/long_trace/hiprofiler_data.htrace';
69    } else {
70      if (this.outputPath && this.outputPath.value !== '') {
71        return `/data/local/tmp/${this.outputPath.value}`;
72      }
73      return '/data/local/tmp/hiprofiler_data.htrace';
74    }
75  }
76
77  get bufferSize(): number {
78    if (this.bufferNumber?.hasAttribute('percent')) {
79      info('bufferSize  is : ', this.bufferNumber!.getAttribute('percent'));
80      return Number(this.bufferNumber!.getAttribute('percent'));
81    }
82    return NUM_64;
83  }
84
85  get maxDur(): number {
86    if (this.durationNumber?.hasAttribute('percent')) {
87      info('maxDur  is : ', this.durationNumber!.getAttribute('percent'));
88      return Number(this.durationNumber!.getAttribute('percent'));
89    }
90    return NUM_30;
91  }
92
93  resetValue(): void {
94    let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement;
95    let parentElement = this.memoryBufferSlider!.parentNode as Element;
96    if (bufferInput.style.color !== 'var(--dark-color1,#000000)' && this.lastMemoryValue) {
97      bufferInput.value = `${this.lastMemoryValue}`;
98      this.memoryBufferSlider!.percent = `${this.lastMemoryValue}`;
99      this.memoryBufferSlider!.sliderStyle = {
100        minRange: 4,
101        maxRange: 512,
102        defaultValue: `${this.lastMemoryValue}`,
103        resultUnit: 'MB',
104        stepSize: 2,
105        lineColor: 'var(--dark-color3,#46B1E3)',
106        buttonColor: '#999999',
107      };
108      parentElement.setAttribute('percent', `${this.lastMemoryValue}`);
109      this.lastMemoryValue = `${this.lastMemoryValue}`;
110      bufferInput.style.color = 'var(--dark-color1,#000000)';
111    }
112
113    let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement;
114    let durationEl = this.maxDurationSliders!.parentNode as Element;
115    if (durationInput.style.color !== 'var(--dark-color1,#000000)' && this.lastDurationValue) {
116      durationInput.style.color = 'var(--dark-color1,#000000)';
117      let durationList = this.lastDurationValue.split(':');
118      let resultDuration =
119        Number(durationList[0]) * NUM_3600 + Number(durationList[1]) * NUM_60 + Number(durationList[2]);
120      durationInput.value = this.lastDurationValue;
121      this.maxDurationSliders!.sliderStyle = {
122        minRange: 10,
123        maxRange: 3600,
124        defaultValue: this.lastDurationValue!,
125        resultUnit: 'h:m:s',
126        stepSize: 1,
127        lineColor: 'var(--dark-color4,#61CFBE)',
128        buttonColor: '#999999',
129      };
130      durationEl.setAttribute('percent', resultDuration.toString());
131    }
132  }
133
134  initElements(): void {
135    this.bufferNumber = this.shadowRoot?.querySelector('.buffer-size') as HTMLElement;
136    this.durationNumber = this.shadowRoot?.querySelector('.max-duration') as HTMLElement;
137    let inputs = this.shadowRoot?.querySelectorAll('input');
138    inputs!.forEach((item) => {
139      item.addEventListener('keydown', (ev) => {
140        // @ts-ignore
141        if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') {
142          ev.preventDefault();
143        }
144      });
145    });
146    this.shadowRoot?.querySelectorAll<HTMLButtonElement>('.MenuButton').forEach((button) => {
147      button!.addEventListener('mouseenter', () => {
148        button.style.backgroundColor = '#EFEFEF';
149      });
150      button!.addEventListener('mouseout', () => {
151        button.style.backgroundColor = '#E4E3E9';
152      });
153    });
154    this.radioBox = this.shadowRoot?.querySelector('#litradio') as LitRadioBox;
155    this.addLongTraceConfig();
156    this.initLitSlider();
157  }
158
159  private getLongTraceSlideHTML(): string {
160    return `<div class="max-single-file-size">
161        <div class="record-title">
162            <span class="record-mode" >Single file max size</span>
163            <span class="record-prompt"> (single file size after cutting is 200MB - 300MB) </span>
164        </div>
165        <lit-slider id="max-size" defaultColor="var(--dark-color4,#86C5E3)" open dir="right">
166        </lit-slider>
167        <div class='resultValue'>
168            <input class="max_size_result" type="text" value = '200' 
169            oninput="if(this.value > 300){this.value = '300'} 
170            if (this.value < 200) { 
171              this.parentElement.style.border = '1px solid red'
172            } else { 
173              this.parentElement.style.border = '1px solid #ccc'
174            } 
175            if (this.value > 0 && this.value.toString().startsWith('0')){
176              this.value = Number(this.value) 
177            }" >
178            <span style="text-align: center; margin: 8px 8px 8px 0"> MB </span>
179        </div>
180      </div>`;
181  }
182
183  private addLongTraceConfig(): void {
184    this.longTraceRadio = this.shadowRoot?.querySelector('#longTraceRadio') as LitRadioBox;
185    this.outputPath = this.shadowRoot?.querySelector<HTMLInputElement>('#trace_path') as HTMLInputElement;
186    let rootEl = this.shadowRoot?.querySelector('.root') as HTMLDivElement;
187    let longTraceMaxSlide = document.createElement('div');
188    longTraceMaxSlide.innerHTML = this.getLongTraceSlideHTML();
189    let maxSingleFileEl = longTraceMaxSlide.querySelector<HTMLDivElement>('.max-single-file-size');
190    let maxSizeSliders = longTraceMaxSlide.querySelector('#max-size') as LitSlider;
191    this.maxSizeInput = longTraceMaxSlide.querySelector('.max_size_result') as HTMLInputElement;
192    this.maxSizeInput.onkeydown = (ev): void => {
193      // @ts-ignore
194      if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') {
195        ev.preventDefault();
196      }
197    };
198    let maxSizeParentElement = maxSizeSliders.parentNode as Element;
199    maxSizeSliders.sliderStyle = {
200      minRange: 200,
201      maxRange: 300,
202      defaultValue: '200',
203      resultUnit: 'MB',
204      stepSize: 2,
205      lineColor: 'var(--dark-color3,#46B1E3)',
206      buttonColor: '#999999',
207    };
208    maxSizeSliders.addEventListener('input', () => {
209      if (maxSingleFileEl?.hasAttribute('percent')) {
210        this.maxSizeInput!.value = `${maxSingleFileEl?.getAttribute('percent')}`;
211      } else {
212        this.maxSizeInput!.value = maxSizeSliders.sliderStyle.defaultValue;
213      }
214    });
215    this.maxSizeInput.value = maxSizeSliders.sliderStyle.defaultValue;
216    maxSizeParentElement.setAttribute('percent', '50');
217    this.maxSizeInput.style.color = 'var(--dark-color1,#000000)';
218    this.maxSizeInput.addEventListener('input', () => {
219      this.maxSizeInputHandler(maxSizeSliders, maxSizeParentElement);
220    });
221    this.radioBox!.addEventListener('click', () => {
222      this.normalModelRadioHandler(rootEl, longTraceMaxSlide);
223    });
224    this.longTraceRadio.addEventListener('click', () => {
225      this.longTraceModelRadioHandler(rootEl, longTraceMaxSlide);
226    });
227  }
228
229  private normalModelRadioHandler(rootEl: HTMLDivElement, longTraceMaxSlide: HTMLDivElement): void {
230    SpApplication.isLongTrace = false;
231    if (rootEl.lastChild === longTraceMaxSlide) {
232      rootEl.removeChild(longTraceMaxSlide);
233    }
234    this.outputPath!.value = 'hiprofiler_data.htrace';
235  }
236
237  private longTraceModelRadioHandler(rootEl: HTMLDivElement, longTraceMaxSlide: HTMLDivElement): void {
238    SpApplication.isLongTrace = true;
239    rootEl.appendChild(longTraceMaxSlide);
240    this.outputPath!.value = 'long_trace';
241  }
242
243  private maxSizeInputHandler(maxSizeSliders: LitSlider, maxSizeParentElement: Element): void {
244    maxSizeSliders!.percent = this.maxSizeInput!.value;
245    let htmlInputElement = maxSizeSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
246    htmlInputElement.value = this.maxSizeInput!.value;
247    maxSizeSliders!.sliderStyle = {
248      minRange: 200,
249      maxRange: 300,
250      defaultValue: this.maxSizeInput!.value,
251      resultUnit: 'MB',
252      stepSize: 2,
253      lineColor: 'var(--dark-color3,#46B1E3)',
254      buttonColor: '#999999',
255    };
256    maxSizeParentElement.setAttribute('percent', this.maxSizeInput!.value);
257  }
258
259  initLitSlider(): void {
260    this.memoryBufferSlider = this.shadowRoot?.querySelector<LitSlider>('#memory-buffer') as LitSlider;
261    this.memoryBufferSlider.sliderStyle = {
262      minRange: 4,
263      maxRange: 512,
264      defaultValue: '64',
265      resultUnit: 'MB',
266      stepSize: 2,
267      lineColor: 'var(--dark-color3,#46B1E3)',
268      buttonColor: '#999999',
269    };
270    this.lastMemoryValue = '64';
271    this.initMemoryBufferEl();
272    this.maxDurationSliders = this.shadowRoot?.querySelector<LitSlider>('#max-duration') as LitSlider;
273    this.maxDurationSliders.sliderStyle = {
274      minRange: 10,
275      maxRange: 3600,
276      defaultValue: '00:00:30',
277      resultUnit: 'h:m:s',
278      stepSize: 1,
279      lineColor: 'var(--dark-color4,#61CFBE)',
280      buttonColor: '#999999',
281    };
282    this.lastDurationValue = '00:00:30';
283    let durationParentElement = this.maxDurationSliders!.parentNode as Element;
284    let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement;
285    durationInput.value = this.maxDurationSliders.sliderStyle.defaultValue;
286    this.maxDurationSliders.addEventListener('input', () => {
287      durationInput.value = this.maxDurationSliders!.formatSeconds(this.maxDur.toString());
288    });
289    durationInput.style.color = 'var(--dark-color1,#000000)';
290    durationInput.addEventListener('input', () => {
291      this.maxDurationInputHandler(durationInput, durationParentElement);
292    });
293    let maxDurationInput = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
294    maxDurationInput.addEventListener('input', () => {
295      durationInput.style.color = 'var(--dark-color1,#000000)';
296      durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
297      durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
298    });
299  }
300
301  private initMemoryBufferEl(): void {
302    let parentElement = this.memoryBufferSlider!.parentNode as Element;
303    let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement;
304    bufferInput.value = this.memoryBufferSlider!.sliderStyle.defaultValue;
305    this.memoryBufferSlider!.addEventListener('input', () => {
306      bufferInput.value = this.bufferSize.toString();
307    });
308    parentElement.setAttribute('percent', '64');
309    bufferInput.style.color = 'var(--dark-color1,#000000)';
310    bufferInput.addEventListener('input', () => {
311      this.memoryBufferInputHandler(bufferInput, parentElement);
312    });
313    let memoryBufferInput = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
314    memoryBufferInput.addEventListener('input', () => {
315      bufferInput.style.color = 'var(--dark-color1,#000000)';
316      bufferInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
317      bufferInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
318    });
319  }
320
321  private maxDurationInputHandler(durationInput: HTMLInputElement, durationParentElement: Element): void {
322    if (this.durationNumber!.hasAttribute('percent')) {
323      this.durationNumber!.removeAttribute('percent');
324    }
325    durationInput.style.color = 'var(--dark-color1,#000000)';
326    durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
327    durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
328    let regExpMatchArray = durationInput.value.trim();
329    if (regExpMatchArray === '') {
330      durationInput.style.color = 'red';
331      durationParentElement.setAttribute('percent', '30');
332      return;
333    }
334    let regExpMatch = durationInput.value.trim().match('^\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}$');
335    if (regExpMatch) {
336      let durationList = regExpMatchArray.split(':');
337      let resultDuration =
338        Number(durationList[0]) * NUM_3600 + Number(durationList[1]) * NUM_60 + Number(durationList[2]);
339      if (
340        Number(durationList[0]) > NUM_60 ||
341        Number(durationList[1]) > NUM_60 ||
342        Number(durationList[2]) > NUM_60 ||
343        resultDuration > this.maxDurationSliders!.sliderStyle.maxRange ||
344        resultDuration < this.maxDurationSliders!.sliderStyle.minRange
345      ) {
346        durationInput.style.color = 'red';
347        durationParentElement.setAttribute('percent', '30');
348      } else {
349        durationInput.style.color = 'var(--dark-color1,#000000)';
350        durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
351        durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
352        let htmlInputElement = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
353        htmlInputElement.value = `${resultDuration}`;
354        this.maxDurationSliders!.sliderStyle = {
355          minRange: 10,
356          maxRange: 3600,
357          defaultValue: `${Number(durationList[0])}:${Number(durationList[1])}:${Number(durationList[2])}`,
358          resultUnit: 'h:m:s',
359          stepSize: 1,
360          lineColor: 'var(--dark-color4,#61CFBE)',
361          buttonColor: '#999999',
362        };
363        durationParentElement.setAttribute('percent', resultDuration.toString());
364        this.lastDurationValue = regExpMatchArray;
365      }
366    } else {
367      durationInput.style.color = 'red';
368      durationParentElement.setAttribute('percent', '30');
369    }
370  }
371
372  private memoryBufferInputHandler(bufferInput: HTMLInputElement, parentElement: Element): void {
373    if (this.bufferNumber!.hasAttribute('percent')) {
374      this.bufferNumber!.removeAttribute('percent');
375    }
376    bufferInput.style.color = 'var(--dark-color1,#000000)';
377    bufferInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
378    bufferInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)';
379    if (bufferInput.value.trim() === '') {
380      bufferInput.style.color = 'red';
381      parentElement.setAttribute('percent', '64');
382      return;
383    }
384    let memorySize = Number(bufferInput.value);
385    if (
386      !memorySize ||
387      memorySize < this.memoryBufferSlider!.sliderStyle.minRange ||
388      memorySize > this.memoryBufferSlider!.sliderStyle.maxRange
389    ) {
390      bufferInput.style.color = 'red';
391      parentElement.setAttribute('percent', '64');
392    } else {
393      this.memoryBufferSlider!.percent = bufferInput.value;
394      let htmlInputElement = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement;
395      htmlInputElement.value = bufferInput.value;
396      this.memoryBufferSlider!.sliderStyle = {
397        minRange: 4,
398        maxRange: 512,
399        defaultValue: bufferInput.value,
400        resultUnit: 'MB',
401        stepSize: 2,
402        lineColor: 'var(--dark-color3,#46B1E3)',
403        buttonColor: '#999999',
404      };
405      parentElement.setAttribute('percent', bufferInput.value);
406      this.lastMemoryValue = bufferInput.value;
407    }
408  }
409
410  initHtml(): string {
411    return SpRecordSettingHtml;
412  }
413}
414