import * as d3 from 'd3';
import { ConditionalDisplayElement } from '../base/conditional-display-element';
import { GetAlarmsArgs } from '../../config';
import * as moment from 'moment';
import { LOGGER_SERVICE_TOKEN } from '../../logger';
import { LOCALIZATION } from '../../localization';
export class AlarmElement extends ConditionalDisplayElement {
    constructor(element, injector, permissionChecker, variableCommunicator, variableStore, alarmsStore, signalRAppId) {
        var _a;
        super(element, permissionChecker, variableCommunicator, variableStore, signalRAppId);
        this.alarmsStore = alarmsStore;
        this.displayOption = {
            dataLimit: 500,
            dataZoomHeight: 32,
            marginLeft: 1,
            marginRight: 20,
            mobileMinWidth: 450,
            operationAreaHeight: 32,
            operationAreaMarginTop: 10,
            operationSelectFontSize: '16px',
            operationButtonWidth: 24,
            operationButtonHeight: 24,
            operationButtonMargin: 4
        };
        this.alarmNames = [];
        this.alarmList = [];
        this.currentAlarmList = [];
        this.page = 0;
        this.totalCount = 0;
        this.pageSize = 5;
        this.rootElement.selectAll('*').remove();
        this.logger = injector.get(LOGGER_SERVICE_TOKEN);
        this.localization = injector.get(LOCALIZATION);
        this.variableCommunicator = variableCommunicator;
        this.timePeriods = this.getValidTimePeriods();
        this.pageSize = this.model.generalSetting.pageSize;
        localStorage.setItem('simulate-time', moment().valueOf() + '');
        if (this.model.filterSetting) {
            this.alarmNames = this.model.filterSetting.detailsData.map(item => item.name);
            this.currentTimePeriod = (_a = this.model.filterSetting) === null || _a === void 0 ? void 0 : _a.displayPeriod;
            this.updateQueryTimeRange();
            if (this.model.filterSetting.alarmType) {
                this.refreshIntervalId = setInterval(() => {
                    this.loadFirstPage();
                    this.logger.debug(`[GUI]Refresh Alarm Table:${d3.time.format('%x %X')(new Date())}`);
                }, this.model.filterSetting.refreshCycle * 60 * 1000);
            }
            else {
                variableCommunicator.subscribeUserDeviceAlarms(signalRAppId).subscribe(alarms => {
                    alarms.forEach(alarm => {
                        if (this.alarmNames.indexOf(alarm.name) !== -1) {
                            this.init();
                            return;
                        }
                    });
                });
            }
            this.init();
        }
        else {
            this.totalCount = 0;
            this.alarmList = [];
            this.renderElement();
        }
    }
    dispose() {
        clearInterval(this.refreshIntervalId);
        if (this.element) {
            this.element.tooltip.hidden(true);
        }
        this.logger.debug(`[GUI]Dispose Alarm Table Refresh Interval:${d3.time.format('%x %X')(new Date())}`);
    }
    getValidTimePeriods() {
        const timePeriods = new Array();
        timePeriods.push({ key: 6, name: this.localization.lastThirtyMinutes });
        timePeriods.push({ key: 1, name: this.localization.lastOneHour });
        timePeriods.push({ key: 7, name: this.localization.lastEightHour });
        timePeriods.push({ key: 2, name: this.localization.lastTwentyFourHours });
        timePeriods.push({ key: 3, name: this.localization.lastSevenDays });
        timePeriods.push({ key: 4, name: this.localization.lastThirtyDays });
        timePeriods.push({ key: 5, name: this.localization.lastOneYear });
        return timePeriods;
    }
    init() {
        clearTimeout(this.getAlarmDataId);
        this.getAlarmDataId = setTimeout(() => {
            if (this.model.filterSetting.alarmType) {
                this.updateQueryTimeRange();
                const input = new GetAlarmsArgs(this.alarmNames, this.startTime, this.endTime, this.pageSize, this.page * this.pageSize);
                this.alarmsStore.getHistoryAlarms(input).subscribe(result => {
                    if (!result.error) {
                        this.totalCount = result.totalCount;
                        this.alarmList = result.items.map(item => [
                            item.name,
                            item.message,
                            item.alarmLevel,
                            item.triggeredTime.format('YYYY-MM-DD HH:mm:ss')
                        ]);
                        this.renderElement();
                    }
                });
            }
            else {
                const input = new GetAlarmsArgs(this.alarmNames, undefined, undefined, this.pageSize, this.page * this.pageSize);
                this.alarmsStore.getCurrentAlarms(input).subscribe(result => {
                    if (!result.error) {
                        this.totalCount = result.totalCount;
                        this.currentAlarmList = result.items;
                        if (!result.items.length && result.totalCount) {
                            this.page = 0;
                            this.init();
                            return;
                        }
                        this.alarmList = this.currentAlarmList.map(item => [
                            item.name,
                            item.message,
                            item.alarmLevel,
                            item.triggeredTime.format('YYYY-MM-DD HH:mm:ss')
                        ]);
                        this.renderElement();
                    }
                });
            }
        }, 500);
    }
    renderElement() {
        this.rootElement.selectAll('*').remove();
        const elementHeight = this.model.size.height;
        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
        this.element.setAttribute('width', this.model.size.width.toString());
        this.element.setAttribute('height', elementHeight.toString());
        this.$element.append(this.element);
        const table = document.createElement('table');
        table.style.cssText = `border: 2px solid ${this.model.generalSetting.stroke};
            height: ${elementHeight - 39}`;
        let tr = document.createElement('tr');
        let fontString = '';
        if (this.model.generalSetting.headerFont.isItalic) {
            fontString += 'italic ';
        }
        if (this.model.generalSetting.headerFont.isBold) {
            fontString += 'bold ';
        }
        fontString += this.model.generalSetting.headerFont.fontSize + ' ' + this.model.generalSetting.headerFont.fontFamily;
        tr.style.cssText = `height: ${this.model.heights[0]}px;
            background: ${this.model.generalSetting.headerFillColor};
            color: ${this.model.generalSetting.headerFont.color};
            font: ${fontString};
            text-align: ${this.model.generalSetting.headerFont.textAlign};
            ${this.model.generalSetting.headerFont.isUnderline ? 'text-decoration: underline' : ''};
            vertical-align: middle;`;
        for (let row = 0; row < 4; row++) {
            const th = document.createElement('th');
            th.innerHTML = this.model.columLabels[row];
            th.style.cssText = `width: ${this.model.widths[row] / this.model.size.width * 100}%;
                border-style: solid;
                border-color: ${this.model.generalSetting.splitLine};
                border-left-width: ${!row || this.model.generalSetting.isHiddenColumnSplitLine ? 0 : 1}px;`;
            tr.appendChild(th);
        }
        table.appendChild(tr);
        const levelColors = ['#3695FF', '#FFE900', '#FFA800', '#E84F4F'];
        for (let row = 0; row < this.pageSize; row++) {
            tr = document.createElement('tr');
            tr.style.cssText = `height: ${this.model.heights[row + 1]}px;
                    background: ${this.model.generalSetting.tableFillColor};
                    font: ${this.model.generalSetting.fontStyle};
                    color: ${this.model.generalSetting.fontColor};
                    text-align: ${this.model.generalSetting.textAlign};
                    vertical-align: middle;`;
            for (let col = 0; col < 4; col++) {
                const td = document.createElement('td');
                td.style.cssText = `border-style: solid;
                border-color: ${this.model.generalSetting.splitLine};
                border-top-width: ${this.model.generalSetting.isHiddenColumnSplitLine ? 0 : 1}px;
                border-left-width: ${!col || this.model.generalSetting.isHiddenColumnSplitLine ? 0 : 1}px;`;
                if (this.alarmList[row]) {
                    if (col !== 2) {
                        td.innerHTML = this.alarmList[row][col];
                        td.style.cssText += `${this.model.generalSetting.isUnderline ? 'text-decoration: underline' : ''};`;
                    }
                    else {
                        const alarmLevel = document.createElement('div');
                        let alarmHeight = parseInt(this.model.generalSetting.fontSize) + 15;
                        if (alarmHeight > this.model.heights[row + 1])
                            alarmHeight = this.model.heights[row + 1];
                        let margin = '0 15px';
                        if (this.model.generalSetting.textAlign === 'left') {
                            margin = '0 30px 0 0';
                        }
                        else if (this.model.generalSetting.textAlign === 'right') {
                            margin = '0 0 0 30px';
                        }
                        alarmLevel.style.cssText = `margin: ${margin};
                            border-radius: 5px;
                            background: ${levelColors[this.alarmList[row][col]]};
                            color: #ffffff;
                            width: ${this.model.widths[col] - 30}px;
                            height: ${alarmHeight}px;
                            max-height: ${this.model.heights[row + 1]}px;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            ${this.model.generalSetting.isUnderline ? 'text-decoration: underline' : ''};`;
                        alarmLevel.innerHTML = this.model.levelText[this.alarmList[row][col]];
                        td.appendChild(alarmLevel);
                    }
                }
                else if (col === 2) {
                    const alarmLevel = document.createElement('div');
                    let margin = '0 15px';
                    if (this.model.generalSetting.textAlign === 'left') {
                        margin = '0 30px 0 0';
                    }
                    else if (this.model.generalSetting.textAlign === 'right') {
                        margin = '0 0 0 30px';
                    }
                    alarmLevel.style.cssText = `margin: ${margin};
                            width: ${this.model.widths[col] - 30}px;`;
                    td.appendChild(alarmLevel);
                }
                tr.appendChild(td);
            }
            table.appendChild(tr);
        }
        this.element.appendChild(table);
        this.renderOperationArea(this.model.size.width, elementHeight - 39);
    }
    renderOperationArea(chartWidth, chartHeight) {
        var _a;
        const operationArea = this.rootElement.append('g').attr('transform', `translate(0,${chartHeight + this.displayOption.operationAreaMarginTop})`)
            .append('foreignObject').attr('width', chartWidth).attr('height', this.displayOption.operationAreaHeight).attr('fill', 'none')
            .append('xhtml:div').style('height', (this.displayOption.operationAreaHeight - 4) + 'px').style('overflow', 'hidden').style('margin-top', '4px');
        if ((_a = this.model.filterSetting) === null || _a === void 0 ? void 0 : _a.alarmType) {
            const selectElement = operationArea.append('select').style('margin-left', this.displayOption.marginLeft + 'px')
                .style('font-size', this.displayOption.operationSelectFontSize).on('change', () => {
                const displayTimePeriod = this.rootElement.select('select').property('value');
                this.updateTimeRange(displayTimePeriod);
                this.init();
            });
            const options = selectElement.selectAll('option').data(this.timePeriods).enter().append('option');
            options.text(d => d.name).attr('value', d => d.key).property('selected', d => d.key === Number(this.currentTimePeriod));
        }
        const buttonWidth = this.displayOption.operationButtonWidth + 'px', buttonHeight = this.displayOption.operationButtonHeight + 'px';
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background', 'white').style('background-image', 'url(assets/img/last_page.svg)')
            .on('click', () => { this.loadLastPage(); });
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background', 'white').style('background-image', 'url(assets/img/next_page.svg)')
            .style('margin', `0 ${this.displayOption.operationButtonMargin}px 0 0`)
            .on('click', () => { this.loadNextPage(); });
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background', 'white').style('background-image', 'url(assets/img/previous_page.svg)')
            .style('margin', `0 ${this.displayOption.operationButtonMargin}px 0 0`)
            .on('click', () => { this.loadPreviousPage(); });
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background', 'white').style('background-image', 'url(assets/img/first_page.svg)')
            .style('margin', `0 ${this.displayOption.operationButtonMargin}px 0 0`)
            .on('click', () => { this.loadFirstPage(); });
    }
    updateTimeRange(timePeriodType) {
        this.currentTimePeriod = +timePeriodType;
        this.updateQueryTimeRange();
    }
    updateQueryTimeRange() {
        this.endTime = moment();
        switch (this.currentTimePeriod) {
            case 1:
                this.startTime = moment().subtract(1, 'hours');
                break;
            case 3:
                this.startTime = moment().subtract(7, 'days');
                break;
            case 4:
                this.startTime = moment().subtract(30, 'days');
                break;
            case 5:
                this.startTime = moment().subtract(1, 'years');
                break;
            case 6:
                this.startTime = moment().subtract(30, 'minutes');
                break;
            case 7:
                this.startTime = moment().subtract(8, 'hours');
                break;
            default:
                this.startTime = moment().subtract(1, 'days');
        }
    }
    loadFirstPage() {
        if (this.page > 0) {
            this.page = 0;
            this.init();
        }
    }
    loadNextPage() {
        let last_page = Math.ceil(this.totalCount / this.pageSize);
        if (last_page)
            last_page--;
        if (this.page < last_page) {
            this.page++;
            this.init();
        }
    }
    loadPreviousPage() {
        if (this.page > 0) {
            this.page--;
            this.init();
        }
    }
    loadLastPage() {
        let last_page = Math.ceil(this.totalCount / this.pageSize);
        if (last_page)
            last_page--;
        if (this.page !== last_page) {
            this.page = last_page;
            this.init();
        }
    }
}
