import { Component, EventEmitter, Input, Output } from '@angular/core';
import {
    CVSS3_REG,
    OptionType,
    OptionType_I18n_Map,
    OptionTypeValueMap,
    SearchEventData,
    SEVERITY_OPTIONS,
} from '../security-hub.interface';

@Component({
    selector: 'app-vulnerability-filter',
    templateUrl: './vulnerability-filter.component.html',
    styleUrls: ['./vulnerability-filter.component.scss'],
})
export class VulnerabilityFilterComponent {
    severity: string;
    selectedOptions: string[] = ['all'];
    candidates: string[] = [
        OptionType.CVE_ID,
        OptionType.SEVERITY,
        OptionType.CVSS3,
        OptionType.PROJECT_ID,
        OptionType.REPO,
        OptionType.PACKAGE,
        OptionType.TAG,
        OptionType.DIGEST,
    ];
    allOptions: string[] = [
        OptionType.CVE_ID,
        OptionType.SEVERITY,
        OptionType.CVSS3,
        OptionType.PROJECT_ID,
        OptionType.REPO,
        OptionType.PACKAGE,
        OptionType.TAG,
        OptionType.DIGEST,
    ];

    valueMap: OptionTypeValueMap = {};
    startScore: string;
    endScore: string;
    @Output()
    search = new EventEmitter<SearchEventData>();
    readonly SEVERITY_OPTIONS = SEVERITY_OPTIONS;
    readonly OptionType = OptionType;
    readonly OptionType_I18n_Map = OptionType_I18n_Map;
    @Input()
    loading: boolean = false;
    constructor() {}

    select() {
        if (this.selectedOptions[0] === 'all') {
            this.selectedOptions = ['all'];
        }
        this.candidates = this.allOptions.filter(item => {
            return !this.selectedOptions.find(item2 => item2 === item);
        });
    }
    add() {
        if (this.canAdd()) {
            this.selectedOptions.push(this.candidates[0]);
            this.candidates.shift();
        }
    }
    reduce() {
        if (this.canReduce()) {
            this.candidates.unshift(
                this.selectedOptions[this.selectedOptions.length - 1]
            );
            this.selectedOptions.pop();
        }
    }

    canAdd(): boolean {
        return this.selectedOptions.length < this.allOptions.length;
    }

    canReduce(): boolean {
        return this.selectedOptions.length >= 2;
    }

    getOption(currentOption: string): string[] {
        if (currentOption === 'all') {
            return this.candidates;
        }
        return [currentOption].concat(this.candidates);
    }
    fireSearchEvent() {
        let result: SearchEventData = {
            normal: [],
            projectId: '',
        };
        this.selectedOptions.forEach(item => {
            if (item === OptionType.ALL) {
                this.search.emit(result);
                return;
            } else if (
                item === OptionType.PROJECT_ID &&
                this.valueMap[OptionType.PROJECT_ID]?.trim()
            ) {
                result.projectId = this.valueMap[OptionType.PROJECT_ID]?.trim();
            } else if (item === OptionType.SEVERITY) {
                if (this.severity) {
                    result.normal.push(
                        `${OptionType.SEVERITY}=${this.severity}`
                    );
                }
            } else if (item === OptionType.CVSS3) {
                if (this.startScore?.trim() || this.endScore?.trim()) {
                    result.normal.push(
                        `${OptionType.CVSS3}=[${
                            this.startScore ? this.startScore?.trim() : '0.0'
                        }~${this.endScore ? this.endScore?.trim() : '10.0'}]`
                    );
                }
            } else if (this.valueMap[item]?.trim()) {
                result.normal.push(`${item}=${this.valueMap[item]?.trim()}`);
            }
        });
        this.search.emit(result);
    }

    isInvalid(): boolean {
        if (this.selectedOptions.indexOf(OptionType.CVSS3) !== -1) {
            if (this.startScore && !CVSS3_REG.test(this.startScore)) {
                return true;
            }
            if (this.endScore && !CVSS3_REG.test(this.endScore)) {
                return true;
            }
            if (this.startScore && this.endScore) {
                return +this.startScore > +this.endScore;
            }
        }
        return false;
    }
}
