// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {
    Component,
    ElementRef,
    EventEmitter,
    HostListener,
    OnDestroy,
    OnInit,
    Output,
    ViewChild,
} from '@angular/core';
import { SecurityhubService } from '../../../../../../../ng-swagger-gen/services/securityhub.service';
import { SecuritySummary } from '../../../../../../../ng-swagger-gen/models/security-summary';
import { MessageHandlerService } from '../../../../../shared/services/message-handler.service';
import {
    getDigestLink,
    SeverityColors,
    severityText,
    VUL_ID,
} from '../security-hub.interface';
import { HAS_STYLE_MODE, StyleMode } from '../../../../../services/theme';
import { Subscription } from 'rxjs';
import {
    EventService,
    HarborEvent,
} from '../../../../../services/event-service/event.service';
import { TranslateService } from '@ngx-translate/core';
import { DangerousArtifact } from '../../../../../../../ng-swagger-gen/models/dangerous-artifact';
import * as echarts from 'echarts/core';
import { finalize } from 'rxjs/operators';

@Component({
    selector: 'app-vulnerability-summary',
    templateUrl: './vulnerability-summary.component.html',
    styleUrls: ['./vulnerability-summary.component.scss'],
})
export class VulnerabilitySummaryComponent implements OnInit, OnDestroy {
    @Output()
    searchCVE = new EventEmitter<string>();
    @Output()
    searchRepo = new EventEmitter<DangerousArtifact>();
    securitySummary: SecuritySummary;
    readonly vulId: string = VUL_ID;
    readonly severityText = severityText;
    readonly getDigestLink = getDigestLink;
    harborEventSub: Subscription;
    chart: any;
    @ViewChild('pieChart', { static: true })
    pieChartEle: ElementRef;
    loadingSummary: boolean = false;
    constructor(
        private securityHubService: SecurityhubService,
        private messageHandler: MessageHandlerService,
        private event: EventService,
        private translate: TranslateService
    ) {}

    ngOnInit() {
        this.chart = echarts.init(this.pieChartEle.nativeElement);
        this.getSummary();
        if (!this.harborEventSub) {
            this.harborEventSub = this.event.subscribe(
                HarborEvent.THEME_CHANGE,
                () => {
                    if (this.securitySummary) {
                        this.setOption(this.securitySummary);
                    }
                }
            );
        }
    }
    ngOnDestroy() {
        if (this.harborEventSub) {
            this.harborEventSub.unsubscribe();
            this.harborEventSub = null;
        }
    }

    getSummary() {
        this.loadingSummary = true;
        this.securityHubService
            .getSecuritySummary({
                withDangerousArtifact: true,
                withDangerousCve: true,
            })
            .pipe(finalize(() => (this.loadingSummary = false)))
            .subscribe({
                next: res => {
                    this.securitySummary = res;
                    this.setOption(res);
                },
                error: err => {
                    this.messageHandler.error(err);
                },
            });
    }

    setOption(summary: SecuritySummary) {
        const [severity, c, h, m, l, n, u] = [
            'VULNERABILITY.GRID.COLUMN_SEVERITY',
            'VULNERABILITY.SEVERITY.CRITICAL',
            'VULNERABILITY.SEVERITY.HIGH',
            'VULNERABILITY.SEVERITY.MEDIUM',
            'VULNERABILITY.SEVERITY.LOW',
            'VULNERABILITY.SEVERITY.NONE',
            'UNKNOWN',
        ];
        this.translate.get([severity, c, h, m, l, n, u]).subscribe(res => {
            this.chart.setOption({
                color: [
                    SeverityColors.CRITICAL,
                    SeverityColors.HIGH,
                    SeverityColors.MEDIUM,
                    SeverityColors.LOW,
                    SeverityColors.NA,
                    SeverityColors.NONE,
                ],
                title: {
                    text: '',
                },
                tooltip: {
                    formatter: '<b>{b}: {d}%</b>',
                },
                legend: {
                    align: 'left',
                    left: 5,
                    bottom: 5,
                    formatter: '{a|{name}}',
                    textStyle: {
                        color: this.getColorByTheme(),
                        width: 50,
                        backgroundColor: 'transparent',
                        rich: {
                            a: {
                                fontWeight: '100',
                                fontSize: '12px',
                                verticalAlign: 'bottom',
                                height: 12,
                                lineHeight: 15,
                            },
                        },
                    },
                    itemWidth: 12,
                    itemHeight: 12,
                    width: '50%',
                },
                series: [
                    {
                        itemStyle: {
                            borderRadius: 3,
                            borderWidth: 1,
                        },
                        label: {
                            show: false,
                        },
                        radius: ['50%', '80%'],
                        name: res[severity],
                        type: 'pie',
                        center: ['68%', '50%'],
                        data: [
                            {
                                name: res[c],
                                value: summary?.critical_cnt || 0,
                            },
                            {
                                name: res[h],
                                value: summary?.high_cnt || 0,
                            },
                            {
                                name: res[m],
                                value: summary?.medium_cnt || 0,
                            },
                            {
                                name: res[l],
                                value: summary?.low_cnt || 0,
                            },
                            {
                                name: res[u],
                                value: summary?.unknown_cnt || 0,
                            },
                            {
                                name: res[n],
                                value: summary?.none_cnt || 0,
                            },
                        ],
                    },
                ],
            });
        });
    }

    searchCVEClick(cveId: string) {
        this.searchCVE.emit(cveId);
    }

    searchRepoClick(artifact: DangerousArtifact) {
        this.searchRepo.emit(artifact);
    }

    getColorByTheme(): string {
        return localStorage?.getItem(HAS_STYLE_MODE) === StyleMode.LIGHT
            ? '#000'
            : '#fff';
    }

    @HostListener('window:resize', ['$event'])
    onResize(event: any) {
        this.chart.resize();
    }
}
