/* Copyright CloudLinux Zug GmbH 2010-2017 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 */

import { AfterViewInit, Component, Input } from '@angular/core';

import { XHR } from '../utils/xhr';
import { Incident, Search } from './incident.model';
import { COUNTRIES } from './country.model';
import { BaseComponent } from '../utils/base_component';
import { AppState } from '../app.service';
import { Router } from '@angular/router';
import { LoaderSelector } from '../utils/loader';


const severity = {
    modsec: {
        low: [5, 7],
        medium: [4, 4],
        high: [0, 3],
    },
    ossec: {
        low: [0, 3],
        medium: [4, 10],
        high: [11, 15],
    }
};

@Component({
    selector: 'incidents',
    styles: [
        require('./incidents.component.less'),
    ],
    providers: [XHR, Search],
    template: require('./incidents.component.html'),
})
export class IncidentsComponent extends BaseComponent implements AfterViewInit {
    public activeSearchIP: boolean = true;
    public activeSearchCountry: boolean = false;
    public searchIP: string = '';
    public searchCountry: string = '';
    public COUNTRIES: any[] = [];
    public incidents: Incident[] = [];
    public confirm_disabling: boolean = false;

    private typeaheadNoResults: boolean;
    private _currentPage = 1;
    private _maxPage;
    private _limit;
    private _maxCount;
    private _disabled;
    private _pagination;
    private _enabled = true;

    constructor(
        public request: XHR,
        public search: Search,
        public appState: AppState,
        private router: Router,
    ) {
        super();
        this.COUNTRIES = COUNTRIES;
        this.loaderSelector = new LoaderSelector('.incidents_component');
    }

    public async load() {
        this.loading = true;
        try {
            let response = await this.request.post({
                handler: 'imunify',
                method: 'get',
                params: Object.assign({'--json': ''}, ...this.search.getParams())
            });
            this.incidents = response['items'].map(item => new Incident(item));
            this.maxCount = response['max_count'];
        } catch (e) {
            this.loading = false;
        } finally {
            this.loading = false;
        }
    }

    public get enabled(): boolean {
        return this._enabled;
    }

    public set enabled(value: boolean) {
        this._enabled = value;
        if(!value) {
            this.confirm_disabling = true;
        }
    }

    public disableService() {
        this.loading = true;
        this.confirm_disabling = false;
        this.request.post({
            handler: 'imunify',
            command: 'setServiceStatus',
            status: 0
        }).then((data) => {
            this.loading = false;
            this.router.navigate(['incidents/status']);
        }).catch((err) => {
            this.loading = false;
        });
    }

    public cancelDisabling() {
        this.enabled = true;
        this.confirm_disabling = false;
    }

    public addFilterParam(item: string, value = null) {
        this.currentPage = 1;
        this.search.setSelected(item, value);
        this.load();
    }

    public removeFilterParam(item: string) {
        this.currentPage = 1;
        this.search.removeSelected(item);
        this.load();
    }

    public addSearchParam(item: string) {
        let value = this[item];
        if (!this.search.validate(item, value)) {
            return false;
        }
        if (item === 'searchCountry') {
            value = COUNTRIES.find(v => v.name.toLowerCase() === value.toLowerCase())['code'];
        }
        this.currentPage = 1;
        this.search.setSelected(item, value);
        this.load();
    }

    public removeSearchParam(item: string) {
        this.currentPage = 1;
        this[item] = '';
        this.search.removeSelected(item);
        this.load();
    }

    public toggleSearch(enabled: boolean, item: string) {
        if (!enabled && this.search.getSelected(item)) {
            let value = this[item];
            this.removeSearchParam(item);
            this[item] = value;
        } else if (enabled && this[item]) {
            this.addSearchParam(item);
        }
    }

    public getSeverityIconClass(incident: Incident) {
        if (incident.plugin in severity) {
            return Object.keys(severity[incident.plugin]).find(key => {
                    let [min, max] = severity[incident.plugin][key];
                    return min <= incident.severity && max >= incident.severity;
                }) || 'hidden';
        }
        return 'hidden';
    }

    public getTitle(incident: Incident) {
        if (!incident.severity) {
            return '';
        }
        return 'Severity: <span class="severity-icon '
            + this.getSeverityIconClass(incident) + '"></span> '
            + incident.severity;
    }

    public changeTypeaheadNoResults(e: boolean): void {
        this.typeaheadNoResults = e;
    }

    public ngAfterViewInit() {
        this.load();
    }

    public paginatorChange(currentPage) {
        let offset = (currentPage - 1) * Number(this.search.getSelected('limit')) || 0;
        this.search.setSelected('offset', offset);
        this.load();
    }

    @Input()
    public set limit(val) {
        let offset = 0;
        this.search.setSelected('offset', offset);
        this._limit = val || 100;
        this._maxPage = Math.ceil(this._maxCount / this._limit);
    }

    @Input()
    public set maxCount(val) {
        this._maxCount = val;
        this._maxPage = Math.ceil(val / Number(this._limit)) || 1;
        this.limit = this.search.getSelected('limit');
        this.preparePagination();
    }

    @Input()
    public set currentPage(val) {
        this._currentPage = val || 1;
        this.preparePagination();
    }

    @Input()
    public set disabled(val) {
        this._disabled = val;
    }

    public goToPage(page: number) {
        if (page && !this._disabled) {
            this._currentPage = page;
            this.preparePagination();
            this.paginatorChange(page);
        }
    }

    public goToPrevPage() {
        if (this._currentPage > 1) {
            this.goToPage(this._currentPage - 1);
        }
    }

    public goToNextPage() {
        if (this._currentPage < this._maxPage) {
            this.goToPage(this._currentPage + 1);
        }
    }

    public preparePagination() {
        this._pagination = this._preparePagination();
    }

    private _preparePagination(): Array<{}> {
        if (this._maxPage > 7) {
            if (this._currentPage <= 4) {
                return [
                    {title: '1',                  value: 1},
                    {title: '2',                  value: 2},
                    {title: '3',                  value: 3},
                    {title: '4',                  value: 4},
                    {title: '5',                  value: 5},
                    {title: '...',                value: null},
                    {title: String(this._maxPage), value: this._maxPage},
                ];
            } else if (this._currentPage > (this._maxPage - 4)) {
                return [
                    {title: '1',                      value: 1},
                    {title: '...',                    value: null},
                    {title: String(this._maxPage - 4), value: this._maxPage - 4},
                    {title: String(this._maxPage - 3), value: this._maxPage - 3},
                    {title: String(this._maxPage - 2), value: this._maxPage - 2},
                    {title: String(this._maxPage - 1), value: this._maxPage - 1},
                    {title: String(this._maxPage),     value: this._maxPage},
                ];
            } else {
                return [
                    {title: '1',   value: 1},
                    {title: '...', value: null},
                    {
                        title: String(this._currentPage - 1),
                        value: this._currentPage - 1,
                    },
                    {title: String(this._currentPage), value: this._currentPage},
                    {
                        title: String(this._currentPage + 1),
                        value: this._currentPage + 1,
                    },
                    {title: '...', value: null},
                    {title: String(this._maxPage), value: this._maxPage},
                ];
            }
        } else {
            let res = [];
            for (let i = 1; i <= this._maxPage; i++) {
                res.push({title: String(i), value: i});
            }
            return res;
        }
    }
}
