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

import { Component, ViewChild } from '@angular/core';
import { AppState } from '../app.service';
import { GroupedGrid } from './grouped_grid';
import { Column } from './column';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { StatsRepo } from '../repository/stats_repo';
import { BaseComponent } from './base_component';
import { Helper } from './helper';
import { Access } from '../services/access';
import * as common from '../common';
import { HIDE_MYUSQL_LIMITS_MODES } from '../services/constants';
import { commonColumnsArray, ExtendedColumnProperties }
    from './componentProperties/columnExtendedProperties';
import { DateRange } from './ui-elements/calendar/ui-date-range/ui-date-range.component';
import * as moment from 'moment';
import { LoaderSelector } from './loader';

declare var jQuery: any;

@Component({
    selector: 'modal_stats',
    template: require('./../../templates/modal_stats.html'),
    styles: [
      require('../../styles/modal_stats.less')
    ],
    providers: [Access]
})
export class ModalStats extends BaseComponent {
    showChart: boolean = false;
    _data: any;
    chart: SafeHtml;
    userId: number;
    rows: any[] = [];
    period: string = '10m';
    useTimeUnit: string = '1h';
    dateRange: DateRange = {};
    availableLimits: any;
    columns: any[] = [];
    rowsOnPage: number = 25;

    possibleLimits = {
      'cpu':   {'title': 'SPEED',   'checked': true},
      'io':    {'title': 'IO',    'checked': true},
      'ep':    {'title': 'EP',    'checked': true},
      'vmem':  {'title': 'VMEM',  'checked': true},
      'pmem':  {'title': 'PMEM',  'checked': true},
      'nproc': {'title': 'NPROC', 'checked': true},
      'iops':  {'title': 'IOPS',  'checked': true},
      'mysql': {'title': 'MySQL', 'checked': true},
    };
    mySQLParam = 'mysql';
    availableTimeframe = common.availableTimeframe;
    availableTimeUnit = common.availableTimeUnit;

    possibleColumns: Array<ExtendedColumnProperties> = commonColumnsArray.concat([
        {name: 'from', descr: 'From', convertToFormat: 'string', group: 'Period'},
        {name: 'to', descr: 'To', convertToFormat: 'string', group: 'Period'}
    ]);

    set data(value: any){
        this._data = value;
        if (typeof value.user[0] === 'undefined') {
          this.availableLimits = [];
          this.columns = [];
          this.GroupedGrid.noFound = true;
        } else {
          let etalon = value.user[0];
          this.accessService.dropPermission(value, etalon);
          this.defineAvailableLimits(etalon['limits'], value.mySqlGov);
          this.columns = this.getColumns(etalon);
          this.rows = this.parseStats(value.user);
          this.GroupedGrid.noFound = false;
        }

    }

    setPeriod(val: string = '') {
        this.loadHistory(this.userId, this.showChart, val, this.useTimeUnit);
    }

    onUseRangeChange(range) {
        this.dateRange = range;
        this.loadHistory(this.userId, this.showChart, null, this.useTimeUnit);
    }

    onTimeUnitChange(timeUnit: string) {
        this.loadHistory(this.userId, this.showChart, this.period, timeUnit);
    }

    @ViewChild(GroupedGrid) GroupedGrid: GroupedGrid;

    constructor(
        public appState: AppState,
        private _sanitizer: DomSanitizer,
        private statsRepo: StatsRepo,
        private accessService: Access
    ) {
        super();
    }

    public formatDate(unixtime: number) {
        return moment.unix(unixtime).format('MMM D, YYYY, HH:mm:ss');
    }

    async loadHistory(
        user_id: number, showChart: boolean, period: string = '10m', timeUnit = '1h') {
        this.userId = user_id;
        let periodParams = {};
        if (!period) {
            periodParams['from'] = this.dateRange.start.format('YYYY-MM-DD 00:00');
            periodParams['to'] = this.dateRange.end.format('YYYY-MM-DD 23:59');
        } else {
            periodParams['period'] = period;
        }

        this.period = period;
        this.useTimeUnit = timeUnit;
        this.loading = true;
        this.data = await this.statsRepo.history(
            user_id, Object.assign({'time-unit': timeUnit}, periodParams));
        this.showChart = showChart;
        if (showChart) {
            let responseChart = await this.statsRepo.chart(user_id,
                Object.assign({'format': 'svg'}, periodParams));
            this.chart = this._sanitizer.bypassSecurityTrustHtml(responseChart.chart);
            jQuery('#history_modal').modal('show');
            this.loading = false;
            return;
        } else {
            jQuery('#history_modal').modal('show');
            this.loading = false;
            return;
        }

    }

    defineAvailableLimits(limitEtalon, mySqlGov) {
      let keysOfAvailableLimits = Object.keys(limitEtalon);

      if (mySqlGov === 'enabled') {
        keysOfAvailableLimits.push(this.mySQLParam);
      }

      this.availableLimits = {};
      for (let limit in this.possibleLimits) {
        if (keysOfAvailableLimits.indexOf(limit) !== -1) {
          this.availableLimits[limit] = this.possibleLimits[limit];
        }
      }
    }

    // TODO concat with stats component getColumns
    getColumns(userStandard): Column[] {
        let columns = [];
        for (let column of this.possibleColumns) {
            let icon = column.icon;
            let tooltip = column.tooltip;

            if (Helper.hasOwnPropetyRecursively(userStandard, column.name)) {
                let addColumn = new Column(column);
                if (typeof icon !== 'undefined' && icon !== '') {
                    addColumn.setIcon(icon);
                }
                if (typeof tooltip !== 'undefined') {
                    addColumn.setTooltip(tooltip);
                }
                let limit = column.name.split('_')[1];
                if (this.availableLimits.hasOwnProperty(limit)
                    && !this.availableLimits[limit].checked
                ) {
                    addColumn.hide();
                }
                columns.push(addColumn);
            }
        }
        return columns;
    }

    parseStats(user) {
        for (let item of user) {
            if (this.appState.get('mySqlGovMode') === 'all') {
                if (item.usage.cpu.mysql > item.usage.cpu.lve) {
                    item.usage.cpu.mysql = item.usage.cpu.lve;
                }
                if (item.usage.io.mysql > item.usage.io.lve) {
                   item.usage.io.mysql = item.usage.io.lve;
                }
            }
            if (HIDE_MYUSQL_LIMITS_MODES.includes(this.appState.get('mySqlGovMode'))) {
                item.limits.cpu.mysql = '-';
                item.limits.io.mysql = '-';
            }

            for (let column of this.possibleColumns) {
                let name = column.name;
                if (column.group === 'Period') {
                    item[name] = {
                        'value': this.formatDate(
                            Helper.getValueFromObjectRecursively(item, name)
                        )
                    };
                } else {
                  let value = Helper.getValueFromObjectRecursively(item, name);
                  item[name] = (typeof column.units !== 'undefined') ?
                      Helper.reformatValue(value, column.units) :
                      { value: (typeof value === 'number') ? value.toString() : value };
                }
              }
          }
        return user;
    }

    ngAfterViewInit() {
        this.loaderSelector = new LoaderSelector('#history_modal .modal-dialog', true);
    }

}
