import * as d3 from 'd3';
import { SYSTEM_TEXT_LIBRARY_TYPES, ALARM_TABLE_HEADER_KEYS, TIME_PERIOD_KEYS } from '../../service';
import { ConditionalDisplayElement } from '../base/conditional-display-element';
import { GetAlarmsArgs } from '../../config';
import * as moment from 'moment';
import { LOGGER_SERVICE_TOKEN } from '../../logger';
var AlaertElementStatus;
(function (AlaertElementStatus) {
    AlaertElementStatus[AlaertElementStatus["Normal"] = 0] = "Normal";
    AlaertElementStatus[AlaertElementStatus["Loading"] = 1] = "Loading"; // 加载中
})(AlaertElementStatus || (AlaertElementStatus = {}));
export class AlarmElement extends ConditionalDisplayElement {
    constructor(element, injector, permissionChecker, variableCommunicator, variableStore, alarmsStore, signalRAppId, systemTextLibraryService, languageService, guiContext) {
        var _a;
        super(element, permissionChecker, variableCommunicator, variableStore, signalRAppId);
        this.alarmsStore = alarmsStore;
        this.systemTextLibraryService = systemTextLibraryService;
        this.languageService = languageService;
        this.guiContext = guiContext;
        this.elementStatus = AlaertElementStatus.Loading;
        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.setStatusAsLoading();
        this.logger = injector.get(LOGGER_SERVICE_TOKEN);
        this.variableCommunicator = variableCommunicator;
        this.pageSize = this.model.generalSetting.pageSize;
        localStorage.setItem('simulate-time', moment().valueOf() + '');
        // 订阅语种变化事件
        this.subscribeLanguageChange();
        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.getAlarmData();
                            return;
                        }
                    });
                });
            }
            this.getAlarmData();
        }
        else {
            this.totalCount = 0;
            this.alarmList = [];
            this.renderElement();
        }
    }
    dispose() {
        clearInterval(this.refreshIntervalId);
        if (this.element) {
            this.element.tooltip.hidden(true);
        }
        // 取消语种变化订阅
        if (this.languageChangeSubscription) {
            this.languageChangeSubscription.unsubscribe();
            this.languageChangeSubscription = undefined;
        }
        this.logger.debug(`[GUI]Dispose Alarm Table Refresh Interval:${d3.time.format('%x %X')(new Date())}`);
    }
    /**
     * 订阅语种变化事件
     */
    subscribeLanguageChange() {
        if (this.guiContext && this.guiContext.languageChanged$) {
            this.languageChangeSubscription = this.guiContext.languageChanged$.subscribe(() => {
                // 只更新文案，不重新查询数据
                this.updateLanguageTexts();
            });
        }
    }
    /**
     * 更新语种相关的文案（表头和时间段选择器）
     */
    updateLanguageTexts() {
        var _a;
        // 更新表头文本
        const headerCells = this.$element.find('table th');
        for (let col = 0; col < 4 && col < headerCells.length; col++) {
            headerCells.eq(col).text(this.getHeaderTextByColumn(col));
        }
        // 更新时间段选择器选项
        if ((_a = this.model.filterSetting) === null || _a === void 0 ? void 0 : _a.alarmType) {
            const selectElement = this.rootElement.select('select');
            if (!selectElement.empty()) {
                // 重新生成时间段数据
                const updatedTimePeriods = this.getValidTimePeriods();
                this.timePeriods = updatedTimePeriods;
                // 更新选项文本
                const options = selectElement.selectAll('option');
                options.each(function (_d, i) {
                    if (i < updatedTimePeriods.length) {
                        d3.select(this).text(updatedTimePeriods[i].name);
                    }
                });
            }
        }
    }
    /**
     * 获取当前语种的 culture 代码
     */
    getCurrentCulture() {
        var _a, _b, _c, _e, _f, _g;
        // 获取当前语种ID
        const currentLanguageId = (_c = (_b = (_a = this.guiContext) === null || _a === void 0 ? void 0 : _a.getCurrentLanguageId) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : null;
        // 确定要使用的语种代码（culture）
        const defaultLanguage = ((_e = this.languageService) === null || _e === void 0 ? void 0 : _e.getDefaultLanguage()) || 'zh-CN';
        if (currentLanguageId === null || currentLanguageId === undefined) {
            // 设备未设置当前语种，使用默认语种
            return defaultLanguage;
        }
        else {
            // 设备已设置当前语种，获取对应的语种代码
            const currentLanguage = (_g = (_f = this.guiContext) === null || _f === void 0 ? void 0 : _f.getLanguageCultureById) === null || _g === void 0 ? void 0 : _g.call(_f, currentLanguageId);
            if (currentLanguage) {
                return currentLanguage;
            }
            else {
                // 无法获取语种代码，使用默认语种
                return defaultLanguage;
            }
        }
    }
    /**
     * 根据列索引获取表头翻译（从系统文本库获取多语种翻译）
     * 固定4项表头，按列索引顺序：告警名称、告警内容、告警等级、时间
     */
    getHeaderTextByColumn(columnIndex) {
        if (columnIndex < 0 || columnIndex > 3) {
            return '';
        }
        const currentCulture = this.getCurrentCulture();
        const systemType = SYSTEM_TEXT_LIBRARY_TYPES.COMPONENT_BUILTIN;
        const headerKeys = [
            ALARM_TABLE_HEADER_KEYS.ALARM_NAME,
            ALARM_TABLE_HEADER_KEYS.ALARM_MESSAGE,
            ALARM_TABLE_HEADER_KEYS.ALARM_LEVEL,
            ALARM_TABLE_HEADER_KEYS.TIME
        ];
        // 尝试从系统文本库获取翻译
        if (this.systemTextLibraryService) {
            const translation = this.systemTextLibraryService.getSystemTextValue(systemType, headerKeys[columnIndex], currentCulture);
            if (translation) {
                return translation;
            }
        }
        return '';
    }
    getValidTimePeriods() {
        const timePeriods = new Array();
        timePeriods.push({ key: 6, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_THIRTY_MINUTES) });
        timePeriods.push({ key: 1, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_ONE_HOUR) });
        timePeriods.push({ key: 7, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_EIGHT_HOURS) });
        timePeriods.push({ key: 2, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_TWENTY_FOUR_HOURS) });
        timePeriods.push({ key: 3, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_SEVEN_DAYS) });
        timePeriods.push({ key: 4, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_THIRTY_DAYS) });
        timePeriods.push({ key: 5, name: this.getTimePeriodText(TIME_PERIOD_KEYS.LAST_ONE_YEAR) });
        return timePeriods;
    }
    /**
     * 获取时间段文案（从系统文本库获取多语种翻译）
     */
    getTimePeriodText(textKey) {
        const currentCulture = this.getCurrentCulture();
        const systemType = SYSTEM_TEXT_LIBRARY_TYPES.COMPONENT_BUILTIN;
        if (this.systemTextLibraryService) {
            const translation = this.systemTextLibraryService.getSystemTextValue(systemType, textKey, currentCulture);
            if (translation) {
                return translation;
            }
        }
        return '';
    }
    getAlarmData() {
        this.rootElement.selectAll('*').remove();
        this.setStatusAsLoading();
        clearTimeout(this.getAlarmDataId);
        this.getAlarmDataId = setTimeout(() => {
            this.timePeriods = this.getValidTimePeriods();
            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.getAlarmData();
                            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() {
        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 col = 0; col < 4; col++) {
            const th = document.createElement('th');
            th.innerHTML = this.getHeaderTextByColumn(col);
            th.style.cssText = `width: ${this.model.widths[col] / this.model.size.width * 100}%;
                border-style: solid;
                border-color: ${this.model.generalSetting.splitLine};
                border-left-width: ${!col || 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.getAlarmData();
            });
            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-image', 'url(assets/img/last_page.svg)')
            .style('background-color', 'inherit')
            .on('click', () => { this.loadLastPage(); });
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background-image', 'url(assets/img/next_page.svg)')
            .style('margin', `0 ${this.displayOption.operationButtonMargin}px 0 0`)
            .style('background-color', 'inherit')
            .on('click', () => { this.loadNextPage(); });
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background-image', 'url(assets/img/previous_page.svg)')
            .style('margin', `0 ${this.displayOption.operationButtonMargin}px 0 0`)
            .style('background-color', 'inherit')
            .on('click', () => { this.loadPreviousPage(); });
        operationArea.append('button').style('width', buttonWidth).style('height', buttonHeight).style('border', 'none')
            .style('float', 'right').style('background-image', 'url(assets/img/first_page.svg)')
            .style('margin', `0 ${this.displayOption.operationButtonMargin}px 0 0`)
            .style('background-color', 'inherit')
            .on('click', () => { this.loadFirstPage(); });
        this.setStatusAsNormal();
    }
    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.getAlarmData();
        }
    }
    loadNextPage() {
        let last_page = Math.ceil(this.totalCount / this.pageSize);
        if (last_page)
            last_page--;
        if (this.page < last_page) {
            this.page++;
            this.getAlarmData();
        }
    }
    loadPreviousPage() {
        if (this.page > 0) {
            this.page--;
            this.getAlarmData();
        }
    }
    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.getAlarmData();
        }
    }
    setStatusAsNormal() {
        this.elementStatus = AlaertElementStatus.Normal;
        this.clearStatus();
    }
    setStatusAsLoading() {
        this.elementStatus = AlaertElementStatus.Loading;
        this.renderStatus('assets/img/loading.svg', '#226abc');
    }
    renderStatus(icon, stroke) {
        if (this.elementStatus === AlaertElementStatus.Normal) {
            this.clearStatus();
            return;
        }
        this.rootElement.append('rect').attr('id', 'StateFrame').attr('fill', 'transparent')
            .attr('width', this.model.size.width)
            .attr('height', this.model.size.height);
        const document = this.$element[0].ownerDocument;
        const currentRect = this.$element.find('rect#StateFrame').first();
        if (!currentRect.length) {
            return;
        }
        this.$element.find('image#StateImage').remove();
        const imgObj = document.createElementNS('http://www.w3.org/2000/svg', 'image');
        if (imgObj) {
            let x = Number(currentRect[0].getAttribute('width')) - 20;
            const currentRectX = currentRect[0].getAttribute('x');
            if (currentRectX !== null) {
                x += Number(currentRectX);
            }
            currentRect[0].setAttribute('stroke', stroke);
            currentRect[0].setAttribute('stroke-opacity', '0.5');
            imgObj.href.baseVal = icon;
            imgObj.setAttributeNS(null, 'id', 'StateImage');
            imgObj.setAttributeNS(null, 'x', x.toString());
            imgObj.setAttributeNS(null, 'y', '0');
            imgObj.setAttributeNS(null, 'height', '20px');
            imgObj.setAttributeNS(null, 'width', '20px');
            const titleElement = document.createElementNS('http://www.w3.org/2000/svg', 'title');
            imgObj.appendChild(titleElement);
            this.$element.append(imgObj);
        }
    }
    clearStatus() {
        const currentRect = this.$element.find('rect#StateFrame').first();
        if (!currentRect.length) {
            return;
        }
        const stroke = currentRect[0].getAttribute('stroke');
        if (stroke) {
            currentRect[0].removeAttribute('stroke');
        }
        this.$element.find('image#StateImage').remove();
    }
}
