/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import * as zrUtil from 'zrender/src/core/util';
import ExtensionAPI from '../../core/ExtensionAPI';
import { ZRenderType } from 'zrender/src/zrender';
import { TooltipOption } from './TooltipModel';
import { ZRColor } from '../../util/types';
import Model from '../../model/Model';
import ZRText, { TextStyleProps } from 'zrender/src/graphic/Text';
import { TooltipMarkupStyleCreator, getPaddingFromTooltipModel } from './tooltipMarkup';
import { throwError } from '../../util/log';

class TooltipRichContent {

    private _zr: ZRenderType;

    private _show = false;

    private _styleCoord: [number, number, number, number] = [0, 0, 0, 0];

    private _hideTimeout: number;

    private _enterable = true;

    private _inContent: boolean;

    private _hideDelay: number;

    el: ZRText;

    constructor(api: ExtensionAPI) {
        this._zr = api.getZr();
        makeStyleCoord(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2);
    }

    /**
     * Update when tooltip is rendered
     */
    update(tooltipModel: Model<TooltipOption>) {
        const alwaysShowContent = tooltipModel.get('alwaysShowContent');
        alwaysShowContent && this._moveIfResized();
    }

    show() {
        if (this._hideTimeout) {
            clearTimeout(this._hideTimeout);
        }

        this.el.show();
        this._show = true;
    }

    /**
     * Set tooltip content
     */
    setContent(
        content: string | HTMLElement | HTMLElement[],
        markupStyleCreator: TooltipMarkupStyleCreator,
        tooltipModel: Model<TooltipOption>,
        borderColor: ZRColor,
        arrowPosition: TooltipOption['position']
    ) {
        if (zrUtil.isObject(content)) {
            throwError(__DEV__ ? 'Passing DOM nodes as content is not supported in richText tooltip!' : '');
        }
        if (this.el) {
            this._zr.remove(this.el);
        }

        const textStyleModel = tooltipModel.getModel('textStyle');

        this.el = new ZRText({
            style: {
                rich: markupStyleCreator.richTextStyles,
                text: content as string,
                lineHeight: 22,
                borderWidth: 1,
                borderColor: borderColor as string,
                textShadowColor: textStyleModel.get('textShadowColor'),
                fill: tooltipModel.get(['textStyle', 'color']),
                padding: getPaddingFromTooltipModel(tooltipModel, 'richText'),
                verticalAlign: 'top',
                align: 'left'
            },
            z: tooltipModel.get('z')
        });
        zrUtil.each([
            'backgroundColor', 'borderRadius', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'
        ] as const, propName => {
            (this.el.style as any)[propName] = tooltipModel.get(propName);
        });
        zrUtil.each([
            'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'
        ] as const, propName => {
            this.el.style[propName] = textStyleModel.get(propName) || 0;
        });

        this._zr.add(this.el);

        const self = this;
        this.el.on('mouseover', function () {
            // clear the timeout in hideLater and keep showing tooltip
            if (self._enterable) {
                clearTimeout(self._hideTimeout);
                self._show = true;
            }
            self._inContent = true;
        });
        this.el.on('mouseout', function () {
            if (self._enterable) {
                if (self._show) {
                    self.hideLater(self._hideDelay);
                }
            }
            self._inContent = false;
        });
    }

    setEnterable(enterable?: boolean) {
        this._enterable = enterable;
    }

    getSize() {
        const el = this.el;
        const bounding = this.el.getBoundingRect();
        // bounding rect does not include shadow. For renderMode richText,
        // if overflow, it will be cut. So calculate them accurately.
        const shadowOuterSize = calcShadowOuterSize(el.style);
        return [
            bounding.width + shadowOuterSize.left + shadowOuterSize.right,
            bounding.height + shadowOuterSize.top + shadowOuterSize.bottom
        ];
    }

    moveTo(x: number, y: number) {
        const el = this.el;
        if (el) {
            const styleCoord = this._styleCoord;
            makeStyleCoord(styleCoord, this._zr, x, y);
            x = styleCoord[0];
            y = styleCoord[1];
            const style = el.style;
            const borderWidth = mathMaxWith0(style.borderWidth || 0);
            const shadowOuterSize = calcShadowOuterSize(style);
            // rich text x, y do not include border.
            el.x = x + borderWidth + shadowOuterSize.left;
            el.y = y + borderWidth + shadowOuterSize.top;
            el.markRedraw();
        }
    }


    /**
     * when `alwaysShowContent` is true,
     * move the tooltip after chart resized
     */
    _moveIfResized() {
        // The ratio of left to width
        const ratioX = this._styleCoord[2];
        // The ratio of top to height
        const ratioY = this._styleCoord[3];
        this.moveTo(
            ratioX * this._zr.getWidth(),
            ratioY * this._zr.getHeight()
        );
    }

    hide() {
        if (this.el) {
            this.el.hide();
        }
        this._show = false;
    }

    hideLater(time?: number) {
        if (this._show && !(this._inContent && this._enterable)) {
            if (time) {
                this._hideDelay = time;
                // Set show false to avoid invoke hideLater multiple times
                this._show = false;
                this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time) as any;
            }
            else {
                this.hide();
            }
        }
    }

    isShow() {
        return this._show;
    }

    dispose() {
        this._zr.remove(this.el);
    }
}

function mathMaxWith0(val: number): number {
    return Math.max(0, val);
}

function calcShadowOuterSize(style: TextStyleProps) {
    const shadowBlur = mathMaxWith0(style.shadowBlur || 0);
    const shadowOffsetX = mathMaxWith0(style.shadowOffsetX || 0);
    const shadowOffsetY = mathMaxWith0(style.shadowOffsetY || 0);
    return {
        left: mathMaxWith0(shadowBlur - shadowOffsetX),
        right: mathMaxWith0(shadowBlur + shadowOffsetX),
        top: mathMaxWith0(shadowBlur - shadowOffsetY),
        bottom: mathMaxWith0(shadowBlur + shadowOffsetY)
    };
}

function makeStyleCoord(out: number[], zr: ZRenderType, zrX: number, zrY: number) {
    out[0] = zrX;
    out[1] = zrY;
    out[2] = out[0] / zr.getWidth();
    out[3] = out[1] / zr.getHeight();
}

export default TooltipRichContent;
