/*
* 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.
*/

// TODO: move labels out of viewport.

import {
    Text as ZRText,
    BoundingRect,
    Polyline,
    updateProps,
    initProps,
    isElementRemoved
} from '../util/graphic';
import { getECData } from '../util/innerStore';
import ExtensionAPI from '../core/ExtensionAPI';
import {
    ZRTextAlign,
    ZRTextVerticalAlign,
    LabelLayoutOption,
    LabelLayoutOptionCallback,
    LabelLayoutOptionCallbackParams,
    LabelLineOption,
    Dictionary,
    ECElement,
    SeriesDataType
} from '../util/types';
import { parsePercent } from '../util/number';
import ChartView from '../view/Chart';
import Element, { ElementTextConfig } from 'zrender/src/Element';
import { RectLike } from 'zrender/src/core/BoundingRect';
import Transformable from 'zrender/src/core/Transformable';
import { updateLabelLinePoints, setLabelLineStyle, getLabelLineStatesModels } from './labelGuideHelper';
import SeriesModel from '../model/Series';
import { makeInner } from '../util/model';
import { retrieve2, each, keys, isFunction, filter, indexOf } from 'zrender/src/core/util';
import { PathStyleProps } from 'zrender/src/graphic/Path';
import Model from '../model/Model';
import { prepareLayoutList, hideOverlap, shiftLayoutOnX, shiftLayoutOnY } from './labelLayoutHelper';
import { labelInner, animateLabelValue } from './labelStyle';

interface LabelDesc {
    label: ZRText
    labelLine: Polyline

    seriesModel: SeriesModel
    // Can be null if label doesn't represent any data.
    dataIndex?: number
    // Can be null if label doesn't represent any data.
    dataType?: SeriesDataType

    layoutOption: LabelLayoutOptionCallback | LabelLayoutOption
    computedLayoutOption: LabelLayoutOption

    hostRect: RectLike
    rect: RectLike

    priority: number

    defaultAttr: SavedLabelAttr
}

interface SavedLabelAttr {
    ignore: boolean
    labelGuideIgnore: boolean

    x: number
    y: number
    scaleX: number
    scaleY: number
    rotation: number

    style: {
        align: ZRTextAlign
        verticalAlign: ZRTextVerticalAlign
        width: number
        height: number
        fontSize: number | string

        x: number
        y: number
    }

    cursor: string

    // Configuration in attached element
    attachedPos: ElementTextConfig['position']
    attachedRot: ElementTextConfig['rotation']

}

function cloneArr(points: number[][]) {
    if (points) {
        const newPoints = [];
        for (let i = 0; i < points.length; i++) {
            newPoints.push(points[i].slice());
        }
        return newPoints;
    }
}

function prepareLayoutCallbackParams(labelItem: LabelDesc, hostEl?: Element): LabelLayoutOptionCallbackParams {
    const label = labelItem.label;
    const labelLine = hostEl && hostEl.getTextGuideLine();
    return {
        dataIndex: labelItem.dataIndex,
        dataType: labelItem.dataType,
        seriesIndex: labelItem.seriesModel.seriesIndex,
        text: labelItem.label.style.text,
        rect: labelItem.hostRect,
        labelRect: labelItem.rect,
        // x: labelAttr.x,
        // y: labelAttr.y,
        align: label.style.align,
        verticalAlign: label.style.verticalAlign,
        labelLinePoints: cloneArr(labelLine && labelLine.shape.points)
    };
}

const LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height', 'fontSize'] as const;

const dummyTransformable = new Transformable();

const labelLayoutInnerStore = makeInner<{
    oldLayout: {
        x: number,
        y: number,
        rotation: number
    },
    oldLayoutSelect?: {
        x?: number,
        y?: number,
        rotation?: number
    },
    oldLayoutEmphasis?: {
        x?: number,
        y?: number,
        rotation?: number
    },

    needsUpdateLabelLine?: boolean
}, ZRText>();

const labelLineAnimationStore = makeInner<{
    oldLayout: {
        points: number[][]
    }
}, Polyline>();

type LabelLineOptionMixin = {
    labelLine: LabelLineOption,
    emphasis: { labelLine: LabelLineOption }
};

function extendWithKeys(target: Dictionary<any>, source: Dictionary<any>, keys: string[]) {
    for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        if (source[key] != null) {
            target[key] = source[key];
        }
    }
}

const LABEL_LAYOUT_PROPS = ['x', 'y', 'rotation'];

class LabelManager {

    private _labelList: LabelDesc[] = [];
    private _chartViewList: ChartView[] = [];

    constructor() {}

    clearLabels() {
        this._labelList = [];
        this._chartViewList = [];
    }

    /**
     * Add label to manager
     */
    private _addLabel(
        dataIndex: number | null | undefined,
        dataType: SeriesDataType | null | undefined,
        seriesModel: SeriesModel,
        label: ZRText,
        layoutOption: LabelDesc['layoutOption']
    ) {
        const labelStyle = label.style;
        const hostEl = label.__hostTarget;
        const textConfig = hostEl.textConfig || {};

        // TODO: If label is in other state.
        const labelTransform = label.getComputedTransform();
        const labelRect = label.getBoundingRect().plain();
        BoundingRect.applyTransform(labelRect, labelRect, labelTransform);

        if (labelTransform) {
            dummyTransformable.setLocalTransform(labelTransform);
        }
        else {
            // Identity transform.
            dummyTransformable.x = dummyTransformable.y = dummyTransformable.rotation =
                dummyTransformable.originX = dummyTransformable.originY = 0;
            dummyTransformable.scaleX = dummyTransformable.scaleY = 1;
        }

        const host = label.__hostTarget;
        let hostRect;
        if (host) {
            hostRect = host.getBoundingRect().plain();
            const transform = host.getComputedTransform();
            BoundingRect.applyTransform(hostRect, hostRect, transform);
        }

        const labelGuide = hostRect && host.getTextGuideLine();

        this._labelList.push({
            label,
            labelLine: labelGuide,

            seriesModel,
            dataIndex,
            dataType,

            layoutOption,
            computedLayoutOption: null,

            rect: labelRect,

            hostRect,

            // Label with lower priority will be hidden when overlapped
            // Use rect size as default priority
            priority: hostRect ? hostRect.width * hostRect.height : 0,

            // Save default label attributes.
            // For restore if developers want get back to default value in callback.
            defaultAttr: {
                ignore: label.ignore,
                labelGuideIgnore: labelGuide && labelGuide.ignore,

                x: dummyTransformable.x,
                y: dummyTransformable.y,
                scaleX: dummyTransformable.scaleX,
                scaleY: dummyTransformable.scaleY,
                rotation: dummyTransformable.rotation,

                style: {
                    x: labelStyle.x,
                    y: labelStyle.y,

                    align: labelStyle.align,
                    verticalAlign: labelStyle.verticalAlign,
                    width: labelStyle.width,
                    height: labelStyle.height,

                    fontSize: labelStyle.fontSize
                },

                cursor: label.cursor,

                attachedPos: textConfig.position,
                attachedRot: textConfig.rotation
            }
        });
    }

    addLabelsOfSeries(chartView: ChartView) {
        this._chartViewList.push(chartView);

        const seriesModel = chartView.__model;

        const layoutOption = seriesModel.get('labelLayout');

        /**
         * Ignore layouting if it's not specified anything.
         */
        if (!(isFunction(layoutOption) || keys(layoutOption).length)) {
            return;
        }

        chartView.group.traverse((child) => {
            if (child.ignore) {
                return true;    // Stop traverse descendants.
            }

            // Only support label being hosted on graphic elements.
            const textEl = child.getTextContent();
            const ecData = getECData(child);
            // Can only attach the text on the element with dataIndex
            if (textEl && !(textEl as ECElement).disableLabelLayout) {
                this._addLabel(ecData.dataIndex, ecData.dataType, seriesModel, textEl, layoutOption);
            }
        });
    }

    updateLayoutConfig(api: ExtensionAPI) {
        const width = api.getWidth();
        const height = api.getHeight();

        function createDragHandler(el: Element, labelLineModel: Model) {
            return function () {
                updateLabelLinePoints(el, labelLineModel);
            };
        }
        for (let i = 0; i < this._labelList.length; i++) {
            const labelItem = this._labelList[i];
            const label = labelItem.label;
            const hostEl = label.__hostTarget;
            const defaultLabelAttr = labelItem.defaultAttr;
            let layoutOption;
            // TODO A global layout option?
            if (typeof labelItem.layoutOption === 'function') {
                layoutOption = labelItem.layoutOption(
                    prepareLayoutCallbackParams(labelItem, hostEl)
                );
            }
            else {
                layoutOption = labelItem.layoutOption;
            }

            layoutOption = layoutOption || {};
            labelItem.computedLayoutOption = layoutOption;

            const degreeToRadian = Math.PI / 180;
            // TODO hostEl should always exists.
            // Or label should not have parent because the x, y is all in global space.
            if (hostEl) {
                hostEl.setTextConfig({
                    // Force to set local false.
                    local: false,
                    // Ignore position and rotation config on the host el if x or y is changed.
                    position: (layoutOption.x != null || layoutOption.y != null)
                        ? null : defaultLabelAttr.attachedPos,
                    // Ignore rotation config on the host el if rotation is changed.
                    rotation: layoutOption.rotate != null
                        ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot,
                    offset: [layoutOption.dx || 0, layoutOption.dy || 0]
                });
            }
            let needsUpdateLabelLine = false;
            if (layoutOption.x != null) {
                // TODO width of chart view.
                label.x = parsePercent(layoutOption.x, width);
                label.setStyle('x', 0);  // Ignore movement in style. TODO: origin.
                needsUpdateLabelLine = true;
            }
            else {
                label.x = defaultLabelAttr.x;
                label.setStyle('x', defaultLabelAttr.style.x);
            }

            if (layoutOption.y != null) {
                // TODO height of chart view.
                label.y = parsePercent(layoutOption.y, height);
                label.setStyle('y', 0);  // Ignore movement in style.
                needsUpdateLabelLine = true;
            }
            else {
                label.y = defaultLabelAttr.y;
                label.setStyle('y', defaultLabelAttr.style.y);
            }

            if (layoutOption.labelLinePoints) {
                const guideLine = hostEl.getTextGuideLine();
                if (guideLine) {
                    guideLine.setShape({ points: layoutOption.labelLinePoints });
                    // Not update
                    needsUpdateLabelLine = false;
                }
            }

            const labelLayoutStore = labelLayoutInnerStore(label);
            labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine;

            label.rotation = layoutOption.rotate != null
                ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation;

            label.scaleX = defaultLabelAttr.scaleX;
            label.scaleY = defaultLabelAttr.scaleY;

            for (let k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) {
                const key = LABEL_OPTION_TO_STYLE_KEYS[k];
                label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]);
            }


            if (layoutOption.draggable) {
                label.draggable = true;
                label.cursor = 'move';
                if (hostEl) {
                    let hostModel: Model<LabelLineOptionMixin> =
                        labelItem.seriesModel as SeriesModel<LabelLineOptionMixin>;
                    if (labelItem.dataIndex != null) {
                        const data = labelItem.seriesModel.getData(labelItem.dataType);
                        hostModel = data.getItemModel<LabelLineOptionMixin>(labelItem.dataIndex);
                    }
                    label.on('drag', createDragHandler(hostEl, hostModel.getModel('labelLine')));
                }
            }
            else {
                // TODO Other drag functions?
                label.off('drag');
                label.cursor = defaultLabelAttr.cursor;
            }
        }
    }

    layout(api: ExtensionAPI) {
        const width = api.getWidth();
        const height = api.getHeight();

        const labelList = prepareLayoutList(this._labelList);
        const labelsNeedsAdjustOnX = filter(labelList, function (item) {
            return item.layoutOption.moveOverlap === 'shiftX';
        });
        const labelsNeedsAdjustOnY = filter(labelList, function (item) {
            return item.layoutOption.moveOverlap === 'shiftY';
        });

        shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width);
        shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height);

        const labelsNeedsHideOverlap = filter(labelList, function (item) {
            return item.layoutOption.hideOverlap;
        });

        hideOverlap(labelsNeedsHideOverlap);
    }

    /**
     * Process all labels. Not only labels with layoutOption.
     */
    processLabelsOverall() {
        each(this._chartViewList, (chartView) => {
            const seriesModel = chartView.__model;
            const ignoreLabelLineUpdate = chartView.ignoreLabelLineUpdate;
            const animationEnabled = seriesModel.isAnimationEnabled();

            chartView.group.traverse((child) => {
                if (child.ignore) {
                    return true;    // Stop traverse descendants.
                }

                let needsUpdateLabelLine = !ignoreLabelLineUpdate;
                const label = child.getTextContent();
                if (!needsUpdateLabelLine && label) {
                    needsUpdateLabelLine = labelLayoutInnerStore(label).needsUpdateLabelLine;
                }
                if (needsUpdateLabelLine) {
                    this._updateLabelLine(child, seriesModel);
                }

                if (animationEnabled) {
                    this._animateLabels(child, seriesModel);
                }
            });
        });
    }

    private _updateLabelLine(el: Element, seriesModel: SeriesModel) {
        // Only support label being hosted on graphic elements.
        const textEl = el.getTextContent();
        // Update label line style.
        const ecData = getECData(el);
        const dataIndex = ecData.dataIndex;

        // Only support labelLine on the labels represent data.
        if (textEl && dataIndex != null) {
            const data = seriesModel.getData(ecData.dataType);
            const itemModel = data.getItemModel<LabelLineOptionMixin>(dataIndex);

            const defaultStyle: PathStyleProps = {};
            const visualStyle = data.getItemVisual(dataIndex, 'style');
            const visualType = data.getVisual('drawType');
            // Default to be same with main color
            defaultStyle.stroke = visualStyle[visualType];

            const labelLineModel = itemModel.getModel('labelLine');

            setLabelLineStyle(el, getLabelLineStatesModels(itemModel), defaultStyle);

            updateLabelLinePoints(el, labelLineModel);
        }
    }

    private _animateLabels(el: Element, seriesModel: SeriesModel) {
        const textEl = el.getTextContent();
        const guideLine = el.getTextGuideLine();
        // Animate
        if (textEl
            && !textEl.ignore
            && !textEl.invisible
            && !(el as ECElement).disableLabelAnimation
            && !isElementRemoved(el)
        ) {
            const layoutStore = labelLayoutInnerStore(textEl);
            const oldLayout = layoutStore.oldLayout;
            const ecData = getECData(el);
            const dataIndex = ecData.dataIndex;
            const newProps = {
                x: textEl.x,
                y: textEl.y,
                rotation: textEl.rotation
            };
            const data = seriesModel.getData(ecData.dataType);

            if (!oldLayout) {
                textEl.attr(newProps);
                // Disable fade in animation if value animation is enabled.
                if (!labelInner(textEl).valueAnimation) {
                    const oldOpacity = retrieve2(textEl.style.opacity, 1);
                    // Fade in animation
                    textEl.style.opacity = 0;
                    initProps(textEl, {
                        style: { opacity: oldOpacity }
                    }, seriesModel, dataIndex);
                }
            }
            else {
                textEl.attr(oldLayout);

                // Make sure the animation from is in the right status.
                const prevStates = el.prevStates;
                if (prevStates) {
                    if (indexOf(prevStates, 'select') >= 0) {
                        textEl.attr(layoutStore.oldLayoutSelect);
                    }
                    if (indexOf(prevStates, 'emphasis') >= 0) {
                        textEl.attr(layoutStore.oldLayoutEmphasis);
                    }
                }
                updateProps(textEl, newProps, seriesModel, dataIndex);
            }
            layoutStore.oldLayout = newProps;

            if (textEl.states.select) {
                const layoutSelect = layoutStore.oldLayoutSelect = {};
                extendWithKeys(layoutSelect, newProps, LABEL_LAYOUT_PROPS);
                extendWithKeys(layoutSelect, textEl.states.select, LABEL_LAYOUT_PROPS);
            }

            if (textEl.states.emphasis) {
                const layoutEmphasis = layoutStore.oldLayoutEmphasis = {};
                extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS);
                extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS);
            }

            animateLabelValue(textEl, dataIndex, data, seriesModel, seriesModel);
        }

        if (guideLine && !guideLine.ignore && !guideLine.invisible) {
            const layoutStore = labelLineAnimationStore(guideLine);
            const oldLayout = layoutStore.oldLayout;
            const newLayout = { points: guideLine.shape.points };
            if (!oldLayout) {
                guideLine.setShape(newLayout);
                guideLine.style.strokePercent = 0;
                initProps(guideLine, {
                    style: { strokePercent: 1 }
                }, seriesModel);
            }
            else {
                guideLine.attr({ shape: oldLayout });
                updateProps(guideLine, {
                    shape: newLayout
                }, seriesModel);
            }

            layoutStore.oldLayout = newLayout;
        }
    }
}


export default LabelManager;