// Copyright (c) Trung Le
// Distributed under the terms of the Modified BSD License.
import 'echarts-gl';
import { DOMWidgetView } from '@jupyter-widgets/base';
import { Debouncer } from '@lumino/polling';
import * as echarts from 'echarts';
import { INIT_PROPS } from './baseWidgetModel';
import { isLightTheme } from './tools';
class BaseEChartsWidgetView extends DOMWidgetView {
    constructor() {
        super(...arguments);
        this._eventHandlers = {};
        this._resizeDebouncer = new Debouncer(() => {
            var _a;
            if (this.el.clientWidth > 10 && this.el.clientHeight > 10) {
                // Do not resize if the element is hidden
                (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.resize();
            }
        }, 100);
    }
    initialize(parameters) {
        super.initialize(parameters);
        this.setupThemeListener();
        this.setupResizeListener();
        this.model.listenTo(this.model, 'change', this.valueChanged.bind(this));
        this.model.listenTo(this.model, 'msg:custom', this.onCustomMsg.bind(this));
    }
    render() {
        var _a;
        super.render();
        const widget = (_a = this.luminoWidget) !== null && _a !== void 0 ? _a : this.pWidget;
        if (['auto', null].includes(this.model.get('width'))) {
            widget.addClass('echarts-widget-auto-width');
        }
        if (['auto', null].includes(this.model.get('height'))) {
            widget.addClass('echarts-widget-auto-height');
        }
        this.setStyle();
    }
    _processLuminoMessage(msg) {
        var _a;
        const msgType = msg.type;
        if (msgType === 'after-attach') {
            this.initECharts();
            (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.resize();
        }
        if (msgType === 'resize') {
            this._resizeDebouncer.invoke();
        }
    }
    processPhosphorMessage(msg) {
        this._processLuminoMessage(msg);
    }
    processLuminoMessage(msg) {
        this._processLuminoMessage(msg);
    }
    initECharts() {
        let theme = this.model.get('theme');
        if (!theme) {
            if (BaseEChartsWidgetView.themeManager) {
                theme = isLightTheme() ? 'light' : 'dark';
            }
            else {
                theme = 'light';
            }
        }
        const devicePixelRatio = this.model.get('device_pixel_ratio');
        const renderer = this.model.get('renderer');
        const useDirtyRect = this.model.get('use_dirty_rect');
        const useCoarsePointer = this.model.get('use_coarse_pointer');
        const pointerSize = this.model.get('pointer_size');
        const width = this.model.get('width');
        const height = this.model.get('height');
        const locale = this.model.get('locale');
        const initOptions = {
            devicePixelRatio,
            renderer,
            useDirtyRect,
            useCoarsePointer,
            pointerSize,
            width,
            height,
            locale
        };
        this._myChart = echarts.init(this.el, theme, initOptions);
        this._myChart.setOption(this._createOptionDict());
        const msg = {
            action: 'widget_init'
        };
        this.send(msg);
    }
    valueChanged(changedModel) {
        var _a, _b;
        if (!changedModel) {
            // Event from the update manager
            (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.setOption(this._createOptionDict());
            return;
        }
        const changedDict = (_b = changedModel.changed) !== null && _b !== void 0 ? _b : {};
        Object.keys(changedDict).forEach(key => {
            var _a;
            if (key in INIT_PROPS) {
                // Init props changed
                this.recreateChart();
            }
            else if (key === 'style') {
                // Style changed
                this.setStyle();
            }
            else {
                // option or other keys changed
                (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.setOption(this._createOptionDict());
            }
        });
    }
    update_classes(old_classes, new_classes) {
        var _a;
        super.update_classes(old_classes, new_classes);
        (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.resize();
    }
    setStyle() {
        var _a;
        const style = this.model.get('style') || {};
        for (const [key, value] of Object.entries(style)) {
            const cssKey = key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);
            this.el.style.setProperty(cssKey, value);
        }
        (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.resize();
    }
    onCustomMsg(data) {
        var _a, _b, _c, _d, _e;
        const { action, payload } = data;
        switch (action) {
            case 'register_event': {
                const { event, query, handler_id } = payload;
                console.log('register_event', event, query, handler_id);
                const cb = (params) => {
                    const paramsStr = JSON.stringify(params, (key, value) => {
                        return key === 'event' ? undefined : value;
                    });
                    const msg = {
                        action: 'event_handler_params',
                        payload: {
                            event,
                            handlerId: handler_id,
                            params: JSON.parse(paramsStr)
                        }
                    };
                    this.send(msg);
                };
                if (typeof query !== 'string') {
                    (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.on(event, query, cb, this);
                }
                else {
                    if (query === '__all__') {
                        (_b = this._myChart) === null || _b === void 0 ? void 0 : _b.on(event, cb, this);
                    }
                    else {
                        (_c = this._myChart) === null || _c === void 0 ? void 0 : _c.on(event, query, cb, this);
                    }
                }
                const eventDict = this._eventHandlers[event];
                if (eventDict) {
                    eventDict[handler_id] = cb;
                }
                else {
                    this._eventHandlers[event] = { [handler_id]: cb };
                }
                break;
            }
            case 'unregister_event': {
                const { event, id_to_remove } = payload;
                if (!id_to_remove) {
                    (_d = this._myChart) === null || _d === void 0 ? void 0 : _d.off(event);
                    delete this._eventHandlers[event];
                }
                else {
                    id_to_remove.forEach(handlerId => {
                        var _a, _b;
                        const cb = (_a = this._eventHandlers[event]) === null || _a === void 0 ? void 0 : _a[handlerId];
                        if (cb) {
                            (_b = this._myChart) === null || _b === void 0 ? void 0 : _b.off(event, cb);
                            delete this._eventHandlers[event][handlerId];
                        }
                    });
                }
                break;
            }
            case 'dispatch_action': {
                (_e = this._myChart) === null || _e === void 0 ? void 0 : _e.dispatchAction(payload);
                break;
            }
            default:
                break;
        }
    }
    recreateChart() {
        var _a;
        (_a = this._myChart) === null || _a === void 0 ? void 0 : _a.dispose();
        this.initECharts();
    }
    setupThemeListener() {
        const themeManager = BaseEChartsWidgetView.themeManager;
        if (themeManager) {
            themeManager.themeChanged.connect(() => {
                this.recreateChart();
            });
        }
    }
    setupResizeListener() {
        window.addEventListener('resize', () => this._resizeDebouncer.invoke());
    }
}
BaseEChartsWidgetView.themeManager = null;
export { BaseEChartsWidgetView };
