/**
 * DevExtreme (viz/core/tooltip.js)
 * Version: 20.2.0 (build 20182-0310)
 * Build date: Tue Jun 30 2020
 *
 * Copyright (c) 2012 - 2020 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
var _dom_adapter = require("../../core/dom_adapter");
var _dom_adapter2 = _interopRequireDefault(_dom_adapter);
var _window = require("../../core/utils/window");
var _window2 = _interopRequireDefault(_window);
var _inflector = require("../../core/utils/inflector");
var _inflector2 = _interopRequireDefault(_inflector);
var _renderer = require("../../core/renderer");
var _renderer2 = _interopRequireDefault(_renderer);
var _renderer3 = require("./renderers/renderer");
var _renderer4 = _interopRequireDefault(_renderer3);
var _type = require("../../core/utils/type");
var _type2 = _interopRequireDefault(_type);
var _extend = require("../../core/utils/extend");
var _utils = require("./utils");
var _utils2 = _interopRequireDefault(_utils);
var _format_helper = require("../../format_helper");
var _plaque = require("./plaque");

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        "default": obj
    }
}
var mathCeil = Math.ceil;
var mathMax = Math.max;
var mathMin = Math.min;
var window = _window2.default.getWindow();
var DEFAULT_HTML_GROUP_WIDTH = 3e3;

function hideElement($element) {
    $element.css({
        left: "-9999px"
    }).detach()
}

function getSpecialFormatOptions(options, specialFormat) {
    var result = options;
    switch (specialFormat) {
        case "argument":
            result = {
                format: options.argumentFormat
            };
            break;
        case "percent":
            result = {
                format: {
                    type: "percent",
                    precision: options.format && options.format.percentPrecision
                }
            }
    }
    return result
}

function Tooltip(params) {
    var that = this;
    var renderer;
    that._eventTrigger = params.eventTrigger;
    that._widgetRoot = params.widgetRoot;
    that._widget = params.widget;
    that._wrapper = (0, _renderer2.default)("<div>").css({
        position: "absolute",
        overflow: "hidden",
        pointerEvents: "none"
    }).addClass(params.cssClass);
    that._renderer = renderer = new _renderer4.default.Renderer({
        pathModified: params.pathModified,
        container: that._wrapper[0]
    });
    var root = renderer.root;
    root.attr({
        "pointer-events": "none"
    });
    that._text = renderer.text(void 0, 0, 0);
    that._textGroupHtml = (0, _renderer2.default)("<div>").css({
        position: "absolute",
        padding: 0,
        margin: 0,
        border: "0px solid transparent"
    }).appendTo(that._wrapper);
    that._textHtml = (0, _renderer2.default)("<div>").css({
        position: "relative",
        display: "inline-block",
        padding: 0,
        margin: 0,
        border: "0px solid transparent"
    }).appendTo(that._textGroupHtml)
}
Tooltip.prototype = {
    constructor: Tooltip,
    dispose: function() {
        this._wrapper.remove();
        this._renderer.dispose();
        this._options = this._widgetRoot = null
    },
    _getContainer: function() {
        var options = this._options;
        var container = (0, _renderer2.default)(this._widgetRoot).closest(options.container);
        if (0 === container.length) {
            container = (0, _renderer2.default)(options.container)
        }
        return (container.length ? container : (0, _renderer2.default)("body")).get(0)
    },
    setTemplate: function(contentTemplate) {
        var that = this;
        that._template = contentTemplate ? that._widget._getTemplate(contentTemplate) : null
    },
    setOptions: function(options) {
        var _this = this;
        options = options || {};
        var that = this;
        that._options = options;
        that._textFontStyles = _utils2.default.patchFontOptions(options.font);
        that._textFontStyles.color = that._textFontStyles.fill;
        that._wrapper.css({
            zIndex: options.zIndex
        });
        that._customizeTooltip = options.customizeTooltip;
        var textGroupHtml = that._textGroupHtml;
        var textHtml = that._textHtml;
        if (this.plaque) {
            this.plaque.clear()
        }
        this.setTemplate(options.contentTemplate);
        var pointerEvents = options.interactive ? "auto" : "none";
        if (options.interactive) {
            this._renderer.root.css({
                "-ms-user-select": "auto",
                "-moz-user-select": "auto",
                "-webkit-user-select": "auto"
            })
        }
        var drawTooltip = function(tooltip, group) {
            var state = tooltip._state;
            var template = tooltip._template;
            var useTemplate = template && !state.formatObject.skipTemplate;
            if (state.html || useTemplate) {
                if (!state.isRendered) {
                    if (useTemplate) {
                        template.render({
                            model: state.formatObject,
                            container: textHtml
                        });
                        state.html = textHtml.html();
                        if (!state.html) {
                            _this.plaque.clear();
                            return
                        }
                    } else {
                        that._text.attr({
                            text: ""
                        });
                        textHtml.html(state.html)
                    }
                    textGroupHtml.css({
                        color: state.textColor,
                        width: DEFAULT_HTML_GROUP_WIDTH,
                        pointerEvents: pointerEvents
                    });
                    state.isRendered = true
                }
            } else {
                that._text.css({
                    fill: state.textColor
                }).attr({
                    text: state.text,
                    "class": options.cssClass,
                    "pointer-events": pointerEvents
                }).append(group.attr({
                    align: options.textAlignment
                }))
            }
            tooltip.plaque.customizeCloud({
                fill: state.color,
                stroke: state.borderColor,
                "pointer-events": pointerEvents
            })
        };
        this.plaque = new _plaque.Plaque({
            opacity: that._options.opacity,
            color: that._options.color,
            border: that._options.border,
            paddingLeftRight: that._options.paddingLeftRight,
            paddingTopBottom: that._options.paddingTopBottom,
            arrowLength: that._options.arrowLength,
            arrowWidth: 20,
            shadow: that._options.shadow,
            cornerRadius: that._options.cornerRadius
        }, that, that._renderer.root, drawTooltip, true, function(tooltip, g) {
            var state = tooltip._state;
            if (state.html) {
                var bBox;
                var getComputedStyle = window.getComputedStyle;
                if (getComputedStyle) {
                    bBox = getComputedStyle(textHtml.get(0));
                    bBox = {
                        x: 0,
                        y: 0,
                        width: mathCeil(parseFloat(bBox.width)),
                        height: mathCeil(parseFloat(bBox.height))
                    }
                } else {
                    bBox = textHtml.get(0).getBoundingClientRect();
                    bBox = {
                        x: 0,
                        y: 0,
                        width: mathCeil(bBox.width ? bBox.width : bBox.right - bBox.left),
                        height: mathCeil(bBox.height ? bBox.height : bBox.bottom - bBox.top)
                    }
                }
                return bBox
            }
            return g.getBBox()
        }, function(tooltip, g, x, y) {
            var state = tooltip._state;
            if (state.html) {
                that._textGroupHtml.css({
                    left: x,
                    top: y
                })
            } else {
                g.move(x, y)
            }
        });
        return that
    },
    setRendererOptions: function(options) {
        this._renderer.setOptions(options);
        this._textGroupHtml.css({
            direction: options.rtl ? "rtl" : "ltr"
        });
        return this
    },
    render: function() {
        var that = this;
        hideElement(that._wrapper);
        var normalizedCSS = {};
        for (var name in that._textFontStyles) {
            normalizedCSS[_inflector2.default.camelize(name)] = that._textFontStyles[name]
        }
        that._textGroupHtml.css(normalizedCSS);
        that._text.css(that._textFontStyles);
        that._eventData = null;
        return that
    },
    update: function(options) {
        return this.setOptions(options).render()
    },
    _prepare: function(formatObject, state) {
        var customizeTooltip = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : this._customizeTooltip;
        var options = this._options;
        var customize = {};
        if (_type2.default.isFunction(customizeTooltip)) {
            customize = customizeTooltip.call(formatObject, formatObject);
            customize = _type2.default.isPlainObject(customize) ? customize : {};
            if ("text" in customize) {
                state.text = _type2.default.isDefined(customize.text) ? String(customize.text) : ""
            }
            if ("html" in customize) {
                state.html = _type2.default.isDefined(customize.html) ? String(customize.html) : ""
            }
        }
        if (!("text" in state) && !("html" in state)) {
            state.text = formatObject.valueText || formatObject.description || ""
        }
        state.color = customize.color || options.color;
        state.borderColor = customize.borderColor || (options.border || {}).color;
        state.textColor = customize.fontColor || (this._textFontStyles || {}).color;
        return !!state.text || !!state.html || !!this._template
    },
    show: function(formatObject, params, eventData, customizeTooltip) {
        var that = this;
        var state = {
            formatObject: formatObject
        };
        if (!that._prepare(formatObject, state, customizeTooltip)) {
            return false
        }
        that._state = state;
        that._wrapper.appendTo(that._getContainer());
        that._clear();
        this.plaque.clear().draw((0, _extend.extend)({}, that._options, {
            canvas: that._getCanvas()
        }, state, {
            x: params.x,
            y: params.y,
            offset: params.offset
        }));
        that.moveWrapper();
        that._eventData && that._eventTrigger("tooltipHidden", that._eventData);
        that._eventData = eventData;
        that._eventTrigger("tooltipShown", that._eventData);
        return true
    },
    hide: function() {
        var that = this;
        hideElement(that._wrapper);
        if (that._eventData) {
            that._eventTrigger("tooltipHidden", that._eventData);
            that._clear();
            that._eventData = null
        }
    },
    _clear: function() {
        this._textHtml.empty()
    },
    move: function(x, y, offset) {
        this.plaque.draw({
            x: x,
            y: y,
            offset: offset,
            canvas: this._getCanvas()
        });
        this.moveWrapper()
    },
    moveWrapper: function() {
        var that = this;
        var plaqueBBox = this.plaque.getBBox();
        that._renderer.resize(plaqueBBox.width, plaqueBBox.height);
        var offset = that._wrapper.css({
            left: 0,
            top: 0
        }).offset();
        var left = plaqueBBox.x;
        var top = plaqueBBox.y;
        that._wrapper.css({
            left: left - offset.left,
            top: top - offset.top
        });
        this.plaque.moveRoot(-left, -top);
        if (this._state.html) {
            that._textHtml.css({
                left: -left,
                top: -top
            });
            that._textGroupHtml.css({
                width: plaqueBBox.width
            })
        }
    },
    formatValue: function(value, _specialFormat) {
        var options = _specialFormat ? getSpecialFormatOptions(this._options, _specialFormat) : this._options;
        return (0, _format_helper.format)(value, options.format)
    },
    getLocation: function() {
        return _utils2.default.normalizeEnum(this._options.location)
    },
    isEnabled: function() {
        return !!this._options.enabled
    },
    isShared: function() {
        return !!this._options.shared
    },
    _getCanvas: function() {
        var container = this._getContainer();
        var containerBox = container.getBoundingClientRect();
        var html = _dom_adapter2.default.getDocumentElement();
        var document = _dom_adapter2.default.getDocument();
        var left = window.pageXOffset || html.scrollLeft || 0;
        var top = window.pageYOffset || html.scrollTop || 0;
        var box = {
            left: left,
            top: top,
            width: html.clientWidth + left || 0,
            height: mathMax(document.body.scrollHeight, html.scrollHeight, document.body.offsetHeight, html.offsetHeight, document.body.clientHeight, html.clientHeight) || 0,
            right: 0,
            bottom: 0
        };
        if (container !== _dom_adapter2.default.getBody()) {
            left = mathMax(box.left, box.left + containerBox.left);
            top = mathMax(box.top, box.top + containerBox.top);
            box.width = mathMin(containerBox.width, box.width) + left + box.left;
            box.height = mathMin(containerBox.height, box.height) + top + box.top;
            box.left = left;
            box.top = top
        }
        return box
    }
};
exports.Tooltip = Tooltip;
exports.plugin = {
    name: "tooltip",
    init: function() {
        this._initTooltip()
    },
    dispose: function() {
        this._disposeTooltip()
    },
    members: {
        _initTooltip: function() {
            this._tooltip = new exports.Tooltip({
                cssClass: this._rootClassPrefix + "-tooltip",
                eventTrigger: this._eventTrigger,
                pathModified: this.option("pathModified"),
                widgetRoot: this.element(),
                widget: this
            })
        },
        _disposeTooltip: function() {
            this._tooltip.dispose();
            this._tooltip = null
        },
        _setTooltipRendererOptions: function() {
            this._tooltip.setRendererOptions(this._getRendererOptions())
        },
        _setTooltipOptions: function() {
            this._tooltip.update(this._getOption("tooltip"))
        }
    },
    extenders: {
        _stopCurrentHandling: function() {
            this._tooltip && this._tooltip.hide()
        }
    },
    customize: function(constructor) {
        var proto = constructor.prototype;
        proto._eventsMap.onTooltipShown = {
            name: "tooltipShown"
        };
        proto._eventsMap.onTooltipHidden = {
            name: "tooltipHidden"
        };
        constructor.addChange({
            code: "TOOLTIP_RENDERER",
            handler: function() {
                this._setTooltipRendererOptions()
            },
            isThemeDependent: true,
            isOptionChange: true
        });
        constructor.addChange({
            code: "TOOLTIP",
            handler: function() {
                this._setTooltipOptions()
            },
            isThemeDependent: true,
            isOptionChange: true,
            option: "tooltip"
        })
    },
    fontFields: ["tooltip.font"]
};
